Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin: (47 commits)
  Blackfin: bfin_spi.h: add MMR peripheral layout
  Blackfin: bfin_ppi.h: start a common PPI/EPPI header
  Blackfin: bfin_can.h: add missing VERSION/VERSION2 MMRs
  Blackfin: bf538: add missing SIC_RVECT define
  Blackfin: bf561: rewrite SICA_xxx to just SIC_xxx
  Blackfin: bf54x: add missing SIC_RVECT definition
  Blackfin: H8606: move 8250 irqflags to platform resources
  Blackfin: glue XIP/ROM kernel kconfigs
  Blackfin: update sparse flags for latest upstream changes
  Blackfin: coreb: update ioctl numbers
  Blackfin: coreb: add gpl module license
  Blackfin: bf518-ezkit: add ssm2603 codec resources
  Blackfin: bf51x/bf52x: fix 16/32bit SPORT MMR helpers
  Blackfin: tll6527m: new board port
  Blackfin: bf526-ezbrd/bf527-ezkit: add NAND partition for u-boot
  Blackfin: merge kernel init memory back into main memory region
  Blackfin: gpio: add peripheral group check
  Blackfin: dma: bf54x: add missing break for SPORT1 TX IRQ
  Blackfin: add new cacheflush syscall
  Blackfin: bf548-ezkit: increase u-boot partition size
  ...
diff --git a/Documentation/ABI/testing/sysfs-module b/Documentation/ABI/testing/sysfs-module
new file mode 100644
index 0000000..cfcec3b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-module
@@ -0,0 +1,12 @@
+What:		/sys/module/pch_phub/drivers/.../pch_mac
+Date:		August 2010
+KernelVersion:	2.6.35
+Contact:	masa-korg@dsn.okisemi.com
+Description:	Write/read GbE MAC address.
+
+What:		/sys/module/pch_phub/drivers/.../pch_firmware
+Date:		August 2010
+KernelVersion:	2.6.35
+Contact:	masa-korg@dsn.okisemi.com
+Description:	Write/read Option ROM data.
+
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 910c923..2861055 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -136,6 +136,7 @@
 #ifdef CONFIG_COMPAT
 		.compat_ioctl = i915_compat_ioctl,
 #endif
+		.llseek = noop_llseek,
 		},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 6899f47..6b4e07f 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -257,7 +257,8 @@
 !Iblock/blk-sysfs.c
 !Eblock/blk-settings.c
 !Eblock/blk-exec.c
-!Eblock/blk-barrier.c
+!Eblock/blk-flush.c
+!Eblock/blk-lib.c
 !Eblock/blk-tag.c
 !Iblock/blk-tag.c
 !Eblock/blk-integrity.c
diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX
index a406286f..d111e3b 100644
--- a/Documentation/block/00-INDEX
+++ b/Documentation/block/00-INDEX
@@ -1,7 +1,5 @@
 00-INDEX
 	- This file
-barrier.txt
-	- I/O Barriers
 biodoc.txt
 	- Notes on the Generic Block Layer Rewrite in Linux 2.5
 capability.txt
@@ -16,3 +14,5 @@
 	- Block layer statistics in /sys/block/<dev>/stat
 switching-sched.txt
 	- Switching I/O schedulers at runtime
+writeback_cache_control.txt
+	- Control of volatile write back caches
diff --git a/Documentation/block/barrier.txt b/Documentation/block/barrier.txt
deleted file mode 100644
index 2c2f24f6..0000000
--- a/Documentation/block/barrier.txt
+++ /dev/null
@@ -1,261 +0,0 @@
-I/O Barriers
-============
-Tejun Heo <htejun@gmail.com>, July 22 2005
-
-I/O barrier requests are used to guarantee ordering around the barrier
-requests.  Unless you're crazy enough to use disk drives for
-implementing synchronization constructs (wow, sounds interesting...),
-the ordering is meaningful only for write requests for things like
-journal checkpoints.  All requests queued before a barrier request
-must be finished (made it to the physical medium) before the barrier
-request is started, and all requests queued after the barrier request
-must be started only after the barrier request is finished (again,
-made it to the physical medium).
-
-In other words, I/O barrier requests have the following two properties.
-
-1. Request ordering
-
-Requests cannot pass the barrier request.  Preceding requests are
-processed before the barrier and following requests after.
-
-Depending on what features a drive supports, this can be done in one
-of the following three ways.
-
-i. For devices which have queue depth greater than 1 (TCQ devices) and
-support ordered tags, block layer can just issue the barrier as an
-ordered request and the lower level driver, controller and drive
-itself are responsible for making sure that the ordering constraint is
-met.  Most modern SCSI controllers/drives should support this.
-
-NOTE: SCSI ordered tag isn't currently used due to limitation in the
-      SCSI midlayer, see the following random notes section.
-
-ii. For devices which have queue depth greater than 1 but don't
-support ordered tags, block layer ensures that the requests preceding
-a barrier request finishes before issuing the barrier request.  Also,
-it defers requests following the barrier until the barrier request is
-finished.  Older SCSI controllers/drives and SATA drives fall in this
-category.
-
-iii. Devices which have queue depth of 1.  This is a degenerate case
-of ii.  Just keeping issue order suffices.  Ancient SCSI
-controllers/drives and IDE drives are in this category.
-
-2. Forced flushing to physical medium
-
-Again, if you're not gonna do synchronization with disk drives (dang,
-it sounds even more appealing now!), the reason you use I/O barriers
-is mainly to protect filesystem integrity when power failure or some
-other events abruptly stop the drive from operating and possibly make
-the drive lose data in its cache.  So, I/O barriers need to guarantee
-that requests actually get written to non-volatile medium in order.
-
-There are four cases,
-
-i. No write-back cache.  Keeping requests ordered is enough.
-
-ii. Write-back cache but no flush operation.  There's no way to
-guarantee physical-medium commit order.  This kind of devices can't to
-I/O barriers.
-
-iii. Write-back cache and flush operation but no FUA (forced unit
-access).  We need two cache flushes - before and after the barrier
-request.
-
-iv. Write-back cache, flush operation and FUA.  We still need one
-flush to make sure requests preceding a barrier are written to medium,
-but post-barrier flush can be avoided by using FUA write on the
-barrier itself.
-
-
-How to support barrier requests in drivers
-------------------------------------------
-
-All barrier handling is done inside block layer proper.  All low level
-drivers have to are implementing its prepare_flush_fn and using one
-the following two functions to indicate what barrier type it supports
-and how to prepare flush requests.  Note that the term 'ordered' is
-used to indicate the whole sequence of performing barrier requests
-including draining and flushing.
-
-typedef void (prepare_flush_fn)(struct request_queue *q, struct request *rq);
-
-int blk_queue_ordered(struct request_queue *q, unsigned ordered,
-		      prepare_flush_fn *prepare_flush_fn);
-
-@q			: the queue in question
-@ordered		: the ordered mode the driver/device supports
-@prepare_flush_fn	: this function should prepare @rq such that it
-			  flushes cache to physical medium when executed
-
-For example, SCSI disk driver's prepare_flush_fn looks like the
-following.
-
-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;
-	rq->cmd_len = 10;
-}
-
-The following seven ordered modes are supported.  The following table
-shows which mode should be used depending on what features a
-device/driver supports.  In the leftmost column of table,
-QUEUE_ORDERED_ prefix is omitted from the mode names to save space.
-
-The table is followed by description of each mode.  Note that in the
-descriptions of QUEUE_ORDERED_DRAIN*, '=>' is used whereas '->' is
-used for QUEUE_ORDERED_TAG* descriptions.  '=>' indicates that the
-preceding step must be complete before proceeding to the next step.
-'->' indicates that the next step can start as soon as the previous
-step is issued.
-
-	    write-back cache	ordered tag	flush		FUA
------------------------------------------------------------------------
-NONE		yes/no		N/A		no		N/A
-DRAIN		no		no		N/A		N/A
-DRAIN_FLUSH	yes		no		yes		no
-DRAIN_FUA	yes		no		yes		yes
-TAG		no		yes		N/A		N/A
-TAG_FLUSH	yes		yes		yes		no
-TAG_FUA		yes		yes		yes		yes
-
-
-QUEUE_ORDERED_NONE
-	I/O barriers are not needed and/or supported.
-
-	Sequence: N/A
-
-QUEUE_ORDERED_DRAIN
-	Requests are ordered by draining the request queue and cache
-	flushing isn't needed.
-
-	Sequence: drain => barrier
-
-QUEUE_ORDERED_DRAIN_FLUSH
-	Requests are ordered by draining the request queue and both
-	pre-barrier and post-barrier cache flushings are needed.
-
-	Sequence: drain => preflush => barrier => postflush
-
-QUEUE_ORDERED_DRAIN_FUA
-	Requests are ordered by draining the request queue and
-	pre-barrier cache flushing is needed.  By using FUA on barrier
-	request, post-barrier flushing can be skipped.
-
-	Sequence: drain => preflush => barrier
-
-QUEUE_ORDERED_TAG
-	Requests are ordered by ordered tag and cache flushing isn't
-	needed.
-
-	Sequence: barrier
-
-QUEUE_ORDERED_TAG_FLUSH
-	Requests are ordered by ordered tag and both pre-barrier and
-	post-barrier cache flushings are needed.
-
-	Sequence: preflush -> barrier -> postflush
-
-QUEUE_ORDERED_TAG_FUA
-	Requests are ordered by ordered tag and pre-barrier cache
-	flushing is needed.  By using FUA on barrier request,
-	post-barrier flushing can be skipped.
-
-	Sequence: preflush -> barrier
-
-
-Random notes/caveats
---------------------
-
-* SCSI layer currently can't use TAG ordering even if the drive,
-controller and driver support it.  The problem is that SCSI midlayer
-request dispatch function is not atomic.  It releases queue lock and
-switch to SCSI host lock during issue and it's possible and likely to
-happen in time that requests change their relative positions.  Once
-this problem is solved, TAG ordering can be enabled.
-
-* Currently, no matter which ordered mode is used, there can be only
-one barrier request in progress.  All I/O barriers are held off by
-block layer until the previous I/O barrier is complete.  This doesn't
-make any difference for DRAIN ordered devices, but, for TAG ordered
-devices with very high command latency, passing multiple I/O barriers
-to low level *might* be helpful if they are very frequent.  Well, this
-certainly is a non-issue.  I'm writing this just to make clear that no
-two I/O barrier is ever passed to low-level driver.
-
-* Completion order.  Requests in ordered sequence are issued in order
-but not required to finish in order.  Barrier implementation can
-handle out-of-order completion of ordered sequence.  IOW, the requests
-MUST be processed in order but the hardware/software completion paths
-are allowed to reorder completion notifications - eg. current SCSI
-midlayer doesn't preserve completion order during error handling.
-
-* Requeueing order.  Low-level drivers are free to requeue any request
-after they removed it from the request queue with
-blkdev_dequeue_request().  As barrier sequence should be kept in order
-when requeued, generic elevator code takes care of putting requests in
-order around barrier.  See blk_ordered_req_seq() and
-ELEVATOR_INSERT_REQUEUE handling in __elv_add_request() for details.
-
-Note that block drivers must not requeue preceding requests while
-completing latter requests in an ordered sequence.  Currently, no
-error checking is done against this.
-
-* Error handling.  Currently, block layer will report error to upper
-layer if any of requests in an ordered sequence fails.  Unfortunately,
-this doesn't seem to be enough.  Look at the following request flow.
-QUEUE_ORDERED_TAG_FLUSH is in use.
-
- [0] [1] [2] [3] [pre] [barrier] [post] < [4] [5] [6] ... >
-					  still in elevator
-
-Let's say request [2], [3] are write requests to update file system
-metadata (journal or whatever) and [barrier] is used to mark that
-those updates are valid.  Consider the following sequence.
-
- i.	Requests [0] ~ [post] leaves the request queue and enters
-	low-level driver.
- ii.	After a while, unfortunately, something goes wrong and the
-	drive fails [2].  Note that any of [0], [1] and [3] could have
-	completed by this time, but [pre] couldn't have been finished
-	as the drive must process it in order and it failed before
-	processing that command.
- iii.	Error handling kicks in and determines that the error is
-	unrecoverable and fails [2], and resumes operation.
- iv.	[pre] [barrier] [post] gets processed.
- v.	*BOOM* power fails
-
-The problem here is that the barrier request is *supposed* to indicate
-that filesystem update requests [2] and [3] made it safely to the
-physical medium and, if the machine crashes after the barrier is
-written, filesystem recovery code can depend on that.  Sadly, that
-isn't true in this case anymore.  IOW, the success of a I/O barrier
-should also be dependent on success of some of the preceding requests,
-where only upper layer (filesystem) knows what 'some' is.
-
-This can be solved by implementing a way to tell the block layer which
-requests affect the success of the following barrier request and
-making lower lever drivers to resume operation on error only after
-block layer tells it to do so.
-
-As the probability of this happening is very low and the drive should
-be faulty, implementing the fix is probably an overkill.  But, still,
-it's there.
-
-* In previous drafts of barrier implementation, there was fallback
-mechanism such that, if FUA or ordered TAG fails, less fancy ordered
-mode can be selected and the failed barrier request is retried
-automatically.  The rationale for this feature was that as FUA is
-pretty new in ATA world and ordered tag was never used widely, there
-could be devices which report to support those features but choke when
-actually given such requests.
-
- This was removed for two reasons 1. it's an overkill 2. it's
-impossible to implement properly when TAG ordering is used as low
-level drivers resume after an error automatically.  If it's ever
-needed adding it back and modifying low level drivers accordingly
-shouldn't be difficult.
diff --git a/Documentation/block/writeback_cache_control.txt b/Documentation/block/writeback_cache_control.txt
new file mode 100644
index 0000000..83407d3
--- /dev/null
+++ b/Documentation/block/writeback_cache_control.txt
@@ -0,0 +1,86 @@
+
+Explicit volatile write back cache control
+=====================================
+
+Introduction
+------------
+
+Many storage devices, especially in the consumer market, come with volatile
+write back caches.  That means the devices signal I/O completion to the
+operating system before data actually has hit the non-volatile storage.  This
+behavior obviously speeds up various workloads, but it means the operating
+system needs to force data out to the non-volatile storage when it performs
+a data integrity operation like fsync, sync or an unmount.
+
+The Linux block layer provides two simple mechanisms that let filesystems
+control the caching behavior of the storage device.  These mechanisms are
+a forced cache flush, and the Force Unit Access (FUA) flag for requests.
+
+
+Explicit cache flushes
+----------------------
+
+The REQ_FLUSH flag can be OR ed into the r/w flags of a bio submitted from
+the filesystem and will make sure the volatile cache of the storage device
+has been flushed before the actual I/O operation is started.  This explicitly
+guarantees that previously completed write requests are on non-volatile
+storage before the flagged bio starts. In addition the REQ_FLUSH flag can be
+set on an otherwise empty bio structure, which causes only an explicit cache
+flush without any dependent I/O.  It is recommend to use
+the blkdev_issue_flush() helper for a pure cache flush.
+
+
+Forced Unit Access
+-----------------
+
+The REQ_FUA flag can be OR ed into the r/w flags of a bio submitted from the
+filesystem and will make sure that I/O completion for this request is only
+signaled after the data has been committed to non-volatile storage.
+
+
+Implementation details for filesystems
+--------------------------------------
+
+Filesystems can simply set the REQ_FLUSH and REQ_FUA bits and do not have to
+worry if the underlying devices need any explicit cache flushing and how
+the Forced Unit Access is implemented.  The REQ_FLUSH and REQ_FUA flags
+may both be set on a single bio.
+
+
+Implementation details for make_request_fn based block drivers
+--------------------------------------------------------------
+
+These drivers will always see the REQ_FLUSH and REQ_FUA bits as they sit
+directly below the submit_bio interface.  For remapping drivers the REQ_FUA
+bits need to be propagated to underlying devices, and a global flush needs
+to be implemented for bios with the REQ_FLUSH bit set.  For real device
+drivers that do not have a volatile cache the REQ_FLUSH and REQ_FUA bits
+on non-empty bios can simply be ignored, and REQ_FLUSH requests without
+data can be completed successfully without doing any work.  Drivers for
+devices with volatile caches need to implement the support for these
+flags themselves without any help from the block layer.
+
+
+Implementation details for request_fn based block drivers
+--------------------------------------------------------------
+
+For devices that do not support volatile write caches there is no driver
+support required, the block layer completes empty REQ_FLUSH requests before
+entering the driver and strips off the REQ_FLUSH and REQ_FUA bits from
+requests that have a payload.  For devices with volatile write caches the
+driver needs to tell the block layer that it supports flushing caches by
+doing:
+
+	blk_queue_flush(sdkp->disk->queue, REQ_FLUSH);
+
+and handle empty REQ_FLUSH requests in its prep_fn/request_fn.  Note that
+REQ_FLUSH requests with a payload are automatically turned into a sequence
+of an empty REQ_FLUSH request followed by the actual write by the block
+layer.  For devices that also support the FUA bit the block layer needs
+to be told to pass through the REQ_FUA bit using:
+
+	blk_queue_flush(sdkp->disk->queue, REQ_FLUSH | REQ_FUA);
+
+and the driver must handle write requests that have the REQ_FUA bit set
+in prep_fn/request_fn.  If the FUA bit is not natively supported the block
+layer turns it into an empty REQ_FLUSH request after the actual write.
diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt
index 6919d62..d6da611 100644
--- a/Documentation/cgroups/blkio-controller.txt
+++ b/Documentation/cgroups/blkio-controller.txt
@@ -8,12 +8,17 @@
 Plan is to use the same cgroup based management interface for blkio controller
 and based on user options switch IO policies in the background.
 
-In the first phase, this patchset implements proportional weight time based
-division of disk policy. It is implemented in CFQ. Hence this policy takes
-effect only on leaf nodes when CFQ is being used.
+Currently two IO control policies are implemented. First one is proportional
+weight time based division of disk policy. It is implemented in CFQ. Hence
+this policy takes effect only on leaf nodes when CFQ is being used. The second
+one is throttling policy which can be used to specify upper IO rate limits
+on devices. This policy is implemented in generic block layer and can be
+used on leaf nodes as well as higher level logical devices like device mapper.
 
 HOWTO
 =====
+Proportional Weight division of bandwidth
+-----------------------------------------
 You can do a very simple testing of running two dd threads in two different
 cgroups. Here is what you can do.
 
@@ -55,6 +60,35 @@
   group dispatched to the disk. We provide fairness in terms of disk time, so
   ideally io.disk_time of cgroups should be in proportion to the weight.
 
+Throttling/Upper Limit policy
+-----------------------------
+- Enable Block IO controller
+	CONFIG_BLK_CGROUP=y
+
+- Enable throttling in block layer
+	CONFIG_BLK_DEV_THROTTLING=y
+
+- Mount blkio controller
+        mount -t cgroup -o blkio none /cgroup/blkio
+
+- Specify a bandwidth rate on particular device for root group. The format
+  for policy is "<major>:<minor>  <byes_per_second>".
+
+        echo "8:16  1048576" > /cgroup/blkio/blkio.read_bps_device
+
+  Above will put a limit of 1MB/second on reads happening for root group
+  on device having major/minor number 8:16.
+
+- Run dd to read a file and see if rate is throttled to 1MB/s or not.
+
+		# dd if=/mnt/common/zerofile of=/dev/null bs=4K count=1024
+		# iflag=direct
+        1024+0 records in
+        1024+0 records out
+        4194304 bytes (4.2 MB) copied, 4.0001 s, 1.0 MB/s
+
+ Limits for writes can be put using blkio.write_bps_device file.
+
 Various user visible config options
 ===================================
 CONFIG_BLK_CGROUP
@@ -68,8 +102,13 @@
 	- Enables group scheduling in CFQ. Currently only 1 level of group
 	  creation is allowed.
 
+CONFIG_BLK_DEV_THROTTLING
+	- Enable block device throttling support in block layer.
+
 Details of cgroup files
 =======================
+Proportional weight policy files
+--------------------------------
 - blkio.weight
 	- Specifies per cgroup weight. This is default weight of the group
 	  on all the devices until and unless overridden by per device rule.
@@ -210,6 +249,67 @@
 	  and minor number of the device and third field specifies the number
 	  of times a group was dequeued from a particular device.
 
+Throttling/Upper limit policy files
+-----------------------------------
+- blkio.throttle.read_bps_device
+	- Specifies upper limit on READ rate from the device. IO rate is
+	  specified in bytes per second. Rules are per deivce. Following is
+	  the format.
+
+  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.read_bps_device
+
+- blkio.throttle.write_bps_device
+	- Specifies upper limit on WRITE rate to the device. IO rate is
+	  specified in bytes per second. Rules are per deivce. Following is
+	  the format.
+
+  echo "<major>:<minor>  <rate_bytes_per_second>" > /cgrp/blkio.write_bps_device
+
+- blkio.throttle.read_iops_device
+	- Specifies upper limit on READ rate from the device. IO rate is
+	  specified in IO per second. Rules are per deivce. Following is
+	  the format.
+
+  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.read_iops_device
+
+- blkio.throttle.write_iops_device
+	- Specifies upper limit on WRITE rate to the device. IO rate is
+	  specified in io per second. Rules are per deivce. Following is
+	  the format.
+
+  echo "<major>:<minor>  <rate_io_per_second>" > /cgrp/blkio.write_iops_device
+
+Note: If both BW and IOPS rules are specified for a device, then IO is
+      subjectd to both the constraints.
+
+- blkio.throttle.io_serviced
+	- Number of IOs (bio) completed to/from the disk by the group (as
+	  seen by throttling policy). These are further divided by the type
+	  of operation - read or write, sync or async. First two fields specify
+	  the major and minor number of the device, third field specifies the
+	  operation type and the fourth field specifies the number of IOs.
+
+	  blkio.io_serviced does accounting as seen by CFQ and counts are in
+	  number of requests (struct request). On the other hand,
+	  blkio.throttle.io_serviced counts number of IO in terms of number
+	  of bios as seen by throttling policy.  These bios can later be
+	  merged by elevator and total number of requests completed can be
+	  lesser.
+
+- blkio.throttle.io_service_bytes
+	- Number of bytes transferred to/from the disk by the group. These
+	  are further divided by the type of operation - read or write, sync
+	  or async. First two fields specify the major and minor number of the
+	  device, third field specifies the operation type and the fourth field
+	  specifies the number of bytes.
+
+	  These numbers should roughly be same as blkio.io_service_bytes as
+	  updated by CFQ. The difference between two is that
+	  blkio.io_service_bytes will not be updated if CFQ is not operating
+	  on request queue.
+
+Common files among various policies
+-----------------------------------
 - blkio.reset_stats
 	- Writing an int to this file will result in resetting all the stats
 	  for that cgroup.
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index d0d1df6..c58abf1 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -239,6 +239,7 @@
 		  0 = /dev/tty		Current TTY device
 		  1 = /dev/console	System console
 		  2 = /dev/ptmx		PTY master multiplex
+		  3 = /dev/ttyprintk	User messages via printk TTY device
 		 64 = /dev/cua0		Callout device for ttyS0
 		    ...
 		255 = /dev/cua191	Callout device for ttyS191
@@ -2553,7 +2554,10 @@
 		175 = /dev/usb/legousbtower15	16th USB Legotower device
 		176 = /dev/usb/usbtmc1	First USB TMC device
 		   ...
-		192 = /dev/usb/usbtmc16	16th USB TMC device
+		191 = /dev/usb/usbtmc16	16th USB TMC device
+		192 = /dev/usb/yurex1	First USB Yurex device
+		   ...
+		209 = /dev/usb/yurex16	16th USB Yurex device
 		240 = /dev/usb/dabusb0	First daubusb device
 		    ...
 		243 = /dev/usb/dabusb3	Fourth dabusb device
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt
index 674c566..58ea64a9 100644
--- a/Documentation/dynamic-debug-howto.txt
+++ b/Documentation/dynamic-debug-howto.txt
@@ -24,7 +24,7 @@
    read to display the complete list of known debug statements, to help guide you
 
 Controlling dynamic debug Behaviour
-===============================
+===================================
 
 The behaviour of pr_debug()/dev_debug()s are controlled via writing to a
 control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
@@ -212,6 +212,26 @@
 Note also that there is no convenient syntax to remove all
 the flags at once, you need to use "-psc".
 
+
+Debug messages during boot process
+==================================
+
+To be able to activate debug messages during the boot process,
+even before userspace and debugfs exists, use the boot parameter:
+ddebug_query="QUERY"
+
+QUERY follows the syntax described above, but must not exceed 1023
+characters. The enablement of debug messages is done as an arch_initcall.
+Thus you can enable debug messages in all code processed after this
+arch_initcall via this boot parameter.
+On an x86 system for example ACPI enablement is a subsys_initcall and
+ddebug_query="file ec.c +p"
+will show early Embedded Controller transactions during ACPI setup if
+your machine (typically a laptop) has an Embedded Controller.
+PCI (or other devices) initialization also is a hot candidate for using
+this boot parameter for debugging purposes.
+
+
 Examples
 ========
 
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index a6aca87..98223a6 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1075,6 +1075,7 @@
  drivers       list of drivers and their usage                
  ldiscs        registered line disciplines                    
  driver/serial usage statistic and status of single tty lines 
+ consoles      registered system console lines
 ..............................................................................
 
 To see  which  tty's  are  currently in use, you can simply look into the file
@@ -1093,6 +1094,37 @@
   /dev/tty             /dev/tty        5       0 system:/dev/tty 
   unknown              /dev/tty        4    1-63 console 
 
+To see which character device lines are currently used for the system console
+/dev/console, you may simply look into the file /proc/tty/consoles:
+
+  > cat /proc/tty/consoles
+  tty0                 -WU (ECp)       4:7
+  ttyS0                -W- (Ep)        4:64
+
+The columns are:
+
+  device               name of the device
+  operations           R = can do read operations
+                       W = can do write operations
+                       U = can do unblank
+  flags                E = it is enabled
+                       C = it is prefered console
+                       B = it is primary boot console
+                       p = it is used for printk buffer
+                       b = it is not a TTY but a Braille device
+                       a = it is safe to use when cpu is offline
+                       * = it is standard input of the reading process
+  major:minor          major and minor number of the device separated by a colon
+
+If the reading process holds /dev/console open at the regular standard input
+stream the active device will be marked by an asterisk:
+
+  > cat /proc/tty/consoles < /dev/console
+  tty0                 -WU (ECp*)      4:7
+  ttyS0                -W- (Ep)        4:64
+  > tty
+  /dev/pts/3
+
 
 1.8 Miscellaneous kernel statistics in /proc/stat
 -------------------------------------------------
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 02f21d9..4cd8b86 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -43,10 +43,11 @@
 	AVR32	AVR32 architecture is enabled.
 	AX25	Appropriate AX.25 support is enabled.
 	BLACKFIN Blackfin architecture is enabled.
-	DRM	Direct Rendering Management support is enabled.
 	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
 	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
+	DRM	Direct Rendering Management support is enabled.
+	DYNAMIC_DEBUG Build in debug messages and enable them at runtime
 	FB	The frame buffer device is enabled.
 	GCOV	GCOV profiling is enabled.
 	HW	Appropriate hardware is enabled.
@@ -570,6 +571,10 @@
 			Format: <port#>,<type>
 			See also Documentation/input/joystick-parport.txt
 
+	ddebug_query=   [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot
+			time. See Documentation/dynamic-debug-howto.txt for
+			details.
+
 	debug		[KNL] Enable kernel debugging (events log level).
 
 	debug_locks_verbose=
@@ -2370,6 +2375,15 @@
 
 	switches=	[HW,M68k]
 
+	sysfs.deprecated=0|1 [KNL]
+			Enable/disable old style sysfs layout for old udev
+			on older distributions. When this option is enabled
+			very new udev will not work anymore. When this option
+			is disabled (or CONFIG_SYSFS_DEPRECATED not compiled)
+			in older udev will not work anymore.
+			Default depends on CONFIG_SYSFS_DEPRECATED_V2 set in
+			the kernel configuration.
+
 	sysrq_always_enabled
 			[KNL]
 			Ignore sysrq setting - this boot parameter will
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 8a6a8c6..dc73bc54 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -1640,15 +1640,6 @@
 	off = out->sector * 512;
 
 	/*
-	 * The block device implements "barriers", where the Guest indicates
-	 * that it wants all previous writes to occur before this write.  We
-	 * don't have a way of asking our kernel to do a barrier, so we just
-	 * synchronize all the data in the file.  Pretty poor, no?
-	 */
-	if (out->type & VIRTIO_BLK_T_BARRIER)
-		fdatasync(vblk->fd);
-
-	/*
 	 * In general the virtio block driver is allowed to try SCSI commands.
 	 * It'd be nice if we supported eject, for example, but we don't.
 	 */
@@ -1680,6 +1671,13 @@
 			/* Die, bad Guest, die. */
 			errx(1, "Write past end %llu+%u", off, ret);
 		}
+
+		wlen = sizeof(*in);
+		*in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
+	} else if (out->type & VIRTIO_BLK_T_FLUSH) {
+		/* Flush */
+		ret = fdatasync(vblk->fd);
+		verbose("FLUSH fdatasync: %i\n", ret);
 		wlen = sizeof(*in);
 		*in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
 	} else {
@@ -1703,15 +1701,6 @@
 		}
 	}
 
-	/*
-	 * OK, so we noted that it was pretty poor to use an fdatasync as a
-	 * barrier.  But Christoph Hellwig points out that we need a sync
-	 * *afterwards* as well: "Barriers specify no reordering to the front
-	 * or the back."  And Jens Axboe confirmed it, so here we are:
-	 */
-	if (out->type & VIRTIO_BLK_T_BARRIER)
-		fdatasync(vblk->fd);
-
 	/* Finished that request. */
 	add_used(vq, head, wlen);
 }
@@ -1736,8 +1725,8 @@
 	vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE);
 	vblk->len = lseek64(vblk->fd, 0, SEEK_END);
 
-	/* We support barriers. */
-	add_feature(dev, VIRTIO_BLK_F_BARRIER);
+	/* We support FLUSH. */
+	add_feature(dev, VIRTIO_BLK_F_FLUSH);
 
 	/* Tell Guest how many sectors this device has. */
 	conf.capacity = cpu_to_le64(vblk->len / 512);
diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentation/powerpc/dts-bindings/fsl/usb.txt
index b001524..bd5723f 100644
--- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
@@ -8,6 +8,7 @@
 Required properties :
  - compatible : Should be "fsl-usb2-mph" for multi port host USB
    controllers, or "fsl-usb2-dr" for dual role USB controllers
+   or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
  - phy_type : For multi port host USB controllers, should be one of
    "ulpi", or "serial". For dual role USB controllers, should be
    one of "ulpi", "utmi", "utmi_wide", or "serial".
@@ -33,6 +34,12 @@
  - interrupt-parent : the phandle for the interrupt controller that
    services interrupts for this device.
 
+Optional properties :
+ - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the
+   port power polarity of internal PHY signal DRVVBUS is inverted.
+ - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates
+   the PWR_FAULT signal polarity is inverted.
+
 Example multi port host USB controller device node :
 	usb@22000 {
 		compatible = "fsl-usb2-mph";
@@ -57,3 +64,18 @@
 		dr_mode = "otg";
 		phy = "ulpi";
 	};
+
+Example dual role USB controller device node for MPC5121ADS:
+
+	usb@4000 {
+		compatible = "fsl,mpc5121-usb2-dr";
+		reg = <0x4000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-parent = < &ipic >;
+		interrupts = <44 0x8>;
+		dr_mode = "otg";
+		phy_type = "utmi_wide";
+		fsl,invert-drvvbus;
+		fsl,invert-pwr-fault;
+	};
diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
index 4075260..691ca29 100644
--- a/Documentation/scsi/st.txt
+++ b/Documentation/scsi/st.txt
@@ -2,7 +2,7 @@
 The driver is currently maintained by Kai Mäkisara (email
 Kai.Makisara@kolumbus.fi)
 
-Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara
+Last modified: Sun Aug 29 18:25:47 2010 by kai.makisara
 
 
 BASICS
@@ -85,6 +85,17 @@
 optionally written. In both cases end of data is signified by
 returning zero bytes for two consecutive reads.
 
+Writing filemarks without the immediate bit set in the SCSI command block acts
+as a synchronization point, i.e., all remaining data form the drive buffers is
+written to tape before the command returns. This makes sure that write errors
+are caught at that point, but this takes time. In some applications, several
+consecutive files must be written fast. The MTWEOFI operation can be used to
+write the filemarks without flushing the drive buffer. Writing filemark at
+close() is always flushing the drive buffers. However, if the previous
+operation is MTWEOFI, close() does not write a filemark. This can be used if
+the program wants to close/open the tape device between files and wants to
+skip waiting.
+
 If rewind, offline, bsf, or seek is done and previous tape operation was
 write, a filemark is written before moving tape.
 
@@ -301,6 +312,8 @@
 MTFSS   Space forward over count setmarks.
 MTBSS   Space backward over count setmarks.
 MTWEOF  Write count filemarks.
+MTWEOFI	Write count filemarks with immediate bit set (i.e., does not
+	wait until data is on tape)
 MTWSM   Write count setmarks.
 MTREW   Rewind tape.
 MTOFFL  Set device off line (often rewind plus eject).
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
index fafcd47..afe596d 100644
--- a/Documentation/usb/proc_usb_info.txt
+++ b/Documentation/usb/proc_usb_info.txt
@@ -1,12 +1,17 @@
 /proc/bus/usb filesystem output
 ===============================
-(version 2003.05.30)
+(version 2010.09.13)
 
 
 The usbfs filesystem for USB devices is traditionally mounted at
 /proc/bus/usb.  It provides the /proc/bus/usb/devices file, as well as
 the /proc/bus/usb/BBB/DDD files.
 
+In many modern systems the usbfs filsystem isn't used at all.  Instead
+USB device nodes are created under /dev/usb/ or someplace similar.  The
+"devices" file is available in debugfs, typically as
+/sys/kernel/debug/usb/devices.
+
 
 **NOTE**: If /proc/bus/usb appears empty, and a host controller
 	  driver has been linked, then you need to mount the
@@ -106,8 +111,8 @@
 
 Topology info:
 
-T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd
-|   |      |      |       |       |      |        |       |__MaxChildren
+T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd
+|   |      |      |       |       |      |        |        |__MaxChildren
 |   |      |      |       |       |      |        |__Device Speed in Mbps
 |   |      |      |       |       |      |__DeviceNumber
 |   |      |      |       |       |__Count of devices at this level
@@ -120,8 +125,13 @@
     Speed may be:
     	1.5	Mbit/s for low speed USB
 	12	Mbit/s for full speed USB
-	480	Mbit/s for high speed USB (added for USB 2.0)
+	480	Mbit/s for high speed USB (added for USB 2.0);
+		  also used for Wireless USB, which has no fixed speed
+	5000	Mbit/s for SuperSpeed USB (added for USB 3.0)
 
+    For reasons lost in the mists of time, the Port number is always
+    too low by 1.  For example, a device plugged into port 4 will
+    show up with "Port=03".
 
 Bandwidth info:
 B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
@@ -291,7 +301,7 @@
 an external hub connected to the root hub, and a mouse and
 a serial converter connected to the external hub.
 
-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
 B:  Alloc= 28/900 us ( 3%), #Int=  2, #Iso=  0
 D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0000 ProdID=0000 Rev= 0.00
@@ -301,21 +311,21 @@
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
 
-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4
 D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0451 ProdID=1446 Rev= 1.00
 C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms
 
-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=04b4 ProdID=0001 Rev= 0.00
 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
 E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms
 
-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0565 ProdID=0001 Rev= 1.08
 S:  Manufacturer=Peracom Networks, Inc.
@@ -330,12 +340,12 @@
 Selecting only the "T:" and "I:" lines from this (for example, by using
 "procusb ti"), we have:
 
-T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
-T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
-T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
-T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0
 I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
 
 
diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt
index e4498a2..996a27d 100644
--- a/Documentation/workqueue.txt
+++ b/Documentation/workqueue.txt
@@ -196,11 +196,11 @@
 	suspend operations.  Work items on the wq are drained and no
 	new work item starts execution until thawed.
 
-  WQ_RESCUER
+  WQ_MEM_RECLAIM
 
 	All wq which might be used in the memory reclaim paths _MUST_
-	have this flag set.  This reserves one worker exclusively for
-	the execution of this wq under memory pressure.
+	have this flag set.  The wq is guaranteed to have at least one
+	execution context regardless of memory pressure.
 
   WQ_HIGHPRI
 
@@ -356,11 +356,11 @@
 
 6. Guidelines
 
-* Do not forget to use WQ_RESCUER if a wq may process work items which
-  are used during memory reclaim.  Each wq with WQ_RESCUER set has one
-  rescuer thread reserved for it.  If there is dependency among
-  multiple work items used during memory reclaim, they should be
-  queued to separate wq each with WQ_RESCUER.
+* Do not forget to use WQ_MEM_RECLAIM if a wq may process work items
+  which are used during memory reclaim.  Each wq with WQ_MEM_RECLAIM
+  set has an execution context reserved for it.  If there is
+  dependency among multiple work items used during memory reclaim,
+  they should be queued to separate wq each with WQ_MEM_RECLAIM.
 
 * Unless strict ordering is required, there is no need to use ST wq.
 
@@ -368,12 +368,13 @@
   recommended.  In most use cases, concurrency level usually stays
   well under the default limit.
 
-* A wq serves as a domain for forward progress guarantee (WQ_RESCUER),
-  flush and work item attributes.  Work items which are not involved
-  in memory reclaim and don't need to be flushed as a part of a group
-  of work items, and don't require any special attribute, can use one
-  of the system wq.  There is no difference in execution
-  characteristics between using a dedicated wq and a system wq.
+* A wq serves as a domain for forward progress guarantee
+  (WQ_MEM_RECLAIM, flush and work item attributes.  Work items which
+  are not involved in memory reclaim and don't need to be flushed as a
+  part of a group of work items, and don't require any special
+  attribute, can use one of the system wq.  There is no difference in
+  execution characteristics between using a dedicated wq and a system
+  wq.
 
 * Unless work items are expected to consume a huge amount of CPU
   cycles, using a bound wq is usually beneficial due to the increased
diff --git a/Documentation/x86/x86_64/kernel-stacks b/Documentation/x86/x86_64/kernel-stacks
index 5ad65d5..a01eec5 100644
--- a/Documentation/x86/x86_64/kernel-stacks
+++ b/Documentation/x86/x86_64/kernel-stacks
@@ -18,9 +18,9 @@
   Used for external hardware interrupts.  If this is the first external
   hardware interrupt (i.e. not a nested hardware interrupt) then the
   kernel switches from the current task to the interrupt stack.  Like
-  the split thread and interrupt stacks on i386 (with CONFIG_4KSTACKS),
-  this gives more room for kernel interrupt processing without having
-  to increase the size of every per thread stack.
+  the split thread and interrupt stacks on i386, this gives more room
+  for kernel interrupt processing without having to increase the size
+  of every per thread stack.
 
   The interrupt stack is also used when processing a softirq.
 
diff --git a/MAINTAINERS b/MAINTAINERS
index b618b1e..9a0432d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -157,9 +157,11 @@
 F:	drivers/net/r8169.c
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
+M:	Greg Kroah-Hartman <gregkh@suse.de>
 L:	linux-serial@vger.kernel.org
 W:	http://serial.sourceforge.net
-S:	Orphan
+S:	Maintained
+T:	quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 F:	drivers/serial/8250*
 F:	include/linux/serial_8250.h
 
@@ -2064,14 +2066,16 @@
 F:	lib/lru_cache.c
 F:	Documentation/blockdev/drbd/
 
-DRIVER CORE, KOBJECTS, AND SYSFS
+DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
 M:	Greg Kroah-Hartman <gregkh@suse.de>
 T:	quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 S:	Supported
 F:	Documentation/kobject.txt
 F:	drivers/base/
 F:	fs/sysfs/
+F:	fs/debugfs/
 F:	include/linux/kobj*
+F:	include/linux/debugfs.h
 F:	lib/kobj*
 
 DRM DRIVERS
@@ -3351,6 +3355,12 @@
 F:	include/linux/ext*jbd*.h
 F:	include/linux/jbd*.h
 
+JSM Neo PCI based serial card
+M:	Breno Leitao <leitao@linux.vnet.ibm.com>
+L:	linux-serial@vger.kernel.org
+S:	Maintained
+F:	drivers/serial/jsm/
+
 K8TEMP HARDWARE MONITORING DRIVER
 M:	Rudolf Marek <r.marek@assembler.cz>
 L:	lm-sensors@lm-sensors.org
@@ -5963,6 +5973,14 @@
 F:	Documentation/usb/acm.txt
 F:	drivers/usb/class/cdc-acm.*
 
+USB ATTACHED SCSI
+M:	Matthew Wilcox <willy@linux.intel.com>
+M:	Sarah Sharp <sarah.a.sharp@linux.intel.com>
+L:	linux-usb@vger.kernel.org
+L:	linux-scsi@vger.kernel.org
+S:	Supported
+F:	drivers/usb/storage/uas.c
+
 USB BLOCK DRIVER (UB ub)
 M:	Pete Zaitcev <zaitcev@redhat.com>
 L:	linux-usb@vger.kernel.org
diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h
index 0b30894..9c96298 100644
--- a/arch/arm/include/asm/ioctls.h
+++ b/arch/arm/include/asm/ioctls.h
@@ -1,89 +1,8 @@
 #ifndef __ASM_ARM_IOCTLS_H
 #define __ASM_ARM_IOCTLS_H
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define TIOCGRS485      0x542E
-#define TIOCSRS485      0x542F
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT	0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index a48d512..11db628 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -329,6 +329,7 @@
 	.read = etb_read,
 	.open = etb_open,
 	.release = etb_release,
+	.llseek = no_llseek,
 };
 
 static struct miscdevice etb_miscdev = {
diff --git a/arch/arm/mach-msm/last_radio_log.c b/arch/arm/mach-msm/last_radio_log.c
index b64ba5a..1e243f4 100644
--- a/arch/arm/mach-msm/last_radio_log.c
+++ b/arch/arm/mach-msm/last_radio_log.c
@@ -48,7 +48,8 @@
 }
 
 static struct file_operations last_radio_log_fops = {
-	.read = last_radio_log_read
+	.read = last_radio_log_read,
+	.llseek = default_llseek,
 };
 
 void msm_init_last_radio_log(struct module *owner)
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index 3b2dd71..f91c3b7 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -212,6 +212,7 @@
 static const struct file_operations debug_ops = {
 	.read = debug_read,
 	.open = debug_open,
+	.llseek = default_llseek,
 };
 
 static void debug_create(const char *name, mode_t mode,
diff --git a/arch/arm/mach-mx3/mach-cpuimx35.c b/arch/arm/mach-mx3/mach-cpuimx35.c
index 8533bf0..9fde873 100644
--- a/arch/arm/mach-mx3/mach-cpuimx35.c
+++ b/arch/arm/mach-mx3/mach-cpuimx35.c
@@ -131,6 +131,7 @@
 static struct fsl_usb2_platform_data otg_device_pdata = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI,
+	.workaround	= FLS_USB2_WORKAROUND_ENGCM09152,
 };
 
 static int otg_mode_host;
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index f85c8da..d547036 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -375,6 +375,31 @@
 	omap_gpio_init();
 }
 
+static struct omap_musb_board_data musb_board_data = {
+	.interface_type         = MUSB_INTERFACE_ULPI,
+	.mode                   = MUSB_OTG,
+	.power                  = 500,
+};
+
+static __init void am3517_evm_musb_init(void)
+{
+	u32 devconf2;
+
+	/*
+	 * Set up USB clock/mode in the DEVCONF2 register.
+	 */
+	devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+	/* USB2.0 PHY reference clock is 13 MHz */
+	devconf2 &= ~(CONF2_REFFREQ | CONF2_OTGMODE | CONF2_PHY_GPIOMODE);
+	devconf2 |=  CONF2_REFFREQ_13MHZ | CONF2_SESENDEN | CONF2_VBDTCTEN
+			| CONF2_DATPOL;
+
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+	usb_musb_init(&musb_board_data);
+}
+
 static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
 	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
 #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
@@ -393,6 +418,8 @@
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+	/* USB OTG DRVVBUS offset = 0x212 */
+	OMAP3_MUX(SAD2D_MCAD23, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #else
@@ -459,6 +486,9 @@
 				ARRAY_SIZE(am3517evm_i2c1_boardinfo));
 	/*Ethernet*/
 	am3517_evm_ethernet_init(&am3517_evm_emac_pdata);
+
+	/* MUSB */
+	am3517_evm_musb_init();
 }
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 33a5cde..7260558 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -28,6 +28,7 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
+#include <mach/am35xx.h>
 #include <plat/usb.h>
 
 #ifdef CONFIG_USB_MUSB_SOC
@@ -89,6 +90,9 @@
 {
 	if (cpu_is_omap243x()) {
 		musb_resources[0].start = OMAP243X_HS_BASE;
+	} else if (cpu_is_omap3517() || cpu_is_omap3505()) {
+		musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
+		musb_resources[1].start = INT_35XX_USBOTG_IRQ;
 	} else if (cpu_is_omap34xx()) {
 		musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
 	} else if (cpu_is_omap44xx()) {
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c
index 6292049..0be1ac7 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/arch/arm/plat-mxc/audmux-v2.c
@@ -137,6 +137,7 @@
 static const struct file_operations audmux_debugfs_fops = {
 	.open = audmux_open_file,
 	.read = audmux_read_file,
+	.llseek = default_llseek,
 };
 
 static void audmux_debugfs_init(void)
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 2a9427c..9feddac 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -218,6 +218,27 @@
 #	define	USBT2TLL5PI		(1 << 17)
 #	define	USB0PUENACTLOI		(1 << 16)
 #	define	USBSTANDBYCTRL		(1 << 15)
+/* AM35x */
+/* USB 2.0 PHY Control */
+#define CONF2_PHY_GPIOMODE	(1 << 23)
+#define CONF2_OTGMODE		(3 << 14)
+#define CONF2_NO_OVERRIDE	(0 << 14)
+#define CONF2_FORCE_HOST	(1 << 14)
+#define CONF2_FORCE_DEVICE	(2 << 14)
+#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
+#define CONF2_SESENDEN		(1 << 13)
+#define CONF2_VBDTCTEN		(1 << 12)
+#define CONF2_REFFREQ_24MHZ	(2 << 8)
+#define CONF2_REFFREQ_26MHZ	(7 << 8)
+#define CONF2_REFFREQ_13MHZ	(6 << 8)
+#define CONF2_REFFREQ		(0xf << 8)
+#define CONF2_PHYCLKGD		(1 << 7)
+#define CONF2_VBUSSENSE		(1 << 6)
+#define CONF2_PHY_PLLON		(1 << 5)
+#define CONF2_RESET		(1 << 4)
+#define CONF2_PHYPWRDN		(1 << 3)
+#define CONF2_OTGPWRDN		(1 << 2)
+#define CONF2_DATPOL		(1 << 1)
 
 #if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_USB)
 u32 omap1_usb0_init(unsigned nwires, unsigned is_device);
diff --git a/arch/arm/plat-omap/iommu-debug.c b/arch/arm/plat-omap/iommu-debug.c
index e6c0d53..f07cf2f 100644
--- a/arch/arm/plat-omap/iommu-debug.c
+++ b/arch/arm/plat-omap/iommu-debug.c
@@ -328,12 +328,14 @@
 		.open = debug_open_generic,				\
 		.read = debug_read_##name,				\
 		.write = debug_write_##name,				\
+		.llseek = generic_file_llseek,				\
 	};
 
 #define DEBUG_FOPS_RO(name)						\
 	static const struct file_operations debug_##name##_fops = {	\
 		.open = debug_open_generic,				\
 		.read = debug_read_##name,				\
+		.llseek = generic_file_llseek,				\
 	};
 
 DEBUG_FOPS_RO(ver);
diff --git a/arch/avr32/boards/mimc200/fram.c b/arch/avr32/boards/mimc200/fram.c
index 54fbd95..9764a1a 100644
--- a/arch/avr32/boards/mimc200/fram.c
+++ b/arch/avr32/boards/mimc200/fram.c
@@ -41,6 +41,7 @@
 static const struct file_operations fram_fops = {
 	.owner			= THIS_MODULE,
 	.mmap			= fram_mmap,
+	.llseek			= noop_llseek,
 };
 
 #define FRAM_MINOR	0
diff --git a/arch/avr32/include/asm/ioctls.h b/arch/avr32/include/asm/ioctls.h
index b7dd324..909cf66 100644
--- a/arch/avr32/include/asm/ioctls.h
+++ b/arch/avr32/include/asm/ioctls.h
@@ -1,90 +1,6 @@
 #ifndef __ASM_AVR32_IOCTLS_H
 #define __ASM_AVR32_IOCTLS_H
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define TIOCGRS485      0x542E
-#define TIOCSRS485      0x542F
-
-#define FIONCLEX	0x5450
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ASM_AVR32_IOCTLS_H */
diff --git a/arch/blackfin/kernel/kgdb_test.c b/arch/blackfin/kernel/kgdb_test.c
index 9a4b075..08c0236 100644
--- a/arch/blackfin/kernel/kgdb_test.c
+++ b/arch/blackfin/kernel/kgdb_test.c
@@ -88,6 +88,7 @@
 	.owner = THIS_MODULE,
 	.read  = kgdb_test_proc_read,
 	.write = kgdb_test_proc_write,
+	.llseek = noop_llseek,
 };
 
 static int __init kgdbtest_init(void)
diff --git a/arch/blackfin/mach-bf561/coreb.c b/arch/blackfin/mach-bf561/coreb.c
index 6197902..78ecb50 100644
--- a/arch/blackfin/mach-bf561/coreb.c
+++ b/arch/blackfin/mach-bf561/coreb.c
@@ -51,6 +51,7 @@
 static const struct file_operations coreb_fops = {
 	.owner          = THIS_MODULE,
 	.unlocked_ioctl = coreb_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice coreb_dev = {
diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c
index 8842756..3d655dc 100644
--- a/arch/cris/arch-v10/drivers/ds1302.c
+++ b/arch/cris/arch-v10/drivers/ds1302.c
@@ -19,7 +19,7 @@
 #include <linux/module.h>
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/bcd.h>
 #include <linux/capability.h>
 
@@ -34,6 +34,7 @@
 
 #define RTC_MAJOR_NR 121 /* local major, change later */
 
+static DEFINE_MUTEX(ds1302_mutex);
 static const char ds1302_name[] = "ds1302";
 
 /* The DS1302 might be connected to different bits on different products. 
@@ -357,9 +358,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ds1302_mutex);
 	ret = rtc_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ds1302_mutex);
 
 	return ret;
 }
@@ -387,6 +388,7 @@
 static const struct file_operations rtc_fops = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl = rtc_unlocked_ioctl,
+	.llseek		= noop_llseek,
 }; 
 
 /* Probe for the chip by writing something to its RAM and try reading it back. */
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index a07b6d2..a276f08 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -745,6 +745,7 @@
 	.write          = gpio_write,
 	.open           = gpio_open,
 	.release        = gpio_release,
+	.llseek		= noop_llseek,
 };
 
 static void ioif_watcher(const unsigned int gpio_in_available,
diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c
index 77a9418..c413539 100644
--- a/arch/cris/arch-v10/drivers/i2c.c
+++ b/arch/cris/arch-v10/drivers/i2c.c
@@ -617,6 +617,7 @@
 	.unlocked_ioctl	= i2c_ioctl,
 	.open		= i2c_open,
 	.release	= i2c_release,
+	.llseek		= noop_llseek,
 };
 
 int __init
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index 7dcb1f8..ea69fab 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -49,6 +48,7 @@
 #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
 #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
 
+static DEFINE_MUTEX(pcf8563_mutex);
 static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
 
 static const unsigned char days_in_month[] =
@@ -64,6 +64,7 @@
 static const struct file_operations pcf8563_fops = {
 	.owner = THIS_MODULE,
 	.unlocked_ioctl = pcf8563_unlocked_ioctl,
+	.llseek		= noop_llseek,
 };
 
 unsigned char
@@ -343,9 +344,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pcf8563_mutex);
 	return pcf8563_ioctl(filp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pcf8563_mutex);
 
 	return ret;
 }
diff --git a/arch/cris/arch-v10/drivers/sync_serial.c b/arch/cris/arch-v10/drivers/sync_serial.c
index ee2dd43..399dc1e 100644
--- a/arch/cris/arch-v10/drivers/sync_serial.c
+++ b/arch/cris/arch-v10/drivers/sync_serial.c
@@ -20,7 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/timer.h>
 #include <asm/irq.h>
 #include <asm/dma.h>
@@ -149,6 +149,7 @@
 };
 
 
+static DEFINE_MUTEX(sync_serial_mutex);
 static int etrax_sync_serial_init(void);
 static void initialize_port(int portnbr);
 static inline int sync_data_avail(struct sync_port *port);
@@ -250,7 +251,8 @@
 	.poll		= sync_serial_poll,
 	.unlocked_ioctl	= sync_serial_ioctl,
 	.open		= sync_serial_open,
-	.release	= sync_serial_release
+	.release	= sync_serial_release,
+	.llseek		= noop_llseek,
 };
 
 static int __init etrax_sync_serial_init(void)
@@ -445,7 +447,7 @@
 	int mode;
 	int err = -EBUSY;
 
-	lock_kernel();
+	mutex_lock(&sync_serial_mutex);
 	DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
 
 	if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) {
@@ -626,7 +628,7 @@
 	ret = 0;
 	
 out:
-	unlock_kernel();
+	mutex_unlock(&sync_serial_mutex);
 	return ret;
 }
 
@@ -961,9 +963,9 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&sync_serial_mutex);
 	ret = sync_serial_ioctl_unlocked(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&sync_serial_mutex);
 
 	return ret;
 }
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index b07646a..c03bc3b 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -281,7 +281,8 @@
 	.owner		= THIS_MODULE,
 	.open		= cryptocop_open,
 	.release	= cryptocop_release,
-	.unlocked_ioctl = cryptocop_ioctl
+	.unlocked_ioctl = cryptocop_ioctl,
+	.llseek		= noop_llseek,
 };
 
 
@@ -3139,9 +3140,9 @@
        struct inode *inode = file->f_path.dentry->d_inode;
        long ret;
 
-       lock_kernel();
+       mutex_lock(&cryptocop_mutex);
        ret = cryptocop_ioctl_unlocked(inode, filp, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&cryptocop_mutex);
 
        return ret;
 }
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index 5a3e900..ddb2399 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -698,6 +698,7 @@
 	.unlocked_ioctl = i2c_ioctl,
 	.open		= i2c_open,
 	.release	= i2c_release,
+	.llseek		= noop_llseek,
 };
 
 static int __init i2c_init(void)
diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
index 2dcd27a..c845831 100644
--- a/arch/cris/arch-v32/drivers/mach-a3/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
@@ -23,7 +23,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/etraxgpio.h>
 #include <hwregs/reg_map.h>
@@ -66,6 +66,7 @@
 #define DP(x)
 #endif
 
+static DEFINE_MUTEX(gpio_mutex);
 static char gpio_name[] = "etrax gpio";
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
@@ -391,7 +392,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&gpio_mutex);
 	memset(priv, 0, sizeof(*priv));
 
 	priv->minor = p;
@@ -414,7 +415,7 @@
 		spin_unlock_irq(&gpio_lock);
 	}
 
-	unlock_kernel();
+	mutex_unlock(&gpio_mutex);
 	return 0;
 }
 
@@ -667,9 +668,9 @@
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&gpio_mutex);
        ret = gpio_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&gpio_mutex);
 
        return ret;
 }
@@ -893,6 +894,7 @@
 	.write		= gpio_write,
 	.open		= gpio_open,
 	.release	= gpio_release,
+	.llseek		= noop_llseek,
 };
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
diff --git a/arch/cris/arch-v32/drivers/mach-fs/gpio.c b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
index 5ec8a7d..ee90d26 100644
--- a/arch/cris/arch-v32/drivers/mach-fs/gpio.c
+++ b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/etraxgpio.h>
 #include <hwregs/reg_map.h>
@@ -64,6 +64,7 @@
 #define DP(x)
 #endif
 
+static DEFINE_MUTEX(gpio_mutex);
 static char gpio_name[] = "etrax gpio";
 
 #if 0
@@ -429,7 +430,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&gpio_mutex);
 	memset(priv, 0, sizeof(*priv));
 
 	priv->minor = p;
@@ -450,7 +451,7 @@
 	alarmlist = priv;
 	spin_unlock_irq(&alarm_lock);
 
-	unlock_kernel();
+	mutex_unlock(&gpio_mutex);
 	return 0;
 }
 
@@ -708,9 +709,9 @@
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&gpio_mutex);
        ret = gpio_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&gpio_mutex);
 
        return ret;
 }
@@ -870,6 +871,7 @@
 	.write		= gpio_write,
 	.open		= gpio_open,
 	.release	= gpio_release,
+	.llseek		= noop_llseek,
 };
 
 #ifdef CONFIG_ETRAX_VIRTUAL_GPIO
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index bef6eb5..b6e4fc0 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -24,7 +24,6 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/bcd.h>
 #include <linux/mutex.h>
@@ -45,6 +44,7 @@
 #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
 #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
 
+static DEFINE_MUTEX(pcf8563_mutex);
 static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
 
 static const unsigned char days_in_month[] =
@@ -60,6 +60,7 @@
 static const struct file_operations pcf8563_fops = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl = pcf8563_unlocked_ioctl,
+	.llseek		= noop_llseek,
 };
 
 unsigned char
@@ -339,9 +340,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pcf8563_mutex);
 	return pcf8563_ioctl(filp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pcf8563_mutex);
 
 	return ret;
 }
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index ca248f3..c8637a9 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -13,7 +13,7 @@
 #include <linux/errno.h>
 #include <linux/major.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
 #include <linux/init.h>
@@ -145,6 +145,7 @@
 	spinlock_t lock;
 } sync_port;
 
+static DEFINE_MUTEX(sync_serial_mutex);
 static int etrax_sync_serial_init(void);
 static void initialize_port(int portnbr);
 static inline int sync_data_avail(struct sync_port *port);
@@ -247,7 +248,8 @@
 	.poll		= sync_serial_poll,
 	.unlocked_ioctl	= sync_serial_ioctl,
 	.open		= sync_serial_open,
-	.release	= sync_serial_release
+	.release	= sync_serial_release,
+	.llseek		= noop_llseek,
 };
 
 static int __init etrax_sync_serial_init(void)
@@ -434,7 +436,7 @@
 	reg_dma_rw_cfg cfg = {.en = regk_dma_yes};
 	reg_dma_rw_intr_mask intr_mask = {.data = regk_dma_yes};
 
-	lock_kernel();
+	mutex_lock(&sync_serial_mutex);
 	DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev));
 
 	if (dev < 0 || dev >= NBR_PORTS || !ports[dev].enabled)
@@ -583,7 +585,7 @@
 	port->busy++;
 	ret = 0;
 out:
-	unlock_kernel();
+	mutex_unlock(&sync_serial_mutex);
 	return ret;
 }
 
@@ -966,9 +968,9 @@
 {
        long ret;
 
-       lock_kernel();
+       mutex_lock(&sync_serial_mutex);
        ret = sync_serial_ioctl_unlocked(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&sync_serial_mutex);
 
        return ret;
 }
diff --git a/arch/cris/include/asm/ioctls.h b/arch/cris/include/asm/ioctls.h
index c9129ed..488fbb3 100644
--- a/arch/cris/include/asm/ioctls.h
+++ b/arch/cris/include/asm/ioctls.h
@@ -1,93 +1,11 @@
 #ifndef __ARCH_CRIS_IOCTLS_H__
 #define __ARCH_CRIS_IOCTLS_H__
 
-/* verbatim copy of asm-i386/ioctls.h */
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
 #define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
 #define TIOCSERSETRS485	0x5461  /* enable rs-485 (deprecated) */
 #define TIOCSERWRRS485	0x5462  /* write rs-485 */
 #define TIOCSRS485	0x5463  /* enable rs-485 */
-#define TIOCGRS485	0x542E  /* get rs-485 */
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
index 195ec5f..b82e086 100644
--- a/arch/cris/kernel/profile.c
+++ b/arch/cris/kernel/profile.c
@@ -59,6 +59,7 @@
 static const struct file_operations cris_proc_profile_operations = {
 	.read		= read_cris_profile,
 	.write		= write_cris_profile,
+	.llseek		= default_llseek,
 };
 
 static int __init init_cris_profile(void)
diff --git a/arch/frv/include/asm/ioctls.h b/arch/frv/include/asm/ioctls.h
index a993e37..2f9fb43 100644
--- a/arch/frv/include/asm/ioctls.h
+++ b/arch/frv/include/asm/ioctls.h
@@ -1,88 +1,10 @@
 #ifndef __ASM_IOCTLS_H__
 #define __ASM_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
 #define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ASM_IOCTLS_H__ */
 
diff --git a/arch/h8300/include/asm/ioctls.h b/arch/h8300/include/asm/ioctls.h
index b6b249f..30eaed2 100644
--- a/arch/h8300/include/asm/ioctls.h
+++ b/arch/h8300/include/asm/ioctls.h
@@ -1,87 +1,8 @@
 #ifndef __ARCH_H8300_IOCTLS_H__
 #define __ARCH_H8300_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ARCH_H8300_IOCTLS_H__ */
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 1e8d71a..13633da 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -395,7 +395,7 @@
 {
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
 	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -433,16 +433,6 @@
 		case TIOCMIWAIT:
 			printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
 			return 0;
-		/*
-		 * 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:
-			printk(KERN_INFO "rs_ioctl: TIOCGICOUNT called\n");
-			return 0;
-
 		case TIOCSERGWILD:
 		case TIOCSERSWILD:
 			/* "setserial -W" is called in Debian boot */
diff --git a/arch/ia64/include/asm/ioctls.h b/arch/ia64/include/asm/ioctls.h
index b79c385..f3aab551 100644
--- a/arch/ia64/include/asm/ioctls.h
+++ b/arch/ia64/include/asm/ioctls.h
@@ -1,93 +1,6 @@
 #ifndef _ASM_IA64_IOCTLS_H
 #define _ASM_IA64_IOCTLS_H
 
-/*
- * Based on <asm-i386/ioctls.h>
- *
- * Modified 1998, 1999, 2002
- *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402	/* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* _ASM_IA64_IOCTLS_H */
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 45d7543..79802e5 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -354,6 +354,7 @@
 static const struct file_operations salinfo_event_fops = {
 	.open  = salinfo_event_open,
 	.read  = salinfo_event_read,
+	.llseek = noop_llseek,
 };
 
 static int
@@ -571,6 +572,7 @@
 	.release = salinfo_log_release,
 	.read    = salinfo_log_read,
 	.write   = salinfo_log_write,
+	.llseek  = default_llseek,
 };
 
 static int __cpuinit
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index fa1ecee..30862c0 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -860,6 +860,7 @@
 
 static const struct file_operations sn_hwperf_fops = {
 	.unlocked_ioctl = sn_hwperf_ioctl,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice sn_hwperf_dev = {
diff --git a/arch/m32r/include/asm/ioctls.h b/arch/m32r/include/asm/ioctls.h
index 6628806..349bf87 100644
--- a/arch/m32r/include/asm/ioctls.h
+++ b/arch/m32r/include/asm/ioctls.h
@@ -1,87 +1,6 @@
 #ifndef __ARCH_M32R_IOCTLS_H__
 #define __ARCH_M32R_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ARCH_M32R_IOCTLS_H__ */
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 8030e24..77bb0d6 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -434,7 +434,7 @@
 
 config ISA
 	bool
-	depends on Q40 || AMIGA_PCMCIA || GG2
+	depends on Q40 || AMIGA_PCMCIA
 	default y
 	help
 	  Find out whether you have ISA slots on your motherboard.  ISA is the
@@ -445,7 +445,7 @@
 
 config GENERIC_ISA_DMA
 	bool
-	depends on Q40 || AMIGA_PCMCIA || GG2
+	depends on Q40 || AMIGA_PCMCIA
 	default y
 
 config ZONE_DMA
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index cb8617b..1c4d4c7 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -155,6 +155,7 @@
 	.unlocked_ioctl	= rtc_ioctl,
 	.open		= rtc_open,
 	.release	= rtc_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice rtc_dev = {
diff --git a/arch/m68k/include/asm/amigahw.h b/arch/m68k/include/asm/amigahw.h
index 5ca5dd9..7a19b56 100644
--- a/arch/m68k/include/asm/amigahw.h
+++ b/arch/m68k/include/asm/amigahw.h
@@ -102,7 +102,6 @@
     AMIGAHW_DECLARE(ALICE_NTSC);	/* NTSC Alice (8374) */
     AMIGAHW_DECLARE(MAGIC_REKICK);	/* A3000 Magic Hard Rekick */
     AMIGAHW_DECLARE(PCMCIA);		/* PCMCIA Slot */
-    AMIGAHW_DECLARE(GG2_ISA);		/* GG2 Zorro2ISA Bridge */
     AMIGAHW_DECLARE(ZORRO);		/* Zorro AutoConfig */
     AMIGAHW_DECLARE(ZORRO3);		/* Zorro III */
 };
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h
index eab36dc..03ae3d1 100644
--- a/arch/m68k/include/asm/atomic.h
+++ b/arch/m68k/include/asm/atomic.h
@@ -1,7 +1,211 @@
-#ifdef __uClinux__
-#include "atomic_no.h"
+#ifndef __ARCH_M68K_ATOMIC__
+#define __ARCH_M68K_ATOMIC__
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+/*
+ * We do not have SMP m68k systems, so we don't have to deal with that.
+ */
+
+#define ATOMIC_INIT(i)	{ (i) }
+
+#define atomic_read(v)		(*(volatile int *)&(v)->counter)
+#define atomic_set(v, i)	(((v)->counter) = i)
+
+/*
+ * The ColdFire parts cannot do some immediate to memory operations,
+ * so for them we do not specify the "i" asm constraint.
+ */
+#ifdef CONFIG_COLDFIRE
+#define	ASM_DI	"d"
 #else
-#include "atomic_mm.h"
+#define	ASM_DI	"di"
 #endif
 
+static inline void atomic_add(int i, atomic_t *v)
+{
+	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : ASM_DI (i));
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : ASM_DI (i));
+}
+
+static inline void atomic_inc(atomic_t *v)
+{
+	__asm__ __volatile__("addql #1,%0" : "+m" (*v));
+}
+
+static inline void atomic_dec(atomic_t *v)
+{
+	__asm__ __volatile__("subql #1,%0" : "+m" (*v));
+}
+
+static inline int atomic_dec_and_test(atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
+	return c != 0;
+}
+
+static inline int atomic_inc_and_test(atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
+	return c != 0;
+}
+
+#ifdef CONFIG_RMW_INSNS
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+	int t, tmp;
+
+	__asm__ __volatile__(
+			"1:	movel %2,%1\n"
+			"	addl %3,%1\n"
+			"	casl %2,%1,%0\n"
+			"	jne 1b"
+			: "+m" (*v), "=&d" (t), "=&d" (tmp)
+			: "g" (i), "2" (atomic_read(v)));
+	return t;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+	int t, tmp;
+
+	__asm__ __volatile__(
+			"1:	movel %2,%1\n"
+			"	subl %3,%1\n"
+			"	casl %2,%1,%0\n"
+			"	jne 1b"
+			: "+m" (*v), "=&d" (t), "=&d" (tmp)
+			: "g" (i), "2" (atomic_read(v)));
+	return t;
+}
+
+#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+#else /* !CONFIG_RMW_INSNS */
+
+static inline int atomic_add_return(int i, atomic_t * v)
+{
+	unsigned long flags;
+	int t;
+
+	local_irq_save(flags);
+	t = atomic_read(v);
+	t += i;
+	atomic_set(v, t);
+	local_irq_restore(flags);
+
+	return t;
+}
+
+static inline int atomic_sub_return(int i, atomic_t * v)
+{
+	unsigned long flags;
+	int t;
+
+	local_irq_save(flags);
+	t = atomic_read(v);
+	t -= i;
+	atomic_set(v, t);
+	local_irq_restore(flags);
+
+	return t;
+}
+
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+	unsigned long flags;
+	int prev;
+
+	local_irq_save(flags);
+	prev = atomic_read(v);
+	if (prev == old)
+		atomic_set(v, new);
+	local_irq_restore(flags);
+	return prev;
+}
+
+static inline int atomic_xchg(atomic_t *v, int new)
+{
+	unsigned long flags;
+	int prev;
+
+	local_irq_save(flags);
+	prev = atomic_read(v);
+	atomic_set(v, new);
+	local_irq_restore(flags);
+	return prev;
+}
+
+#endif /* !CONFIG_RMW_INSNS */
+
+#define atomic_dec_return(v)	atomic_sub_return(1, (v))
+#define atomic_inc_return(v)	atomic_add_return(1, (v))
+
+static inline int atomic_sub_and_test(int i, atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("subl %2,%1; seq %0"
+			     : "=d" (c), "+m" (*v)
+			     : ASM_DI (i));
+	return c != 0;
+}
+
+static inline int atomic_add_negative(int i, atomic_t *v)
+{
+	char c;
+	__asm__ __volatile__("addl %2,%1; smi %0"
+			     : "=d" (c), "+m" (*v)
+			     : "id" (i));
+	return c != 0;
+}
+
+static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
+{
+	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
+}
+
+static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
+{
+	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
+}
+
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int c, old;
+	c = atomic_read(v);
+	for (;;) {
+		if (unlikely(c == (u)))
+			break;
+		old = atomic_cmpxchg((v), c, c + (a));
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+	return c != (u);
+}
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()	barrier()
+#define smp_mb__after_atomic_dec()	barrier()
+#define smp_mb__before_atomic_inc()	barrier()
+#define smp_mb__after_atomic_inc()	barrier()
+
+#include <asm-generic/atomic-long.h>
 #include <asm-generic/atomic64.h>
+#endif /* __ARCH_M68K_ATOMIC __ */
diff --git a/arch/m68k/include/asm/atomic_mm.h b/arch/m68k/include/asm/atomic_mm.h
deleted file mode 100644
index 6a223b3..0000000
--- a/arch/m68k/include/asm/atomic_mm.h
+++ /dev/null
@@ -1,200 +0,0 @@
-#ifndef __ARCH_M68K_ATOMIC__
-#define __ARCH_M68K_ATOMIC__
-
-#include <linux/types.h>
-#include <asm/system.h>
-
-/*
- * Atomic operations that C can't guarantee us.  Useful for
- * resource counting etc..
- */
-
-/*
- * We do not have SMP m68k systems, so we don't have to deal with that.
- */
-
-#define ATOMIC_INIT(i)	{ (i) }
-
-#define atomic_read(v)		(*(volatile int *)&(v)->counter)
-#define atomic_set(v, i)	(((v)->counter) = i)
-
-static inline void atomic_add(int i, atomic_t *v)
-{
-	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : "id" (i));
-}
-
-static inline void atomic_sub(int i, atomic_t *v)
-{
-	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : "id" (i));
-}
-
-static inline void atomic_inc(atomic_t *v)
-{
-	__asm__ __volatile__("addql #1,%0" : "+m" (*v));
-}
-
-static inline void atomic_dec(atomic_t *v)
-{
-	__asm__ __volatile__("subql #1,%0" : "+m" (*v));
-}
-
-static inline int atomic_dec_and_test(atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
-	return c != 0;
-}
-
-static inline int atomic_inc_and_test(atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
-	return c != 0;
-}
-
-#ifdef CONFIG_RMW_INSNS
-
-static inline int atomic_add_return(int i, atomic_t *v)
-{
-	int t, tmp;
-
-	__asm__ __volatile__(
-			"1:	movel %2,%1\n"
-			"	addl %3,%1\n"
-			"	casl %2,%1,%0\n"
-			"	jne 1b"
-			: "+m" (*v), "=&d" (t), "=&d" (tmp)
-			: "g" (i), "2" (atomic_read(v)));
-	return t;
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
-	int t, tmp;
-
-	__asm__ __volatile__(
-			"1:	movel %2,%1\n"
-			"	subl %3,%1\n"
-			"	casl %2,%1,%0\n"
-			"	jne 1b"
-			: "+m" (*v), "=&d" (t), "=&d" (tmp)
-			: "g" (i), "2" (atomic_read(v)));
-	return t;
-}
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#else /* !CONFIG_RMW_INSNS */
-
-static inline int atomic_add_return(int i, atomic_t * v)
-{
-	unsigned long flags;
-	int t;
-
-	local_irq_save(flags);
-	t = atomic_read(v);
-	t += i;
-	atomic_set(v, t);
-	local_irq_restore(flags);
-
-	return t;
-}
-
-static inline int atomic_sub_return(int i, atomic_t * v)
-{
-	unsigned long flags;
-	int t;
-
-	local_irq_save(flags);
-	t = atomic_read(v);
-	t -= i;
-	atomic_set(v, t);
-	local_irq_restore(flags);
-
-	return t;
-}
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
-	unsigned long flags;
-	int prev;
-
-	local_irq_save(flags);
-	prev = atomic_read(v);
-	if (prev == old)
-		atomic_set(v, new);
-	local_irq_restore(flags);
-	return prev;
-}
-
-static inline int atomic_xchg(atomic_t *v, int new)
-{
-	unsigned long flags;
-	int prev;
-
-	local_irq_save(flags);
-	prev = atomic_read(v);
-	atomic_set(v, new);
-	local_irq_restore(flags);
-	return prev;
-}
-
-#endif /* !CONFIG_RMW_INSNS */
-
-#define atomic_dec_return(v)	atomic_sub_return(1, (v))
-#define atomic_inc_return(v)	atomic_add_return(1, (v))
-
-static inline int atomic_sub_and_test(int i, atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("subl %2,%1; seq %0"
-			     : "=d" (c), "+m" (*v)
-			     : "id" (i));
-	return c != 0;
-}
-
-static inline int atomic_add_negative(int i, atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("addl %2,%1; smi %0"
-			     : "=d" (c), "+m" (*v)
-			     : "id" (i));
-	return c != 0;
-}
-
-static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
-}
-
-static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
-}
-
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
-{
-	int c, old;
-	c = atomic_read(v);
-	for (;;) {
-		if (unlikely(c == (u)))
-			break;
-		old = atomic_cmpxchg((v), c, c + (a));
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-	return c != (u);
-}
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()	barrier()
-#define smp_mb__after_atomic_dec()	barrier()
-#define smp_mb__before_atomic_inc()	barrier()
-#define smp_mb__after_atomic_inc()	barrier()
-
-#include <asm-generic/atomic-long.h>
-#endif /* __ARCH_M68K_ATOMIC __ */
diff --git a/arch/m68k/include/asm/atomic_no.h b/arch/m68k/include/asm/atomic_no.h
deleted file mode 100644
index 289310c..0000000
--- a/arch/m68k/include/asm/atomic_no.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef __ARCH_M68KNOMMU_ATOMIC__
-#define __ARCH_M68KNOMMU_ATOMIC__
-
-#include <linux/types.h>
-#include <asm/system.h>
-
-/*
- * Atomic operations that C can't guarantee us.  Useful for
- * resource counting etc..
- */
-
-/*
- * We do not have SMP m68k systems, so we don't have to deal with that.
- */
-
-#define ATOMIC_INIT(i)	{ (i) }
-
-#define atomic_read(v)		(*(volatile int *)&(v)->counter)
-#define atomic_set(v, i)	(((v)->counter) = i)
-
-static __inline__ void atomic_add(int i, atomic_t *v)
-{
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : "d" (i));
-#else
-	__asm__ __volatile__("addl %1,%0" : "+m" (*v) : "di" (i));
-#endif
-}
-
-static __inline__ void atomic_sub(int i, atomic_t *v)
-{
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : "d" (i));
-#else
-	__asm__ __volatile__("subl %1,%0" : "+m" (*v) : "di" (i));
-#endif
-}
-
-static __inline__ int atomic_sub_and_test(int i, atomic_t * v)
-{
-	char c;
-#ifdef CONFIG_COLDFIRE
-	__asm__ __volatile__("subl %2,%1; seq %0"
-			     : "=d" (c), "+m" (*v)
-			     : "d" (i));
-#else
-	__asm__ __volatile__("subl %2,%1; seq %0"
-			     : "=d" (c), "+m" (*v)
-			     : "di" (i));
-#endif
-	return c != 0;
-}
-
-static __inline__ void atomic_inc(volatile atomic_t *v)
-{
-	__asm__ __volatile__("addql #1,%0" : "+m" (*v));
-}
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-
-static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v));
-	return c != 0;
-}
-
-static __inline__ void atomic_dec(volatile atomic_t *v)
-{
-	__asm__ __volatile__("subql #1,%0" : "+m" (*v));
-}
-
-static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
-{
-	char c;
-	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v));
-	return c != 0;
-}
-
-static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("andl %1,%0" : "+m" (*v) : "id" (~(mask)));
-}
-
-static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask));
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-static inline int atomic_add_return(int i, atomic_t * v)
-{
-	unsigned long temp, flags;
-
-	local_irq_save(flags);
-	temp = *(long *)v;
-	temp += i;
-	*(long *)v = temp;
-	local_irq_restore(flags);
-
-	return temp;
-}
-
-#define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
-
-static inline int atomic_sub_return(int i, atomic_t * v)
-{
-	unsigned long temp, flags;
-
-	local_irq_save(flags);
-	temp = *(long *)v;
-	temp -= i;
-	*(long *)v = temp;
-	local_irq_restore(flags);
-
-	return temp;
-}
-
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
-{
-	int c, old;
-	c = atomic_read(v);
-	for (;;) {
-		if (unlikely(c == (u)))
-			break;
-		old = atomic_cmpxchg((v), c, c + (a));
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-	return c != (u);
-}
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-#define atomic_dec_return(v) atomic_sub_return(1,(v))
-#define atomic_inc_return(v) atomic_add_return(1,(v))
-
-#include <asm-generic/atomic-long.h>
-#endif /* __ARCH_M68KNOMMU_ATOMIC __ */
diff --git a/arch/m68k/include/asm/entry_mm.h b/arch/m68k/include/asm/entry_mm.h
index 4741258..e41fea3 100644
--- a/arch/m68k/include/asm/entry_mm.h
+++ b/arch/m68k/include/asm/entry_mm.h
@@ -3,6 +3,9 @@
 
 #include <asm/setup.h>
 #include <asm/page.h>
+#ifdef __ASSEMBLY__
+#include <asm/thread_info.h>
+#endif
 
 /*
  * Stack layout in 'ret_from_exception':
diff --git a/arch/m68k/include/asm/io_mm.h b/arch/m68k/include/asm/io_mm.h
index 9e673e3..0fb3468 100644
--- a/arch/m68k/include/asm/io_mm.h
+++ b/arch/m68k/include/asm/io_mm.h
@@ -49,23 +49,6 @@
 #define MULTI_ISA 0
 #endif /* Q40 */
 
-/* GG-II Zorro to ISA bridge */
-#ifdef CONFIG_GG2
-
-extern unsigned long gg2_isa_base;
-#define GG2_ISA_IO_B(ioaddr) (gg2_isa_base+1+((unsigned long)(ioaddr)*4))
-#define GG2_ISA_IO_W(ioaddr) (gg2_isa_base+  ((unsigned long)(ioaddr)*4))
-#define GG2_ISA_MEM_B(madr)  (gg2_isa_base+1+(((unsigned long)(madr)*4) & 0xfffff))
-#define GG2_ISA_MEM_W(madr)  (gg2_isa_base+  (((unsigned long)(madr)*4) & 0xfffff))
-
-#ifndef MULTI_ISA
-#define MULTI_ISA 0
-#else
-#undef MULTI_ISA
-#define MULTI_ISA 1
-#endif
-#endif /* GG2 */
-
 #ifdef CONFIG_AMIGA_PCMCIA
 #include <asm/amigayle.h>
 
@@ -89,8 +72,7 @@
 #endif
 
 #define ISA_TYPE_Q40 (1)
-#define ISA_TYPE_GG2 (2)
-#define ISA_TYPE_AG  (3)
+#define ISA_TYPE_AG  (2)
 
 #if defined(CONFIG_Q40) && !defined(MULTI_ISA)
 #define ISA_TYPE ISA_TYPE_Q40
@@ -100,10 +82,6 @@
 #define ISA_TYPE ISA_TYPE_AG
 #define ISA_SEX  1
 #endif
-#if defined(CONFIG_GG2) && !defined(MULTI_ISA)
-#define ISA_TYPE ISA_TYPE_GG2
-#define ISA_SEX  0
-#endif
 
 #ifdef MULTI_ISA
 extern int isa_type;
@@ -125,9 +103,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: return (u8 __iomem *)Q40_ISA_IO_B(addr);
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: return (u8 __iomem *)GG2_ISA_IO_B(addr);
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: return (u8 __iomem *)AG_ISA_IO_B(addr);
 #endif
@@ -141,9 +116,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: return (u16 __iomem *)Q40_ISA_IO_W(addr);
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: return (u16 __iomem *)GG2_ISA_IO_W(addr);
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: return (u16 __iomem *)AG_ISA_IO_W(addr);
 #endif
@@ -167,9 +139,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: return (u8 __iomem *)Q40_ISA_MEM_B(addr);
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: return (u8 __iomem *)GG2_ISA_MEM_B(addr);
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: return (u8 __iomem *)addr;
 #endif
@@ -183,9 +152,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: return (u16 __iomem *)Q40_ISA_MEM_W(addr);
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: return (u16 __iomem *)GG2_ISA_MEM_W(addr);
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: return (u16 __iomem *)addr;
 #endif
@@ -217,9 +183,6 @@
 #ifdef CONFIG_Q40
     case ISA_TYPE_Q40: isa_outb(0,0x80); break;
 #endif
-#ifdef CONFIG_GG2
-    case ISA_TYPE_GG2: break;
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
     case ISA_TYPE_AG: break;
 #endif
@@ -287,9 +250,13 @@
 #define outb(val,port)     ((void)0)
 #define outb_p(val,port)   ((void)0)
 #define inw(port)          0xffff
+#define inw_p(port)        0xffff
 #define outw(val,port)     ((void)0)
+#define outw_p(val,port)   ((void)0)
 #define inl(port)          0xffffffffUL
+#define inl_p(port)        0xffffffffUL
 #define outl(val,port)     ((void)0)
+#define outl_p(val,port)   ((void)0)
 
 #define insb(port,buf,nr)  ((void)0)
 #define outsb(port,buf,nr) ((void)0)
diff --git a/arch/m68k/include/asm/ioctls.h b/arch/m68k/include/asm/ioctls.h
index 91a57d6..1332bb4 100644
--- a/arch/m68k/include/asm/ioctls.h
+++ b/arch/m68k/include/asm/ioctls.h
@@ -1,86 +1,8 @@
 #ifndef __ARCH_M68K_IOCTLS_H__
 #define __ARCH_M68K_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* __ARCH_M68K_IOCTLS_H__ */
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index fc24b6f..789f3b2 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -1,5 +1,44 @@
-#ifdef __uClinux__
-#include "machdep_no.h"
-#else
-#include "machdep_mm.h"
-#endif
+#ifndef _M68K_MACHDEP_H
+#define _M68K_MACHDEP_H
+
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+
+struct pt_regs;
+struct mktime;
+struct rtc_time;
+struct rtc_pll_info;
+struct buffer_head;
+
+extern void (*mach_sched_init) (irq_handler_t handler);
+/* machine dependent irq functions */
+extern void (*mach_init_IRQ) (void);
+extern void (*mach_get_model) (char *model);
+extern void (*mach_get_hardware_list) (struct seq_file *m);
+/* machine dependent timer functions */
+extern unsigned long (*mach_gettimeoffset)(void);
+extern int (*mach_hwclk)(int, struct rtc_time*);
+extern unsigned int (*mach_get_ss)(void);
+extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
+extern int (*mach_set_rtc_pll)(struct rtc_pll_info *);
+extern int (*mach_set_clock_mmss)(unsigned long);
+extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour,
+			    int *min, int *sec);
+extern void (*mach_reset)( void );
+extern void (*mach_halt)( void );
+extern void (*mach_power_off)( void );
+extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
+extern void (*mach_hd_setup)(char *, int *);
+extern long mach_max_dma_address;
+extern void (*mach_heartbeat) (int);
+extern void (*mach_l2_flush) (int);
+extern void (*mach_beep) (unsigned int, unsigned int);
+
+/* Hardware clock functions */
+extern void hw_timer_init(void);
+extern unsigned long hw_timer_offset(void);
+extern irqreturn_t arch_timer_interrupt(int irq, void *dummy);
+
+extern void config_BSP(char *command, int len);
+
+#endif /* _M68K_MACHDEP_H */
diff --git a/arch/m68k/include/asm/machdep_mm.h b/arch/m68k/include/asm/machdep_mm.h
deleted file mode 100644
index 5637dce..0000000
--- a/arch/m68k/include/asm/machdep_mm.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _M68K_MACHDEP_H
-#define _M68K_MACHDEP_H
-
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-
-struct pt_regs;
-struct mktime;
-struct rtc_time;
-struct rtc_pll_info;
-struct buffer_head;
-
-extern void (*mach_sched_init) (irq_handler_t handler);
-/* machine dependent irq functions */
-extern void (*mach_init_IRQ) (void);
-extern void (*mach_get_model) (char *model);
-extern void (*mach_get_hardware_list) (struct seq_file *m);
-/* machine dependent timer functions */
-extern unsigned long (*mach_gettimeoffset)(void);
-extern int (*mach_hwclk)(int, struct rtc_time*);
-extern unsigned int (*mach_get_ss)(void);
-extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
-extern int (*mach_set_rtc_pll)(struct rtc_pll_info *);
-extern int (*mach_set_clock_mmss)(unsigned long);
-extern void (*mach_reset)( void );
-extern void (*mach_halt)( void );
-extern void (*mach_power_off)( void );
-extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
-extern void (*mach_hd_setup)(char *, int *);
-extern long mach_max_dma_address;
-extern void (*mach_heartbeat) (int);
-extern void (*mach_l2_flush) (int);
-extern void (*mach_beep) (unsigned int, unsigned int);
-
-#endif /* _M68K_MACHDEP_H */
diff --git a/arch/m68k/include/asm/machdep_no.h b/arch/m68k/include/asm/machdep_no.h
deleted file mode 100644
index de9f47a..0000000
--- a/arch/m68k/include/asm/machdep_no.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _M68KNOMMU_MACHDEP_H
-#define _M68KNOMMU_MACHDEP_H
-
-#include <linux/interrupt.h>
-
-/* Hardware clock functions */
-extern void hw_timer_init(void);
-extern unsigned long hw_timer_offset(void);
-
-extern irqreturn_t arch_timer_interrupt(int irq, void *dummy);
-
-/* Machine dependent time handling */
-extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour,
-			   int *min, int *sec);
-extern int (*mach_set_clock_mmss)(unsigned long);
-
-/* machine dependent power off functions */
-extern void (*mach_reset)( void );
-extern void (*mach_halt)( void );
-extern void (*mach_power_off)( void );
-
-extern void config_BSP(char *command, int len);
-
-extern void do_IRQ(int irq, struct pt_regs *fp);
-
-#endif /* _M68KNOMMU_MACHDEP_H */
diff --git a/arch/m68k/include/asm/page.h b/arch/m68k/include/asm/page.h
index f2b4480..dfebb7c 100644
--- a/arch/m68k/include/asm/page.h
+++ b/arch/m68k/include/asm/page.h
@@ -1,5 +1,49 @@
-#ifdef __uClinux__
-#include "page_no.h"
+#ifndef _M68K_PAGE_H
+#define _M68K_PAGE_H
+
+#include <linux/const.h>
+#include <asm/setup.h>
+#include <asm/page_offset.h>
+
+/* PAGE_SHIFT determines the page size */
+#ifndef CONFIG_SUN3
+#define PAGE_SHIFT	(12)
 #else
-#include "page_mm.h"
+#define PAGE_SHIFT	(13)
 #endif
+#define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
+#define PAGE_MASK	(~(PAGE_SIZE-1))
+#define PAGE_OFFSET	(PAGE_OFFSET_RAW)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd[16]; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pte_val(x)	((x).pte)
+#define pmd_val(x)	((&x)->pmd[0])
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __pmd(x)	((pmd_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+#endif /* !__ASSEMBLY__ */
+
+#ifdef CONFIG_MMU
+#include "page_mm.h"
+#else
+#include "page_no.h"
+#endif
+
+#include <asm-generic/getorder.h>
+
+#endif /* _M68K_PAGE_H */
diff --git a/arch/m68k/include/asm/page_mm.h b/arch/m68k/include/asm/page_mm.h
index d009f3e..31d5570 100644
--- a/arch/m68k/include/asm/page_mm.h
+++ b/arch/m68k/include/asm/page_mm.h
@@ -1,29 +1,9 @@
-#ifndef _M68K_PAGE_H
-#define _M68K_PAGE_H
-
-#include <linux/const.h>
-
-/* PAGE_SHIFT determines the page size */
-#ifndef CONFIG_SUN3
-#define PAGE_SHIFT	(12)
-#else
-#define PAGE_SHIFT	(13)
-#endif
-#define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
-#define PAGE_MASK	(~(PAGE_SIZE-1))
-
-#include <asm/setup.h>
-
-#if PAGE_SHIFT < 13
-#define THREAD_SIZE (8192)
-#else
-#define THREAD_SIZE PAGE_SIZE
-#endif
+#ifndef _M68K_PAGE_MM_H
+#define _M68K_PAGE_MM_H
 
 #ifndef __ASSEMBLY__
 
 #include <linux/compiler.h>
-
 #include <asm/module.h>
 
 #define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
@@ -84,33 +64,6 @@
 		flush_dcache_page(page);	\
 	} while (0)
 
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd[16]; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x)	((x).pte)
-#define pmd_val(x)	((&x)->pmd[0])
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)	((x).pgprot)
-
-#define __pte(x)	((pte_t) { (x) } )
-#define __pmd(x)	((pmd_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __pgprot(x)	((pgprot_t) { (x) } )
-
-#endif /* !__ASSEMBLY__ */
-
-#include <asm/page_offset.h>
-
-#define PAGE_OFFSET		(PAGE_OFFSET_RAW)
-
-#ifndef __ASSEMBLY__
-
 extern unsigned long m68k_memoffset;
 
 #ifndef CONFIG_SUN3
@@ -127,7 +80,7 @@
 		: "0" (vaddr), "i" (m68k_fixup_memoffset));
 	return paddr;
 }
-#define __pa(vaddr)	___pa((void *)(vaddr))
+#define __pa(vaddr)	___pa((void *)(long)(vaddr))
 static inline void *__va(unsigned long paddr)
 {
 	void *vaddr;
@@ -223,6 +176,4 @@
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#include <asm-generic/getorder.h>
-
-#endif /* _M68K_PAGE_H */
+#endif /* _M68K_PAGE_MM_H */
diff --git a/arch/m68k/include/asm/page_no.h b/arch/m68k/include/asm/page_no.h
index 8029a33..9059572 100644
--- a/arch/m68k/include/asm/page_no.h
+++ b/arch/m68k/include/asm/page_no.h
@@ -1,18 +1,11 @@
-#ifndef _M68KNOMMU_PAGE_H
-#define _M68KNOMMU_PAGE_H
-
-#include <linux/const.h>
-
-/* PAGE_SHIFT determines the page size */
-
-#define PAGE_SHIFT	(12)
-#define PAGE_SIZE	(_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK	(~(PAGE_SIZE-1))
-
-#include <asm/setup.h>
+#ifndef _M68K_PAGE_NO_H
+#define _M68K_PAGE_NO_H
 
 #ifndef __ASSEMBLY__
  
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
 #define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
 #define free_user_page(page, addr)	free_page(addr)
 
@@ -26,36 +19,6 @@
 	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd[16]; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x)	((x).pte)
-#define pmd_val(x)	((&x)->pmd[0])
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)	((x).pgprot)
-
-#define __pte(x)	((pte_t) { (x) } )
-#define __pmd(x)	((pmd_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __pgprot(x)	((pgprot_t) { (x) } )
-
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
-#endif /* !__ASSEMBLY__ */
-
-#include <asm/page_offset.h>
-
-#define PAGE_OFFSET		(PAGE_OFFSET_RAW)
-
-#ifndef __ASSEMBLY__
-
 #define __pa(vaddr)		((unsigned long)(vaddr))
 #define __va(paddr)		((void *)(paddr))
 
@@ -74,6 +37,4 @@
 
 #endif /* __ASSEMBLY__ */
 
-#include <asm-generic/getorder.h>
-
-#endif /* _M68KNOMMU_PAGE_H */
+#endif /* _M68K_PAGE_NO_H */
diff --git a/arch/m68k/include/asm/string.h b/arch/m68k/include/asm/string.h
index 2c356f9..2936dda 100644
--- a/arch/m68k/include/asm/string.h
+++ b/arch/m68k/include/asm/string.h
@@ -1,5 +1,133 @@
-#ifdef __uClinux__
-#include "string_no.h"
+#ifndef _M68K_STRING_H_
+#define _M68K_STRING_H_
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+static inline size_t __kernel_strlen(const char *s)
+{
+	const char *sc;
+
+	for (sc = s; *sc++; )
+		;
+	return sc - s - 1;
+}
+
+static inline char *__kernel_strcpy(char *dest, const char *src)
+{
+	char *xdest = dest;
+
+	asm volatile ("\n"
+		"1:	move.b	(%1)+,(%0)+\n"
+		"	jne	1b"
+		: "+a" (dest), "+a" (src)
+		: : "memory");
+	return xdest;
+}
+
+#ifndef __IN_STRING_C
+
+#define __HAVE_ARCH_STRLEN
+#define strlen(s)	(__builtin_constant_p(s) ?	\
+			 __builtin_strlen(s) :		\
+			 __kernel_strlen(s))
+
+#define __HAVE_ARCH_STRNLEN
+static inline size_t strnlen(const char *s, size_t count)
+{
+	const char *sc = s;
+
+	asm volatile ("\n"
+		"1:     subq.l  #1,%1\n"
+		"       jcs     2f\n"
+		"       tst.b   (%0)+\n"
+		"       jne     1b\n"
+		"       subq.l  #1,%0\n"
+		"2:"
+		: "+a" (sc), "+d" (count));
+	return sc - s;
+}
+
+#define __HAVE_ARCH_STRCPY
+#if __GNUC__ >= 4
+#define strcpy(d, s)	(__builtin_constant_p(s) &&	\
+			 __builtin_strlen(s) <= 32 ?	\
+			 __builtin_strcpy(d, s) :	\
+			 __kernel_strcpy(d, s))
 #else
-#include "string_mm.h"
+#define strcpy(d, s)	__kernel_strcpy(d, s)
 #endif
+
+#define __HAVE_ARCH_STRNCPY
+static inline char *strncpy(char *dest, const char *src, size_t n)
+{
+	char *xdest = dest;
+
+	asm volatile ("\n"
+		"	jra	2f\n"
+		"1:	move.b	(%1),(%0)+\n"
+		"	jeq	2f\n"
+		"	addq.l	#1,%1\n"
+		"2:	subq.l	#1,%2\n"
+		"	jcc	1b\n"
+		: "+a" (dest), "+a" (src), "+d" (n)
+		: : "memory");
+	return xdest;
+}
+
+#define __HAVE_ARCH_STRCAT
+#define strcat(d, s)	({			\
+	char *__d = (d);			\
+	strcpy(__d + strlen(__d), (s));		\
+})
+
+#define __HAVE_ARCH_STRCHR
+static inline char *strchr(const char *s, int c)
+{
+	char sc, ch = c;
+
+	for (; (sc = *s++) != ch; ) {
+		if (!sc)
+			return NULL;
+	}
+	return (char *)s - 1;
+}
+
+#ifndef CONFIG_COLDFIRE
+#define __HAVE_ARCH_STRCMP
+static inline int strcmp(const char *cs, const char *ct)
+{
+	char res;
+
+	asm ("\n"
+		"1:	move.b	(%0)+,%2\n"	/* get *cs */
+		"	cmp.b	(%1)+,%2\n"	/* compare a byte */
+		"	jne	2f\n"		/* not equal, break out */
+		"	tst.b	%2\n"		/* at end of cs? */
+		"	jne	1b\n"		/* no, keep going */
+		"	jra	3f\n"		/* strings are equal */
+		"2:	sub.b	-(%1),%2\n"	/* *cs - *ct */
+		"3:"
+		: "+a" (cs), "+a" (ct), "=d" (res));
+	return res;
+}
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMCMP
+extern int memcmp(const void *, const void *, __kernel_size_t);
+#define memcmp(d, s, n) __builtin_memcmp(d, s, n)
+#endif /* CONFIG_COLDFIRE */
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, __kernel_size_t);
+#define memset(d, c, n) __builtin_memset(d, c, n)
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, __kernel_size_t);
+#define memcpy(d, s, n) __builtin_memcpy(d, s, n)
+
+#endif
+
+#endif /* _M68K_STRING_H_ */
diff --git a/arch/m68k/include/asm/string_mm.h b/arch/m68k/include/asm/string_mm.h
deleted file mode 100644
index 2eb7df1..0000000
--- a/arch/m68k/include/asm/string_mm.h
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef _M68K_STRING_H_
-#define _M68K_STRING_H_
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-static inline size_t __kernel_strlen(const char *s)
-{
-	const char *sc;
-
-	for (sc = s; *sc++; )
-		;
-	return sc - s - 1;
-}
-
-static inline char *__kernel_strcpy(char *dest, const char *src)
-{
-	char *xdest = dest;
-
-	asm volatile ("\n"
-		"1:	move.b	(%1)+,(%0)+\n"
-		"	jne	1b"
-		: "+a" (dest), "+a" (src)
-		: : "memory");
-	return xdest;
-}
-
-#ifndef __IN_STRING_C
-
-#define __HAVE_ARCH_STRLEN
-#define strlen(s)	(__builtin_constant_p(s) ?	\
-			 __builtin_strlen(s) :		\
-			 __kernel_strlen(s))
-
-#define __HAVE_ARCH_STRNLEN
-static inline size_t strnlen(const char *s, size_t count)
-{
-	const char *sc = s;
-
-	asm volatile ("\n"
-		"1:     subq.l  #1,%1\n"
-		"       jcs     2f\n"
-		"       tst.b   (%0)+\n"
-		"       jne     1b\n"
-		"       subq.l  #1,%0\n"
-		"2:"
-		: "+a" (sc), "+d" (count));
-	return sc - s;
-}
-
-#define __HAVE_ARCH_STRCPY
-#if __GNUC__ >= 4
-#define strcpy(d, s)	(__builtin_constant_p(s) &&	\
-			 __builtin_strlen(s) <= 32 ?	\
-			 __builtin_strcpy(d, s) :	\
-			 __kernel_strcpy(d, s))
-#else
-#define strcpy(d, s)	__kernel_strcpy(d, s)
-#endif
-
-#define __HAVE_ARCH_STRNCPY
-static inline char *strncpy(char *dest, const char *src, size_t n)
-{
-	char *xdest = dest;
-
-	asm volatile ("\n"
-		"	jra	2f\n"
-		"1:	move.b	(%1),(%0)+\n"
-		"	jeq	2f\n"
-		"	addq.l	#1,%1\n"
-		"2:	subq.l	#1,%2\n"
-		"	jcc	1b\n"
-		: "+a" (dest), "+a" (src), "+d" (n)
-		: : "memory");
-	return xdest;
-}
-
-#define __HAVE_ARCH_STRCAT
-#define strcat(d, s)	({			\
-	char *__d = (d);			\
-	strcpy(__d + strlen(__d), (s));		\
-})
-
-#define __HAVE_ARCH_STRCHR
-static inline char *strchr(const char *s, int c)
-{
-	char sc, ch = c;
-
-	for (; (sc = *s++) != ch; ) {
-		if (!sc)
-			return NULL;
-	}
-	return (char *)s - 1;
-}
-
-#define __HAVE_ARCH_STRCMP
-static inline int strcmp(const char *cs, const char *ct)
-{
-	char res;
-
-	asm ("\n"
-		"1:	move.b	(%0)+,%2\n"	/* get *cs */
-		"	cmp.b	(%1)+,%2\n"	/* compare a byte */
-		"	jne	2f\n"		/* not equal, break out */
-		"	tst.b	%2\n"		/* at end of cs? */
-		"	jne	1b\n"		/* no, keep going */
-		"	jra	3f\n"		/* strings are equal */
-		"2:	sub.b	-(%1),%2\n"	/* *cs - *ct */
-		"3:"
-		: "+a" (cs), "+a" (ct), "=d" (res));
-	return res;
-}
-
-#define __HAVE_ARCH_MEMSET
-extern void *memset(void *, int, __kernel_size_t);
-#define memset(d, c, n) __builtin_memset(d, c, n)
-
-#define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-#define memcpy(d, s, n) __builtin_memcpy(d, s, n)
-
-#define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-
-#define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *, const void *, __kernel_size_t);
-#define memcmp(d, s, n) __builtin_memcmp(d, s, n)
-
-#endif
-
-#endif /* _M68K_STRING_H_ */
diff --git a/arch/m68k/include/asm/string_no.h b/arch/m68k/include/asm/string_no.h
deleted file mode 100644
index af09e17..0000000
--- a/arch/m68k/include/asm/string_no.h
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef _M68KNOMMU_STRING_H_
-#define _M68KNOMMU_STRING_H_
-
-#ifdef __KERNEL__ /* only set these up for kernel code */
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-#define __HAVE_ARCH_STRCPY
-static inline char * strcpy(char * dest,const char *src)
-{
-  char *xdest = dest;
-
-  __asm__ __volatile__
-       ("1:\tmoveb %1@+,%0@+\n\t"
-        "jne 1b"
-	: "=a" (dest), "=a" (src)
-        : "0" (dest), "1" (src) : "memory");
-  return xdest;
-}
-
-#define __HAVE_ARCH_STRNCPY
-static inline char * strncpy(char *dest, const char *src, size_t n)
-{
-  char *xdest = dest;
-
-  if (n == 0)
-    return xdest;
-
-  __asm__ __volatile__
-       ("1:\tmoveb %1@+,%0@+\n\t"
-	"jeq 2f\n\t"
-        "subql #1,%2\n\t"
-        "jne 1b\n\t"
-        "2:"
-        : "=a" (dest), "=a" (src), "=d" (n)
-        : "0" (dest), "1" (src), "2" (n)
-        : "memory");
-  return xdest;
-}
-
-
-#ifndef CONFIG_COLDFIRE
-
-#define __HAVE_ARCH_STRCMP
-static inline int strcmp(const char * cs,const char * ct)
-{
-  char __res;
-
-  __asm__
-       ("1:\tmoveb %0@+,%2\n\t" /* get *cs */
-        "cmpb %1@+,%2\n\t"      /* compare a byte */
-        "jne  2f\n\t"           /* not equal, break out */
-        "tstb %2\n\t"           /* at end of cs? */
-        "jne  1b\n\t"           /* no, keep going */
-        "jra  3f\n\t"		/* strings are equal */
-        "2:\tsubb %1@-,%2\n\t"  /* *cs - *ct */
-        "3:"
-        : "=a" (cs), "=a" (ct), "=d" (__res)
-        : "0" (cs), "1" (ct));
-
-  return __res;
-}
-
-#define __HAVE_ARCH_STRNCMP
-static inline int strncmp(const char * cs,const char * ct,size_t count)
-{
-  char __res;
-
-  if (!count)
-    return 0;
-  __asm__
-       ("1:\tmovb %0@+,%3\n\t"          /* get *cs */
-        "cmpb   %1@+,%3\n\t"            /* compare a byte */
-        "jne    3f\n\t"                 /* not equal, break out */
-        "tstb   %3\n\t"                 /* at end of cs? */
-        "jeq    4f\n\t"                 /* yes, all done */
-        "subql  #1,%2\n\t"              /* no, adjust count */
-        "jne    1b\n\t"                 /* more to do, keep going */
-        "2:\tmoveq #0,%3\n\t"           /* strings are equal */
-        "jra    4f\n\t"
-        "3:\tsubb %1@-,%3\n\t"          /* *cs - *ct */
-        "4:"
-        : "=a" (cs), "=a" (ct), "=d" (count), "=d" (__res)
-        : "0" (cs), "1" (ct), "2" (count));
-  return __res;
-}
-
-#endif /* CONFIG_COLDFIRE */
-
-#define __HAVE_ARCH_MEMSET
-extern void * memset(void * s, int c, size_t count);
-
-#define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *d, const void *s, size_t count);
-
-#else /* KERNEL */
-
-/*
- *	let user libraries deal with these,
- *	IMHO the kernel has no place defining these functions for user apps
- */
-
-#define __HAVE_ARCH_STRCPY 1
-#define __HAVE_ARCH_STRNCPY 1
-#define __HAVE_ARCH_STRCAT 1
-#define __HAVE_ARCH_STRNCAT 1
-#define __HAVE_ARCH_STRCMP 1
-#define __HAVE_ARCH_STRNCMP 1
-#define __HAVE_ARCH_STRNICMP 1
-#define __HAVE_ARCH_STRCHR 1
-#define __HAVE_ARCH_STRRCHR 1
-#define __HAVE_ARCH_STRSTR 1
-#define __HAVE_ARCH_STRLEN 1
-#define __HAVE_ARCH_STRNLEN 1
-#define __HAVE_ARCH_MEMSET 1
-#define __HAVE_ARCH_MEMCPY 1
-#define __HAVE_ARCH_MEMMOVE 1
-#define __HAVE_ARCH_MEMSCAN 1
-#define __HAVE_ARCH_MEMCMP 1
-#define __HAVE_ARCH_MEMCHR 1
-#define __HAVE_ARCH_STRTOK 1
-
-#endif /* KERNEL */
-
-#endif /* _M68K_STRING_H_ */
diff --git a/arch/m68k/include/asm/system_mm.h b/arch/m68k/include/asm/system_mm.h
index 12053c4..47b01f47 100644
--- a/arch/m68k/include/asm/system_mm.h
+++ b/arch/m68k/include/asm/system_mm.h
@@ -182,9 +182,7 @@
 	((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
 			(unsigned long)(n), sizeof(*(ptr))))
 
-#ifndef CONFIG_SMP
 #include <asm-generic/cmpxchg.h>
-#endif
 
 #endif
 
diff --git a/arch/m68k/include/asm/system_no.h b/arch/m68k/include/asm/system_no.h
index 20126c0..6fe9f93 100644
--- a/arch/m68k/include/asm/system_no.h
+++ b/arch/m68k/include/asm/system_no.h
@@ -59,17 +59,10 @@
 #define wmb()  asm volatile (""   : : :"memory")
 #define set_mb(var, value)	({ (var) = (value); wmb(); })
 
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#define smp_rmb()	rmb()
-#define smp_wmb()	wmb()
-#define smp_read_barrier_depends()	read_barrier_depends()
-#else
 #define smp_mb()	barrier()
 #define smp_rmb()	barrier()
 #define smp_wmb()	barrier()
 #define smp_read_barrier_depends()	do { } while(0)
-#endif
 
 #define read_barrier_depends()  ((void)0)
 
@@ -152,9 +145,7 @@
 			(unsigned long)(n), sizeof(*(ptr))))
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 
-#ifndef CONFIG_SMP
 #include <asm-generic/cmpxchg.h>
-#endif
 
 #define arch_align_stack(x) (x)
 
diff --git a/arch/m68k/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info.h
index f31a3f4..1da5d53 100644
--- a/arch/m68k/include/asm/thread_info.h
+++ b/arch/m68k/include/asm/thread_info.h
@@ -1,5 +1,108 @@
-#ifdef __uClinux__
-#include "thread_info_no.h"
+#ifndef _ASM_M68K_THREAD_INFO_H
+#define _ASM_M68K_THREAD_INFO_H
+
+#include <asm/types.h>
+#include <asm/page.h>
+
+/*
+ * On machines with 4k pages we default to an 8k thread size, though we
+ * allow a 4k with config option. Any other machine page size then
+ * the thread size must match the page size (which is 8k and larger here).
+ */
+#if PAGE_SHIFT < 13
+#ifdef CONFIG_4KSTACKS
+#define THREAD_SIZE	4096
 #else
-#include "thread_info_mm.h"
+#define THREAD_SIZE	8192
 #endif
+#else
+#define THREAD_SIZE	PAGE_SIZE
+#endif
+#define THREAD_SIZE_ORDER	((THREAD_SIZE / PAGE_SIZE) - 1)
+
+#ifndef __ASSEMBLY__
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	unsigned long		flags;
+	struct exec_domain	*exec_domain;	/* execution domain */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	__u32			cpu;		/* should always be 0 on m68k */
+	unsigned long		tp_value;	/* thread pointer */
+	struct restart_block    restart_block;
+};
+#endif /* __ASSEMBLY__ */
+
+#define PREEMPT_ACTIVE		0x4000000
+
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.task		= &tsk,			\
+	.exec_domain	= &default_exec_domain,	\
+	.preempt_count	= INIT_PREEMPT_COUNT,	\
+	.restart_block = {			\
+		.fn = do_no_restart_syscall,	\
+	},					\
+}
+
+#define init_stack		(init_thread_union.stack)
+
+#ifdef CONFIG_MMU
+
+#ifndef __ASSEMBLY__
+#include <asm/current.h>
+#endif
+
+#ifdef ASM_OFFSETS_C
+#define task_thread_info(tsk)	((struct thread_info *) NULL)
+#else
+#include <asm/asm-offsets.h>
+#define task_thread_info(tsk)	((struct thread_info *)((char *)tsk+TASK_TINFO))
+#endif
+
+#define init_thread_info	(init_task.thread.info)
+#define task_stack_page(tsk)	((tsk)->stack)
+#define current_thread_info()	task_thread_info(current)
+
+#define __HAVE_THREAD_FUNCTIONS
+
+#define setup_thread_stack(p, org) ({			\
+	*(struct task_struct **)(p)->stack = (p);	\
+	task_thread_info(p)->task = (p);		\
+})
+
+#define end_of_stack(p)		((unsigned long *)(p)->stack + 1)
+
+#else /* !CONFIG_MMU */
+
+#ifndef __ASSEMBLY__
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+	struct thread_info *ti;
+	__asm__(
+		"move.l %%sp, %0 \n\t"
+		"and.l  %1, %0"
+		: "=&d"(ti)
+		: "di" (~(THREAD_SIZE-1))
+		);
+	return ti;
+}
+#endif
+
+#define init_thread_info	(init_thread_union.thread_info)
+
+#endif /* CONFIG_MMU */
+
+/* entry.S relies on these definitions!
+ * bits 0-7 are tested at every exception exit
+ * bits 8-15 are also tested at syscall exit
+ */
+#define TIF_SIGPENDING		6	/* signal pending */
+#define TIF_NEED_RESCHED	7	/* rescheduling necessary */
+#define TIF_DELAYED_TRACE	14	/* single step a syscall */
+#define TIF_SYSCALL_TRACE	15	/* syscall trace active */
+#define TIF_MEMDIE		16	/* is terminating due to OOM killer */
+#define TIF_FREEZE		17	/* thread is freezing for suspend */
+
+#endif	/* _ASM_M68K_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/thread_info_mm.h b/arch/m68k/include/asm/thread_info_mm.h
deleted file mode 100644
index 3bf31dc..0000000
--- a/arch/m68k/include/asm/thread_info_mm.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef _ASM_M68K_THREAD_INFO_H
-#define _ASM_M68K_THREAD_INFO_H
-
-#ifndef ASM_OFFSETS_C
-#include <asm/asm-offsets.h>
-#endif
-#include <asm/types.h>
-#include <asm/page.h>
-
-#ifndef __ASSEMBLY__
-#include <asm/current.h>
-
-struct thread_info {
-	struct task_struct	*task;		/* main task structure */
-	unsigned long		flags;
-	struct exec_domain	*exec_domain;	/* execution domain */
-	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-	__u32 cpu; /* should always be 0 on m68k */
-	unsigned long		tp_value;	/* thread pointer */
-	struct restart_block    restart_block;
-};
-#endif /* __ASSEMBLY__ */
-
-#define PREEMPT_ACTIVE		0x4000000
-
-#define INIT_THREAD_INFO(tsk)			\
-{						\
-	.task		= &tsk,			\
-	.exec_domain	= &default_exec_domain,	\
-	.preempt_count	= INIT_PREEMPT_COUNT,	\
-	.restart_block = {			\
-		.fn = do_no_restart_syscall,	\
-	},					\
-}
-
-/* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */
-#define THREAD_SIZE_ORDER (13 - PAGE_SHIFT)
-
-#define init_thread_info	(init_task.thread.info)
-#define init_stack		(init_thread_union.stack)
-
-#ifdef ASM_OFFSETS_C
-#define task_thread_info(tsk)	((struct thread_info *) NULL)
-#else
-#define task_thread_info(tsk)	((struct thread_info *)((char *)tsk+TASK_TINFO))
-#endif
-
-#define task_stack_page(tsk)	((tsk)->stack)
-#define current_thread_info()	task_thread_info(current)
-
-#define __HAVE_THREAD_FUNCTIONS
-
-#define setup_thread_stack(p, org) ({			\
-	*(struct task_struct **)(p)->stack = (p);	\
-	task_thread_info(p)->task = (p);		\
-})
-
-#define end_of_stack(p) ((unsigned long *)(p)->stack + 1)
-
-/* entry.S relies on these definitions!
- * bits 0-7 are tested at every exception exit
- * bits 8-15 are also tested at syscall exit
- */
-#define TIF_SIGPENDING		6	/* signal pending */
-#define TIF_NEED_RESCHED	7	/* rescheduling necessary */
-#define TIF_DELAYED_TRACE	14	/* single step a syscall */
-#define TIF_SYSCALL_TRACE	15	/* syscall trace active */
-#define TIF_MEMDIE		16	/* is terminating due to OOM killer */
-#define TIF_FREEZE		17	/* thread is freezing for suspend */
-
-#endif	/* _ASM_M68K_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/thread_info_no.h b/arch/m68k/include/asm/thread_info_no.h
deleted file mode 100644
index 51f354b..0000000
--- a/arch/m68k/include/asm/thread_info_no.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* thread_info.h: m68knommu low-level thread information
- * adapted from the i386 and PPC versions by Greg Ungerer (gerg@snapgear.com)
- *
- * Copyright (C) 2002  David Howells (dhowells@redhat.com)
- * - Incorporating suggestions made by Linus Torvalds and Dave Miller
- */
-
-#ifndef _ASM_THREAD_INFO_H
-#define _ASM_THREAD_INFO_H
-
-#include <asm/page.h>
-
-#ifdef __KERNEL__
-
-/*
- * Size of kernel stack for each process. This must be a power of 2...
- */
-#ifdef CONFIG_4KSTACKS
-#define THREAD_SIZE_ORDER (0)
-#else
-#define THREAD_SIZE_ORDER (1)
-#endif
-                                                                                
-/*
- * for asm files, THREAD_SIZE is now generated by asm-offsets.c
- */
-#define THREAD_SIZE (PAGE_SIZE<<THREAD_SIZE_ORDER)
-
-#ifndef __ASSEMBLY__
-
-/*
- * low level task data.
- */
-struct thread_info {
-	struct task_struct *task;		/* main task structure */
-	struct exec_domain *exec_domain;	/* execution domain */
-	unsigned long	   flags;		/* low level flags */
-	int		   cpu;			/* cpu we're on */
-	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
-	unsigned long	   tp_value;		/* thread pointer */
-	struct restart_block restart_block;
-};
-
-/*
- * macros/functions for gaining access to the thread information structure
- */
-#define INIT_THREAD_INFO(tsk)			\
-{						\
-	.task		= &tsk,			\
-	.exec_domain	= &default_exec_domain,	\
-	.flags		= 0,			\
-	.cpu		= 0,			\
-	.preempt_count	= INIT_PREEMPT_COUNT,	\
-	.restart_block	= {			\
-		.fn = do_no_restart_syscall,	\
-	},					\
-}
-
-#define init_thread_info	(init_thread_union.thread_info)
-#define init_stack		(init_thread_union.stack)
-
-
-/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
-{
-	struct thread_info *ti;
-	__asm__(
-		"move.l	%%sp, %0 \n\t"
-		"and.l	%1, %0"
-		: "=&d"(ti)
-		: "di" (~(THREAD_SIZE-1))
-		);
-	return ti;
-}
-
-#endif /* __ASSEMBLY__ */
-
-#define	PREEMPT_ACTIVE	0x4000000
-
-/*
- * thread information flag bit numbers
- */
-#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-#define TIF_SIGPENDING		1	/* signal pending */
-#define TIF_NEED_RESCHED	2	/* rescheduling necessary */
-#define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
-					   TIF_NEED_RESCHED */
-#define TIF_MEMDIE		4	/* is terminating due to OOM killer */
-#define TIF_FREEZE		16	/* is freezing for suspend */
-
-/* as above, but as bit values */
-#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
-#define _TIF_FREEZE		(1<<TIF_FREEZE)
-
-#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/m68k/include/asm/traps.h b/arch/m68k/include/asm/traps.h
index 3011ec0..0bffb17 100644
--- a/arch/m68k/include/asm/traps.h
+++ b/arch/m68k/include/asm/traps.h
@@ -1,5 +1,272 @@
-#ifdef __uClinux__
-#include "traps_no.h"
-#else
-#include "traps_mm.h"
+/*
+ *  linux/include/asm/traps.h
+ *
+ *  Copyright (C) 1993        Hamish Macdonald
+ *
+ * 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 _M68K_TRAPS_H
+#define _M68K_TRAPS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+
+typedef void (*e_vector)(void);
+extern e_vector vectors[];
+
+asmlinkage void auto_inthandler(void);
+asmlinkage void user_inthandler(void);
+asmlinkage void bad_inthandler(void);
+extern void init_vectors(void);
+
 #endif
+
+#define VEC_RESETSP (0)
+#define VEC_RESETPC (1)
+#define VEC_BUSERR  (2)
+#define VEC_ADDRERR (3)
+#define VEC_ILLEGAL (4)
+#define VEC_ZERODIV (5)
+#define VEC_CHK     (6)
+#define VEC_TRAP    (7)
+#define VEC_PRIV    (8)
+#define VEC_TRACE   (9)
+#define VEC_LINE10  (10)
+#define VEC_LINE11  (11)
+#define VEC_RESV12  (12)
+#define VEC_COPROC  (13)
+#define VEC_FORMAT  (14)
+#define VEC_UNINT   (15)
+#define VEC_RESV16  (16)
+#define VEC_RESV17  (17)
+#define VEC_RESV18  (18)
+#define VEC_RESV19  (19)
+#define VEC_RESV20  (20)
+#define VEC_RESV21  (21)
+#define VEC_RESV22  (22)
+#define VEC_RESV23  (23)
+#define VEC_SPUR    (24)
+#define VEC_INT1    (25)
+#define VEC_INT2    (26)
+#define VEC_INT3    (27)
+#define VEC_INT4    (28)
+#define VEC_INT5    (29)
+#define VEC_INT6    (30)
+#define VEC_INT7    (31)
+#define VEC_SYS     (32)
+#define VEC_TRAP1   (33)
+#define VEC_TRAP2   (34)
+#define VEC_TRAP3   (35)
+#define VEC_TRAP4   (36)
+#define VEC_TRAP5   (37)
+#define VEC_TRAP6   (38)
+#define VEC_TRAP7   (39)
+#define VEC_TRAP8   (40)
+#define VEC_TRAP9   (41)
+#define VEC_TRAP10  (42)
+#define VEC_TRAP11  (43)
+#define VEC_TRAP12  (44)
+#define VEC_TRAP13  (45)
+#define VEC_TRAP14  (46)
+#define VEC_TRAP15  (47)
+#define VEC_FPBRUC  (48)
+#define VEC_FPIR    (49)
+#define VEC_FPDIVZ  (50)
+#define VEC_FPUNDER (51)
+#define VEC_FPOE    (52)
+#define VEC_FPOVER  (53)
+#define VEC_FPNAN   (54)
+#define VEC_FPUNSUP (55)
+#define VEC_MMUCFG  (56)
+#define VEC_MMUILL  (57)
+#define VEC_MMUACC  (58)
+#define VEC_RESV59  (59)
+#define	VEC_UNIMPEA (60)
+#define	VEC_UNIMPII (61)
+#define VEC_RESV62  (62)
+#define VEC_RESV63  (63)
+#define VEC_USER    (64)
+
+#define VECOFF(vec) ((vec)<<2)
+
+#ifndef __ASSEMBLY__
+
+/* Status register bits */
+#define PS_T  (0x8000)
+#define PS_S  (0x2000)
+#define PS_M  (0x1000)
+#define PS_C  (0x0001)
+
+/* bits for 68020/68030 special status word */
+
+#define FC    (0x8000)
+#define FB    (0x4000)
+#define RC    (0x2000)
+#define RB    (0x1000)
+#define DF    (0x0100)
+#define RM    (0x0080)
+#define RW    (0x0040)
+#define SZ    (0x0030)
+#define DFC   (0x0007)
+
+/* bits for 68030 MMU status register (mmusr,psr) */
+
+#define MMU_B	     (0x8000)    /* bus error */
+#define MMU_L	     (0x4000)    /* limit violation */
+#define MMU_S	     (0x2000)    /* supervisor violation */
+#define MMU_WP	     (0x0800)    /* write-protected */
+#define MMU_I	     (0x0400)    /* invalid descriptor */
+#define MMU_M	     (0x0200)    /* ATC entry modified */
+#define MMU_T	     (0x0040)    /* transparent translation */
+#define MMU_NUM      (0x0007)    /* number of levels traversed */
+
+
+/* bits for 68040 special status word */
+#define CP_040	(0x8000)
+#define CU_040	(0x4000)
+#define CT_040	(0x2000)
+#define CM_040	(0x1000)
+#define MA_040	(0x0800)
+#define ATC_040 (0x0400)
+#define LK_040	(0x0200)
+#define RW_040	(0x0100)
+#define SIZ_040 (0x0060)
+#define TT_040	(0x0018)
+#define TM_040	(0x0007)
+
+/* bits for 68040 write back status word */
+#define WBV_040   (0x80)
+#define WBSIZ_040 (0x60)
+#define WBBYT_040 (0x20)
+#define WBWRD_040 (0x40)
+#define WBLNG_040 (0x00)
+#define WBTT_040  (0x18)
+#define WBTM_040  (0x07)
+
+/* bus access size codes */
+#define BA_SIZE_BYTE    (0x20)
+#define BA_SIZE_WORD    (0x40)
+#define BA_SIZE_LONG    (0x00)
+#define BA_SIZE_LINE    (0x60)
+
+/* bus access transfer type codes */
+#define BA_TT_MOVE16    (0x08)
+
+/* bits for 68040 MMU status register (mmusr) */
+#define MMU_B_040   (0x0800)
+#define MMU_G_040   (0x0400)
+#define MMU_S_040   (0x0080)
+#define MMU_CM_040  (0x0060)
+#define MMU_M_040   (0x0010)
+#define MMU_WP_040  (0x0004)
+#define MMU_T_040   (0x0002)
+#define MMU_R_040   (0x0001)
+
+/* bits in the 68060 fault status long word (FSLW) */
+#define	MMU060_MA	(0x08000000)	/* misaligned */
+#define	MMU060_LK	(0x02000000)	/* locked transfer */
+#define	MMU060_RW	(0x01800000)	/* read/write */
+# define MMU060_RW_W	(0x00800000)	/* write */
+# define MMU060_RW_R	(0x01000000)	/* read */
+# define MMU060_RW_RMW	(0x01800000)	/* read/modify/write */
+# define MMU060_W	(0x00800000)	/* general write, includes rmw */
+#define	MMU060_SIZ	(0x00600000)	/* transfer size */
+#define	MMU060_TT	(0x00180000)	/* transfer type (TT) bits */
+#define	MMU060_TM	(0x00070000)	/* transfer modifier (TM) bits */
+#define	MMU060_IO	(0x00008000)	/* instruction or operand */
+#define	MMU060_PBE	(0x00004000)	/* push buffer bus error */
+#define	MMU060_SBE	(0x00002000)	/* store buffer bus error */
+#define	MMU060_PTA	(0x00001000)	/* pointer A fault */
+#define	MMU060_PTB	(0x00000800)	/* pointer B fault */
+#define	MMU060_IL	(0x00000400)	/* double indirect descr fault */
+#define	MMU060_PF	(0x00000200)	/* page fault (invalid descr) */
+#define	MMU060_SP	(0x00000100)	/* supervisor protection */
+#define	MMU060_WP	(0x00000080)	/* write protection */
+#define	MMU060_TWE	(0x00000040)	/* bus error on table search */
+#define	MMU060_RE	(0x00000020)	/* bus error on read */
+#define	MMU060_WE	(0x00000010)	/* bus error on write */
+#define	MMU060_TTR	(0x00000008)	/* error caused by TTR translation */
+#define	MMU060_BPE	(0x00000004)	/* branch prediction error */
+#define	MMU060_SEE	(0x00000001)	/* software emulated error */
+
+/* cases of missing or invalid descriptors */
+#define MMU060_DESC_ERR (MMU060_PTA | MMU060_PTB | \
+			 MMU060_IL  | MMU060_PF)
+/* bits that indicate real errors */
+#define MMU060_ERR_BITS (MMU060_PBE | MMU060_SBE | MMU060_DESC_ERR | MMU060_SP | \
+			 MMU060_WP  | MMU060_TWE | MMU060_RE       | MMU060_WE)
+
+/* structure for stack frames */
+
+struct frame {
+    struct pt_regs ptregs;
+    union {
+	    struct {
+		    unsigned long  iaddr;    /* instruction address */
+	    } fmt2;
+	    struct {
+		    unsigned long  effaddr;  /* effective address */
+	    } fmt3;
+	    struct {
+		    unsigned long  effaddr;  /* effective address */
+		    unsigned long  pc;	     /* pc of faulted instr */
+	    } fmt4;
+	    struct {
+		    unsigned long  effaddr;  /* effective address */
+		    unsigned short ssw;      /* special status word */
+		    unsigned short wb3s;     /* write back 3 status */
+		    unsigned short wb2s;     /* write back 2 status */
+		    unsigned short wb1s;     /* write back 1 status */
+		    unsigned long  faddr;    /* fault address */
+		    unsigned long  wb3a;     /* write back 3 address */
+		    unsigned long  wb3d;     /* write back 3 data */
+		    unsigned long  wb2a;     /* write back 2 address */
+		    unsigned long  wb2d;     /* write back 2 data */
+		    unsigned long  wb1a;     /* write back 1 address */
+		    unsigned long  wb1dpd0;  /* write back 1 data/push data 0*/
+		    unsigned long  pd1;      /* push data 1*/
+		    unsigned long  pd2;      /* push data 2*/
+		    unsigned long  pd3;      /* push data 3*/
+	    } fmt7;
+	    struct {
+		    unsigned long  iaddr;    /* instruction address */
+		    unsigned short int1[4];  /* internal registers */
+	    } fmt9;
+	    struct {
+		    unsigned short int1;
+		    unsigned short ssw;      /* special status word */
+		    unsigned short isc;      /* instruction stage c */
+		    unsigned short isb;      /* instruction stage b */
+		    unsigned long  daddr;    /* data cycle fault address */
+		    unsigned short int2[2];
+		    unsigned long  dobuf;    /* data cycle output buffer */
+		    unsigned short int3[2];
+	    } fmta;
+	    struct {
+		    unsigned short int1;
+		    unsigned short ssw;     /* special status word */
+		    unsigned short isc;     /* instruction stage c */
+		    unsigned short isb;     /* instruction stage b */
+		    unsigned long  daddr;   /* data cycle fault address */
+		    unsigned short int2[2];
+		    unsigned long  dobuf;   /* data cycle output buffer */
+		    unsigned short int3[4];
+		    unsigned long  baddr;   /* stage B address */
+		    unsigned short int4[2];
+		    unsigned long  dibuf;   /* data cycle input buffer */
+		    unsigned short int5[3];
+		    unsigned	   ver : 4; /* stack frame version # */
+		    unsigned	   int6:12;
+		    unsigned short int7[18];
+	    } fmtb;
+    } un;
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _M68K_TRAPS_H */
diff --git a/arch/m68k/include/asm/traps_mm.h b/arch/m68k/include/asm/traps_mm.h
deleted file mode 100644
index 8caef25..0000000
--- a/arch/m68k/include/asm/traps_mm.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- *  linux/include/asm/traps.h
- *
- *  Copyright (C) 1993        Hamish Macdonald
- *
- * 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 _M68K_TRAPS_H
-#define _M68K_TRAPS_H
-
-#ifndef __ASSEMBLY__
-
-#include <linux/linkage.h>
-#include <asm/ptrace.h>
-
-typedef void (*e_vector)(void);
-
-asmlinkage void auto_inthandler(void);
-asmlinkage void user_inthandler(void);
-asmlinkage void bad_inthandler(void);
-
-extern e_vector vectors[];
-
-#endif
-
-#define VEC_RESETSP (0)
-#define VEC_RESETPC (1)
-#define VEC_BUSERR  (2)
-#define VEC_ADDRERR (3)
-#define VEC_ILLEGAL (4)
-#define VEC_ZERODIV (5)
-#define VEC_CHK     (6)
-#define VEC_TRAP    (7)
-#define VEC_PRIV    (8)
-#define VEC_TRACE   (9)
-#define VEC_LINE10  (10)
-#define VEC_LINE11  (11)
-#define VEC_RESV12  (12)
-#define VEC_COPROC  (13)
-#define VEC_FORMAT  (14)
-#define VEC_UNINT   (15)
-#define VEC_RESV16  (16)
-#define VEC_RESV17  (17)
-#define VEC_RESV18  (18)
-#define VEC_RESV19  (19)
-#define VEC_RESV20  (20)
-#define VEC_RESV21  (21)
-#define VEC_RESV22  (22)
-#define VEC_RESV23  (23)
-#define VEC_SPUR    (24)
-#define VEC_INT1    (25)
-#define VEC_INT2    (26)
-#define VEC_INT3    (27)
-#define VEC_INT4    (28)
-#define VEC_INT5    (29)
-#define VEC_INT6    (30)
-#define VEC_INT7    (31)
-#define VEC_SYS     (32)
-#define VEC_TRAP1   (33)
-#define VEC_TRAP2   (34)
-#define VEC_TRAP3   (35)
-#define VEC_TRAP4   (36)
-#define VEC_TRAP5   (37)
-#define VEC_TRAP6   (38)
-#define VEC_TRAP7   (39)
-#define VEC_TRAP8   (40)
-#define VEC_TRAP9   (41)
-#define VEC_TRAP10  (42)
-#define VEC_TRAP11  (43)
-#define VEC_TRAP12  (44)
-#define VEC_TRAP13  (45)
-#define VEC_TRAP14  (46)
-#define VEC_TRAP15  (47)
-#define VEC_FPBRUC  (48)
-#define VEC_FPIR    (49)
-#define VEC_FPDIVZ  (50)
-#define VEC_FPUNDER (51)
-#define VEC_FPOE    (52)
-#define VEC_FPOVER  (53)
-#define VEC_FPNAN   (54)
-#define VEC_FPUNSUP (55)
-#define VEC_MMUCFG  (56)
-#define VEC_MMUILL  (57)
-#define VEC_MMUACC  (58)
-#define VEC_RESV59  (59)
-#define	VEC_UNIMPEA (60)
-#define	VEC_UNIMPII (61)
-#define VEC_RESV62  (62)
-#define VEC_RESV63  (63)
-#define VEC_USER    (64)
-
-#define VECOFF(vec) ((vec)<<2)
-
-#ifndef __ASSEMBLY__
-
-/* Status register bits */
-#define PS_T  (0x8000)
-#define PS_S  (0x2000)
-#define PS_M  (0x1000)
-#define PS_C  (0x0001)
-
-/* bits for 68020/68030 special status word */
-
-#define FC    (0x8000)
-#define FB    (0x4000)
-#define RC    (0x2000)
-#define RB    (0x1000)
-#define DF    (0x0100)
-#define RM    (0x0080)
-#define RW    (0x0040)
-#define SZ    (0x0030)
-#define DFC   (0x0007)
-
-/* bits for 68030 MMU status register (mmusr,psr) */
-
-#define MMU_B	     (0x8000)    /* bus error */
-#define MMU_L	     (0x4000)    /* limit violation */
-#define MMU_S	     (0x2000)    /* supervisor violation */
-#define MMU_WP	     (0x0800)    /* write-protected */
-#define MMU_I	     (0x0400)    /* invalid descriptor */
-#define MMU_M	     (0x0200)    /* ATC entry modified */
-#define MMU_T	     (0x0040)    /* transparent translation */
-#define MMU_NUM      (0x0007)    /* number of levels traversed */
-
-
-/* bits for 68040 special status word */
-#define CP_040	(0x8000)
-#define CU_040	(0x4000)
-#define CT_040	(0x2000)
-#define CM_040	(0x1000)
-#define MA_040	(0x0800)
-#define ATC_040 (0x0400)
-#define LK_040	(0x0200)
-#define RW_040	(0x0100)
-#define SIZ_040 (0x0060)
-#define TT_040	(0x0018)
-#define TM_040	(0x0007)
-
-/* bits for 68040 write back status word */
-#define WBV_040   (0x80)
-#define WBSIZ_040 (0x60)
-#define WBBYT_040 (0x20)
-#define WBWRD_040 (0x40)
-#define WBLNG_040 (0x00)
-#define WBTT_040  (0x18)
-#define WBTM_040  (0x07)
-
-/* bus access size codes */
-#define BA_SIZE_BYTE    (0x20)
-#define BA_SIZE_WORD    (0x40)
-#define BA_SIZE_LONG    (0x00)
-#define BA_SIZE_LINE    (0x60)
-
-/* bus access transfer type codes */
-#define BA_TT_MOVE16    (0x08)
-
-/* bits for 68040 MMU status register (mmusr) */
-#define MMU_B_040   (0x0800)
-#define MMU_G_040   (0x0400)
-#define MMU_S_040   (0x0080)
-#define MMU_CM_040  (0x0060)
-#define MMU_M_040   (0x0010)
-#define MMU_WP_040  (0x0004)
-#define MMU_T_040   (0x0002)
-#define MMU_R_040   (0x0001)
-
-/* bits in the 68060 fault status long word (FSLW) */
-#define	MMU060_MA	(0x08000000)	/* misaligned */
-#define	MMU060_LK	(0x02000000)	/* locked transfer */
-#define	MMU060_RW	(0x01800000)	/* read/write */
-# define MMU060_RW_W	(0x00800000)	/* write */
-# define MMU060_RW_R	(0x01000000)	/* read */
-# define MMU060_RW_RMW	(0x01800000)	/* read/modify/write */
-# define MMU060_W	(0x00800000)	/* general write, includes rmw */
-#define	MMU060_SIZ	(0x00600000)	/* transfer size */
-#define	MMU060_TT	(0x00180000)	/* transfer type (TT) bits */
-#define	MMU060_TM	(0x00070000)	/* transfer modifier (TM) bits */
-#define	MMU060_IO	(0x00008000)	/* instruction or operand */
-#define	MMU060_PBE	(0x00004000)	/* push buffer bus error */
-#define	MMU060_SBE	(0x00002000)	/* store buffer bus error */
-#define	MMU060_PTA	(0x00001000)	/* pointer A fault */
-#define	MMU060_PTB	(0x00000800)	/* pointer B fault */
-#define	MMU060_IL	(0x00000400)	/* double indirect descr fault */
-#define	MMU060_PF	(0x00000200)	/* page fault (invalid descr) */
-#define	MMU060_SP	(0x00000100)	/* supervisor protection */
-#define	MMU060_WP	(0x00000080)	/* write protection */
-#define	MMU060_TWE	(0x00000040)	/* bus error on table search */
-#define	MMU060_RE	(0x00000020)	/* bus error on read */
-#define	MMU060_WE	(0x00000010)	/* bus error on write */
-#define	MMU060_TTR	(0x00000008)	/* error caused by TTR translation */
-#define	MMU060_BPE	(0x00000004)	/* branch prediction error */
-#define	MMU060_SEE	(0x00000001)	/* software emulated error */
-
-/* cases of missing or invalid descriptors */
-#define MMU060_DESC_ERR (MMU060_PTA | MMU060_PTB | \
-			 MMU060_IL  | MMU060_PF)
-/* bits that indicate real errors */
-#define MMU060_ERR_BITS (MMU060_PBE | MMU060_SBE | MMU060_DESC_ERR | MMU060_SP | \
-			 MMU060_WP  | MMU060_TWE | MMU060_RE       | MMU060_WE)
-
-/* structure for stack frames */
-
-struct frame {
-    struct pt_regs ptregs;
-    union {
-	    struct {
-		    unsigned long  iaddr;    /* instruction address */
-	    } fmt2;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-	    } fmt3;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-		    unsigned long  pc;	     /* pc of faulted instr */
-	    } fmt4;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-		    unsigned short ssw;      /* special status word */
-		    unsigned short wb3s;     /* write back 3 status */
-		    unsigned short wb2s;     /* write back 2 status */
-		    unsigned short wb1s;     /* write back 1 status */
-		    unsigned long  faddr;    /* fault address */
-		    unsigned long  wb3a;     /* write back 3 address */
-		    unsigned long  wb3d;     /* write back 3 data */
-		    unsigned long  wb2a;     /* write back 2 address */
-		    unsigned long  wb2d;     /* write back 2 data */
-		    unsigned long  wb1a;     /* write back 1 address */
-		    unsigned long  wb1dpd0;  /* write back 1 data/push data 0*/
-		    unsigned long  pd1;      /* push data 1*/
-		    unsigned long  pd2;      /* push data 2*/
-		    unsigned long  pd3;      /* push data 3*/
-	    } fmt7;
-	    struct {
-		    unsigned long  iaddr;    /* instruction address */
-		    unsigned short int1[4];  /* internal registers */
-	    } fmt9;
-	    struct {
-		    unsigned short int1;
-		    unsigned short ssw;      /* special status word */
-		    unsigned short isc;      /* instruction stage c */
-		    unsigned short isb;      /* instruction stage b */
-		    unsigned long  daddr;    /* data cycle fault address */
-		    unsigned short int2[2];
-		    unsigned long  dobuf;    /* data cycle output buffer */
-		    unsigned short int3[2];
-	    } fmta;
-	    struct {
-		    unsigned short int1;
-		    unsigned short ssw;     /* special status word */
-		    unsigned short isc;     /* instruction stage c */
-		    unsigned short isb;     /* instruction stage b */
-		    unsigned long  daddr;   /* data cycle fault address */
-		    unsigned short int2[2];
-		    unsigned long  dobuf;   /* data cycle output buffer */
-		    unsigned short int3[4];
-		    unsigned long  baddr;   /* stage B address */
-		    unsigned short int4[2];
-		    unsigned long  dibuf;   /* data cycle input buffer */
-		    unsigned short int5[3];
-		    unsigned	   ver : 4; /* stack frame version # */
-		    unsigned	   int6:12;
-		    unsigned short int7[18];
-	    } fmtb;
-    } un;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _M68K_TRAPS_H */
diff --git a/arch/m68k/include/asm/traps_no.h b/arch/m68k/include/asm/traps_no.h
deleted file mode 100644
index d0671e5..0000000
--- a/arch/m68k/include/asm/traps_no.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *  linux/include/asm/traps.h
- *
- *  Copyright (C) 1993        Hamish Macdonald
- *
- * 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 _M68KNOMMU_TRAPS_H
-#define _M68KNOMMU_TRAPS_H
-
-#ifndef __ASSEMBLY__
-
-typedef void (*e_vector)(void);
-
-extern e_vector vectors[];
-extern void init_vectors(void);
-extern void enable_vector(unsigned int irq);
-extern void disable_vector(unsigned int irq);
-extern void ack_vector(unsigned int irq);
-
-#endif
-
-#define VEC_BUSERR  (2)
-#define VEC_ADDRERR (3)
-#define VEC_ILLEGAL (4)
-#define VEC_ZERODIV (5)
-#define VEC_CHK     (6)
-#define VEC_TRAP    (7)
-#define VEC_PRIV    (8)
-#define VEC_TRACE   (9)
-#define VEC_LINE10  (10)
-#define VEC_LINE11  (11)
-#define VEC_RESV1   (12)
-#define VEC_COPROC  (13)
-#define VEC_FORMAT  (14)
-#define VEC_UNINT   (15)
-#define VEC_SPUR    (24)
-#define VEC_INT1    (25)
-#define VEC_INT2    (26)
-#define VEC_INT3    (27)
-#define VEC_INT4    (28)
-#define VEC_INT5    (29)
-#define VEC_INT6    (30)
-#define VEC_INT7    (31)
-#define VEC_SYS     (32)
-#define VEC_TRAP1   (33)
-#define VEC_TRAP2   (34)
-#define VEC_TRAP3   (35)
-#define VEC_TRAP4   (36)
-#define VEC_TRAP5   (37)
-#define VEC_TRAP6   (38)
-#define VEC_TRAP7   (39)
-#define VEC_TRAP8   (40)
-#define VEC_TRAP9   (41)
-#define VEC_TRAP10  (42)
-#define VEC_TRAP11  (43)
-#define VEC_TRAP12  (44)
-#define VEC_TRAP13  (45)
-#define VEC_TRAP14  (46)
-#define VEC_TRAP15  (47)
-#define VEC_FPBRUC  (48)
-#define VEC_FPIR    (49)
-#define VEC_FPDIVZ  (50)
-#define VEC_FPUNDER (51)
-#define VEC_FPOE    (52)
-#define VEC_FPOVER  (53)
-#define VEC_FPNAN   (54)
-#define VEC_FPUNSUP (55)
-#define	VEC_UNIMPEA (60)
-#define	VEC_UNIMPII (61)
-#define VEC_USER    (64)
-
-#define VECOFF(vec) ((vec)<<2)
-
-#ifndef __ASSEMBLY__
-
-/* Status register bits */
-#define PS_T  (0x8000)
-#define PS_S  (0x2000)
-#define PS_M  (0x1000)
-#define PS_C  (0x0001)
-
-/* structure for stack frames */
-
-struct frame {
-    struct pt_regs ptregs;
-    union {
-	    struct {
-		    unsigned long  iaddr;    /* instruction address */
-	    } fmt2;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-	    } fmt3;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-		    unsigned long  pc;	     /* pc of faulted instr */
-	    } fmt4;
-	    struct {
-		    unsigned long  effaddr;  /* effective address */
-		    unsigned short ssw;      /* special status word */
-		    unsigned short wb3s;     /* write back 3 status */
-		    unsigned short wb2s;     /* write back 2 status */
-		    unsigned short wb1s;     /* write back 1 status */
-		    unsigned long  faddr;    /* fault address */
-		    unsigned long  wb3a;     /* write back 3 address */
-		    unsigned long  wb3d;     /* write back 3 data */
-		    unsigned long  wb2a;     /* write back 2 address */
-		    unsigned long  wb2d;     /* write back 2 data */
-		    unsigned long  wb1a;     /* write back 1 address */
-		    unsigned long  wb1dpd0;  /* write back 1 data/push data 0*/
-		    unsigned long  pd1;      /* push data 1*/
-		    unsigned long  pd2;      /* push data 2*/
-		    unsigned long  pd3;      /* push data 3*/
-	    } fmt7;
-	    struct {
-		    unsigned long  iaddr;    /* instruction address */
-		    unsigned short int1[4];  /* internal registers */
-	    } fmt9;
-	    struct {
-		    unsigned short int1;
-		    unsigned short ssw;      /* special status word */
-		    unsigned short isc;      /* instruction stage c */
-		    unsigned short isb;      /* instruction stage b */
-		    unsigned long  daddr;    /* data cycle fault address */
-		    unsigned short int2[2];
-		    unsigned long  dobuf;    /* data cycle output buffer */
-		    unsigned short int3[2];
-	    } fmta;
-	    struct {
-		    unsigned short int1;
-		    unsigned short ssw;     /* special status word */
-		    unsigned short isc;     /* instruction stage c */
-		    unsigned short isb;     /* instruction stage b */
-		    unsigned long  daddr;   /* data cycle fault address */
-		    unsigned short int2[2];
-		    unsigned long  dobuf;   /* data cycle output buffer */
-		    unsigned short int3[4];
-		    unsigned long  baddr;   /* stage B address */
-		    unsigned short int4[2];
-		    unsigned long  dibuf;   /* data cycle input buffer */
-		    unsigned short int5[3];
-		    unsigned	   ver : 4; /* stack frame version # */
-		    unsigned	   int6:12;
-		    unsigned short int7[18];
-	    } fmtb;
-    } un;
-};
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _M68KNOMMU_TRAPS_H */
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 303730a..b3963ab 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -359,12 +359,6 @@
 		isa_type = ISA_TYPE_Q40;
 		isa_sex = 0;
 	}
-#ifdef CONFIG_GG2
-	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)) {
-		isa_type = ISA_TYPE_GG2;
-		isa_sex = 0;
-	}
-#endif
 #ifdef CONFIG_AMIGA_PCMCIA
 	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
 		isa_type = ISA_TYPE_AG;
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 2f431ec..3db2e7f 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
@@ -377,7 +376,6 @@
 	struct vm_area_struct *vma;
 	int ret = -EINVAL;
 
-	lock_kernel();
 	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
 	    cache & ~FLUSH_CACHE_BOTH)
 		goto out;
@@ -446,7 +444,6 @@
 	    }
 	}
 out:
-	unlock_kernel();
 	return ret;
 }
 
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 4926b38..06438da 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -42,9 +42,7 @@
 static irqreturn_t timer_interrupt(int irq, void *dummy)
 {
 	do_timer(1);
-#ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
-#endif
 	profile_tick(CPU_PROFILING);
 
 #ifdef CONFIG_HEARTBEAT
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index 11ac6f6..39c79eb 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -144,6 +144,7 @@
 	.unlocked_ioctl	= rtc_ioctl,
 	.open		= rtc_open,
 	.release	= rtc_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice rtc_dev=
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index ad90393..2d9e21b 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -67,9 +67,7 @@
 	intersil_clear();
 #endif
         do_timer(1);
-#ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
-#endif
         if (!(kstat_cpu(0).irqs[irq] % 20))
                 sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
 	return IRQ_HANDLED;
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index a90acf5..7089dd9 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -50,9 +50,8 @@
 
 	write_sequnlock(&xtime_lock);
 
-#ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
-#endif
+
 	return(IRQ_HANDLED);
 }
 #endif
diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68knommu/platform/coldfire/entry.S
index dd7d591..cd79d7e 100644
--- a/arch/m68knommu/platform/coldfire/entry.S
+++ b/arch/m68knommu/platform/coldfire/entry.S
@@ -112,7 +112,7 @@
 	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
 	movel	%d1,%a0
 	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
-	andl	#_TIF_NEED_RESCHED,%d1
+	andl	#(1<<TIF_NEED_RESCHED),%d1
 	jeq	Lkernel_return
 
 	movel	%a0@(TI_PREEMPTCOUNT),%d1
@@ -136,7 +136,7 @@
 	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
 	movel	%d1,%a0
 	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
-	andl	#_TIF_WORK_MASK,%d1
+	andl	#0xefff,%d1
 	jne	Lwork_to_do		/* still work to do */
 
 Lreturn:
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c
index 1dc55ee..3691630 100644
--- a/arch/mips/alchemy/common/platform.c
+++ b/arch/mips/alchemy/common/platform.c
@@ -24,6 +24,33 @@
 
 #include <prom.h>
 
+static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
+			    unsigned int old_state)
+{
+	switch (state) {
+	case 0:
+		if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
+			/* power-on sequence as suggested in the databooks */
+			__raw_writel(0, port->membase + UART_MOD_CNTRL);
+			wmb();
+			__raw_writel(1, port->membase + UART_MOD_CNTRL);
+			wmb();
+		}
+		__raw_writel(3, port->membase + UART_MOD_CNTRL); /* full on */
+		wmb();
+		serial8250_do_pm(port, state, old_state);
+		break;
+	case 3:		/* power off */
+		serial8250_do_pm(port, state, old_state);
+		__raw_writel(0, port->membase + UART_MOD_CNTRL);
+		wmb();
+		break;
+	default:
+		serial8250_do_pm(port, state, old_state);
+		break;
+	}
+}
+
 #define PORT(_base, _irq)					\
 	{							\
 		.mapbase	= _base,			\
@@ -33,6 +60,7 @@
 		.flags		= UPF_SKIP_TEST | UPF_IOREMAP |	\
 				  UPF_FIXED_TYPE,		\
 		.type		= PORT_16550A,			\
+		.pm		= alchemy_8250_pm,		\
 	}
 
 static struct plat_serial8250_port au1x00_uart_data[] = {
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index 5ef06a1..e5916a5 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -49,11 +49,6 @@
  * We only have to save/restore registers that aren't otherwise
  * done as part of a driver pm_* function.
  */
-static unsigned int sleep_uart0_inten;
-static unsigned int sleep_uart0_fifoctl;
-static unsigned int sleep_uart0_linectl;
-static unsigned int sleep_uart0_clkdiv;
-static unsigned int sleep_uart0_enable;
 static unsigned int sleep_usb[2];
 static unsigned int sleep_sys_clocks[5];
 static unsigned int sleep_sys_pinfunc;
@@ -62,22 +57,6 @@
 
 static void save_core_regs(void)
 {
-	extern void save_au1xxx_intctl(void);
-	extern void pm_eth0_shutdown(void);
-
-	/*
-	 * Do the serial ports.....these really should be a pm_*
-	 * registered function by the driver......but of course the
-	 * standard serial driver doesn't understand our Au1xxx
-	 * unique registers.
-	 */
-	sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER);
-	sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR);
-	sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
-	sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
-	sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
-	au_sync();
-
 #ifndef CONFIG_SOC_AU1200
 	/* Shutdown USB host/device. */
 	sleep_usb[0] = au_readl(USB_HOST_CONFIG);
@@ -175,20 +154,6 @@
 	au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
 	au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
 	au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
-
-	/*
-	 * Enable the UART if it was enabled before sleep.
-	 * I guess I should define module control bits........
-	 */
-	if (sleep_uart0_enable & 0x02) {
-		au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync();
-		au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync();
-		au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync();
-		au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync();
-		au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync();
-		au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync();
-		au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync();
-	}
 }
 
 void au_sleep(void)
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 26f9b9a..557ef72 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -468,7 +468,8 @@
 	.release = file_release,
 	.write =   file_write,
 	.read =    file_read,
-	.poll =    file_poll
+	.poll =    file_poll,
+	.llseek =  noop_llseek,
 };
 
 static struct irqaction rtlx_irq = {
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 2bd2151..3eb3cde 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1192,7 +1192,8 @@
 	.owner = THIS_MODULE,
 	.open = vpe_open,
 	.release = vpe_release,
-	.write = vpe_write
+	.write = vpe_write,
+	.llseek = noop_llseek,
 };
 
 /* module wrapper entry points */
diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c
index d4ed7a9..ca35b73 100644
--- a/arch/mips/sibyte/common/sb_tbprof.c
+++ b/arch/mips/sibyte/common/sb_tbprof.c
@@ -545,6 +545,7 @@
 	.unlocked_ioctl	= sbprof_tb_ioctl,
 	.compat_ioctl	= sbprof_tb_ioctl,
 	.mmap		= NULL,
+	.llseek		= default_llseek,
 };
 
 static struct class *tb_class;
diff --git a/arch/mn10300/include/asm/ioctls.h b/arch/mn10300/include/asm/ioctls.h
index cb8cf19..0212f4b 100644
--- a/arch/mn10300/include/asm/ioctls.h
+++ b/arch/mn10300/include/asm/ioctls.h
@@ -1,88 +1,6 @@
 #ifndef _ASM_IOCTLS_H
 #define _ASM_IOCTLS_H
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T', 0x2A, struct termios2)
-#define TCSETS2		_IOW('T', 0x2B, struct termios2)
-#define TCSETSW2	_IOW('T', 0x2C, struct termios2)
-#define TCSETSF2	_IOW('T', 0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T', 0x30, unsigned int) /* Get Pty Number
-						       * (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T', 0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T', 0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-#define FIOQSIZE	0x5460
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif /* _ASM_IOCTLS_H */
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index f9f6783..ba0c053 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -46,7 +46,6 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
@@ -261,16 +260,13 @@
  */
 static int perf_open(struct inode *inode, struct file *file)
 {
-	lock_kernel();
 	spin_lock(&perf_lock);
 	if (perf_enabled) {
 		spin_unlock(&perf_lock);
-		unlock_kernel();
 		return -EBUSY;
 	}
 	perf_enabled = 1;
  	spin_unlock(&perf_lock);
-	unlock_kernel();
 
 	return 0;
 }
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 8d9e3b9..1646836 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -780,6 +780,7 @@
 	.write		= lparcfg_write,
 	.open		= lparcfg_open,
 	.release	= single_release,
+	.llseek		= seq_lseek,
 };
 
 static int __init lparcfg_init(void)
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 67a84d8..2b442e6 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -716,6 +716,7 @@
 	.write		= rtas_flash_write,
 	.open		= rtas_excl_open,
 	.release	= rtas_flash_release,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations manage_flash_operations = {
@@ -724,6 +725,7 @@
 	.write		= manage_flash_write,
 	.open		= rtas_excl_open,
 	.release	= rtas_excl_release,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations validate_flash_operations = {
@@ -732,6 +734,7 @@
 	.write		= validate_flash_write,
 	.open		= rtas_excl_open,
 	.release	= validate_flash_release,
+	.llseek		= default_llseek,
 };
 
 static int __init rtas_flash_init(void)
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 638883e..0438f81 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -354,6 +354,7 @@
 	.poll =		rtas_log_poll,
 	.open =		rtas_log_open,
 	.release =	rtas_log_release,
+	.llseek =	noop_llseek,
 };
 
 static int enable_surveillance(int timeout)
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index 33e5fc7..42d0a88 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -1249,6 +1249,7 @@
 
 static const struct file_operations proc_vmlinux_operations = {
 	.write		= proc_mf_change_vmlinux,
+	.llseek		= default_llseek,
 };
 
 static int __init mf_proc_init(void)
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 57ddbb4..1de2cbb 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -539,7 +539,8 @@
 }
 
 static const struct file_operations ofdt_fops = {
-	.write = ofdt_write
+	.write = ofdt_write,
+	.llseek = noop_llseek,
 };
 
 /* create /proc/powerpc/ofdt write-only by root */
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 80e9e76..5544572 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -170,6 +170,7 @@
 	.write		= scanlog_write,
 	.open		= scanlog_open,
 	.release	= scanlog_release,
+	.llseek		= noop_llseek,
 };
 
 static int __init scanlog_init(void)
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 6c67d9e..19e5015 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -209,169 +209,6 @@
 arch_initcall(of_add_fixed_phys);
 #endif /* CONFIG_FIXED_PHY */
 
-static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
-{
-	if (!phy_type)
-		return FSL_USB2_PHY_NONE;
-	if (!strcasecmp(phy_type, "ulpi"))
-		return FSL_USB2_PHY_ULPI;
-	if (!strcasecmp(phy_type, "utmi"))
-		return FSL_USB2_PHY_UTMI;
-	if (!strcasecmp(phy_type, "utmi_wide"))
-		return FSL_USB2_PHY_UTMI_WIDE;
-	if (!strcasecmp(phy_type, "serial"))
-		return FSL_USB2_PHY_SERIAL;
-
-	return FSL_USB2_PHY_NONE;
-}
-
-static int __init fsl_usb_of_init(void)
-{
-	struct device_node *np;
-	unsigned int i = 0;
-	struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
-		*usb_dev_dr_client = NULL;
-	int ret;
-
-	for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
-		struct resource r[2];
-		struct fsl_usb2_platform_data usb_data;
-		const unsigned char *prop = NULL;
-
-		memset(&r, 0, sizeof(r));
-		memset(&usb_data, 0, sizeof(usb_data));
-
-		ret = of_address_to_resource(np, 0, &r[0]);
-		if (ret)
-			goto err;
-
-		of_irq_to_resource(np, 0, &r[1]);
-
-		usb_dev_mph =
-		    platform_device_register_simple("fsl-ehci", i, r, 2);
-		if (IS_ERR(usb_dev_mph)) {
-			ret = PTR_ERR(usb_dev_mph);
-			goto err;
-		}
-
-		usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
-		usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
-
-		usb_data.operating_mode = FSL_USB2_MPH_HOST;
-
-		prop = of_get_property(np, "port0", NULL);
-		if (prop)
-			usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
-
-		prop = of_get_property(np, "port1", NULL);
-		if (prop)
-			usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
-
-		prop = of_get_property(np, "phy_type", NULL);
-		usb_data.phy_mode = determine_usb_phy(prop);
-
-		ret =
-		    platform_device_add_data(usb_dev_mph, &usb_data,
-					     sizeof(struct
-						    fsl_usb2_platform_data));
-		if (ret)
-			goto unreg_mph;
-		i++;
-	}
-
-	for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
-		struct resource r[2];
-		struct fsl_usb2_platform_data usb_data;
-		const unsigned char *prop = NULL;
-
-		if (!of_device_is_available(np))
-			continue;
-
-		memset(&r, 0, sizeof(r));
-		memset(&usb_data, 0, sizeof(usb_data));
-
-		ret = of_address_to_resource(np, 0, &r[0]);
-		if (ret)
-			goto unreg_mph;
-
-		of_irq_to_resource(np, 0, &r[1]);
-
-		prop = of_get_property(np, "dr_mode", NULL);
-
-		if (!prop || !strcmp(prop, "host")) {
-			usb_data.operating_mode = FSL_USB2_DR_HOST;
-			usb_dev_dr_host = platform_device_register_simple(
-					"fsl-ehci", i, r, 2);
-			if (IS_ERR(usb_dev_dr_host)) {
-				ret = PTR_ERR(usb_dev_dr_host);
-				goto err;
-			}
-		} else if (prop && !strcmp(prop, "peripheral")) {
-			usb_data.operating_mode = FSL_USB2_DR_DEVICE;
-			usb_dev_dr_client = platform_device_register_simple(
-					"fsl-usb2-udc", i, r, 2);
-			if (IS_ERR(usb_dev_dr_client)) {
-				ret = PTR_ERR(usb_dev_dr_client);
-				goto err;
-			}
-		} else if (prop && !strcmp(prop, "otg")) {
-			usb_data.operating_mode = FSL_USB2_DR_OTG;
-			usb_dev_dr_host = platform_device_register_simple(
-					"fsl-ehci", i, r, 2);
-			if (IS_ERR(usb_dev_dr_host)) {
-				ret = PTR_ERR(usb_dev_dr_host);
-				goto err;
-			}
-			usb_dev_dr_client = platform_device_register_simple(
-					"fsl-usb2-udc", i, r, 2);
-			if (IS_ERR(usb_dev_dr_client)) {
-				ret = PTR_ERR(usb_dev_dr_client);
-				goto err;
-			}
-		} else {
-			ret = -EINVAL;
-			goto err;
-		}
-
-		prop = of_get_property(np, "phy_type", NULL);
-		usb_data.phy_mode = determine_usb_phy(prop);
-
-		if (usb_dev_dr_host) {
-			usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
-			usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
-				dev.coherent_dma_mask;
-			if ((ret = platform_device_add_data(usb_dev_dr_host,
-						&usb_data, sizeof(struct
-						fsl_usb2_platform_data))))
-				goto unreg_dr;
-		}
-		if (usb_dev_dr_client) {
-			usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
-			usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
-				dev.coherent_dma_mask;
-			if ((ret = platform_device_add_data(usb_dev_dr_client,
-						&usb_data, sizeof(struct
-						fsl_usb2_platform_data))))
-				goto unreg_dr;
-		}
-		i++;
-	}
-	return 0;
-
-unreg_dr:
-	if (usb_dev_dr_host)
-		platform_device_unregister(usb_dev_dr_host);
-	if (usb_dev_dr_client)
-		platform_device_unregister(usb_dev_dr_client);
-unreg_mph:
-	if (usb_dev_mph)
-		platform_device_unregister(usb_dev_mph);
-err:
-	return ret;
-}
-
-arch_initcall(fsl_usb_of_init);
-
 #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
 static __be32 __iomem *rstcr;
 
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
index aa819da..975e3ab 100644
--- a/arch/s390/crypto/prng.c
+++ b/arch/s390/crypto/prng.c
@@ -152,6 +152,7 @@
 	.open		= &prng_open,
 	.release	= NULL,
 	.read		= &prng_read,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice prng_dev = {
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 1211bb1..020e51c 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -618,6 +618,7 @@
 	.open		= dbfs_d204_open,
 	.read		= dbfs_d204_read,
 	.release	= dbfs_d204_release,
+	.llseek		= no_llseek,
 };
 
 static int hypfs_dbfs_init(void)
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
index ee5ab1a..26cf177 100644
--- a/arch/s390/hypfs/hypfs_vm.c
+++ b/arch/s390/hypfs/hypfs_vm.c
@@ -275,6 +275,7 @@
 	.open		= dbfs_d2fc_open,
 	.read		= dbfs_d2fc_read,
 	.release	= dbfs_d2fc_release,
+	.llseek		= no_llseek,
 };
 
 int hypfs_vm_init(void)
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 98a4a4c..74d9867 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -449,6 +449,7 @@
 	.write		= do_sync_write,
 	.aio_read	= hypfs_aio_read,
 	.aio_write	= hypfs_aio_write,
+	.llseek		= no_llseek,
 };
 
 static struct file_system_type hypfs_type = {
diff --git a/arch/s390/include/asm/ioctls.h b/arch/s390/include/asm/ioctls.h
index 2f3d873..960a4c1 100644
--- a/arch/s390/include/asm/ioctls.h
+++ b/arch/s390/include/asm/ioctls.h
@@ -1,94 +1,8 @@
-/*
- *  include/asm-s390/ioctls.h
- *
- *  S390 version
- *
- *  Derived from "include/asm-i386/ioctls.h"
- */
-
 #ifndef __ARCH_S390_IOCTLS_H__
 #define __ARCH_S390_IOCTLS_H__
 
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS		0x5401
-#define TCSETS		0x5402
-#define TCSETSW		0x5403
-#define TCSETSF		0x5404
-#define TCGETA		0x5405
-#define TCSETA		0x5406
-#define TCSETAW		0x5407
-#define TCSETAF		0x5408
-#define TCSBRK		0x5409
-#define TCXONC		0x540A
-#define TCFLSH		0x540B
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-#define TIOCGPGRP	0x540F
-#define TIOCSPGRP	0x5410
-#define TIOCOUTQ	0x5411
-#define TIOCSTI		0x5412
-#define TIOCGWINSZ	0x5413
-#define TIOCSWINSZ	0x5414
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define FIONREAD	0x541B
-#define TIOCINQ		FIONREAD
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-#define FIONBIO		0x5421
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK	0x5427  /* BSD compatibility */
-#define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
-#define TCGETS2		_IOR('T',0x2A, struct termios2)
-#define TCSETS2		_IOW('T',0x2B, struct termios2)
-#define TCSETSW2	_IOW('T',0x2C, struct termios2)
-#define TCSETSF2	_IOW('T',0x2D, struct termios2)
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
-
-#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX		0x5451
-#define FIOASYNC	0x5452
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define FIOQSIZE	0x545E
 
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-#define TIOCPKT_IOCTL		64
-
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#include <asm-generic/ioctls.h>
 
 #endif
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 9819226..5ad6bc0 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -174,6 +174,7 @@
 	.write   = debug_input,
 	.open    = debug_open,
 	.release = debug_close,
+	.llseek  = no_llseek,
 };
 
 static struct dentry *debug_debugfs_root_entry;
diff --git a/arch/sh/boards/mach-landisk/gio.c b/arch/sh/boards/mach-landisk/gio.c
index 01e6abb..8132dff 100644
--- a/arch/sh/boards/mach-landisk/gio.c
+++ b/arch/sh/boards/mach-landisk/gio.c
@@ -128,6 +128,7 @@
 	.open = gio_open,	/* open */
 	.release = gio_close,	/* release */
 	.unlocked_ioctl = gio_ioctl,
+	.llseek = noop_llseek,
 };
 
 static int __init gio_init(void)
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c
index 2c0046e..52de4a9 100644
--- a/arch/sparc/kernel/apc.c
+++ b/arch/sparc/kernel/apc.c
@@ -132,6 +132,7 @@
 	.unlocked_ioctl =	apc_ioctl,
 	.open =			apc_open,
 	.release =		apc_release,
+	.llseek =		noop_llseek,
 };
 
 static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index 83e85c2..6addb91 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -890,6 +890,7 @@
 static const struct file_operations mdesc_fops = {
 	.read	= mdesc_read,
 	.owner	= THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice mdesc_misc = {
diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h
index 6832b4b..6d4f0ff 100644
--- a/arch/tile/include/asm/bitops.h
+++ b/arch/tile/include/asm/bitops.h
@@ -120,6 +120,7 @@
 
 #include <asm-generic/bitops/const_hweight.h>
 #include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/ext2-non-atomic.h>
 #include <asm-generic/bitops/minix.h>
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index 584b965..1e54a78 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -774,6 +774,7 @@
 #endif
 	.flush          = hardwall_flush,
 	.release        = hardwall_release,
+	.llseek		= noop_llseek,
 };
 
 static struct cdev hardwall_dev;
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index cfcac1f..2d0266d 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -42,7 +42,7 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
@@ -50,6 +50,7 @@
 
 MODULE_LICENSE("GPL");
 
+static DEFINE_MUTEX(harddog_mutex);
 static DEFINE_SPINLOCK(lock);
 static int timer_alive;
 static int harddog_in_fd = -1;
@@ -66,7 +67,7 @@
 	int err = -EBUSY;
 	char *sock = NULL;
 
-	lock_kernel();
+	mutex_lock(&harddog_mutex);
 	spin_lock(&lock);
 	if(timer_alive)
 		goto err;
@@ -83,11 +84,11 @@
 
 	timer_alive = 1;
 	spin_unlock(&lock);
-	unlock_kernel();
+	mutex_unlock(&harddog_mutex);
 	return nonseekable_open(inode, file);
 err:
 	spin_unlock(&lock);
-	unlock_kernel();
+	mutex_unlock(&harddog_mutex);
 	return err;
 }
 
@@ -153,9 +154,9 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&harddog_mutex);
 	ret = harddog_ioctl_unlocked(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&harddog_mutex);
 
 	return ret;
 }
@@ -166,6 +167,7 @@
 	.unlocked_ioctl	= harddog_ioctl,
 	.open		= harddog_open,
 	.release	= harddog_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice harddog_miscdev = {
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 63c740a..f9f6a4e 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -8,7 +8,7 @@
 #include "linux/slab.h"
 #include "linux/sound.h"
 #include "linux/soundcard.h"
-#include "linux/smp_lock.h"
+#include "linux/mutex.h"
 #include "asm/uaccess.h"
 #include "init.h"
 #include "os.h"
@@ -63,6 +63,8 @@
 __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
 #endif
 
+static DEFINE_MUTEX(hostaudio_mutex);
+
 /* /dev/dsp file operations */
 
 static ssize_t hostaudio_read(struct file *file, char __user *buffer,
@@ -198,9 +200,9 @@
 		w = 1;
 
 	kparam_block_sysfs_write(dsp);
-	lock_kernel();
+	mutex_lock(&hostaudio_mutex);
 	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-	unlock_kernel();
+	mutex_unlock(&hostaudio_mutex);
 	kparam_unblock_sysfs_write(dsp);
 
 	if (ret < 0) {
@@ -259,9 +261,9 @@
 		w = 1;
 
 	kparam_block_sysfs_write(mixer);
-	lock_kernel();
+	mutex_lock(&hostaudio_mutex);
 	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
-	unlock_kernel();
+	mutex_unlock(&hostaudio_mutex);
 	kparam_unblock_sysfs_write(mixer);
 
 	if (ret < 0) {
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index ebc6807..975613b 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -843,6 +843,7 @@
 static const struct file_operations mconsole_proc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= mconsole_proc_write,
+	.llseek		= noop_llseek,
 };
 
 static int create_proc_mconsole(void)
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 7158393..8501e7d 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -93,6 +93,7 @@
 	.mmap		= mmapper_mmap,
 	.open		= mmapper_open,
 	.release	= mmapper_release,
+	.llseek		= default_llseek,
 };
 
 /*
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 4949044..981085a 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -100,6 +100,7 @@
 	.owner		= THIS_MODULE,
 	.open		= rng_dev_open,
 	.read		= rng_dev_read,
+	.llseek		= noop_llseek,
 };
 
 /* rng_init shouldn't be called more than once at boot time */
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 9734994..ba4a98b 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -33,7 +33,7 @@
 #include "linux/mm.h"
 #include "linux/slab.h"
 #include "linux/vmalloc.h"
-#include "linux/smp_lock.h"
+#include "linux/mutex.h"
 #include "linux/blkpg.h"
 #include "linux/genhd.h"
 #include "linux/spinlock.h"
@@ -100,6 +100,7 @@
 #define DRIVER_NAME "uml-blkdev"
 
 static DEFINE_MUTEX(ubd_lock);
+static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */
 
 static int ubd_open(struct block_device *bdev, fmode_t mode);
 static int ubd_release(struct gendisk *disk, fmode_t mode);
@@ -1101,7 +1102,7 @@
 	struct ubd *ubd_dev = disk->private_data;
 	int err = 0;
 
-	lock_kernel();
+	mutex_lock(&ubd_mutex);
 	if(ubd_dev->count == 0){
 		err = ubd_open_dev(ubd_dev);
 		if(err){
@@ -1120,7 +1121,7 @@
 	        err = -EROFS;
 	}*/
 out:
-	unlock_kernel();
+	mutex_unlock(&ubd_mutex);
 	return err;
 }
 
@@ -1128,10 +1129,10 @@
 {
 	struct ubd *ubd_dev = disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&ubd_mutex);
 	if(--ubd_dev->count == 0)
 		ubd_close_dev(ubd_dev);
-	unlock_kernel();
+	mutex_unlock(&ubd_mutex);
 	return 0;
 }
 
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 49b5e1e..340268b 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -78,13 +78,11 @@
 	long error;
 	char *filename;
 
-	lock_kernel();
 	filename = getname(file);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename)) goto out;
 	error = execve1(filename, argv, env);
 	putname(filename);
  out:
-	unlock_kernel();
 	return error;
 }
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index e5bb96b..b59ee76 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -125,16 +125,6 @@
 	  and the software setup of this feature.
 	  If in doubt, say "N"
 
-config 4KSTACKS
-	bool "Use 4Kb for kernel stacks instead of 8Kb"
-	depends on X86_32
-	---help---
-	  If you say Y here the kernel will use a 4Kb stacksize for the
-	  kernel stack attached to each process/thread. This facilitates
-	  running more threads on a system and also reduces the pressure
-	  on the VM subsystem for higher order allocations. This option
-	  will also use IRQ stacks to compensate for the reduced stackspace.
-
 config DOUBLEFAULT
 	default y
 	bool "Enable doublefault exception handler" if EMBEDDED
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index bafd80d..903683b0 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -440,6 +440,8 @@
 
 #ifdef __KERNEL__
 
+#include <asm-generic/bitops/find.h>
+
 #include <asm-generic/bitops/sched.h>
 
 #define ARCH_HAS_FAST_MULTIPLIER 1
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 5458380..0bf5b00 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -19,18 +19,16 @@
 # define ARCH_HAS_NMI_WATCHDOG
 #endif
 
-#ifdef CONFIG_4KSTACKS
-  extern void irq_ctx_init(int cpu);
-  extern void irq_ctx_exit(int cpu);
-# define __ARCH_HAS_DO_SOFTIRQ
+#ifdef CONFIG_X86_32
+extern void irq_ctx_init(int cpu);
+extern void irq_ctx_exit(int cpu);
 #else
 # define irq_ctx_init(cpu) do { } while (0)
 # define irq_ctx_exit(cpu) do { } while (0)
-# ifdef CONFIG_X86_64
-#  define __ARCH_HAS_DO_SOFTIRQ
-# endif
 #endif
 
+#define __ARCH_HAS_DO_SOFTIRQ
+
 #ifdef CONFIG_HOTPLUG_CPU
 #include <linux/cpumask.h>
 extern void fixup_irqs(void);
diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h
index 3e2ce58..67763c5 100644
--- a/arch/x86/include/asm/module.h
+++ b/arch/x86/include/asm/module.h
@@ -60,12 +60,7 @@
 #endif
 
 #ifdef CONFIG_X86_32
-# ifdef CONFIG_4KSTACKS
-#  define MODULE_STACKSIZE "4KSTACKS "
-# else
-#  define MODULE_STACKSIZE ""
-# endif
-# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE
+# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
 #endif
 
 #endif /* _ASM_X86_MODULE_H */
diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h
index 6f1b733..ade619f 100644
--- a/arch/x86/include/asm/page_32_types.h
+++ b/arch/x86/include/asm/page_32_types.h
@@ -15,11 +15,7 @@
  */
 #define __PAGE_OFFSET		_AC(CONFIG_PAGE_OFFSET, UL)
 
-#ifdef CONFIG_4KSTACKS
-#define THREAD_ORDER	0
-#else
 #define THREAD_ORDER	1
-#endif
 #define THREAD_SIZE 	(PAGE_SIZE << THREAD_ORDER)
 
 #define STACKFAULT_STACK 0
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index cd28f9a..f899e01 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -47,6 +47,20 @@
 #ifdef CONFIG_SMP
 #define __percpu_arg(x)		"%%"__stringify(__percpu_seg)":%P" #x
 #define __my_cpu_offset		percpu_read(this_cpu_off)
+
+/*
+ * Compared to the generic __my_cpu_offset version, the following
+ * saves one instruction and avoids clobbering a temp register.
+ */
+#define __this_cpu_ptr(ptr)				\
+({							\
+	unsigned long tcp_ptr__;			\
+	__verify_pcpu_ptr(ptr);				\
+	asm volatile("add " __percpu_arg(1) ", %0"	\
+		     : "=r" (tcp_ptr__)			\
+		     : "m" (this_cpu_off), "0" (ptr));	\
+	(typeof(*(ptr)) __kernel __force *)tcp_ptr__;	\
+})
 #else
 #define __percpu_arg(x)		"%P" #x
 #endif
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h
index f686f49..8abde9e 100644
--- a/arch/x86/include/asm/pgtable_32.h
+++ b/arch/x86/include/asm/pgtable_32.h
@@ -26,7 +26,7 @@
 struct vm_area_struct;
 
 extern pgd_t swapper_pg_dir[1024];
-extern pgd_t trampoline_pg_dir[1024];
+extern pgd_t initial_page_table[1024];
 
 static inline void pgtable_cache_init(void) { }
 static inline void check_pgt_cache(void) { }
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 7f3eba0..169be89 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -172,6 +172,4 @@
 	flush_tlb_all();
 }
 
-extern void zap_low_mappings(bool early);
-
 #endif /* _ASM_X86_TLBFLUSH_H */
diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h
index 4dde797..f4500fb 100644
--- a/arch/x86/include/asm/trampoline.h
+++ b/arch/x86/include/asm/trampoline.h
@@ -13,16 +13,13 @@
 
 extern unsigned long init_rsp;
 extern unsigned long initial_code;
-extern unsigned long initial_page_table;
 extern unsigned long initial_gs;
 
 #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE)
 
 extern unsigned long setup_trampoline(void);
-extern void __init setup_trampoline_page_table(void);
 extern void __init reserve_trampoline_memory(void);
 #else
-static inline void setup_trampoline_page_table(void) {}
 static inline void reserve_trampoline_memory(void) {}
 #endif /* CONFIG_X86_TRAMPOLINE */
 
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index e125207..74a84783 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -13,6 +13,11 @@
 #include <asm/segment.h>
 #include <asm/desc.h>
 
+#ifdef CONFIG_X86_32
+#include <asm/pgtable.h>
+#include <asm/pgtable_32.h>
+#endif
+
 #include "realmode/wakeup.h"
 #include "sleep.h"
 
@@ -91,7 +96,7 @@
 
 #ifndef CONFIG_64BIT
 	header->pmode_entry = (u32)&wakeup_pmode_return;
-	header->pmode_cr3 = (u32)(swsusp_pg_dir - __PAGE_OFFSET);
+	header->pmode_cr3 = (u32)__pa(&initial_page_table);
 	saved_magic = 0x12345678;
 #else /* CONFIG_64BIT */
 	header->trampoline_segment = setup_trampoline() >> 4;
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 4c9c67b..fbbc4da 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1926,6 +1926,7 @@
 	.unlocked_ioctl	= do_ioctl,
 	.open		= do_open,
 	.release	= do_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice apm_device = {
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 8a85dd1..1e8d66c 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -192,6 +192,7 @@
 	.release	= seq_release,
 	.read		= seq_read,
 	.write		= severities_coverage_write,
+	.llseek		= seq_lseek,
 };
 
 static int __init severities_debugfs_init(void)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index ed41562..7a35b72 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1665,6 +1665,7 @@
 	.read			= mce_read,
 	.poll			= mce_poll,
 	.unlocked_ioctl		= mce_ioctl,
+	.llseek		= no_llseek,
 };
 EXPORT_SYMBOL_GPL(mce_chrdev_ops);
 
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 9a6ca23..7633101 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -18,6 +18,7 @@
 #include <asm/apic.h>
 #include <asm/io_apic.h>
 #include <asm/bios_ebda.h>
+#include <asm/tlbflush.h>
 
 static void __init i386_default_early_setup(void)
 {
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index fa8c1b8..bcece91 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -183,13 +183,12 @@
 #ifdef CONFIG_X86_PAE
 
 	/*
-	 * In PAE mode swapper_pg_dir is statically defined to contain enough
-	 * entries to cover the VMSPLIT option (that is the top 1, 2 or 3
-	 * entries). The identity mapping is handled by pointing two PGD
-	 * entries to the first kernel PMD.
+	 * In PAE mode initial_page_table is statically defined to contain
+	 * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+	 * entries). The identity mapping is handled by pointing two PGD entries
+	 * to the first kernel PMD.
 	 *
-	 * Note the upper half of each PMD or PTE are always zero at
-	 * this stage.
+	 * Note the upper half of each PMD or PTE are always zero at this stage.
 	 */
 
 #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
@@ -197,7 +196,7 @@
 	xorl %ebx,%ebx				/* %ebx is kept at zero */
 
 	movl $pa(__brk_base), %edi
-	movl $pa(swapper_pg_pmd), %edx
+	movl $pa(initial_pg_pmd), %edx
 	movl $PTE_IDENT_ATTR, %eax
 10:
 	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PMD entry */
@@ -226,14 +225,14 @@
 	movl %eax, pa(max_pfn_mapped)
 
 	/* Do early initialization of the fixmap area */
-	movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
-	movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8)
+	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+	movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
 #else	/* Not PAE */
 
 page_pde_offset = (__PAGE_OFFSET >> 20);
 
 	movl $pa(__brk_base), %edi
-	movl $pa(swapper_pg_dir), %edx
+	movl $pa(initial_page_table), %edx
 	movl $PTE_IDENT_ATTR, %eax
 10:
 	leal PDE_IDENT_ATTR(%edi),%ecx		/* Create PDE entry */
@@ -257,8 +256,8 @@
 	movl %eax, pa(max_pfn_mapped)
 
 	/* Do early initialization of the fixmap area */
-	movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
-	movl %eax,pa(swapper_pg_dir+0xffc)
+	movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+	movl %eax,pa(initial_page_table+0xffc)
 #endif
 	jmp 3f
 /*
@@ -334,7 +333,7 @@
 /*
  * Enable paging
  */
-	movl pa(initial_page_table), %eax
+	movl $pa(initial_page_table), %eax
 	movl %eax,%cr3		/* set the page table pointer.. */
 	movl %cr0,%eax
 	orl  $X86_CR0_PG,%eax
@@ -614,8 +613,6 @@
 .align 4
 ENTRY(initial_code)
 	.long i386_start_kernel
-ENTRY(initial_page_table)
-	.long pa(swapper_pg_dir)
 
 /*
  * BSS section
@@ -623,20 +620,18 @@
 __PAGE_ALIGNED_BSS
 	.align PAGE_SIZE_asm
 #ifdef CONFIG_X86_PAE
-swapper_pg_pmd:
+initial_pg_pmd:
 	.fill 1024*KPMDS,4,0
 #else
-ENTRY(swapper_pg_dir)
+ENTRY(initial_page_table)
 	.fill 1024,4,0
 #endif
-swapper_pg_fixmap:
+initial_pg_fixmap:
 	.fill 1024,4,0
-#ifdef CONFIG_X86_TRAMPOLINE
-ENTRY(trampoline_pg_dir)
-	.fill 1024,4,0
-#endif
 ENTRY(empty_zero_page)
 	.fill 4096,1,0
+ENTRY(swapper_pg_dir)
+	.fill 1024,4,0
 
 /*
  * This starts the data section.
@@ -645,20 +640,20 @@
 __PAGE_ALIGNED_DATA
 	/* Page-aligned for the benefit of paravirt? */
 	.align PAGE_SIZE_asm
-ENTRY(swapper_pg_dir)
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR),0	/* low identity map */
+ENTRY(initial_page_table)
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0	/* low identity map */
 # if KPMDS == 3
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x2000),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x2000),0
 # elif KPMDS == 2
 	.long	0,0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR+0x1000),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR+0x1000),0
 # elif KPMDS == 1
 	.long	0,0
 	.long	0,0
-	.long	pa(swapper_pg_pmd+PGD_IDENT_ATTR),0
+	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0
 # else
 #  error "Kernel PMDs should be 1, 2 or 3"
 # endif
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index efaf906..aff0b3c 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -380,44 +380,35 @@
 			   struct clock_event_device *evt, int timer)
 {
 	u32 cnt;
+	s32 res;
 
 	cnt = hpet_readl(HPET_COUNTER);
 	cnt += (u32) delta;
 	hpet_writel(cnt, HPET_Tn_CMP(timer));
 
 	/*
-	 * We need to read back the CMP register on certain HPET
-	 * implementations (ATI chipsets) which seem to delay the
-	 * transfer of the compare register into the internal compare
-	 * logic. With small deltas this might actually be too late as
-	 * the counter could already be higher than the compare value
-	 * at that point and we would wait for the next hpet interrupt
-	 * forever. We found out that reading the CMP register back
-	 * forces the transfer so we can rely on the comparison with
-	 * the counter register below. If the read back from the
-	 * compare register does not match the value we programmed
-	 * then we might have a real hardware problem. We can not do
-	 * much about it here, but at least alert the user/admin with
-	 * a prominent warning.
-	 *
-	 * An erratum on some chipsets (ICH9,..), results in
-	 * comparator read immediately following a write returning old
-	 * value. Workaround for this is to read this value second
-	 * time, when first read returns old value.
-	 *
-	 * In fact the write to the comparator register is delayed up
-	 * to two HPET cycles so the workaround we tried to restrict
-	 * the readback to those known to be borked ATI chipsets
-	 * failed miserably. So we give up on optimizations forever
-	 * and penalize all HPET incarnations unconditionally.
+	 * HPETs are a complete disaster. The compare register is
+	 * based on a equal comparison and neither provides a less
+	 * than or equal functionality (which would require to take
+	 * the wraparound into account) nor a simple count down event
+	 * mode. Further the write to the comparator register is
+	 * delayed internally up to two HPET clock cycles in certain
+	 * chipsets (ATI, ICH9,10). We worked around that by reading
+	 * back the compare register, but that required another
+	 * workaround for ICH9,10 chips where the first readout after
+	 * write can return the old stale value. We already have a
+	 * minimum delta of 5us enforced, but a NMI or SMI hitting
+	 * between the counter readout and the comparator write can
+	 * move us behind that point easily. Now instead of reading
+	 * the compare register back several times, we make the ETIME
+	 * decision based on the following: Return ETIME if the
+	 * counter value after the write is less than 8 HPET cycles
+	 * away from the event or if the counter is already ahead of
+	 * the event.
 	 */
-	if (unlikely((u32)hpet_readl(HPET_Tn_CMP(timer)) != cnt)) {
-		if (hpet_readl(HPET_Tn_CMP(timer)) != cnt)
-			printk_once(KERN_WARNING
-				"hpet: compare register read back failed.\n");
-	}
+	res = (s32)(cnt - hpet_readl(HPET_COUNTER));
 
-	return (s32)(hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
+	return res < 8 ? -ETIME : 0;
 }
 
 static void hpet_legacy_set_mode(enum clock_event_mode mode,
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 10709f2..50fbbe6 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -49,20 +49,19 @@
 static inline void print_stack_overflow(void) { }
 #endif
 
-#ifdef CONFIG_4KSTACKS
 /*
  * per-CPU IRQ handling contexts (thread information and stack)
  */
 union irq_ctx {
 	struct thread_info      tinfo;
 	u32                     stack[THREAD_SIZE/sizeof(u32)];
-} __attribute__((aligned(PAGE_SIZE)));
+} __attribute__((aligned(THREAD_SIZE)));
 
 static DEFINE_PER_CPU(union irq_ctx *, hardirq_ctx);
 static DEFINE_PER_CPU(union irq_ctx *, softirq_ctx);
 
-static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, hardirq_stack);
-static DEFINE_PER_CPU_PAGE_ALIGNED(union irq_ctx, softirq_stack);
+static DEFINE_PER_CPU_MULTIPAGE_ALIGNED(union irq_ctx, hardirq_stack, THREAD_SIZE);
+static DEFINE_PER_CPU_MULTIPAGE_ALIGNED(union irq_ctx, softirq_stack, THREAD_SIZE);
 
 static void call_on_stack(void *func, void *stack)
 {
@@ -187,11 +186,6 @@
 	local_irq_restore(flags);
 }
 
-#else
-static inline int
-execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; }
-#endif
-
 bool handle_irq(unsigned irq, struct pt_regs *regs)
 {
 	struct irq_desc *desc;
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index 8afd9f3..90fcf62 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -78,6 +78,7 @@
 static const struct file_operations fops_setup_data = {
 	.read		= setup_data_read,
 	.open		= setup_data_open,
+	.llseek		= default_llseek,
 };
 
 static int __init
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 852b819..d81cfeb 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -477,8 +477,6 @@
 				   raw_smp_processor_id());
 		}
 
-		kgdb_correct_hw_break();
-
 		return 0;
 	}
 
@@ -621,7 +619,12 @@
 static void kgdb_hw_overflow_handler(struct perf_event *event, int nmi,
 		struct perf_sample_data *data, struct pt_regs *regs)
 {
-	kgdb_ll_trap(DIE_DEBUG, "debug", regs, 0, 0, SIGTRAP);
+	struct task_struct *tsk = current;
+	int i;
+
+	for (i = 0; i < 4; i++)
+		if (breakinfo[i].enabled)
+			tsk->thread.debugreg6 |= (DR_TRAP0 << i);
 }
 
 void kgdb_arch_late(void)
@@ -644,7 +647,7 @@
 		if (breakinfo[i].pev)
 			continue;
 		breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL);
-		if (IS_ERR(breakinfo[i].pev)) {
+		if (IS_ERR((void * __force)breakinfo[i].pev)) {
 			printk(KERN_ERR "kgdb: Could not allocate hw"
 			       "breakpoints\nDisabling the kernel debugger\n");
 			breakinfo[i].pev = NULL;
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index fa6551d..0b3d37e 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -232,6 +232,7 @@
 	.owner			= THIS_MODULE,
 	.write			= microcode_write,
 	.open			= microcode_open,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice microcode_dev = {
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 7a4cf14..f7f53dc 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -371,16 +371,10 @@
 	CMOS_WRITE(0x00, 0x8f);
 	spin_unlock(&rtc_lock);
 
-	/* Remap the kernel at virtual address zero, as well as offset zero
-	   from the kernel segment.  This assumes the kernel segment starts at
-	   virtual address PAGE_OFFSET. */
-	memcpy(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
-		sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
-
 	/*
-	 * Use `swapper_pg_dir' as our page directory.
+	 * Switch back to the initial page table.
 	 */
-	load_cr3(swapper_pg_dir);
+	load_cr3(initial_page_table);
 
 	/* Write 0x1234 to absolute memory location 0x472.  The BIOS reads
 	   this on booting to tell it to "Bypass memory test (also warm
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 420e641..95a3274 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -700,6 +700,17 @@
 #ifdef CONFIG_X86_32
 	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
 	visws_early_detect();
+
+	/*
+	 * copy kernel address range established so far and switch
+	 * to the proper swapper page table
+	 */
+	clone_pgd_range(swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
+			initial_page_table + KERNEL_PGD_BOUNDARY,
+			KERNEL_PGD_PTRS);
+
+	load_cr3(swapper_pg_dir);
+	__flush_tlb_all();
 #else
 	printk(KERN_INFO "Command line: %s\n", boot_command_line);
 #endif
@@ -985,7 +996,12 @@
 	paging_init();
 	x86_init.paging.pagetable_setup_done(swapper_pg_dir);
 
-	setup_trampoline_page_table();
+#ifdef CONFIG_X86_32
+	/* sync back kernel address range */
+	clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
+			swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
+			KERNEL_PGD_PTRS);
+#endif
 
 	tboot_probe();
 
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index dfb5089..6af1185 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -299,22 +299,16 @@
 	 * fragile that we want to limit the things done here to the
 	 * most necessary things.
 	 */
-
-#ifdef CONFIG_X86_32
-	/*
-	 * Switch away from the trampoline page-table
-	 *
-	 * Do this before cpu_init() because it needs to access per-cpu
-	 * data which may not be mapped in the trampoline page-table.
-	 */
-	load_cr3(swapper_pg_dir);
-	__flush_tlb_all();
-#endif
-
 	cpu_init();
 	preempt_disable();
 	smp_callin();
 
+#ifdef CONFIG_X86_32
+	/* switch away from the initial page table */
+	load_cr3(swapper_pg_dir);
+	__flush_tlb_all();
+#endif
+
 	/* otherwise gcc will move up smp_processor_id before the cpu_init */
 	barrier();
 	/*
@@ -785,7 +779,6 @@
 #ifdef CONFIG_X86_32
 	/* Stack for startup_32 can be just as for start_secondary onwards */
 	irq_ctx_init(cpu);
-	initial_page_table = __pa(&trampoline_pg_dir);
 #else
 	clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
 	initial_gs = per_cpu_offset(cpu);
@@ -934,7 +927,6 @@
 	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
 
 	err = do_boot_cpu(apicid, cpu);
-
 	if (err) {
 		pr_debug("do_boot_cpu failed %d\n", err);
 		return -EIO;
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c
index 312ef02..50ac949 100644
--- a/arch/x86/kernel/tlb_uv.c
+++ b/arch/x86/kernel/tlb_uv.c
@@ -1285,6 +1285,7 @@
 	.open		= tunables_open,
 	.read		= tunables_read,
 	.write		= tunables_write,
+	.llseek		= default_llseek,
 };
 
 static int __init uv_ptc_init(void)
diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
index 4c3da56..a375616 100644
--- a/arch/x86/kernel/trampoline.c
+++ b/arch/x86/kernel/trampoline.c
@@ -38,19 +38,3 @@
 	memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE);
 	return virt_to_phys(trampoline_base);
 }
-
-void __init setup_trampoline_page_table(void)
-{
-#ifdef CONFIG_X86_32
-	/* Copy kernel address range */
-	clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY,
-			swapper_pg_dir + KERNEL_PGD_BOUNDARY,
-			KERNEL_PGD_PTRS);
-
-	/* Initialize low mappings */
-	clone_pgd_range(trampoline_pg_dir,
-			swapper_pg_dir + KERNEL_PGD_BOUNDARY,
-			min_t(unsigned long, KERNEL_PGD_PTRS,
-			      KERNEL_PGD_BOUNDARY));
-#endif
-}
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 38e2b67..e03530a 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -301,7 +301,7 @@
 	}
 
 #if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
-	PERCPU(PAGE_SIZE)
+	PERCPU(THREAD_SIZE)
 #endif
 
 	. = ALIGN(PAGE_SIZE);
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 5d0a671..0e969f9 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -528,48 +528,6 @@
 	permanent_kmaps_init(pgd_base);
 }
 
-#ifdef CONFIG_ACPI_SLEEP
-/*
- * ACPI suspend needs this for resume, because things like the intel-agp
- * driver might have split up a kernel 4MB mapping.
- */
-char swsusp_pg_dir[PAGE_SIZE]
-	__attribute__ ((aligned(PAGE_SIZE)));
-
-static inline void save_pg_dir(void)
-{
-	copy_page(swsusp_pg_dir, swapper_pg_dir);
-}
-#else /* !CONFIG_ACPI_SLEEP */
-static inline void save_pg_dir(void)
-{
-}
-#endif /* !CONFIG_ACPI_SLEEP */
-
-void zap_low_mappings(bool early)
-{
-	int i;
-
-	/*
-	 * Zap initial low-memory mappings.
-	 *
-	 * Note that "pgd_clear()" doesn't do it for
-	 * us, because pgd_clear() is a no-op on i386.
-	 */
-	for (i = 0; i < KERNEL_PGD_BOUNDARY; i++) {
-#ifdef CONFIG_X86_PAE
-		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
-#else
-		set_pgd(swapper_pg_dir+i, __pgd(0));
-#endif
-	}
-
-	if (early)
-		__flush_tlb();
-	else
-		flush_tlb_all();
-}
-
 pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP);
 EXPORT_SYMBOL_GPL(__supported_pte_mask);
 
@@ -882,9 +840,6 @@
 
 	if (boot_cpu_data.wp_works_ok < 0)
 		test_wp_bit();
-
-	save_pg_dir();
-	zap_low_mappings(true);
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
diff --git a/arch/x86/xen/debugfs.c b/arch/x86/xen/debugfs.c
index 1304bce..7c0fedd 100644
--- a/arch/x86/xen/debugfs.c
+++ b/arch/x86/xen/debugfs.c
@@ -106,6 +106,7 @@
 	.open	= u32_array_open,
 	.release= xen_array_release,
 	.read	= u32_array_read,
+	.llseek = no_llseek,
 };
 
 struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode,
diff --git a/block/Kconfig b/block/Kconfig
index 9be0b56..6c9213e 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -77,6 +77,18 @@
 	T10/SCSI Data Integrity Field or the T13/ATA External Path
 	Protection.  If in doubt, say N.
 
+config BLK_DEV_THROTTLING
+	bool "Block layer bio throttling support"
+	depends on BLK_CGROUP=y && EXPERIMENTAL
+	default n
+	---help---
+	Block layer bio throttling support. It can be used to limit
+	the IO rate to a device. IO rate policies are per cgroup and
+	one needs to mount and use blkio cgroup controller for creating
+	cgroups and specifying per device IO rate policies.
+
+	See Documentation/cgroups/blkio-controller.txt for more information.
+
 endif # BLOCK
 
 config BLOCK_COMPAT
diff --git a/block/Makefile b/block/Makefile
index 0bb499a..0fec4b3 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -3,12 +3,13 @@
 #
 
 obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \
-			blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \
+			blk-flush.o blk-settings.o blk-ioc.o blk-map.o \
 			blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \
 			blk-iopoll.o blk-lib.o ioctl.o genhd.o scsi_ioctl.o
 
 obj-$(CONFIG_BLK_DEV_BSG)	+= bsg.o
 obj-$(CONFIG_BLK_CGROUP)	+= blk-cgroup.o
+obj-$(CONFIG_BLK_DEV_THROTTLING)	+= blk-throttle.o
 obj-$(CONFIG_IOSCHED_NOOP)	+= noop-iosched.o
 obj-$(CONFIG_IOSCHED_DEADLINE)	+= deadline-iosched.o
 obj-$(CONFIG_IOSCHED_CFQ)	+= cfq-iosched.o
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
deleted file mode 100644
index f0faefc..0000000
--- a/block/blk-barrier.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Functions related to barrier IO handling
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/bio.h>
-#include <linux/blkdev.h>
-#include <linux/gfp.h>
-
-#include "blk.h"
-
-/**
- * blk_queue_ordered - does this queue support ordered writes
- * @q:        the request queue
- * @ordered:  one of QUEUE_ORDERED_*
- *
- * Description:
- *   For journalled file systems, doing ordered writes on a commit
- *   block instead of explicitly doing wait_on_buffer (which is bad
- *   for performance) can be a big win. Block drivers supporting this
- *   feature should call this function and indicate so.
- *
- **/
-int blk_queue_ordered(struct request_queue *q, unsigned ordered)
-{
-	if (ordered != QUEUE_ORDERED_NONE &&
-	    ordered != QUEUE_ORDERED_DRAIN &&
-	    ordered != QUEUE_ORDERED_DRAIN_FLUSH &&
-	    ordered != QUEUE_ORDERED_DRAIN_FUA &&
-	    ordered != QUEUE_ORDERED_TAG &&
-	    ordered != QUEUE_ORDERED_TAG_FLUSH &&
-	    ordered != QUEUE_ORDERED_TAG_FUA) {
-		printk(KERN_ERR "blk_queue_ordered: bad value %d\n", ordered);
-		return -EINVAL;
-	}
-
-	q->ordered = ordered;
-	q->next_ordered = ordered;
-
-	return 0;
-}
-EXPORT_SYMBOL(blk_queue_ordered);
-
-/*
- * Cache flushing for ordered writes handling
- */
-unsigned blk_ordered_cur_seq(struct request_queue *q)
-{
-	if (!q->ordseq)
-		return 0;
-	return 1 << ffz(q->ordseq);
-}
-
-unsigned blk_ordered_req_seq(struct request *rq)
-{
-	struct request_queue *q = rq->q;
-
-	BUG_ON(q->ordseq == 0);
-
-	if (rq == &q->pre_flush_rq)
-		return QUEUE_ORDSEQ_PREFLUSH;
-	if (rq == &q->bar_rq)
-		return QUEUE_ORDSEQ_BAR;
-	if (rq == &q->post_flush_rq)
-		return QUEUE_ORDSEQ_POSTFLUSH;
-
-	/*
-	 * !fs requests don't need to follow barrier ordering.  Always
-	 * put them at the front.  This fixes the following deadlock.
-	 *
-	 * http://thread.gmane.org/gmane.linux.kernel/537473
-	 */
-	if (rq->cmd_type != REQ_TYPE_FS)
-		return QUEUE_ORDSEQ_DRAIN;
-
-	if ((rq->cmd_flags & REQ_ORDERED_COLOR) ==
-	    (q->orig_bar_rq->cmd_flags & REQ_ORDERED_COLOR))
-		return QUEUE_ORDSEQ_DRAIN;
-	else
-		return QUEUE_ORDSEQ_DONE;
-}
-
-bool blk_ordered_complete_seq(struct request_queue *q, unsigned seq, int error)
-{
-	struct request *rq;
-
-	if (error && !q->orderr)
-		q->orderr = error;
-
-	BUG_ON(q->ordseq & seq);
-	q->ordseq |= seq;
-
-	if (blk_ordered_cur_seq(q) != QUEUE_ORDSEQ_DONE)
-		return false;
-
-	/*
-	 * Okay, sequence complete.
-	 */
-	q->ordseq = 0;
-	rq = q->orig_bar_rq;
-	__blk_end_request_all(rq, q->orderr);
-	return true;
-}
-
-static void pre_flush_end_io(struct request *rq, int error)
-{
-	elv_completed_request(rq->q, rq);
-	blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_PREFLUSH, error);
-}
-
-static void bar_end_io(struct request *rq, int error)
-{
-	elv_completed_request(rq->q, rq);
-	blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_BAR, error);
-}
-
-static void post_flush_end_io(struct request *rq, int error)
-{
-	elv_completed_request(rq->q, rq);
-	blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_POSTFLUSH, error);
-}
-
-static void queue_flush(struct request_queue *q, unsigned which)
-{
-	struct request *rq;
-	rq_end_io_fn *end_io;
-
-	if (which == QUEUE_ORDERED_DO_PREFLUSH) {
-		rq = &q->pre_flush_rq;
-		end_io = pre_flush_end_io;
-	} else {
-		rq = &q->post_flush_rq;
-		end_io = post_flush_end_io;
-	}
-
-	blk_rq_init(q, rq);
-	rq->cmd_type = REQ_TYPE_FS;
-	rq->cmd_flags = REQ_HARDBARRIER | REQ_FLUSH;
-	rq->rq_disk = q->orig_bar_rq->rq_disk;
-	rq->end_io = end_io;
-
-	elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
-}
-
-static inline bool start_ordered(struct request_queue *q, struct request **rqp)
-{
-	struct request *rq = *rqp;
-	unsigned skip = 0;
-
-	q->orderr = 0;
-	q->ordered = q->next_ordered;
-	q->ordseq |= QUEUE_ORDSEQ_STARTED;
-
-	/*
-	 * For an empty barrier, there's no actual BAR request, which
-	 * in turn makes POSTFLUSH unnecessary.  Mask them off.
-	 */
-	if (!blk_rq_sectors(rq)) {
-		q->ordered &= ~(QUEUE_ORDERED_DO_BAR |
-				QUEUE_ORDERED_DO_POSTFLUSH);
-		/*
-		 * Empty barrier on a write-through device w/ ordered
-		 * tag has no command to issue and without any command
-		 * to issue, ordering by tag can't be used.  Drain
-		 * instead.
-		 */
-		if ((q->ordered & QUEUE_ORDERED_BY_TAG) &&
-		    !(q->ordered & QUEUE_ORDERED_DO_PREFLUSH)) {
-			q->ordered &= ~QUEUE_ORDERED_BY_TAG;
-			q->ordered |= QUEUE_ORDERED_BY_DRAIN;
-		}
-	}
-
-	/* stash away the original request */
-	blk_dequeue_request(rq);
-	q->orig_bar_rq = rq;
-	rq = NULL;
-
-	/*
-	 * Queue ordered sequence.  As we stack them at the head, we
-	 * need to queue in reverse order.  Note that we rely on that
-	 * no fs request uses ELEVATOR_INSERT_FRONT and thus no fs
-	 * request gets inbetween ordered sequence.
-	 */
-	if (q->ordered & QUEUE_ORDERED_DO_POSTFLUSH) {
-		queue_flush(q, QUEUE_ORDERED_DO_POSTFLUSH);
-		rq = &q->post_flush_rq;
-	} else
-		skip |= QUEUE_ORDSEQ_POSTFLUSH;
-
-	if (q->ordered & QUEUE_ORDERED_DO_BAR) {
-		rq = &q->bar_rq;
-
-		/* initialize proxy request and queue it */
-		blk_rq_init(q, rq);
-		if (bio_data_dir(q->orig_bar_rq->bio) == WRITE)
-			rq->cmd_flags |= REQ_WRITE;
-		if (q->ordered & QUEUE_ORDERED_DO_FUA)
-			rq->cmd_flags |= REQ_FUA;
-		init_request_from_bio(rq, q->orig_bar_rq->bio);
-		rq->end_io = bar_end_io;
-
-		elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
-	} else
-		skip |= QUEUE_ORDSEQ_BAR;
-
-	if (q->ordered & QUEUE_ORDERED_DO_PREFLUSH) {
-		queue_flush(q, QUEUE_ORDERED_DO_PREFLUSH);
-		rq = &q->pre_flush_rq;
-	} else
-		skip |= QUEUE_ORDSEQ_PREFLUSH;
-
-	if ((q->ordered & QUEUE_ORDERED_BY_DRAIN) && queue_in_flight(q))
-		rq = NULL;
-	else
-		skip |= QUEUE_ORDSEQ_DRAIN;
-
-	*rqp = rq;
-
-	/*
-	 * Complete skipped sequences.  If whole sequence is complete,
-	 * return false to tell elevator that this request is gone.
-	 */
-	return !blk_ordered_complete_seq(q, skip, 0);
-}
-
-bool blk_do_ordered(struct request_queue *q, struct request **rqp)
-{
-	struct request *rq = *rqp;
-	const int is_barrier = rq->cmd_type == REQ_TYPE_FS &&
-				(rq->cmd_flags & REQ_HARDBARRIER);
-
-	if (!q->ordseq) {
-		if (!is_barrier)
-			return true;
-
-		if (q->next_ordered != QUEUE_ORDERED_NONE)
-			return start_ordered(q, rqp);
-		else {
-			/*
-			 * Queue ordering not supported.  Terminate
-			 * with prejudice.
-			 */
-			blk_dequeue_request(rq);
-			__blk_end_request_all(rq, -EOPNOTSUPP);
-			*rqp = NULL;
-			return false;
-		}
-	}
-
-	/*
-	 * Ordered sequence in progress
-	 */
-
-	/* Special requests are not subject to ordering rules. */
-	if (rq->cmd_type != REQ_TYPE_FS &&
-	    rq != &q->pre_flush_rq && rq != &q->post_flush_rq)
-		return true;
-
-	if (q->ordered & QUEUE_ORDERED_BY_TAG) {
-		/* Ordered by tag.  Blocking the next barrier is enough. */
-		if (is_barrier && rq != &q->bar_rq)
-			*rqp = NULL;
-	} else {
-		/* Ordered by draining.  Wait for turn. */
-		WARN_ON(blk_ordered_req_seq(rq) < blk_ordered_cur_seq(q));
-		if (blk_ordered_req_seq(rq) > blk_ordered_cur_seq(q))
-			*rqp = NULL;
-	}
-
-	return true;
-}
-
-static void bio_end_empty_barrier(struct bio *bio, int err)
-{
-	if (err) {
-		if (err == -EOPNOTSUPP)
-			set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
-		clear_bit(BIO_UPTODATE, &bio->bi_flags);
-	}
-	if (bio->bi_private)
-		complete(bio->bi_private);
-	bio_put(bio);
-}
-
-/**
- * blkdev_issue_flush - queue a flush
- * @bdev:	blockdev to issue flush for
- * @gfp_mask:	memory allocation flags (for bio_alloc)
- * @error_sector:	error sector
- * @flags:	BLKDEV_IFL_* flags to control behaviour
- *
- * Description:
- *    Issue a flush for the block device in question. Caller can supply
- *    room for storing the error offset in case of a flush error, if they
- *    wish to. If WAIT flag is not passed then caller may check only what
- *    request was pushed in some internal queue for later handling.
- */
-int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
-		sector_t *error_sector, unsigned long flags)
-{
-	DECLARE_COMPLETION_ONSTACK(wait);
-	struct request_queue *q;
-	struct bio *bio;
-	int ret = 0;
-
-	if (bdev->bd_disk == NULL)
-		return -ENXIO;
-
-	q = bdev_get_queue(bdev);
-	if (!q)
-		return -ENXIO;
-
-	/*
-	 * some block devices may not have their queue correctly set up here
-	 * (e.g. loop device without a backing file) and so issuing a flush
-	 * here will panic. Ensure there is a request function before issuing
-	 * the barrier.
-	 */
-	if (!q->make_request_fn)
-		return -ENXIO;
-
-	bio = bio_alloc(gfp_mask, 0);
-	bio->bi_end_io = bio_end_empty_barrier;
-	bio->bi_bdev = bdev;
-	if (test_bit(BLKDEV_WAIT, &flags))
-		bio->bi_private = &wait;
-
-	bio_get(bio);
-	submit_bio(WRITE_BARRIER, bio);
-	if (test_bit(BLKDEV_WAIT, &flags)) {
-		wait_for_completion(&wait);
-		/*
-		 * The driver must store the error location in ->bi_sector, if
-		 * it supports it. For non-stacked drivers, this should be
-		 * copied from blk_rq_pos(rq).
-		 */
-		if (error_sector)
-			*error_sector = bio->bi_sector;
-	}
-
-	if (bio_flagged(bio, BIO_EOPNOTSUPP))
-		ret = -EOPNOTSUPP;
-	else if (!bio_flagged(bio, BIO_UPTODATE))
-		ret = -EIO;
-
-	bio_put(bio);
-	return ret;
-}
-EXPORT_SYMBOL(blkdev_issue_flush);
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 2fef1ef..b1febd0 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -37,6 +37,12 @@
 static void blkiocg_destroy(struct cgroup_subsys *, struct cgroup *);
 static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *);
 
+/* for encoding cft->private value on file */
+#define BLKIOFILE_PRIVATE(x, val)	(((x) << 16) | (val))
+/* What policy owns the file, proportional or throttle */
+#define BLKIOFILE_POLICY(val)		(((val) >> 16) & 0xffff)
+#define BLKIOFILE_ATTR(val)		((val) & 0xffff)
+
 struct cgroup_subsys blkio_subsys = {
 	.name = "blkio",
 	.create = blkiocg_create,
@@ -59,6 +65,27 @@
 	list_add(&pn->node, &blkcg->policy_list);
 }
 
+static inline bool cftype_blkg_same_policy(struct cftype *cft,
+			struct blkio_group *blkg)
+{
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+
+	if (blkg->plid == plid)
+		return 1;
+
+	return 0;
+}
+
+/* Determines if policy node matches cgroup file being accessed */
+static inline bool pn_matches_cftype(struct cftype *cft,
+			struct blkio_policy_node *pn)
+{
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int fileid = BLKIOFILE_ATTR(cft->private);
+
+	return (plid == pn->plid && fileid == pn->fileid);
+}
+
 /* Must be called with blkcg->lock held */
 static inline void blkio_policy_delete_node(struct blkio_policy_node *pn)
 {
@@ -67,12 +94,13 @@
 
 /* Must be called with blkcg->lock held */
 static struct blkio_policy_node *
-blkio_policy_search_node(const struct blkio_cgroup *blkcg, dev_t dev)
+blkio_policy_search_node(const struct blkio_cgroup *blkcg, dev_t dev,
+		enum blkio_policy_id plid, int fileid)
 {
 	struct blkio_policy_node *pn;
 
 	list_for_each_entry(pn, &blkcg->policy_list, node) {
-		if (pn->dev == dev)
+		if (pn->dev == dev && pn->plid == plid && pn->fileid == fileid)
 			return pn;
 	}
 
@@ -86,6 +114,67 @@
 }
 EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup);
 
+static inline void
+blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight)
+{
+	struct blkio_policy_type *blkiop;
+
+	list_for_each_entry(blkiop, &blkio_list, list) {
+		/* If this policy does not own the blkg, do not send updates */
+		if (blkiop->plid != blkg->plid)
+			continue;
+		if (blkiop->ops.blkio_update_group_weight_fn)
+			blkiop->ops.blkio_update_group_weight_fn(blkg->key,
+							blkg, weight);
+	}
+}
+
+static inline void blkio_update_group_bps(struct blkio_group *blkg, u64 bps,
+				int fileid)
+{
+	struct blkio_policy_type *blkiop;
+
+	list_for_each_entry(blkiop, &blkio_list, list) {
+
+		/* If this policy does not own the blkg, do not send updates */
+		if (blkiop->plid != blkg->plid)
+			continue;
+
+		if (fileid == BLKIO_THROTL_read_bps_device
+		    && blkiop->ops.blkio_update_group_read_bps_fn)
+			blkiop->ops.blkio_update_group_read_bps_fn(blkg->key,
+								blkg, bps);
+
+		if (fileid == BLKIO_THROTL_write_bps_device
+		    && blkiop->ops.blkio_update_group_write_bps_fn)
+			blkiop->ops.blkio_update_group_write_bps_fn(blkg->key,
+								blkg, bps);
+	}
+}
+
+static inline void blkio_update_group_iops(struct blkio_group *blkg,
+			unsigned int iops, int fileid)
+{
+	struct blkio_policy_type *blkiop;
+
+	list_for_each_entry(blkiop, &blkio_list, list) {
+
+		/* If this policy does not own the blkg, do not send updates */
+		if (blkiop->plid != blkg->plid)
+			continue;
+
+		if (fileid == BLKIO_THROTL_read_iops_device
+		    && blkiop->ops.blkio_update_group_read_iops_fn)
+			blkiop->ops.blkio_update_group_read_iops_fn(blkg->key,
+								blkg, iops);
+
+		if (fileid == BLKIO_THROTL_write_iops_device
+		    && blkiop->ops.blkio_update_group_write_iops_fn)
+			blkiop->ops.blkio_update_group_write_iops_fn(blkg->key,
+								blkg,iops);
+	}
+}
+
 /*
  * Add to the appropriate stat variable depending on the request type.
  * This should be called with the blkg->stats_lock held.
@@ -341,7 +430,8 @@
 EXPORT_SYMBOL_GPL(blkiocg_update_io_merged_stats);
 
 void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
-			struct blkio_group *blkg, void *key, dev_t dev)
+		struct blkio_group *blkg, void *key, dev_t dev,
+		enum blkio_policy_id plid)
 {
 	unsigned long flags;
 
@@ -350,6 +440,7 @@
 	rcu_assign_pointer(blkg->key, key);
 	blkg->blkcg_id = css_id(&blkcg->css);
 	hlist_add_head_rcu(&blkg->blkcg_node, &blkcg->blkg_list);
+	blkg->plid = plid;
 	spin_unlock_irqrestore(&blkcg->lock, flags);
 	/* Need to take css reference ? */
 	cgroup_path(blkcg->css.cgroup, blkg->path, sizeof(blkg->path));
@@ -408,51 +499,6 @@
 }
 EXPORT_SYMBOL_GPL(blkiocg_lookup_group);
 
-#define SHOW_FUNCTION(__VAR)						\
-static u64 blkiocg_##__VAR##_read(struct cgroup *cgroup,		\
-				       struct cftype *cftype)		\
-{									\
-	struct blkio_cgroup *blkcg;					\
-									\
-	blkcg = cgroup_to_blkio_cgroup(cgroup);				\
-	return (u64)blkcg->__VAR;					\
-}
-
-SHOW_FUNCTION(weight);
-#undef SHOW_FUNCTION
-
-static int
-blkiocg_weight_write(struct cgroup *cgroup, struct cftype *cftype, u64 val)
-{
-	struct blkio_cgroup *blkcg;
-	struct blkio_group *blkg;
-	struct hlist_node *n;
-	struct blkio_policy_type *blkiop;
-	struct blkio_policy_node *pn;
-
-	if (val < BLKIO_WEIGHT_MIN || val > BLKIO_WEIGHT_MAX)
-		return -EINVAL;
-
-	blkcg = cgroup_to_blkio_cgroup(cgroup);
-	spin_lock(&blkio_list_lock);
-	spin_lock_irq(&blkcg->lock);
-	blkcg->weight = (unsigned int)val;
-
-	hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
-		pn = blkio_policy_search_node(blkcg, blkg->dev);
-
-		if (pn)
-			continue;
-
-		list_for_each_entry(blkiop, &blkio_list, list)
-			blkiop->ops.blkio_update_group_weight_fn(blkg,
-					blkcg->weight);
-	}
-	spin_unlock_irq(&blkcg->lock);
-	spin_unlock(&blkio_list_lock);
-	return 0;
-}
-
 static int
 blkiocg_reset_stats(struct cgroup *cgroup, struct cftype *cftype, u64 val)
 {
@@ -593,52 +639,6 @@
 	return disk_total;
 }
 
-#define SHOW_FUNCTION_PER_GROUP(__VAR, type, show_total)		\
-static int blkiocg_##__VAR##_read(struct cgroup *cgroup,		\
-		struct cftype *cftype, struct cgroup_map_cb *cb)	\
-{									\
-	struct blkio_cgroup *blkcg;					\
-	struct blkio_group *blkg;					\
-	struct hlist_node *n;						\
-	uint64_t cgroup_total = 0;					\
-									\
-	if (!cgroup_lock_live_group(cgroup))				\
-		return -ENODEV;						\
-									\
-	blkcg = cgroup_to_blkio_cgroup(cgroup);				\
-	rcu_read_lock();						\
-	hlist_for_each_entry_rcu(blkg, n, &blkcg->blkg_list, blkcg_node) {\
-		if (blkg->dev) {					\
-			spin_lock_irq(&blkg->stats_lock);		\
-			cgroup_total += blkio_get_stat(blkg, cb,	\
-						blkg->dev, type);	\
-			spin_unlock_irq(&blkg->stats_lock);		\
-		}							\
-	}								\
-	if (show_total)							\
-		cb->fill(cb, "Total", cgroup_total);			\
-	rcu_read_unlock();						\
-	cgroup_unlock();						\
-	return 0;							\
-}
-
-SHOW_FUNCTION_PER_GROUP(time, BLKIO_STAT_TIME, 0);
-SHOW_FUNCTION_PER_GROUP(sectors, BLKIO_STAT_SECTORS, 0);
-SHOW_FUNCTION_PER_GROUP(io_service_bytes, BLKIO_STAT_SERVICE_BYTES, 1);
-SHOW_FUNCTION_PER_GROUP(io_serviced, BLKIO_STAT_SERVICED, 1);
-SHOW_FUNCTION_PER_GROUP(io_service_time, BLKIO_STAT_SERVICE_TIME, 1);
-SHOW_FUNCTION_PER_GROUP(io_wait_time, BLKIO_STAT_WAIT_TIME, 1);
-SHOW_FUNCTION_PER_GROUP(io_merged, BLKIO_STAT_MERGED, 1);
-SHOW_FUNCTION_PER_GROUP(io_queued, BLKIO_STAT_QUEUED, 1);
-#ifdef CONFIG_DEBUG_BLK_CGROUP
-SHOW_FUNCTION_PER_GROUP(dequeue, BLKIO_STAT_DEQUEUE, 0);
-SHOW_FUNCTION_PER_GROUP(avg_queue_size, BLKIO_STAT_AVG_QUEUE_SIZE, 0);
-SHOW_FUNCTION_PER_GROUP(group_wait_time, BLKIO_STAT_GROUP_WAIT_TIME, 0);
-SHOW_FUNCTION_PER_GROUP(idle_time, BLKIO_STAT_IDLE_TIME, 0);
-SHOW_FUNCTION_PER_GROUP(empty_time, BLKIO_STAT_EMPTY_TIME, 0);
-#endif
-#undef SHOW_FUNCTION_PER_GROUP
-
 static int blkio_check_dev_num(dev_t dev)
 {
 	int part = 0;
@@ -652,13 +652,14 @@
 }
 
 static int blkio_policy_parse_and_set(char *buf,
-				      struct blkio_policy_node *newpn)
+	struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid)
 {
 	char *s[4], *p, *major_s = NULL, *minor_s = NULL;
 	int ret;
 	unsigned long major, minor, temp;
 	int i = 0;
 	dev_t dev;
+	u64 bps, iops;
 
 	memset(s, 0, sizeof(s));
 
@@ -705,12 +706,47 @@
 	if (s[1] == NULL)
 		return -EINVAL;
 
-	ret = strict_strtoul(s[1], 10, &temp);
-	if (ret || (temp < BLKIO_WEIGHT_MIN && temp > 0) ||
-	    temp > BLKIO_WEIGHT_MAX)
-		return -EINVAL;
+	switch (plid) {
+	case BLKIO_POLICY_PROP:
+		ret = strict_strtoul(s[1], 10, &temp);
+		if (ret || (temp < BLKIO_WEIGHT_MIN && temp > 0) ||
+			temp > BLKIO_WEIGHT_MAX)
+			return -EINVAL;
 
-	newpn->weight =  temp;
+		newpn->plid = plid;
+		newpn->fileid = fileid;
+		newpn->val.weight = temp;
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(fileid) {
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+			ret = strict_strtoull(s[1], 10, &bps);
+			if (ret)
+				return -EINVAL;
+
+			newpn->plid = plid;
+			newpn->fileid = fileid;
+			newpn->val.bps = bps;
+			break;
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			ret = strict_strtoull(s[1], 10, &iops);
+			if (ret)
+				return -EINVAL;
+
+			if (iops > THROTL_IOPS_MAX)
+				return -EINVAL;
+
+			newpn->plid = plid;
+			newpn->fileid = fileid;
+			newpn->val.iops = (unsigned int)iops;
+			break;
+		}
+		break;
+	default:
+		BUG();
+	}
 
 	return 0;
 }
@@ -720,26 +756,180 @@
 {
 	struct blkio_policy_node *pn;
 
-	pn = blkio_policy_search_node(blkcg, dev);
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_PROP,
+				BLKIO_PROP_weight_device);
 	if (pn)
-		return pn->weight;
+		return pn->val.weight;
 	else
 		return blkcg->weight;
 }
 EXPORT_SYMBOL_GPL(blkcg_get_weight);
 
+uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg, dev_t dev)
+{
+	struct blkio_policy_node *pn;
 
-static int blkiocg_weight_device_write(struct cgroup *cgrp, struct cftype *cft,
-				       const char *buffer)
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_read_bps_device);
+	if (pn)
+		return pn->val.bps;
+	else
+		return -1;
+}
+
+uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg, dev_t dev)
+{
+	struct blkio_policy_node *pn;
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_write_bps_device);
+	if (pn)
+		return pn->val.bps;
+	else
+		return -1;
+}
+
+unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg, dev_t dev)
+{
+	struct blkio_policy_node *pn;
+
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_read_iops_device);
+	if (pn)
+		return pn->val.iops;
+	else
+		return -1;
+}
+
+unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg, dev_t dev)
+{
+	struct blkio_policy_node *pn;
+	pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_write_iops_device);
+	if (pn)
+		return pn->val.iops;
+	else
+		return -1;
+}
+
+/* Checks whether user asked for deleting a policy rule */
+static bool blkio_delete_rule_command(struct blkio_policy_node *pn)
+{
+	switch(pn->plid) {
+	case BLKIO_POLICY_PROP:
+		if (pn->val.weight == 0)
+			return 1;
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(pn->fileid) {
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+			if (pn->val.bps == 0)
+				return 1;
+			break;
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			if (pn->val.iops == 0)
+				return 1;
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+static void blkio_update_policy_rule(struct blkio_policy_node *oldpn,
+					struct blkio_policy_node *newpn)
+{
+	switch(oldpn->plid) {
+	case BLKIO_POLICY_PROP:
+		oldpn->val.weight = newpn->val.weight;
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(newpn->fileid) {
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+			oldpn->val.bps = newpn->val.bps;
+			break;
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			oldpn->val.iops = newpn->val.iops;
+		}
+		break;
+	default:
+		BUG();
+	}
+}
+
+/*
+ * Some rules/values in blkg have changed. Propogate those to respective
+ * policies.
+ */
+static void blkio_update_blkg_policy(struct blkio_cgroup *blkcg,
+		struct blkio_group *blkg, struct blkio_policy_node *pn)
+{
+	unsigned int weight, iops;
+	u64 bps;
+
+	switch(pn->plid) {
+	case BLKIO_POLICY_PROP:
+		weight = pn->val.weight ? pn->val.weight :
+				blkcg->weight;
+		blkio_update_group_weight(blkg, weight);
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(pn->fileid) {
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+			bps = pn->val.bps ? pn->val.bps : (-1);
+			blkio_update_group_bps(blkg, bps, pn->fileid);
+			break;
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			iops = pn->val.iops ? pn->val.iops : (-1);
+			blkio_update_group_iops(blkg, iops, pn->fileid);
+			break;
+		}
+		break;
+	default:
+		BUG();
+	}
+}
+
+/*
+ * A policy node rule has been updated. Propogate this update to all the
+ * block groups which might be affected by this update.
+ */
+static void blkio_update_policy_node_blkg(struct blkio_cgroup *blkcg,
+				struct blkio_policy_node *pn)
+{
+	struct blkio_group *blkg;
+	struct hlist_node *n;
+
+	spin_lock(&blkio_list_lock);
+	spin_lock_irq(&blkcg->lock);
+
+	hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
+		if (pn->dev != blkg->dev || pn->plid != blkg->plid)
+			continue;
+		blkio_update_blkg_policy(blkcg, blkg, pn);
+	}
+
+	spin_unlock_irq(&blkcg->lock);
+	spin_unlock(&blkio_list_lock);
+}
+
+static int blkiocg_file_write(struct cgroup *cgrp, struct cftype *cft,
+ 				       const char *buffer)
 {
 	int ret = 0;
 	char *buf;
 	struct blkio_policy_node *newpn, *pn;
 	struct blkio_cgroup *blkcg;
-	struct blkio_group *blkg;
 	int keep_newpn = 0;
-	struct hlist_node *n;
-	struct blkio_policy_type *blkiop;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int fileid = BLKIOFILE_ATTR(cft->private);
 
 	buf = kstrdup(buffer, GFP_KERNEL);
 	if (!buf)
@@ -751,7 +941,7 @@
 		goto free_buf;
 	}
 
-	ret = blkio_policy_parse_and_set(buf, newpn);
+	ret = blkio_policy_parse_and_set(buf, newpn, plid, fileid);
 	if (ret)
 		goto free_newpn;
 
@@ -759,9 +949,9 @@
 
 	spin_lock_irq(&blkcg->lock);
 
-	pn = blkio_policy_search_node(blkcg, newpn->dev);
+	pn = blkio_policy_search_node(blkcg, newpn->dev, plid, fileid);
 	if (!pn) {
-		if (newpn->weight != 0) {
+		if (!blkio_delete_rule_command(newpn)) {
 			blkio_policy_insert_node(blkcg, newpn);
 			keep_newpn = 1;
 		}
@@ -769,33 +959,17 @@
 		goto update_io_group;
 	}
 
-	if (newpn->weight == 0) {
-		/* weight == 0 means deleteing a specific weight */
+	if (blkio_delete_rule_command(newpn)) {
 		blkio_policy_delete_node(pn);
 		spin_unlock_irq(&blkcg->lock);
 		goto update_io_group;
 	}
 	spin_unlock_irq(&blkcg->lock);
 
-	pn->weight = newpn->weight;
+	blkio_update_policy_rule(pn, newpn);
 
 update_io_group:
-	/* update weight for each cfqg */
-	spin_lock(&blkio_list_lock);
-	spin_lock_irq(&blkcg->lock);
-
-	hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
-		if (newpn->dev == blkg->dev) {
-			list_for_each_entry(blkiop, &blkio_list, list)
-				blkiop->ops.blkio_update_group_weight_fn(blkg,
-							 newpn->weight ?
-							 newpn->weight :
-							 blkcg->weight);
-		}
-	}
-
-	spin_unlock_irq(&blkcg->lock);
-	spin_unlock(&blkio_list_lock);
+	blkio_update_policy_node_blkg(blkcg, newpn);
 
 free_newpn:
 	if (!keep_newpn)
@@ -805,23 +979,256 @@
 	return ret;
 }
 
-static int blkiocg_weight_device_read(struct cgroup *cgrp, struct cftype *cft,
-				      struct seq_file *m)
+static void
+blkio_print_policy_node(struct seq_file *m, struct blkio_policy_node *pn)
 {
-	struct blkio_cgroup *blkcg;
+	switch(pn->plid) {
+		case BLKIO_POLICY_PROP:
+			if (pn->fileid == BLKIO_PROP_weight_device)
+				seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev),
+					MINOR(pn->dev), pn->val.weight);
+			break;
+		case BLKIO_POLICY_THROTL:
+			switch(pn->fileid) {
+			case BLKIO_THROTL_read_bps_device:
+			case BLKIO_THROTL_write_bps_device:
+				seq_printf(m, "%u:%u\t%llu\n", MAJOR(pn->dev),
+					MINOR(pn->dev), pn->val.bps);
+				break;
+			case BLKIO_THROTL_read_iops_device:
+			case BLKIO_THROTL_write_iops_device:
+				seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev),
+					MINOR(pn->dev), pn->val.iops);
+				break;
+			}
+			break;
+		default:
+			BUG();
+	}
+}
+
+/* cgroup files which read their data from policy nodes end up here */
+static void blkio_read_policy_node_files(struct cftype *cft,
+			struct blkio_cgroup *blkcg, struct seq_file *m)
+{
 	struct blkio_policy_node *pn;
 
-	seq_printf(m, "dev\tweight\n");
-
-	blkcg = cgroup_to_blkio_cgroup(cgrp);
 	if (!list_empty(&blkcg->policy_list)) {
 		spin_lock_irq(&blkcg->lock);
 		list_for_each_entry(pn, &blkcg->policy_list, node) {
-			seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev),
-				   MINOR(pn->dev), pn->weight);
+			if (!pn_matches_cftype(cft, pn))
+				continue;
+			blkio_print_policy_node(m, pn);
 		}
 		spin_unlock_irq(&blkcg->lock);
 	}
+}
+
+static int blkiocg_file_read(struct cgroup *cgrp, struct cftype *cft,
+				struct seq_file *m)
+{
+	struct blkio_cgroup *blkcg;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int name = BLKIOFILE_ATTR(cft->private);
+
+	blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+	switch(plid) {
+	case BLKIO_POLICY_PROP:
+		switch(name) {
+		case BLKIO_PROP_weight_device:
+			blkio_read_policy_node_files(cft, blkcg, m);
+			return 0;
+		default:
+			BUG();
+		}
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(name){
+		case BLKIO_THROTL_read_bps_device:
+		case BLKIO_THROTL_write_bps_device:
+		case BLKIO_THROTL_read_iops_device:
+		case BLKIO_THROTL_write_iops_device:
+			blkio_read_policy_node_files(cft, blkcg, m);
+			return 0;
+		default:
+			BUG();
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+static int blkio_read_blkg_stats(struct blkio_cgroup *blkcg,
+		struct cftype *cft, struct cgroup_map_cb *cb, enum stat_type type,
+		bool show_total)
+{
+	struct blkio_group *blkg;
+	struct hlist_node *n;
+	uint64_t cgroup_total = 0;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(blkg, n, &blkcg->blkg_list, blkcg_node) {
+		if (blkg->dev) {
+			if (!cftype_blkg_same_policy(cft, blkg))
+				continue;
+			spin_lock_irq(&blkg->stats_lock);
+			cgroup_total += blkio_get_stat(blkg, cb, blkg->dev,
+						type);
+			spin_unlock_irq(&blkg->stats_lock);
+		}
+	}
+	if (show_total)
+		cb->fill(cb, "Total", cgroup_total);
+	rcu_read_unlock();
+	return 0;
+}
+
+/* All map kind of cgroup file get serviced by this function */
+static int blkiocg_file_read_map(struct cgroup *cgrp, struct cftype *cft,
+				struct cgroup_map_cb *cb)
+{
+	struct blkio_cgroup *blkcg;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int name = BLKIOFILE_ATTR(cft->private);
+
+	blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+	switch(plid) {
+	case BLKIO_POLICY_PROP:
+		switch(name) {
+		case BLKIO_PROP_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_TIME, 0);
+		case BLKIO_PROP_sectors:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SECTORS, 0);
+		case BLKIO_PROP_io_service_bytes:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICE_BYTES, 1);
+		case BLKIO_PROP_io_serviced:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICED, 1);
+		case BLKIO_PROP_io_service_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICE_TIME, 1);
+		case BLKIO_PROP_io_wait_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_WAIT_TIME, 1);
+		case BLKIO_PROP_io_merged:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_MERGED, 1);
+		case BLKIO_PROP_io_queued:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_QUEUED, 1);
+#ifdef CONFIG_DEBUG_BLK_CGROUP
+		case BLKIO_PROP_dequeue:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_DEQUEUE, 0);
+		case BLKIO_PROP_avg_queue_size:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_AVG_QUEUE_SIZE, 0);
+		case BLKIO_PROP_group_wait_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_GROUP_WAIT_TIME, 0);
+		case BLKIO_PROP_idle_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_IDLE_TIME, 0);
+		case BLKIO_PROP_empty_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_EMPTY_TIME, 0);
+#endif
+		default:
+			BUG();
+		}
+		break;
+	case BLKIO_POLICY_THROTL:
+		switch(name){
+		case BLKIO_THROTL_io_service_bytes:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICE_BYTES, 1);
+		case BLKIO_THROTL_io_serviced:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_SERVICED, 1);
+		default:
+			BUG();
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+static int blkio_weight_write(struct blkio_cgroup *blkcg, u64 val)
+{
+	struct blkio_group *blkg;
+	struct hlist_node *n;
+	struct blkio_policy_node *pn;
+
+	if (val < BLKIO_WEIGHT_MIN || val > BLKIO_WEIGHT_MAX)
+		return -EINVAL;
+
+	spin_lock(&blkio_list_lock);
+	spin_lock_irq(&blkcg->lock);
+	blkcg->weight = (unsigned int)val;
+
+	hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) {
+		pn = blkio_policy_search_node(blkcg, blkg->dev,
+				BLKIO_POLICY_PROP, BLKIO_PROP_weight_device);
+		if (pn)
+			continue;
+
+		blkio_update_group_weight(blkg, blkcg->weight);
+	}
+	spin_unlock_irq(&blkcg->lock);
+	spin_unlock(&blkio_list_lock);
+	return 0;
+}
+
+static u64 blkiocg_file_read_u64 (struct cgroup *cgrp, struct cftype *cft) {
+	struct blkio_cgroup *blkcg;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int name = BLKIOFILE_ATTR(cft->private);
+
+	blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+	switch(plid) {
+	case BLKIO_POLICY_PROP:
+		switch(name) {
+		case BLKIO_PROP_weight:
+			return (u64)blkcg->weight;
+		}
+		break;
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+static int
+blkiocg_file_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
+{
+	struct blkio_cgroup *blkcg;
+	enum blkio_policy_id plid = BLKIOFILE_POLICY(cft->private);
+	int name = BLKIOFILE_ATTR(cft->private);
+
+	blkcg = cgroup_to_blkio_cgroup(cgrp);
+
+	switch(plid) {
+	case BLKIO_POLICY_PROP:
+		switch(name) {
+		case BLKIO_PROP_weight:
+			return blkio_weight_write(blkcg, val);
+		}
+		break;
+	default:
+		BUG();
+	}
 
 	return 0;
 }
@@ -829,71 +1236,151 @@
 struct cftype blkio_files[] = {
 	{
 		.name = "weight_device",
-		.read_seq_string = blkiocg_weight_device_read,
-		.write_string = blkiocg_weight_device_write,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_weight_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
 		.max_write_len = 256,
 	},
 	{
 		.name = "weight",
-		.read_u64 = blkiocg_weight_read,
-		.write_u64 = blkiocg_weight_write,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_weight),
+		.read_u64 = blkiocg_file_read_u64,
+		.write_u64 = blkiocg_file_write_u64,
 	},
 	{
 		.name = "time",
-		.read_map = blkiocg_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "sectors",
-		.read_map = blkiocg_sectors_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_sectors),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_service_bytes",
-		.read_map = blkiocg_io_service_bytes_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_service_bytes),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_serviced",
-		.read_map = blkiocg_io_serviced_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_serviced),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_service_time",
-		.read_map = blkiocg_io_service_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_service_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_wait_time",
-		.read_map = blkiocg_io_wait_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_wait_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_merged",
-		.read_map = blkiocg_io_merged_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_merged),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "io_queued",
-		.read_map = blkiocg_io_queued_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_io_queued),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "reset_stats",
 		.write_u64 = blkiocg_reset_stats,
 	},
+#ifdef CONFIG_BLK_DEV_THROTTLING
+	{
+		.name = "throttle.read_bps_device",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_read_bps_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
+		.max_write_len = 256,
+	},
+
+	{
+		.name = "throttle.write_bps_device",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_write_bps_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
+		.max_write_len = 256,
+	},
+
+	{
+		.name = "throttle.read_iops_device",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_read_iops_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
+		.max_write_len = 256,
+	},
+
+	{
+		.name = "throttle.write_iops_device",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_write_iops_device),
+		.read_seq_string = blkiocg_file_read,
+		.write_string = blkiocg_file_write,
+		.max_write_len = 256,
+	},
+	{
+		.name = "throttle.io_service_bytes",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_io_service_bytes),
+		.read_map = blkiocg_file_read_map,
+	},
+	{
+		.name = "throttle.io_serviced",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL,
+				BLKIO_THROTL_io_serviced),
+		.read_map = blkiocg_file_read_map,
+	},
+#endif /* CONFIG_BLK_DEV_THROTTLING */
+
 #ifdef CONFIG_DEBUG_BLK_CGROUP
 	{
 		.name = "avg_queue_size",
-		.read_map = blkiocg_avg_queue_size_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_avg_queue_size),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "group_wait_time",
-		.read_map = blkiocg_group_wait_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_group_wait_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "idle_time",
-		.read_map = blkiocg_idle_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_idle_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "empty_time",
-		.read_map = blkiocg_empty_time_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_empty_time),
+		.read_map = blkiocg_file_read_map,
 	},
 	{
 		.name = "dequeue",
-		.read_map = blkiocg_dequeue_read,
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_dequeue),
+		.read_map = blkiocg_file_read_map,
 	},
 #endif
 };
@@ -932,13 +1419,14 @@
 		/*
 		 * This blkio_group is being unlinked as associated cgroup is
 		 * going away. Let all the IO controlling policies know about
-		 * this event. Currently this is static call to one io
-		 * controlling policy. Once we have more policies in place, we
-		 * need some dynamic registration of callback function.
+		 * this event.
 		 */
 		spin_lock(&blkio_list_lock);
-		list_for_each_entry(blkiop, &blkio_list, list)
+		list_for_each_entry(blkiop, &blkio_list, list) {
+			if (blkiop->plid != blkg->plid)
+				continue;
 			blkiop->ops.blkio_unlink_group_fn(key, blkg);
+		}
 		spin_unlock(&blkio_list_lock);
 	} while (1);
 
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 2b866ec..ea4861b 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -15,6 +15,14 @@
 
 #include <linux/cgroup.h>
 
+enum blkio_policy_id {
+	BLKIO_POLICY_PROP = 0,		/* Proportional Bandwidth division */
+	BLKIO_POLICY_THROTL,		/* Throttling */
+};
+
+/* Max limits for throttle policy */
+#define THROTL_IOPS_MAX		UINT_MAX
+
 #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
 
 #ifndef CONFIG_BLK_CGROUP
@@ -65,6 +73,35 @@
 	BLKG_empty,
 };
 
+/* cgroup files owned by proportional weight policy */
+enum blkcg_file_name_prop {
+	BLKIO_PROP_weight = 1,
+	BLKIO_PROP_weight_device,
+	BLKIO_PROP_io_service_bytes,
+	BLKIO_PROP_io_serviced,
+	BLKIO_PROP_time,
+	BLKIO_PROP_sectors,
+	BLKIO_PROP_io_service_time,
+	BLKIO_PROP_io_wait_time,
+	BLKIO_PROP_io_merged,
+	BLKIO_PROP_io_queued,
+	BLKIO_PROP_avg_queue_size,
+	BLKIO_PROP_group_wait_time,
+	BLKIO_PROP_idle_time,
+	BLKIO_PROP_empty_time,
+	BLKIO_PROP_dequeue,
+};
+
+/* cgroup files owned by throttle policy */
+enum blkcg_file_name_throtl {
+	BLKIO_THROTL_read_bps_device,
+	BLKIO_THROTL_write_bps_device,
+	BLKIO_THROTL_read_iops_device,
+	BLKIO_THROTL_write_iops_device,
+	BLKIO_THROTL_io_service_bytes,
+	BLKIO_THROTL_io_serviced,
+};
+
 struct blkio_cgroup {
 	struct cgroup_subsys_state css;
 	unsigned int weight;
@@ -112,6 +149,8 @@
 	char path[128];
 	/* The device MKDEV(major, minor), this group has been created for */
 	dev_t dev;
+	/* policy which owns this blk group */
+	enum blkio_policy_id plid;
 
 	/* Need to serialize the stats in the case of reset/update */
 	spinlock_t stats_lock;
@@ -121,24 +160,60 @@
 struct blkio_policy_node {
 	struct list_head node;
 	dev_t dev;
-	unsigned int weight;
+	/* This node belongs to max bw policy or porportional weight policy */
+	enum blkio_policy_id plid;
+	/* cgroup file to which this rule belongs to */
+	int fileid;
+
+	union {
+		unsigned int weight;
+		/*
+		 * Rate read/write in terms of byptes per second
+		 * Whether this rate represents read or write is determined
+		 * by file type "fileid".
+		 */
+		u64 bps;
+		unsigned int iops;
+	} val;
 };
 
 extern unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg,
 				     dev_t dev);
+extern uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg,
+				     dev_t dev);
+extern uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg,
+				     dev_t dev);
+extern unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg,
+				     dev_t dev);
+extern unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg,
+				     dev_t dev);
 
 typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg);
-typedef void (blkio_update_group_weight_fn) (struct blkio_group *blkg,
-						unsigned int weight);
+
+typedef void (blkio_update_group_weight_fn) (void *key,
+			struct blkio_group *blkg, unsigned int weight);
+typedef void (blkio_update_group_read_bps_fn) (void * key,
+			struct blkio_group *blkg, u64 read_bps);
+typedef void (blkio_update_group_write_bps_fn) (void *key,
+			struct blkio_group *blkg, u64 write_bps);
+typedef void (blkio_update_group_read_iops_fn) (void *key,
+			struct blkio_group *blkg, unsigned int read_iops);
+typedef void (blkio_update_group_write_iops_fn) (void *key,
+			struct blkio_group *blkg, unsigned int write_iops);
 
 struct blkio_policy_ops {
 	blkio_unlink_group_fn *blkio_unlink_group_fn;
 	blkio_update_group_weight_fn *blkio_update_group_weight_fn;
+	blkio_update_group_read_bps_fn *blkio_update_group_read_bps_fn;
+	blkio_update_group_write_bps_fn *blkio_update_group_write_bps_fn;
+	blkio_update_group_read_iops_fn *blkio_update_group_read_iops_fn;
+	blkio_update_group_write_iops_fn *blkio_update_group_write_iops_fn;
 };
 
 struct blkio_policy_type {
 	struct list_head list;
 	struct blkio_policy_ops ops;
+	enum blkio_policy_id plid;
 };
 
 /* Blkio controller policy registration */
@@ -212,7 +287,8 @@
 extern struct blkio_cgroup blkio_root_cgroup;
 extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
 extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
-			struct blkio_group *blkg, void *key, dev_t dev);
+	struct blkio_group *blkg, void *key, dev_t dev,
+	enum blkio_policy_id plid);
 extern int blkiocg_del_blkio_group(struct blkio_group *blkg);
 extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg,
 						void *key);
@@ -234,7 +310,8 @@
 cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; }
 
 static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
-			struct blkio_group *blkg, void *key, dev_t dev) {}
+		struct blkio_group *blkg, void *key, dev_t dev,
+		enum blkio_policy_id plid) {}
 
 static inline int
 blkiocg_del_blkio_group(struct blkio_group *blkg) { return 0; }
diff --git a/block/blk-core.c b/block/blk-core.c
index 32a1c12..4514146 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -64,13 +64,15 @@
 		return;
 
 	cpu = part_stat_lock();
-	part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
 
-	if (!new_io)
+	if (!new_io) {
+		part = rq->part;
 		part_stat_inc(cpu, part, merges[rw]);
-	else {
+	} else {
+		part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
 		part_round_stats(cpu, part);
 		part_inc_in_flight(part, rw);
+		rq->part = part;
 	}
 
 	part_stat_unlock();
@@ -128,6 +130,7 @@
 	rq->ref_count = 1;
 	rq->start_time = jiffies;
 	set_start_time_ns(rq);
+	rq->part = NULL;
 }
 EXPORT_SYMBOL(blk_rq_init);
 
@@ -136,7 +139,7 @@
 {
 	struct request_queue *q = rq->q;
 
-	if (&q->bar_rq != rq) {
+	if (&q->flush_rq != rq) {
 		if (error)
 			clear_bit(BIO_UPTODATE, &bio->bi_flags);
 		else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
@@ -160,13 +163,12 @@
 		if (bio->bi_size == 0)
 			bio_endio(bio, error);
 	} else {
-
 		/*
-		 * Okay, this is the barrier request in progress, just
-		 * record the error;
+		 * Okay, this is the sequenced flush request in
+		 * progress, just record the error;
 		 */
-		if (error && !q->orderr)
-			q->orderr = error;
+		if (error && !q->flush_err)
+			q->flush_err = error;
 	}
 }
 
@@ -382,6 +384,7 @@
 	del_timer_sync(&q->unplug_timer);
 	del_timer_sync(&q->timeout);
 	cancel_work_sync(&q->unplug_work);
+	throtl_shutdown_timer_wq(q);
 }
 EXPORT_SYMBOL(blk_sync_queue);
 
@@ -459,6 +462,8 @@
 	if (q->elevator)
 		elevator_exit(q->elevator);
 
+	blk_throtl_exit(q);
+
 	blk_put_queue(q);
 }
 EXPORT_SYMBOL(blk_cleanup_queue);
@@ -515,11 +520,17 @@
 		return NULL;
 	}
 
+	if (blk_throtl_init(q)) {
+		kmem_cache_free(blk_requestq_cachep, q);
+		return NULL;
+	}
+
 	setup_timer(&q->backing_dev_info.laptop_mode_wb_timer,
 		    laptop_mode_timer_fn, (unsigned long) q);
 	init_timer(&q->unplug_timer);
 	setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q);
 	INIT_LIST_HEAD(&q->timeout_list);
+	INIT_LIST_HEAD(&q->pending_flushes);
 	INIT_WORK(&q->unplug_work, blk_unplug_work);
 
 	kobject_init(&q->kobj, &blk_queue_ktype);
@@ -796,11 +807,16 @@
 	rl->starved[is_sync] = 0;
 
 	priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-	if (priv)
+	if (priv) {
 		rl->elvpriv++;
 
-	if (blk_queue_io_stat(q))
-		rw_flags |= REQ_IO_STAT;
+		/*
+		 * Don't do stats for non-priv requests
+		 */
+		if (blk_queue_io_stat(q))
+			rw_flags |= REQ_IO_STAT;
+	}
+
 	spin_unlock_irq(q->queue_lock);
 
 	rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
@@ -1037,22 +1053,6 @@
 }
 EXPORT_SYMBOL(blk_insert_request);
 
-/*
- * add-request adds a request to the linked list.
- * queue lock is held and interrupts disabled, as we muck with the
- * request queue list.
- */
-static inline void add_request(struct request_queue *q, struct request *req)
-{
-	drive_stat_acct(req, 1);
-
-	/*
-	 * elevator indicated where it wants this request to be
-	 * inserted at elevator_merge time
-	 */
-	__elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0);
-}
-
 static void part_round_stats_single(int cpu, struct hd_struct *part,
 				    unsigned long now)
 {
@@ -1201,13 +1201,16 @@
 	const bool sync = !!(bio->bi_rw & REQ_SYNC);
 	const bool unplug = !!(bio->bi_rw & REQ_UNPLUG);
 	const unsigned long ff = bio->bi_rw & REQ_FAILFAST_MASK;
+	int where = ELEVATOR_INSERT_SORT;
 	int rw_flags;
 
-	if ((bio->bi_rw & REQ_HARDBARRIER) &&
-	    (q->next_ordered == QUEUE_ORDERED_NONE)) {
+	/* REQ_HARDBARRIER is no more */
+	if (WARN_ONCE(bio->bi_rw & REQ_HARDBARRIER,
+		"block: HARDBARRIER is deprecated, use FLUSH/FUA instead\n")) {
 		bio_endio(bio, -EOPNOTSUPP);
 		return 0;
 	}
+
 	/*
 	 * low level driver can indicate that it wants pages above a
 	 * certain limit bounced to low memory (ie for highmem, or even
@@ -1217,7 +1220,12 @@
 
 	spin_lock_irq(q->queue_lock);
 
-	if (unlikely((bio->bi_rw & REQ_HARDBARRIER)) || elv_queue_empty(q))
+	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
+		where = ELEVATOR_INSERT_FRONT;
+		goto get_rq;
+	}
+
+	if (elv_queue_empty(q))
 		goto get_rq;
 
 	el_ret = elv_merge(q, &req, bio);
@@ -1314,7 +1322,10 @@
 		req->cpu = blk_cpu_to_group(smp_processor_id());
 	if (queue_should_plug(q) && elv_queue_empty(q))
 		blk_plug_device(q);
-	add_request(q, req);
+
+	/* insert the request into the elevator */
+	drive_stat_acct(req, 1);
+	__elv_add_request(q, req, where, 0);
 out:
 	if (unplug || !queue_should_plug(q))
 		__generic_unplug_device(q);
@@ -1514,6 +1525,19 @@
 		if (bio_check_eod(bio, nr_sectors))
 			goto end_io;
 
+		/*
+		 * Filter flush bio's early so that make_request based
+		 * drivers without flush support don't have to worry
+		 * about them.
+		 */
+		if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
+			bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
+			if (!nr_sectors) {
+				err = 0;
+				goto end_io;
+			}
+		}
+
 		if ((bio->bi_rw & REQ_DISCARD) &&
 		    (!blk_queue_discard(q) ||
 		     ((bio->bi_rw & REQ_SECURE) &&
@@ -1522,6 +1546,15 @@
 			goto end_io;
 		}
 
+		blk_throtl_bio(q, &bio);
+
+		/*
+		 * If bio = NULL, bio has been throttled and will be submitted
+		 * later.
+		 */
+		if (!bio)
+			break;
+
 		trace_block_bio_queue(q, bio);
 
 		ret = q->make_request_fn(q, bio);
@@ -1612,11 +1645,12 @@
 
 		if (unlikely(block_dump)) {
 			char b[BDEVNAME_SIZE];
-			printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n",
+			printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)\n",
 			current->comm, task_pid_nr(current),
 				(rw & WRITE) ? "WRITE" : "READ",
 				(unsigned long long)bio->bi_sector,
-				bdevname(bio->bi_bdev, b));
+				bdevname(bio->bi_bdev, b),
+				count);
 		}
 	}
 
@@ -1759,7 +1793,7 @@
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+		part = req->part;
 		part_stat_add(cpu, part, sectors[rw], bytes >> 9);
 		part_stat_unlock();
 	}
@@ -1768,18 +1802,18 @@
 static void blk_account_io_done(struct request *req)
 {
 	/*
-	 * Account IO completion.  bar_rq isn't accounted as a normal
-	 * IO on queueing nor completion.  Accounting the containing
-	 * request is enough.
+	 * Account IO completion.  flush_rq isn't accounted as a
+	 * normal IO on queueing nor completion.  Accounting the
+	 * containing request is enough.
 	 */
-	if (blk_do_io_stat(req) && req != &req->q->bar_rq) {
+	if (blk_do_io_stat(req) && req != &req->q->flush_rq) {
 		unsigned long duration = jiffies - req->start_time;
 		const int rw = rq_data_dir(req);
 		struct hd_struct *part;
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+		part = req->part;
 
 		part_stat_inc(cpu, part, ios[rw]);
 		part_stat_add(cpu, part, ticks[rw], duration);
@@ -2497,9 +2531,7 @@
 static void __blk_rq_prep_clone(struct request *dst, struct request *src)
 {
 	dst->cpu = src->cpu;
-	dst->cmd_flags = (rq_data_dir(src) | REQ_NOMERGE);
-	if (src->cmd_flags & REQ_DISCARD)
-		dst->cmd_flags |= REQ_DISCARD;
+	dst->cmd_flags = (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE;
 	dst->cmd_type = src->cmd_type;
 	dst->__sector = blk_rq_pos(src);
 	dst->__data_len = blk_rq_bytes(src);
@@ -2579,6 +2611,13 @@
 }
 EXPORT_SYMBOL(kblockd_schedule_work);
 
+int kblockd_schedule_delayed_work(struct request_queue *q,
+			struct delayed_work *dwork, unsigned long delay)
+{
+	return queue_delayed_work(kblockd_workqueue, dwork, delay);
+}
+EXPORT_SYMBOL(kblockd_schedule_delayed_work);
+
 int __init blk_dev_init(void)
 {
 	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
diff --git a/block/blk-exec.c b/block/blk-exec.c
index e1672f1..cf1456a 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -80,6 +80,7 @@
 	DECLARE_COMPLETION_ONSTACK(wait);
 	char sense[SCSI_SENSE_BUFFERSIZE];
 	int err = 0;
+	unsigned long hang_check;
 
 	/*
 	 * we need an extra reference to the request, so we can look at
@@ -95,7 +96,13 @@
 
 	rq->end_io_data = &wait;
 	blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
-	wait_for_completion(&wait);
+
+	/* Prevent hang_check timer from firing at us during very long I/O */
+	hang_check = sysctl_hung_task_timeout_secs;
+	if (hang_check)
+		while (!wait_for_completion_timeout(&wait, hang_check * (HZ/2)));
+	else
+		wait_for_completion(&wait);
 
 	if (rq->errors)
 		err = -EIO;
diff --git a/block/blk-flush.c b/block/blk-flush.c
new file mode 100644
index 0000000..54b123d
--- /dev/null
+++ b/block/blk-flush.c
@@ -0,0 +1,262 @@
+/*
+ * Functions to sequence FLUSH and FUA writes.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/gfp.h>
+
+#include "blk.h"
+
+/* FLUSH/FUA sequences */
+enum {
+	QUEUE_FSEQ_STARTED	= (1 << 0), /* flushing in progress */
+	QUEUE_FSEQ_PREFLUSH	= (1 << 1), /* pre-flushing in progress */
+	QUEUE_FSEQ_DATA		= (1 << 2), /* data write in progress */
+	QUEUE_FSEQ_POSTFLUSH	= (1 << 3), /* post-flushing in progress */
+	QUEUE_FSEQ_DONE		= (1 << 4),
+};
+
+static struct request *queue_next_fseq(struct request_queue *q);
+
+unsigned blk_flush_cur_seq(struct request_queue *q)
+{
+	if (!q->flush_seq)
+		return 0;
+	return 1 << ffz(q->flush_seq);
+}
+
+static struct request *blk_flush_complete_seq(struct request_queue *q,
+					      unsigned seq, int error)
+{
+	struct request *next_rq = NULL;
+
+	if (error && !q->flush_err)
+		q->flush_err = error;
+
+	BUG_ON(q->flush_seq & seq);
+	q->flush_seq |= seq;
+
+	if (blk_flush_cur_seq(q) != QUEUE_FSEQ_DONE) {
+		/* not complete yet, queue the next flush sequence */
+		next_rq = queue_next_fseq(q);
+	} else {
+		/* complete this flush request */
+		__blk_end_request_all(q->orig_flush_rq, q->flush_err);
+		q->orig_flush_rq = NULL;
+		q->flush_seq = 0;
+
+		/* dispatch the next flush if there's one */
+		if (!list_empty(&q->pending_flushes)) {
+			next_rq = list_entry_rq(q->pending_flushes.next);
+			list_move(&next_rq->queuelist, &q->queue_head);
+		}
+	}
+	return next_rq;
+}
+
+static void blk_flush_complete_seq_end_io(struct request_queue *q,
+					  unsigned seq, int error)
+{
+	bool was_empty = elv_queue_empty(q);
+	struct request *next_rq;
+
+	next_rq = blk_flush_complete_seq(q, seq, error);
+
+	/*
+	 * Moving a request silently to empty queue_head may stall the
+	 * queue.  Kick the queue in those cases.
+	 */
+	if (was_empty && next_rq)
+		__blk_run_queue(q);
+}
+
+static void pre_flush_end_io(struct request *rq, int error)
+{
+	elv_completed_request(rq->q, rq);
+	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_PREFLUSH, error);
+}
+
+static void flush_data_end_io(struct request *rq, int error)
+{
+	elv_completed_request(rq->q, rq);
+	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_DATA, error);
+}
+
+static void post_flush_end_io(struct request *rq, int error)
+{
+	elv_completed_request(rq->q, rq);
+	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_POSTFLUSH, error);
+}
+
+static void init_flush_request(struct request *rq, struct gendisk *disk)
+{
+	rq->cmd_type = REQ_TYPE_FS;
+	rq->cmd_flags = WRITE_FLUSH;
+	rq->rq_disk = disk;
+}
+
+static struct request *queue_next_fseq(struct request_queue *q)
+{
+	struct request *orig_rq = q->orig_flush_rq;
+	struct request *rq = &q->flush_rq;
+
+	blk_rq_init(q, rq);
+
+	switch (blk_flush_cur_seq(q)) {
+	case QUEUE_FSEQ_PREFLUSH:
+		init_flush_request(rq, orig_rq->rq_disk);
+		rq->end_io = pre_flush_end_io;
+		break;
+	case QUEUE_FSEQ_DATA:
+		init_request_from_bio(rq, orig_rq->bio);
+		/*
+		 * orig_rq->rq_disk may be different from
+		 * bio->bi_bdev->bd_disk if orig_rq got here through
+		 * remapping drivers.  Make sure rq->rq_disk points
+		 * to the same one as orig_rq.
+		 */
+		rq->rq_disk = orig_rq->rq_disk;
+		rq->cmd_flags &= ~(REQ_FLUSH | REQ_FUA);
+		rq->cmd_flags |= orig_rq->cmd_flags & (REQ_FLUSH | REQ_FUA);
+		rq->end_io = flush_data_end_io;
+		break;
+	case QUEUE_FSEQ_POSTFLUSH:
+		init_flush_request(rq, orig_rq->rq_disk);
+		rq->end_io = post_flush_end_io;
+		break;
+	default:
+		BUG();
+	}
+
+	elv_insert(q, rq, ELEVATOR_INSERT_FRONT);
+	return rq;
+}
+
+struct request *blk_do_flush(struct request_queue *q, struct request *rq)
+{
+	unsigned int fflags = q->flush_flags; /* may change, cache it */
+	bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA;
+	bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH);
+	bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & REQ_FUA);
+	unsigned skip = 0;
+
+	/*
+	 * Special case.  If there's data but flush is not necessary,
+	 * the request can be issued directly.
+	 *
+	 * Flush w/o data should be able to be issued directly too but
+	 * currently some drivers assume that rq->bio contains
+	 * non-zero data if it isn't NULL and empty FLUSH requests
+	 * getting here usually have bio's without data.
+	 */
+	if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) {
+		rq->cmd_flags &= ~REQ_FLUSH;
+		if (!has_fua)
+			rq->cmd_flags &= ~REQ_FUA;
+		return rq;
+	}
+
+	/*
+	 * Sequenced flushes can't be processed in parallel.  If
+	 * another one is already in progress, queue for later
+	 * processing.
+	 */
+	if (q->flush_seq) {
+		list_move_tail(&rq->queuelist, &q->pending_flushes);
+		return NULL;
+	}
+
+	/*
+	 * Start a new flush sequence
+	 */
+	q->flush_err = 0;
+	q->flush_seq |= QUEUE_FSEQ_STARTED;
+
+	/* adjust FLUSH/FUA of the original request and stash it away */
+	rq->cmd_flags &= ~REQ_FLUSH;
+	if (!has_fua)
+		rq->cmd_flags &= ~REQ_FUA;
+	blk_dequeue_request(rq);
+	q->orig_flush_rq = rq;
+
+	/* skip unneded sequences and return the first one */
+	if (!do_preflush)
+		skip |= QUEUE_FSEQ_PREFLUSH;
+	if (!blk_rq_sectors(rq))
+		skip |= QUEUE_FSEQ_DATA;
+	if (!do_postflush)
+		skip |= QUEUE_FSEQ_POSTFLUSH;
+	return blk_flush_complete_seq(q, skip, 0);
+}
+
+static void bio_end_flush(struct bio *bio, int err)
+{
+	if (err)
+		clear_bit(BIO_UPTODATE, &bio->bi_flags);
+	if (bio->bi_private)
+		complete(bio->bi_private);
+	bio_put(bio);
+}
+
+/**
+ * blkdev_issue_flush - queue a flush
+ * @bdev:	blockdev to issue flush for
+ * @gfp_mask:	memory allocation flags (for bio_alloc)
+ * @error_sector:	error sector
+ *
+ * Description:
+ *    Issue a flush for the block device in question. Caller can supply
+ *    room for storing the error offset in case of a flush error, if they
+ *    wish to. If WAIT flag is not passed then caller may check only what
+ *    request was pushed in some internal queue for later handling.
+ */
+int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
+		sector_t *error_sector)
+{
+	DECLARE_COMPLETION_ONSTACK(wait);
+	struct request_queue *q;
+	struct bio *bio;
+	int ret = 0;
+
+	if (bdev->bd_disk == NULL)
+		return -ENXIO;
+
+	q = bdev_get_queue(bdev);
+	if (!q)
+		return -ENXIO;
+
+	/*
+	 * some block devices may not have their queue correctly set up here
+	 * (e.g. loop device without a backing file) and so issuing a flush
+	 * here will panic. Ensure there is a request function before issuing
+	 * the flush.
+	 */
+	if (!q->make_request_fn)
+		return -ENXIO;
+
+	bio = bio_alloc(gfp_mask, 0);
+	bio->bi_end_io = bio_end_flush;
+	bio->bi_bdev = bdev;
+	bio->bi_private = &wait;
+
+	bio_get(bio);
+	submit_bio(WRITE_FLUSH, bio);
+	wait_for_completion(&wait);
+
+	/*
+	 * The driver must store the error location in ->bi_sector, if
+	 * it supports it. For non-stacked drivers, this should be
+	 * copied from blk_rq_pos(rq).
+	 */
+	if (error_sector)
+               *error_sector = bio->bi_sector;
+
+	if (!bio_flagged(bio, BIO_UPTODATE))
+		ret = -EIO;
+
+	bio_put(bio);
+	return ret;
+}
+EXPORT_SYMBOL(blkdev_issue_flush);
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index edce1ef..54bcba6 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -32,24 +32,37 @@
 
 /**
  * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements
- * @rq:		request with integrity metadata attached
+ * @q:		request queue
+ * @bio:	bio with integrity metadata attached
  *
  * Description: Returns the number of elements required in a
- * scatterlist corresponding to the integrity metadata in a request.
+ * scatterlist corresponding to the integrity metadata in a bio.
  */
-int blk_rq_count_integrity_sg(struct request *rq)
+int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio)
 {
-	struct bio_vec *iv, *ivprv;
-	struct req_iterator iter;
-	unsigned int segments;
+	struct bio_vec *iv, *ivprv = NULL;
+	unsigned int segments = 0;
+	unsigned int seg_size = 0;
+	unsigned int i = 0;
 
-	ivprv = NULL;
-	segments = 0;
+	bio_for_each_integrity_vec(iv, bio, i) {
 
-	rq_for_each_integrity_segment(iv, rq, iter) {
+		if (ivprv) {
+			if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+				goto new_segment;
 
-		if (!ivprv || !BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+			if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
+				goto new_segment;
+
+			if (seg_size + iv->bv_len > queue_max_segment_size(q))
+				goto new_segment;
+
+			seg_size += iv->bv_len;
+		} else {
+new_segment:
 			segments++;
+			seg_size = iv->bv_len;
+		}
 
 		ivprv = iv;
 	}
@@ -60,30 +73,34 @@
 
 /**
  * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
- * @rq:		request with integrity metadata attached
+ * @q:		request queue
+ * @bio:	bio with integrity metadata attached
  * @sglist:	target scatterlist
  *
  * Description: Map the integrity vectors in request into a
  * scatterlist.  The scatterlist must be big enough to hold all
  * elements.  I.e. sized using blk_rq_count_integrity_sg().
  */
-int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist)
+int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio,
+			    struct scatterlist *sglist)
 {
-	struct bio_vec *iv, *ivprv;
-	struct req_iterator iter;
-	struct scatterlist *sg;
-	unsigned int segments;
+	struct bio_vec *iv, *ivprv = NULL;
+	struct scatterlist *sg = NULL;
+	unsigned int segments = 0;
+	unsigned int i = 0;
 
-	ivprv = NULL;
-	sg = NULL;
-	segments = 0;
-
-	rq_for_each_integrity_segment(iv, rq, iter) {
+	bio_for_each_integrity_vec(iv, bio, i) {
 
 		if (ivprv) {
 			if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
 				goto new_segment;
 
+			if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
+				goto new_segment;
+
+			if (sg->length + iv->bv_len > queue_max_segment_size(q))
+				goto new_segment;
+
 			sg->length += iv->bv_len;
 		} else {
 new_segment:
@@ -162,6 +179,40 @@
 }
 EXPORT_SYMBOL(blk_integrity_compare);
 
+int blk_integrity_merge_rq(struct request_queue *q, struct request *req,
+			   struct request *next)
+{
+	if (blk_integrity_rq(req) != blk_integrity_rq(next))
+		return -1;
+
+	if (req->nr_integrity_segments + next->nr_integrity_segments >
+	    q->limits.max_integrity_segments)
+		return -1;
+
+	return 0;
+}
+EXPORT_SYMBOL(blk_integrity_merge_rq);
+
+int blk_integrity_merge_bio(struct request_queue *q, struct request *req,
+			    struct bio *bio)
+{
+	int nr_integrity_segs;
+	struct bio *next = bio->bi_next;
+
+	bio->bi_next = NULL;
+	nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);
+	bio->bi_next = next;
+
+	if (req->nr_integrity_segments + nr_integrity_segs >
+	    q->limits.max_integrity_segments)
+		return -1;
+
+	req->nr_integrity_segments += nr_integrity_segs;
+
+	return 0;
+}
+EXPORT_SYMBOL(blk_integrity_merge_bio);
+
 struct integrity_sysfs_entry {
 	struct attribute attr;
 	ssize_t (*show)(struct blk_integrity *, char *);
@@ -381,7 +432,6 @@
 	kobject_uevent(&bi->kobj, KOBJ_REMOVE);
 	kobject_del(&bi->kobj);
 	kobject_put(&bi->kobj);
-	kmem_cache_free(integrity_cachep, bi);
 	disk->integrity = NULL;
 }
 EXPORT_SYMBOL(blk_integrity_unregister);
diff --git a/block/blk-lib.c b/block/blk-lib.c
index c392029..1a320d2 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -39,8 +39,7 @@
 {
 	DECLARE_COMPLETION_ONSTACK(wait);
 	struct request_queue *q = bdev_get_queue(bdev);
-	int type = flags & BLKDEV_IFL_BARRIER ?
-		DISCARD_BARRIER : DISCARD_NOBARRIER;
+	int type = REQ_WRITE | REQ_DISCARD;
 	unsigned int max_discard_sectors;
 	struct bio *bio;
 	int ret = 0;
@@ -62,10 +61,10 @@
 		max_discard_sectors &= ~(disc_sects - 1);
 	}
 
-	if (flags & BLKDEV_IFL_SECURE) {
+	if (flags & BLKDEV_DISCARD_SECURE) {
 		if (!blk_queue_secdiscard(q))
 			return -EOPNOTSUPP;
-		type |= DISCARD_SECURE;
+		type |= REQ_SECURE;
 	}
 
 	while (nr_sects && !ret) {
@@ -78,8 +77,7 @@
 		bio->bi_sector = sector;
 		bio->bi_end_io = blkdev_discard_end_io;
 		bio->bi_bdev = bdev;
-		if (flags & BLKDEV_IFL_WAIT)
-			bio->bi_private = &wait;
+		bio->bi_private = &wait;
 
 		if (nr_sects > max_discard_sectors) {
 			bio->bi_size = max_discard_sectors << 9;
@@ -93,8 +91,7 @@
 		bio_get(bio);
 		submit_bio(type, bio);
 
-		if (flags & BLKDEV_IFL_WAIT)
-			wait_for_completion(&wait);
+		wait_for_completion(&wait);
 
 		if (bio_flagged(bio, BIO_EOPNOTSUPP))
 			ret = -EOPNOTSUPP;
@@ -140,7 +137,6 @@
  * @sector:	start sector
  * @nr_sects:	number of sectors to write
  * @gfp_mask:	memory allocation flags (for bio_alloc)
- * @flags:	BLKDEV_IFL_* flags to control behaviour
  *
  * Description:
  *  Generate and issue number of bios with zerofiled pages.
@@ -149,7 +145,7 @@
  */
 
 int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
-			sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
+			sector_t nr_sects, gfp_t gfp_mask)
 {
 	int ret;
 	struct bio *bio;
@@ -162,12 +158,6 @@
 	bb.wait = &wait;
 	bb.end_io = NULL;
 
-	if (flags & BLKDEV_IFL_BARRIER) {
-		/* issue async barrier before the data */
-		ret = blkdev_issue_flush(bdev, gfp_mask, NULL, 0);
-		if (ret)
-			return ret;
-	}
 submit:
 	ret = 0;
 	while (nr_sects != 0) {
@@ -181,8 +171,7 @@
 		bio->bi_sector = sector;
 		bio->bi_bdev   = bdev;
 		bio->bi_end_io = bio_batch_end_io;
-		if (flags & BLKDEV_IFL_WAIT)
-			bio->bi_private = &bb;
+		bio->bi_private = &bb;
 
 		while (nr_sects != 0) {
 			sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects);
@@ -199,18 +188,10 @@
 		issued++;
 		submit_bio(WRITE, bio);
 	}
-	/*
-	 * When all data bios are in flight. Send final barrier if requeted.
-	 */
-	if (nr_sects == 0 && flags & BLKDEV_IFL_BARRIER)
-		ret = blkdev_issue_flush(bdev, gfp_mask, NULL,
-					flags & BLKDEV_IFL_WAIT);
 
-
-	if (flags & BLKDEV_IFL_WAIT)
-		/* Wait for bios in-flight */
-		while ( issued != atomic_read(&bb.done))
-			wait_for_completion(&wait);
+	/* Wait for bios in-flight */
+	while (issued != atomic_read(&bb.done))
+		wait_for_completion(&wait);
 
 	if (!test_bit(BIO_UPTODATE, &bb.flags))
 		/* One of bios in the batch was completed with error.*/
diff --git a/block/blk-map.c b/block/blk-map.c
index ade0a08..d4a586d 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -54,7 +54,7 @@
 	 * direct dma. else, set up kernel bounce buffers
 	 */
 	uaddr = (unsigned long) ubuf;
-	if (blk_rq_aligned(q, ubuf, len) && !map_data)
+	if (blk_rq_aligned(q, uaddr, len) && !map_data)
 		bio = bio_map_user(q, NULL, uaddr, len, reading, gfp_mask);
 	else
 		bio = bio_copy_user(q, map_data, uaddr, len, reading, gfp_mask);
@@ -288,6 +288,7 @@
 		    unsigned int len, gfp_t gfp_mask)
 {
 	int reading = rq_data_dir(rq) == READ;
+	unsigned long addr = (unsigned long) kbuf;
 	int do_copy = 0;
 	struct bio *bio;
 	int ret;
@@ -297,7 +298,7 @@
 	if (!len || !kbuf)
 		return -EINVAL;
 
-	do_copy = !blk_rq_aligned(q, kbuf, len) || object_is_on_stack(kbuf);
+	do_copy = !blk_rq_aligned(q, addr, len) || object_is_on_stack(kbuf);
 	if (do_copy)
 		bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading);
 	else
diff --git a/block/blk-merge.c b/block/blk-merge.c
index eafc94f..0a2fd8a 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -205,12 +205,11 @@
 {
 	int nr_phys_segs = bio_phys_segments(q, bio);
 
-	if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(q)) {
-		req->cmd_flags |= REQ_NOMERGE;
-		if (req == q->last_merge)
-			q->last_merge = NULL;
-		return 0;
-	}
+	if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(q))
+		goto no_merge;
+
+	if (bio_integrity(bio) && blk_integrity_merge_bio(q, req, bio))
+		goto no_merge;
 
 	/*
 	 * This will form the start of a new hw segment.  Bump both
@@ -218,6 +217,12 @@
 	 */
 	req->nr_phys_segments += nr_phys_segs;
 	return 1;
+
+no_merge:
+	req->cmd_flags |= REQ_NOMERGE;
+	if (req == q->last_merge)
+		q->last_merge = NULL;
+	return 0;
 }
 
 int ll_back_merge_fn(struct request_queue *q, struct request *req,
@@ -301,6 +306,9 @@
 	if (total_phys_segments > queue_max_segments(q))
 		return 0;
 
+	if (blk_integrity_rq(req) && blk_integrity_merge_rq(q, req, next))
+		return 0;
+
 	/* Merge is OK... */
 	req->nr_phys_segments = total_phys_segments;
 	return 1;
@@ -343,7 +351,7 @@
 		int cpu;
 
 		cpu = part_stat_lock();
-		part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
+		part = req->part;
 
 		part_round_stats(cpu, part);
 		part_dec_in_flight(part, rq_data_dir(req));
@@ -384,9 +392,6 @@
 	    || next->special)
 		return 0;
 
-	if (blk_integrity_rq(req) != blk_integrity_rq(next))
-		return 0;
-
 	/*
 	 * If we are allowed to merge, then append bio list
 	 * from next to rq and release next. merge_requests_fn
diff --git a/block/blk-settings.c b/block/blk-settings.c
index a234f4b..701859f 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -111,6 +111,7 @@
 void blk_set_default_limits(struct queue_limits *lim)
 {
 	lim->max_segments = BLK_MAX_SEGMENTS;
+	lim->max_integrity_segments = 0;
 	lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
 	lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
 	lim->max_sectors = BLK_DEF_MAX_SECTORS;
@@ -213,7 +214,7 @@
 	 */
 	if (b_pfn < (min_t(u64, 0xffffffffUL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
 		dma = 1;
-	q->limits.bounce_pfn = max_low_pfn;
+	q->limits.bounce_pfn = max(max_low_pfn, b_pfn);
 #else
 	if (b_pfn < blk_max_low_pfn)
 		dma = 1;
@@ -343,7 +344,7 @@
  *   hardware can operate on without reverting to read-modify-write
  *   operations.
  */
-void blk_queue_physical_block_size(struct request_queue *q, unsigned short size)
+void blk_queue_physical_block_size(struct request_queue *q, unsigned int size)
 {
 	q->limits.physical_block_size = size;
 
@@ -455,11 +456,6 @@
 }
 EXPORT_SYMBOL(blk_queue_io_opt);
 
-/*
- * Returns the minimum that is _not_ zero, unless both are zero.
- */
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
-
 /**
  * blk_queue_stack_limits - inherit underlying queue limits for stacked drivers
  * @t:	the stacking driver (top)
@@ -514,6 +510,8 @@
 					    b->seg_boundary_mask);
 
 	t->max_segments = min_not_zero(t->max_segments, b->max_segments);
+	t->max_integrity_segments = min_not_zero(t->max_integrity_segments,
+						 b->max_integrity_segments);
 
 	t->max_segment_size = min_not_zero(t->max_segment_size,
 					   b->max_segment_size);
@@ -794,6 +792,26 @@
 }
 EXPORT_SYMBOL(blk_queue_update_dma_alignment);
 
+/**
+ * blk_queue_flush - configure queue's cache flush capability
+ * @q:		the request queue for the device
+ * @flush:	0, REQ_FLUSH or REQ_FLUSH | REQ_FUA
+ *
+ * Tell block layer cache flush capability of @q.  If it supports
+ * flushing, REQ_FLUSH should be set.  If it supports bypassing
+ * write cache for individual writes, REQ_FUA should be set.
+ */
+void blk_queue_flush(struct request_queue *q, unsigned int flush)
+{
+	WARN_ON_ONCE(flush & ~(REQ_FLUSH | REQ_FUA));
+
+	if (WARN_ON_ONCE(!(flush & REQ_FLUSH) && (flush & REQ_FUA)))
+		flush &= ~REQ_FUA;
+
+	q->flush_flags = flush & (REQ_FLUSH | REQ_FUA);
+}
+EXPORT_SYMBOL_GPL(blk_queue_flush);
+
 static int __init blk_settings_init(void)
 {
 	blk_max_low_pfn = max_low_pfn - 1;
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 0749b89..da8a8a4 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -112,6 +112,11 @@
 	return queue_var_show(queue_max_segments(q), (page));
 }
 
+static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *page)
+{
+	return queue_var_show(q->limits.max_integrity_segments, (page));
+}
+
 static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
 {
 	if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
@@ -288,6 +293,11 @@
 	.show = queue_max_segments_show,
 };
 
+static struct queue_sysfs_entry queue_max_integrity_segments_entry = {
+	.attr = {.name = "max_integrity_segments", .mode = S_IRUGO },
+	.show = queue_max_integrity_segments_show,
+};
+
 static struct queue_sysfs_entry queue_max_segment_size_entry = {
 	.attr = {.name = "max_segment_size", .mode = S_IRUGO },
 	.show = queue_max_segment_size_show,
@@ -375,6 +385,7 @@
 	&queue_max_hw_sectors_entry.attr,
 	&queue_max_sectors_entry.attr,
 	&queue_max_segments_entry.attr,
+	&queue_max_integrity_segments_entry.attr,
 	&queue_max_segment_size_entry.attr,
 	&queue_iosched_entry.attr,
 	&queue_hw_sector_size_entry.attr,
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
new file mode 100644
index 0000000..56ad453
--- /dev/null
+++ b/block/blk-throttle.c
@@ -0,0 +1,1123 @@
+/*
+ * Interface for controlling IO bandwidth on a request queue
+ *
+ * Copyright (C) 2010 Vivek Goyal <vgoyal@redhat.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/bio.h>
+#include <linux/blktrace_api.h>
+#include "blk-cgroup.h"
+
+/* Max dispatch from a group in 1 round */
+static int throtl_grp_quantum = 8;
+
+/* Total max dispatch from all groups in one round */
+static int throtl_quantum = 32;
+
+/* Throttling is performed over 100ms slice and after that slice is renewed */
+static unsigned long throtl_slice = HZ/10;	/* 100 ms */
+
+struct throtl_rb_root {
+	struct rb_root rb;
+	struct rb_node *left;
+	unsigned int count;
+	unsigned long min_disptime;
+};
+
+#define THROTL_RB_ROOT	(struct throtl_rb_root) { .rb = RB_ROOT, .left = NULL, \
+			.count = 0, .min_disptime = 0}
+
+#define rb_entry_tg(node)	rb_entry((node), struct throtl_grp, rb_node)
+
+struct throtl_grp {
+	/* List of throtl groups on the request queue*/
+	struct hlist_node tg_node;
+
+	/* active throtl group service_tree member */
+	struct rb_node rb_node;
+
+	/*
+	 * Dispatch time in jiffies. This is the estimated time when group
+	 * will unthrottle and is ready to dispatch more bio. It is used as
+	 * key to sort active groups in service tree.
+	 */
+	unsigned long disptime;
+
+	struct blkio_group blkg;
+	atomic_t ref;
+	unsigned int flags;
+
+	/* Two lists for READ and WRITE */
+	struct bio_list bio_lists[2];
+
+	/* Number of queued bios on READ and WRITE lists */
+	unsigned int nr_queued[2];
+
+	/* bytes per second rate limits */
+	uint64_t bps[2];
+
+	/* IOPS limits */
+	unsigned int iops[2];
+
+	/* Number of bytes disptached in current slice */
+	uint64_t bytes_disp[2];
+	/* Number of bio's dispatched in current slice */
+	unsigned int io_disp[2];
+
+	/* When did we start a new slice */
+	unsigned long slice_start[2];
+	unsigned long slice_end[2];
+
+	/* Some throttle limits got updated for the group */
+	bool limits_changed;
+};
+
+struct throtl_data
+{
+	/* List of throtl groups */
+	struct hlist_head tg_list;
+
+	/* service tree for active throtl groups */
+	struct throtl_rb_root tg_service_tree;
+
+	struct throtl_grp root_tg;
+	struct request_queue *queue;
+
+	/* Total Number of queued bios on READ and WRITE lists */
+	unsigned int nr_queued[2];
+
+	/*
+	 * number of total undestroyed groups
+	 */
+	unsigned int nr_undestroyed_grps;
+
+	/* Work for dispatching throttled bios */
+	struct delayed_work throtl_work;
+
+	atomic_t limits_changed;
+};
+
+enum tg_state_flags {
+	THROTL_TG_FLAG_on_rr = 0,	/* on round-robin busy list */
+};
+
+#define THROTL_TG_FNS(name)						\
+static inline void throtl_mark_tg_##name(struct throtl_grp *tg)		\
+{									\
+	(tg)->flags |= (1 << THROTL_TG_FLAG_##name);			\
+}									\
+static inline void throtl_clear_tg_##name(struct throtl_grp *tg)	\
+{									\
+	(tg)->flags &= ~(1 << THROTL_TG_FLAG_##name);			\
+}									\
+static inline int throtl_tg_##name(const struct throtl_grp *tg)		\
+{									\
+	return ((tg)->flags & (1 << THROTL_TG_FLAG_##name)) != 0;	\
+}
+
+THROTL_TG_FNS(on_rr);
+
+#define throtl_log_tg(td, tg, fmt, args...)				\
+	blk_add_trace_msg((td)->queue, "throtl %s " fmt,		\
+				blkg_path(&(tg)->blkg), ##args);      	\
+
+#define throtl_log(td, fmt, args...)	\
+	blk_add_trace_msg((td)->queue, "throtl " fmt, ##args)
+
+static inline struct throtl_grp *tg_of_blkg(struct blkio_group *blkg)
+{
+	if (blkg)
+		return container_of(blkg, struct throtl_grp, blkg);
+
+	return NULL;
+}
+
+static inline int total_nr_queued(struct throtl_data *td)
+{
+	return (td->nr_queued[0] + td->nr_queued[1]);
+}
+
+static inline struct throtl_grp *throtl_ref_get_tg(struct throtl_grp *tg)
+{
+	atomic_inc(&tg->ref);
+	return tg;
+}
+
+static void throtl_put_tg(struct throtl_grp *tg)
+{
+	BUG_ON(atomic_read(&tg->ref) <= 0);
+	if (!atomic_dec_and_test(&tg->ref))
+		return;
+	kfree(tg);
+}
+
+static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
+			struct cgroup *cgroup)
+{
+	struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
+	struct throtl_grp *tg = NULL;
+	void *key = td;
+	struct backing_dev_info *bdi = &td->queue->backing_dev_info;
+	unsigned int major, minor;
+
+	/*
+	 * TODO: Speed up blkiocg_lookup_group() by maintaining a radix
+	 * tree of blkg (instead of traversing through hash list all
+	 * the time.
+	 */
+	tg = tg_of_blkg(blkiocg_lookup_group(blkcg, key));
+
+	/* Fill in device details for root group */
+	if (tg && !tg->blkg.dev && bdi->dev && dev_name(bdi->dev)) {
+		sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
+		tg->blkg.dev = MKDEV(major, minor);
+		goto done;
+	}
+
+	if (tg)
+		goto done;
+
+	tg = kzalloc_node(sizeof(*tg), GFP_ATOMIC, td->queue->node);
+	if (!tg)
+		goto done;
+
+	INIT_HLIST_NODE(&tg->tg_node);
+	RB_CLEAR_NODE(&tg->rb_node);
+	bio_list_init(&tg->bio_lists[0]);
+	bio_list_init(&tg->bio_lists[1]);
+
+	/*
+	 * Take the initial reference that will be released on destroy
+	 * This can be thought of a joint reference by cgroup and
+	 * request queue which will be dropped by either request queue
+	 * exit or cgroup deletion path depending on who is exiting first.
+	 */
+	atomic_set(&tg->ref, 1);
+
+	/* Add group onto cgroup list */
+	sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor);
+	blkiocg_add_blkio_group(blkcg, &tg->blkg, (void *)td,
+				MKDEV(major, minor), BLKIO_POLICY_THROTL);
+
+	tg->bps[READ] = blkcg_get_read_bps(blkcg, tg->blkg.dev);
+	tg->bps[WRITE] = blkcg_get_write_bps(blkcg, tg->blkg.dev);
+	tg->iops[READ] = blkcg_get_read_iops(blkcg, tg->blkg.dev);
+	tg->iops[WRITE] = blkcg_get_write_iops(blkcg, tg->blkg.dev);
+
+	hlist_add_head(&tg->tg_node, &td->tg_list);
+	td->nr_undestroyed_grps++;
+done:
+	return tg;
+}
+
+static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
+{
+	struct cgroup *cgroup;
+	struct throtl_grp *tg = NULL;
+
+	rcu_read_lock();
+	cgroup = task_cgroup(current, blkio_subsys_id);
+	tg = throtl_find_alloc_tg(td, cgroup);
+	if (!tg)
+		tg = &td->root_tg;
+	rcu_read_unlock();
+	return tg;
+}
+
+static struct throtl_grp *throtl_rb_first(struct throtl_rb_root *root)
+{
+	/* Service tree is empty */
+	if (!root->count)
+		return NULL;
+
+	if (!root->left)
+		root->left = rb_first(&root->rb);
+
+	if (root->left)
+		return rb_entry_tg(root->left);
+
+	return NULL;
+}
+
+static void rb_erase_init(struct rb_node *n, struct rb_root *root)
+{
+	rb_erase(n, root);
+	RB_CLEAR_NODE(n);
+}
+
+static void throtl_rb_erase(struct rb_node *n, struct throtl_rb_root *root)
+{
+	if (root->left == n)
+		root->left = NULL;
+	rb_erase_init(n, &root->rb);
+	--root->count;
+}
+
+static void update_min_dispatch_time(struct throtl_rb_root *st)
+{
+	struct throtl_grp *tg;
+
+	tg = throtl_rb_first(st);
+	if (!tg)
+		return;
+
+	st->min_disptime = tg->disptime;
+}
+
+static void
+tg_service_tree_add(struct throtl_rb_root *st, struct throtl_grp *tg)
+{
+	struct rb_node **node = &st->rb.rb_node;
+	struct rb_node *parent = NULL;
+	struct throtl_grp *__tg;
+	unsigned long key = tg->disptime;
+	int left = 1;
+
+	while (*node != NULL) {
+		parent = *node;
+		__tg = rb_entry_tg(parent);
+
+		if (time_before(key, __tg->disptime))
+			node = &parent->rb_left;
+		else {
+			node = &parent->rb_right;
+			left = 0;
+		}
+	}
+
+	if (left)
+		st->left = &tg->rb_node;
+
+	rb_link_node(&tg->rb_node, parent, node);
+	rb_insert_color(&tg->rb_node, &st->rb);
+}
+
+static void __throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	struct throtl_rb_root *st = &td->tg_service_tree;
+
+	tg_service_tree_add(st, tg);
+	throtl_mark_tg_on_rr(tg);
+	st->count++;
+}
+
+static void throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	if (!throtl_tg_on_rr(tg))
+		__throtl_enqueue_tg(td, tg);
+}
+
+static void __throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	throtl_rb_erase(&tg->rb_node, &td->tg_service_tree);
+	throtl_clear_tg_on_rr(tg);
+}
+
+static void throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	if (throtl_tg_on_rr(tg))
+		__throtl_dequeue_tg(td, tg);
+}
+
+static void throtl_schedule_next_dispatch(struct throtl_data *td)
+{
+	struct throtl_rb_root *st = &td->tg_service_tree;
+
+	/*
+	 * If there are more bios pending, schedule more work.
+	 */
+	if (!total_nr_queued(td))
+		return;
+
+	BUG_ON(!st->count);
+
+	update_min_dispatch_time(st);
+
+	if (time_before_eq(st->min_disptime, jiffies))
+		throtl_schedule_delayed_work(td->queue, 0);
+	else
+		throtl_schedule_delayed_work(td->queue,
+				(st->min_disptime - jiffies));
+}
+
+static inline void
+throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
+{
+	tg->bytes_disp[rw] = 0;
+	tg->io_disp[rw] = 0;
+	tg->slice_start[rw] = jiffies;
+	tg->slice_end[rw] = jiffies + throtl_slice;
+	throtl_log_tg(td, tg, "[%c] new slice start=%lu end=%lu jiffies=%lu",
+			rw == READ ? 'R' : 'W', tg->slice_start[rw],
+			tg->slice_end[rw], jiffies);
+}
+
+static inline void throtl_extend_slice(struct throtl_data *td,
+		struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
+{
+	tg->slice_end[rw] = roundup(jiffy_end, throtl_slice);
+	throtl_log_tg(td, tg, "[%c] extend slice start=%lu end=%lu jiffies=%lu",
+			rw == READ ? 'R' : 'W', tg->slice_start[rw],
+			tg->slice_end[rw], jiffies);
+}
+
+/* Determine if previously allocated or extended slice is complete or not */
+static bool
+throtl_slice_used(struct throtl_data *td, struct throtl_grp *tg, bool rw)
+{
+	if (time_in_range(jiffies, tg->slice_start[rw], tg->slice_end[rw]))
+		return 0;
+
+	return 1;
+}
+
+/* Trim the used slices and adjust slice start accordingly */
+static inline void
+throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
+{
+	unsigned long nr_slices, time_elapsed, io_trim;
+	u64 bytes_trim, tmp;
+
+	BUG_ON(time_before(tg->slice_end[rw], tg->slice_start[rw]));
+
+	/*
+	 * If bps are unlimited (-1), then time slice don't get
+	 * renewed. Don't try to trim the slice if slice is used. A new
+	 * slice will start when appropriate.
+	 */
+	if (throtl_slice_used(td, tg, rw))
+		return;
+
+	time_elapsed = jiffies - tg->slice_start[rw];
+
+	nr_slices = time_elapsed / throtl_slice;
+
+	if (!nr_slices)
+		return;
+	tmp = tg->bps[rw] * throtl_slice * nr_slices;
+	do_div(tmp, HZ);
+	bytes_trim = tmp;
+
+	io_trim = (tg->iops[rw] * throtl_slice * nr_slices)/HZ;
+
+	if (!bytes_trim && !io_trim)
+		return;
+
+	if (tg->bytes_disp[rw] >= bytes_trim)
+		tg->bytes_disp[rw] -= bytes_trim;
+	else
+		tg->bytes_disp[rw] = 0;
+
+	if (tg->io_disp[rw] >= io_trim)
+		tg->io_disp[rw] -= io_trim;
+	else
+		tg->io_disp[rw] = 0;
+
+	tg->slice_start[rw] += nr_slices * throtl_slice;
+
+	throtl_log_tg(td, tg, "[%c] trim slice nr=%lu bytes=%llu io=%lu"
+			" start=%lu end=%lu jiffies=%lu",
+			rw == READ ? 'R' : 'W', nr_slices, bytes_trim, io_trim,
+			tg->slice_start[rw], tg->slice_end[rw], jiffies);
+}
+
+static bool tg_with_in_iops_limit(struct throtl_data *td, struct throtl_grp *tg,
+		struct bio *bio, unsigned long *wait)
+{
+	bool rw = bio_data_dir(bio);
+	unsigned int io_allowed;
+	unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
+	u64 tmp;
+
+	jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw];
+
+	/* Slice has just started. Consider one slice interval */
+	if (!jiffy_elapsed)
+		jiffy_elapsed_rnd = throtl_slice;
+
+	jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, throtl_slice);
+
+	/*
+	 * jiffy_elapsed_rnd should not be a big value as minimum iops can be
+	 * 1 then at max jiffy elapsed should be equivalent of 1 second as we
+	 * will allow dispatch after 1 second and after that slice should
+	 * have been trimmed.
+	 */
+
+	tmp = (u64)tg->iops[rw] * jiffy_elapsed_rnd;
+	do_div(tmp, HZ);
+
+	if (tmp > UINT_MAX)
+		io_allowed = UINT_MAX;
+	else
+		io_allowed = tmp;
+
+	if (tg->io_disp[rw] + 1 <= io_allowed) {
+		if (wait)
+			*wait = 0;
+		return 1;
+	}
+
+	/* Calc approx time to dispatch */
+	jiffy_wait = ((tg->io_disp[rw] + 1) * HZ)/tg->iops[rw] + 1;
+
+	if (jiffy_wait > jiffy_elapsed)
+		jiffy_wait = jiffy_wait - jiffy_elapsed;
+	else
+		jiffy_wait = 1;
+
+	if (wait)
+		*wait = jiffy_wait;
+	return 0;
+}
+
+static bool tg_with_in_bps_limit(struct throtl_data *td, struct throtl_grp *tg,
+		struct bio *bio, unsigned long *wait)
+{
+	bool rw = bio_data_dir(bio);
+	u64 bytes_allowed, extra_bytes, tmp;
+	unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
+
+	jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw];
+
+	/* Slice has just started. Consider one slice interval */
+	if (!jiffy_elapsed)
+		jiffy_elapsed_rnd = throtl_slice;
+
+	jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, throtl_slice);
+
+	tmp = tg->bps[rw] * jiffy_elapsed_rnd;
+	do_div(tmp, HZ);
+	bytes_allowed = tmp;
+
+	if (tg->bytes_disp[rw] + bio->bi_size <= bytes_allowed) {
+		if (wait)
+			*wait = 0;
+		return 1;
+	}
+
+	/* Calc approx time to dispatch */
+	extra_bytes = tg->bytes_disp[rw] + bio->bi_size - bytes_allowed;
+	jiffy_wait = div64_u64(extra_bytes * HZ, tg->bps[rw]);
+
+	if (!jiffy_wait)
+		jiffy_wait = 1;
+
+	/*
+	 * This wait time is without taking into consideration the rounding
+	 * up we did. Add that time also.
+	 */
+	jiffy_wait = jiffy_wait + (jiffy_elapsed_rnd - jiffy_elapsed);
+	if (wait)
+		*wait = jiffy_wait;
+	return 0;
+}
+
+/*
+ * Returns whether one can dispatch a bio or not. Also returns approx number
+ * of jiffies to wait before this bio is with-in IO rate and can be dispatched
+ */
+static bool tg_may_dispatch(struct throtl_data *td, struct throtl_grp *tg,
+				struct bio *bio, unsigned long *wait)
+{
+	bool rw = bio_data_dir(bio);
+	unsigned long bps_wait = 0, iops_wait = 0, max_wait = 0;
+
+	/*
+ 	 * Currently whole state machine of group depends on first bio
+	 * queued in the group bio list. So one should not be calling
+	 * this function with a different bio if there are other bios
+	 * queued.
+	 */
+	BUG_ON(tg->nr_queued[rw] && bio != bio_list_peek(&tg->bio_lists[rw]));
+
+	/* If tg->bps = -1, then BW is unlimited */
+	if (tg->bps[rw] == -1 && tg->iops[rw] == -1) {
+		if (wait)
+			*wait = 0;
+		return 1;
+	}
+
+	/*
+	 * If previous slice expired, start a new one otherwise renew/extend
+	 * existing slice to make sure it is at least throtl_slice interval
+	 * long since now.
+	 */
+	if (throtl_slice_used(td, tg, rw))
+		throtl_start_new_slice(td, tg, rw);
+	else {
+		if (time_before(tg->slice_end[rw], jiffies + throtl_slice))
+			throtl_extend_slice(td, tg, rw, jiffies + throtl_slice);
+	}
+
+	if (tg_with_in_bps_limit(td, tg, bio, &bps_wait)
+	    && tg_with_in_iops_limit(td, tg, bio, &iops_wait)) {
+		if (wait)
+			*wait = 0;
+		return 1;
+	}
+
+	max_wait = max(bps_wait, iops_wait);
+
+	if (wait)
+		*wait = max_wait;
+
+	if (time_before(tg->slice_end[rw], jiffies + max_wait))
+		throtl_extend_slice(td, tg, rw, jiffies + max_wait);
+
+	return 0;
+}
+
+static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
+{
+	bool rw = bio_data_dir(bio);
+	bool sync = bio->bi_rw & REQ_SYNC;
+
+	/* Charge the bio to the group */
+	tg->bytes_disp[rw] += bio->bi_size;
+	tg->io_disp[rw]++;
+
+	/*
+	 * TODO: This will take blkg->stats_lock. Figure out a way
+	 * to avoid this cost.
+	 */
+	blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, rw, sync);
+}
+
+static void throtl_add_bio_tg(struct throtl_data *td, struct throtl_grp *tg,
+			struct bio *bio)
+{
+	bool rw = bio_data_dir(bio);
+
+	bio_list_add(&tg->bio_lists[rw], bio);
+	/* Take a bio reference on tg */
+	throtl_ref_get_tg(tg);
+	tg->nr_queued[rw]++;
+	td->nr_queued[rw]++;
+	throtl_enqueue_tg(td, tg);
+}
+
+static void tg_update_disptime(struct throtl_data *td, struct throtl_grp *tg)
+{
+	unsigned long read_wait = -1, write_wait = -1, min_wait = -1, disptime;
+	struct bio *bio;
+
+	if ((bio = bio_list_peek(&tg->bio_lists[READ])))
+		tg_may_dispatch(td, tg, bio, &read_wait);
+
+	if ((bio = bio_list_peek(&tg->bio_lists[WRITE])))
+		tg_may_dispatch(td, tg, bio, &write_wait);
+
+	min_wait = min(read_wait, write_wait);
+	disptime = jiffies + min_wait;
+
+	/* Update dispatch time */
+	throtl_dequeue_tg(td, tg);
+	tg->disptime = disptime;
+	throtl_enqueue_tg(td, tg);
+}
+
+static void tg_dispatch_one_bio(struct throtl_data *td, struct throtl_grp *tg,
+				bool rw, struct bio_list *bl)
+{
+	struct bio *bio;
+
+	bio = bio_list_pop(&tg->bio_lists[rw]);
+	tg->nr_queued[rw]--;
+	/* Drop bio reference on tg */
+	throtl_put_tg(tg);
+
+	BUG_ON(td->nr_queued[rw] <= 0);
+	td->nr_queued[rw]--;
+
+	throtl_charge_bio(tg, bio);
+	bio_list_add(bl, bio);
+	bio->bi_rw |= REQ_THROTTLED;
+
+	throtl_trim_slice(td, tg, rw);
+}
+
+static int throtl_dispatch_tg(struct throtl_data *td, struct throtl_grp *tg,
+				struct bio_list *bl)
+{
+	unsigned int nr_reads = 0, nr_writes = 0;
+	unsigned int max_nr_reads = throtl_grp_quantum*3/4;
+	unsigned int max_nr_writes = throtl_grp_quantum - nr_reads;
+	struct bio *bio;
+
+	/* Try to dispatch 75% READS and 25% WRITES */
+
+	while ((bio = bio_list_peek(&tg->bio_lists[READ]))
+		&& tg_may_dispatch(td, tg, bio, NULL)) {
+
+		tg_dispatch_one_bio(td, tg, bio_data_dir(bio), bl);
+		nr_reads++;
+
+		if (nr_reads >= max_nr_reads)
+			break;
+	}
+
+	while ((bio = bio_list_peek(&tg->bio_lists[WRITE]))
+		&& tg_may_dispatch(td, tg, bio, NULL)) {
+
+		tg_dispatch_one_bio(td, tg, bio_data_dir(bio), bl);
+		nr_writes++;
+
+		if (nr_writes >= max_nr_writes)
+			break;
+	}
+
+	return nr_reads + nr_writes;
+}
+
+static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl)
+{
+	unsigned int nr_disp = 0;
+	struct throtl_grp *tg;
+	struct throtl_rb_root *st = &td->tg_service_tree;
+
+	while (1) {
+		tg = throtl_rb_first(st);
+
+		if (!tg)
+			break;
+
+		if (time_before(jiffies, tg->disptime))
+			break;
+
+		throtl_dequeue_tg(td, tg);
+
+		nr_disp += throtl_dispatch_tg(td, tg, bl);
+
+		if (tg->nr_queued[0] || tg->nr_queued[1]) {
+			tg_update_disptime(td, tg);
+			throtl_enqueue_tg(td, tg);
+		}
+
+		if (nr_disp >= throtl_quantum)
+			break;
+	}
+
+	return nr_disp;
+}
+
+static void throtl_process_limit_change(struct throtl_data *td)
+{
+	struct throtl_grp *tg;
+	struct hlist_node *pos, *n;
+
+	/*
+	 * Make sure atomic_inc() effects from
+	 * throtl_update_blkio_group_read_bps(), group of functions are
+	 * visible.
+	 * Is this required or smp_mb__after_atomic_inc() was suffcient
+	 * after the atomic_inc().
+	 */
+	smp_rmb();
+	if (!atomic_read(&td->limits_changed))
+		return;
+
+	throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
+
+	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
+		/*
+		 * Do I need an smp_rmb() here to make sure tg->limits_changed
+		 * update is visible. I am relying on smp_rmb() at the
+		 * beginning of function and not putting a new one here.
+		 */
+
+		if (throtl_tg_on_rr(tg) && tg->limits_changed) {
+			throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
+				" riops=%u wiops=%u", tg->bps[READ],
+				tg->bps[WRITE], tg->iops[READ],
+				tg->iops[WRITE]);
+			tg_update_disptime(td, tg);
+			tg->limits_changed = false;
+		}
+	}
+
+	smp_mb__before_atomic_dec();
+	atomic_dec(&td->limits_changed);
+	smp_mb__after_atomic_dec();
+}
+
+/* Dispatch throttled bios. Should be called without queue lock held. */
+static int throtl_dispatch(struct request_queue *q)
+{
+	struct throtl_data *td = q->td;
+	unsigned int nr_disp = 0;
+	struct bio_list bio_list_on_stack;
+	struct bio *bio;
+
+	spin_lock_irq(q->queue_lock);
+
+	throtl_process_limit_change(td);
+
+	if (!total_nr_queued(td))
+		goto out;
+
+	bio_list_init(&bio_list_on_stack);
+
+	throtl_log(td, "dispatch nr_queued=%lu read=%u write=%u",
+			total_nr_queued(td), td->nr_queued[READ],
+			td->nr_queued[WRITE]);
+
+	nr_disp = throtl_select_dispatch(td, &bio_list_on_stack);
+
+	if (nr_disp)
+		throtl_log(td, "bios disp=%u", nr_disp);
+
+	throtl_schedule_next_dispatch(td);
+out:
+	spin_unlock_irq(q->queue_lock);
+
+	/*
+	 * If we dispatched some requests, unplug the queue to make sure
+	 * immediate dispatch
+	 */
+	if (nr_disp) {
+		while((bio = bio_list_pop(&bio_list_on_stack)))
+			generic_make_request(bio);
+		blk_unplug(q);
+	}
+	return nr_disp;
+}
+
+void blk_throtl_work(struct work_struct *work)
+{
+	struct throtl_data *td = container_of(work, struct throtl_data,
+					throtl_work.work);
+	struct request_queue *q = td->queue;
+
+	throtl_dispatch(q);
+}
+
+/* Call with queue lock held */
+void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay)
+{
+
+	struct throtl_data *td = q->td;
+	struct delayed_work *dwork = &td->throtl_work;
+
+	if (total_nr_queued(td) > 0) {
+		/*
+		 * We might have a work scheduled to be executed in future.
+		 * Cancel that and schedule a new one.
+		 */
+		__cancel_delayed_work(dwork);
+		kblockd_schedule_delayed_work(q, dwork, delay);
+		throtl_log(td, "schedule work. delay=%lu jiffies=%lu",
+				delay, jiffies);
+	}
+}
+EXPORT_SYMBOL(throtl_schedule_delayed_work);
+
+static void
+throtl_destroy_tg(struct throtl_data *td, struct throtl_grp *tg)
+{
+	/* Something wrong if we are trying to remove same group twice */
+	BUG_ON(hlist_unhashed(&tg->tg_node));
+
+	hlist_del_init(&tg->tg_node);
+
+	/*
+	 * Put the reference taken at the time of creation so that when all
+	 * queues are gone, group can be destroyed.
+	 */
+	throtl_put_tg(tg);
+	td->nr_undestroyed_grps--;
+}
+
+static void throtl_release_tgs(struct throtl_data *td)
+{
+	struct hlist_node *pos, *n;
+	struct throtl_grp *tg;
+
+	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
+		/*
+		 * If cgroup removal path got to blk_group first and removed
+		 * it from cgroup list, then it will take care of destroying
+		 * cfqg also.
+		 */
+		if (!blkiocg_del_blkio_group(&tg->blkg))
+			throtl_destroy_tg(td, tg);
+	}
+}
+
+static void throtl_td_free(struct throtl_data *td)
+{
+	kfree(td);
+}
+
+/*
+ * Blk cgroup controller notification saying that blkio_group object is being
+ * delinked as associated cgroup object is going away. That also means that
+ * no new IO will come in this group. So get rid of this group as soon as
+ * any pending IO in the group is finished.
+ *
+ * This function is called under rcu_read_lock(). key is the rcu protected
+ * pointer. That means "key" is a valid throtl_data pointer as long as we are
+ * rcu read lock.
+ *
+ * "key" was fetched from blkio_group under blkio_cgroup->lock. That means
+ * it should not be NULL as even if queue was going away, cgroup deltion
+ * path got to it first.
+ */
+void throtl_unlink_blkio_group(void *key, struct blkio_group *blkg)
+{
+	unsigned long flags;
+	struct throtl_data *td = key;
+
+	spin_lock_irqsave(td->queue->queue_lock, flags);
+	throtl_destroy_tg(td, tg_of_blkg(blkg));
+	spin_unlock_irqrestore(td->queue->queue_lock, flags);
+}
+
+/*
+ * For all update functions, key should be a valid pointer because these
+ * update functions are called under blkcg_lock, that means, blkg is
+ * valid and in turn key is valid. queue exit path can not race becuase
+ * of blkcg_lock
+ *
+ * Can not take queue lock in update functions as queue lock under blkcg_lock
+ * is not allowed. Under other paths we take blkcg_lock under queue_lock.
+ */
+static void throtl_update_blkio_group_read_bps(void *key,
+				struct blkio_group *blkg, u64 read_bps)
+{
+	struct throtl_data *td = key;
+
+	tg_of_blkg(blkg)->bps[READ] = read_bps;
+	/* Make sure read_bps is updated before setting limits_changed */
+	smp_wmb();
+	tg_of_blkg(blkg)->limits_changed = true;
+
+	/* Make sure tg->limits_changed is updated before td->limits_changed */
+	smp_mb__before_atomic_inc();
+	atomic_inc(&td->limits_changed);
+	smp_mb__after_atomic_inc();
+
+	/* Schedule a work now to process the limit change */
+	throtl_schedule_delayed_work(td->queue, 0);
+}
+
+static void throtl_update_blkio_group_write_bps(void *key,
+				struct blkio_group *blkg, u64 write_bps)
+{
+	struct throtl_data *td = key;
+
+	tg_of_blkg(blkg)->bps[WRITE] = write_bps;
+	smp_wmb();
+	tg_of_blkg(blkg)->limits_changed = true;
+	smp_mb__before_atomic_inc();
+	atomic_inc(&td->limits_changed);
+	smp_mb__after_atomic_inc();
+	throtl_schedule_delayed_work(td->queue, 0);
+}
+
+static void throtl_update_blkio_group_read_iops(void *key,
+			struct blkio_group *blkg, unsigned int read_iops)
+{
+	struct throtl_data *td = key;
+
+	tg_of_blkg(blkg)->iops[READ] = read_iops;
+	smp_wmb();
+	tg_of_blkg(blkg)->limits_changed = true;
+	smp_mb__before_atomic_inc();
+	atomic_inc(&td->limits_changed);
+	smp_mb__after_atomic_inc();
+	throtl_schedule_delayed_work(td->queue, 0);
+}
+
+static void throtl_update_blkio_group_write_iops(void *key,
+			struct blkio_group *blkg, unsigned int write_iops)
+{
+	struct throtl_data *td = key;
+
+	tg_of_blkg(blkg)->iops[WRITE] = write_iops;
+	smp_wmb();
+	tg_of_blkg(blkg)->limits_changed = true;
+	smp_mb__before_atomic_inc();
+	atomic_inc(&td->limits_changed);
+	smp_mb__after_atomic_inc();
+	throtl_schedule_delayed_work(td->queue, 0);
+}
+
+void throtl_shutdown_timer_wq(struct request_queue *q)
+{
+	struct throtl_data *td = q->td;
+
+	cancel_delayed_work_sync(&td->throtl_work);
+}
+
+static struct blkio_policy_type blkio_policy_throtl = {
+	.ops = {
+		.blkio_unlink_group_fn = throtl_unlink_blkio_group,
+		.blkio_update_group_read_bps_fn =
+					throtl_update_blkio_group_read_bps,
+		.blkio_update_group_write_bps_fn =
+					throtl_update_blkio_group_write_bps,
+		.blkio_update_group_read_iops_fn =
+					throtl_update_blkio_group_read_iops,
+		.blkio_update_group_write_iops_fn =
+					throtl_update_blkio_group_write_iops,
+	},
+	.plid = BLKIO_POLICY_THROTL,
+};
+
+int blk_throtl_bio(struct request_queue *q, struct bio **biop)
+{
+	struct throtl_data *td = q->td;
+	struct throtl_grp *tg;
+	struct bio *bio = *biop;
+	bool rw = bio_data_dir(bio), update_disptime = true;
+
+	if (bio->bi_rw & REQ_THROTTLED) {
+		bio->bi_rw &= ~REQ_THROTTLED;
+		return 0;
+	}
+
+	spin_lock_irq(q->queue_lock);
+	tg = throtl_get_tg(td);
+
+	if (tg->nr_queued[rw]) {
+		/*
+		 * There is already another bio queued in same dir. No
+		 * need to update dispatch time.
+		 * Still update the disptime if rate limits on this group
+		 * were changed.
+		 */
+		if (!tg->limits_changed)
+			update_disptime = false;
+		else
+			tg->limits_changed = false;
+
+		goto queue_bio;
+	}
+
+	/* Bio is with-in rate limit of group */
+	if (tg_may_dispatch(td, tg, bio, NULL)) {
+		throtl_charge_bio(tg, bio);
+		goto out;
+	}
+
+queue_bio:
+	throtl_log_tg(td, tg, "[%c] bio. bdisp=%u sz=%u bps=%llu"
+			" iodisp=%u iops=%u queued=%d/%d",
+			rw == READ ? 'R' : 'W',
+			tg->bytes_disp[rw], bio->bi_size, tg->bps[rw],
+			tg->io_disp[rw], tg->iops[rw],
+			tg->nr_queued[READ], tg->nr_queued[WRITE]);
+
+	throtl_add_bio_tg(q->td, tg, bio);
+	*biop = NULL;
+
+	if (update_disptime) {
+		tg_update_disptime(td, tg);
+		throtl_schedule_next_dispatch(td);
+	}
+
+out:
+	spin_unlock_irq(q->queue_lock);
+	return 0;
+}
+
+int blk_throtl_init(struct request_queue *q)
+{
+	struct throtl_data *td;
+	struct throtl_grp *tg;
+
+	td = kzalloc_node(sizeof(*td), GFP_KERNEL, q->node);
+	if (!td)
+		return -ENOMEM;
+
+	INIT_HLIST_HEAD(&td->tg_list);
+	td->tg_service_tree = THROTL_RB_ROOT;
+	atomic_set(&td->limits_changed, 0);
+
+	/* Init root group */
+	tg = &td->root_tg;
+	INIT_HLIST_NODE(&tg->tg_node);
+	RB_CLEAR_NODE(&tg->rb_node);
+	bio_list_init(&tg->bio_lists[0]);
+	bio_list_init(&tg->bio_lists[1]);
+
+	/* Practically unlimited BW */
+	tg->bps[0] = tg->bps[1] = -1;
+	tg->iops[0] = tg->iops[1] = -1;
+
+	/*
+	 * Set root group reference to 2. One reference will be dropped when
+	 * all groups on tg_list are being deleted during queue exit. Other
+	 * reference will remain there as we don't want to delete this group
+	 * as it is statically allocated and gets destroyed when throtl_data
+	 * goes away.
+	 */
+	atomic_set(&tg->ref, 2);
+	hlist_add_head(&tg->tg_node, &td->tg_list);
+	td->nr_undestroyed_grps++;
+
+	INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work);
+
+	rcu_read_lock();
+	blkiocg_add_blkio_group(&blkio_root_cgroup, &tg->blkg, (void *)td,
+					0, BLKIO_POLICY_THROTL);
+	rcu_read_unlock();
+
+	/* Attach throtl data to request queue */
+	td->queue = q;
+	q->td = td;
+	return 0;
+}
+
+void blk_throtl_exit(struct request_queue *q)
+{
+	struct throtl_data *td = q->td;
+	bool wait = false;
+
+	BUG_ON(!td);
+
+	throtl_shutdown_timer_wq(q);
+
+	spin_lock_irq(q->queue_lock);
+	throtl_release_tgs(td);
+
+	/* If there are other groups */
+	if (td->nr_undestroyed_grps > 0)
+		wait = true;
+
+	spin_unlock_irq(q->queue_lock);
+
+	/*
+	 * Wait for tg->blkg->key accessors to exit their grace periods.
+	 * Do this wait only if there are other undestroyed groups out
+	 * there (other than root group). This can happen if cgroup deletion
+	 * path claimed the responsibility of cleaning up a group before
+	 * queue cleanup code get to the group.
+	 *
+	 * Do not call synchronize_rcu() unconditionally as there are drivers
+	 * which create/delete request queue hundreds of times during scan/boot
+	 * and synchronize_rcu() can take significant time and slow down boot.
+	 */
+	if (wait)
+		synchronize_rcu();
+
+	/*
+	 * Just being safe to make sure after previous flush if some body did
+	 * update limits through cgroup and another work got queued, cancel
+	 * it.
+	 */
+	throtl_shutdown_timer_wq(q);
+	throtl_td_free(td);
+}
+
+static int __init throtl_init(void)
+{
+	blkio_policy_register(&blkio_policy_throtl);
+	return 0;
+}
+
+module_init(throtl_init);
diff --git a/block/blk.h b/block/blk.h
index d6b911a..1e675e5 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -51,6 +51,8 @@
  */
 #define ELV_ON_HASH(rq)		(!hlist_unhashed(&(rq)->hash))
 
+struct request *blk_do_flush(struct request_queue *q, struct request *rq);
+
 static inline struct request *__elv_next_request(struct request_queue *q)
 {
 	struct request *rq;
@@ -58,7 +60,11 @@
 	while (1) {
 		while (!list_empty(&q->queue_head)) {
 			rq = list_entry_rq(q->queue_head.next);
-			if (blk_do_ordered(q, &rq))
+			if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) ||
+			    rq == &q->flush_rq)
+				return rq;
+			rq = blk_do_flush(q, rq);
+			if (rq)
 				return rq;
 		}
 
@@ -110,10 +116,6 @@
 
 int blk_dev_init(void);
 
-void elv_quiesce_start(struct request_queue *q);
-void elv_quiesce_end(struct request_queue *q);
-
-
 /*
  * Return the threshold (number of used requests) at which the queue is
  * considered to be congested.  It include a little hysteresis to keep the
@@ -132,14 +134,6 @@
 	return q->nr_congestion_off;
 }
 
-#if defined(CONFIG_BLK_DEV_INTEGRITY)
-
-#define rq_for_each_integrity_segment(bvl, _rq, _iter)		\
-	__rq_for_each_bio(_iter.bio, _rq)			\
-		bip_for_each_vec(bvl, _iter.bio->bi_integrity, _iter.i)
-
-#endif /* BLK_DEV_INTEGRITY */
-
 static inline int blk_cpu_to_group(int cpu)
 {
 	int group = NR_CPUS;
diff --git a/block/bsg.c b/block/bsg.c
index 0c00870..f20d6a7 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -20,7 +20,6 @@
 #include <linux/uio.h>
 #include <linux/idr.h>
 #include <linux/bsg.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -843,9 +842,7 @@
 {
 	struct bsg_device *bd;
 
-	lock_kernel();
 	bd = bsg_get_device(inode, file);
-	unlock_kernel();
 
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
@@ -968,6 +965,7 @@
 	.release	=	bsg_release,
 	.unlocked_ioctl	=	bsg_ioctl,
 	.owner		=	THIS_MODULE,
+	.llseek		=	default_llseek,
 };
 
 void bsg_unregister_queue(struct request_queue *q)
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 9eba291..4cd59b0 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -160,6 +160,7 @@
 	BE_WORKLOAD = 0,
 	RT_WORKLOAD = 1,
 	IDLE_WORKLOAD = 2,
+	CFQ_PRIO_NR,
 };
 
 /*
@@ -184,10 +185,19 @@
 	/* number of cfqq currently on this group */
 	int nr_cfqq;
 
-	/* Per group busy queus average. Useful for workload slice calc. */
-	unsigned int busy_queues_avg[2];
 	/*
-	 * rr lists of queues with requests, onle rr for each priority class.
+	 * Per group busy queus average. Useful for workload slice calc. We
+	 * create the array for each prio class but at run time it is used
+	 * only for RT and BE class and slot for IDLE class remains unused.
+	 * This is primarily done to avoid confusion and a gcc warning.
+	 */
+	unsigned int busy_queues_avg[CFQ_PRIO_NR];
+	/*
+	 * rr lists of queues with requests. We maintain service trees for
+	 * RT and BE classes. These trees are subdivided in subclasses
+	 * of SYNC, SYNC_NOIDLE and ASYNC based on workload type. For IDLE
+	 * class there is no subclassification and all the cfq queues go on
+	 * a single tree service_tree_idle.
 	 * Counts are embedded in the cfq_rb_root
 	 */
 	struct cfq_rb_root service_trees[2][3];
@@ -221,7 +231,6 @@
 	enum wl_type_t serving_type;
 	unsigned long workload_expires;
 	struct cfq_group *serving_group;
-	bool noidle_tree_requires_idle;
 
 	/*
 	 * Each priority tree is sorted by next_request position.  These
@@ -977,8 +986,8 @@
 	return NULL;
 }
 
-void
-cfq_update_blkio_group_weight(struct blkio_group *blkg, unsigned int weight)
+void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
+					unsigned int weight)
 {
 	cfqg_of_blkg(blkg)->weight = weight;
 }
@@ -2180,7 +2189,6 @@
 	slice = max_t(unsigned, slice, CFQ_MIN_TT);
 	cfq_log(cfqd, "workload slice:%d", slice);
 	cfqd->workload_expires = jiffies + slice;
-	cfqd->noidle_tree_requires_idle = false;
 }
 
 static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd)
@@ -3177,7 +3185,9 @@
 	if (cfqq->queued[0] + cfqq->queued[1] >= 4)
 		cfq_mark_cfqq_deep(cfqq);
 
-	if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
+	if (cfqq->next_rq && (cfqq->next_rq->cmd_flags & REQ_NOIDLE))
+		enable_idle = 0;
+	else if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
 	    (!cfq_cfqq_deep(cfqq) && CFQQ_SEEKY(cfqq)))
 		enable_idle = 0;
 	else if (sample_valid(cic->ttime_samples)) {
@@ -3494,17 +3504,7 @@
 			cfq_slice_expired(cfqd, 1);
 		else if (sync && cfqq_empty &&
 			 !cfq_close_cooperator(cfqd, cfqq)) {
-			cfqd->noidle_tree_requires_idle |=
-				!(rq->cmd_flags & REQ_NOIDLE);
-			/*
-			 * Idling is enabled for SYNC_WORKLOAD.
-			 * SYNC_NOIDLE_WORKLOAD idles at the end of the tree
-			 * only if we processed at least one !REQ_NOIDLE request
-			 */
-			if (cfqd->serving_type == SYNC_WORKLOAD
-			    || cfqd->noidle_tree_requires_idle
-			    || cfqq->cfqg->nr_cfqq == 1)
-				cfq_arm_slice_timer(cfqd);
+			cfq_arm_slice_timer(cfqd);
 		}
 	}
 
@@ -4090,6 +4090,7 @@
 		.blkio_unlink_group_fn =	cfq_unlink_blkio_group,
 		.blkio_update_group_weight_fn =	cfq_update_blkio_group_weight,
 	},
+	.plid = BLKIO_POLICY_PROP,
 };
 #else
 static struct blkio_policy_type blkio_policy_cfq;
diff --git a/block/cfq.h b/block/cfq.h
index 93448e5..54a6d90 100644
--- a/block/cfq.h
+++ b/block/cfq.h
@@ -69,7 +69,7 @@
 
 static inline void cfq_blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
 			struct blkio_group *blkg, void *key, dev_t dev) {
-	blkiocg_add_blkio_group(blkcg, blkg, key, dev);
+	blkiocg_add_blkio_group(blkcg, blkg, key, dev, BLKIO_POLICY_PROP);
 }
 
 static inline int cfq_blkiocg_del_blkio_group(struct blkio_group *blkg)
diff --git a/block/elevator.c b/block/elevator.c
index 4e11559..282e830 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -617,8 +617,6 @@
 
 void elv_insert(struct request_queue *q, struct request *rq, int where)
 {
-	struct list_head *pos;
-	unsigned ordseq;
 	int unplug_it = 1;
 
 	trace_block_rq_insert(q, rq);
@@ -626,9 +624,16 @@
 	rq->q = q;
 
 	switch (where) {
+	case ELEVATOR_INSERT_REQUEUE:
+		/*
+		 * Most requeues happen because of a busy condition,
+		 * don't force unplug of the queue for that case.
+		 * Clear unplug_it and fall through.
+		 */
+		unplug_it = 0;
+
 	case ELEVATOR_INSERT_FRONT:
 		rq->cmd_flags |= REQ_SOFTBARRIER;
-
 		list_add(&rq->queuelist, &q->queue_head);
 		break;
 
@@ -668,36 +673,6 @@
 		q->elevator->ops->elevator_add_req_fn(q, rq);
 		break;
 
-	case ELEVATOR_INSERT_REQUEUE:
-		/*
-		 * If ordered flush isn't in progress, we do front
-		 * insertion; otherwise, requests should be requeued
-		 * in ordseq order.
-		 */
-		rq->cmd_flags |= REQ_SOFTBARRIER;
-
-		/*
-		 * Most requeues happen because of a busy condition,
-		 * don't force unplug of the queue for that case.
-		 */
-		unplug_it = 0;
-
-		if (q->ordseq == 0) {
-			list_add(&rq->queuelist, &q->queue_head);
-			break;
-		}
-
-		ordseq = blk_ordered_req_seq(rq);
-
-		list_for_each(pos, &q->queue_head) {
-			struct request *pos_rq = list_entry_rq(pos);
-			if (ordseq <= blk_ordered_req_seq(pos_rq))
-				break;
-		}
-
-		list_add_tail(&rq->queuelist, pos);
-		break;
-
 	default:
 		printk(KERN_ERR "%s: bad insertion point %d\n",
 		       __func__, where);
@@ -716,26 +691,8 @@
 void __elv_add_request(struct request_queue *q, struct request *rq, int where,
 		       int plug)
 {
-	if (q->ordcolor)
-		rq->cmd_flags |= REQ_ORDERED_COLOR;
-
 	if (rq->cmd_flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
-		/*
-		 * toggle ordered color
-		 */
-		if (rq->cmd_flags & REQ_HARDBARRIER)
-			q->ordcolor ^= 1;
-
-		/*
-		 * barriers implicitly indicate back insertion
-		 */
-		if (where == ELEVATOR_INSERT_SORT)
-			where = ELEVATOR_INSERT_BACK;
-
-		/*
-		 * this request is scheduling boundary, update
-		 * end_sector
-		 */
+		/* barriers are scheduling boundary, update end_sector */
 		if (rq->cmd_type == REQ_TYPE_FS ||
 		    (rq->cmd_flags & REQ_DISCARD)) {
 			q->end_sector = rq_end_sector(rq);
@@ -855,24 +812,6 @@
 		    e->ops->elevator_completed_req_fn)
 			e->ops->elevator_completed_req_fn(q, rq);
 	}
-
-	/*
-	 * Check if the queue is waiting for fs requests to be
-	 * drained for flush sequence.
-	 */
-	if (unlikely(q->ordseq)) {
-		struct request *next = NULL;
-
-		if (!list_empty(&q->queue_head))
-			next = list_entry_rq(q->queue_head.next);
-
-		if (!queue_in_flight(q) &&
-		    blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN &&
-		    (!next || blk_ordered_req_seq(next) > QUEUE_ORDSEQ_DRAIN)) {
-			blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0);
-			__blk_run_queue(q);
-		}
-	}
 }
 
 #define to_elv(atr) container_of((atr), struct elv_fs_entry, attr)
diff --git a/block/genhd.c b/block/genhd.c
index 59a2db6..a8adf96 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -22,9 +22,7 @@
 #include "blk.h"
 
 static DEFINE_MUTEX(block_class_lock);
-#ifndef CONFIG_SYSFS_DEPRECATED
 struct kobject *block_depr;
-#endif
 
 /* for extended dynamic devt allocation, currently only one major is used */
 #define MAX_EXT_DEVT		(1 << MINORBITS)
@@ -541,13 +539,15 @@
 	disk->major = MAJOR(devt);
 	disk->first_minor = MINOR(devt);
 
+	/* Register BDI before referencing it from bdev */ 
+	bdi = &disk->queue->backing_dev_info;
+	bdi_register_dev(bdi, disk_devt(disk));
+
 	blk_register_region(disk_devt(disk), 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, disk_devt(disk));
 	retval = sysfs_create_link(&disk_to_dev(disk)->kobj, &bdi->dev->kobj,
 				   "bdi");
 	WARN_ON(retval);
@@ -642,6 +642,7 @@
 		struct hd_struct *part;
 		char name_buf[BDEVNAME_SIZE];
 		char devt_buf[BDEVT_SIZE];
+		u8 uuid[PARTITION_META_INFO_UUIDLTH * 2 + 1];
 
 		/*
 		 * Don't show empty devices or things that have been
@@ -660,10 +661,14 @@
 		while ((part = disk_part_iter_next(&piter))) {
 			bool is_part0 = part == &disk->part0;
 
-			printk("%s%s %10llu %s", is_part0 ? "" : "  ",
+			uuid[0] = 0;
+			if (part->info)
+				part_unpack_uuid(part->info->uuid, uuid);
+
+			printk("%s%s %10llu %s %s", is_part0 ? "" : "  ",
 			       bdevt_str(part_devt(part), devt_buf),
 			       (unsigned long long)part->nr_sects >> 1,
-			       disk_name(disk, part->partno, name_buf));
+			       disk_name(disk, part->partno, name_buf), uuid);
 			if (is_part0) {
 				if (disk->driverfs_dev != NULL &&
 				    disk->driverfs_dev->driver != NULL)
@@ -803,10 +808,9 @@
 
 	register_blkdev(BLOCK_EXT_MAJOR, "blkext");
 
-#ifndef CONFIG_SYSFS_DEPRECATED
 	/* create top-level block dir */
-	block_depr = kobject_create_and_add("block", NULL);
-#endif
+	if (!sysfs_deprecated)
+		block_depr = kobject_create_and_add("block", NULL);
 	return 0;
 }
 
@@ -925,8 +929,15 @@
 {
 	struct disk_part_tbl *ptbl =
 		container_of(head, struct disk_part_tbl, rcu_head);
+	struct gendisk *disk = ptbl->disk;
+	struct request_queue *q = disk->queue;
+	unsigned long flags;
 
 	kfree(ptbl);
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	elv_quiesce_end(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 /**
@@ -944,11 +955,17 @@
 				  struct disk_part_tbl *new_ptbl)
 {
 	struct disk_part_tbl *old_ptbl = disk->part_tbl;
+	struct request_queue *q = disk->queue;
 
 	rcu_assign_pointer(disk->part_tbl, new_ptbl);
 
 	if (old_ptbl) {
 		rcu_assign_pointer(old_ptbl->last_lookup, NULL);
+
+		spin_lock_irq(q->queue_lock);
+		elv_quiesce_start(q);
+		spin_unlock_irq(q->queue_lock);
+
 		call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
 	}
 }
@@ -989,6 +1006,7 @@
 		return -ENOMEM;
 
 	new_ptbl->len = target;
+	new_ptbl->disk = disk;
 
 	for (i = 0; i < len; i++)
 		rcu_assign_pointer(new_ptbl->part[i], old_ptbl->part[i]);
@@ -1004,6 +1022,7 @@
 	kfree(disk->random);
 	disk_replace_part_tbl(disk, NULL);
 	free_part_stats(&disk->part0);
+	free_part_info(&disk->part0);
 	kfree(disk);
 }
 struct class block_class = {
diff --git a/block/ioctl.c b/block/ioctl.c
index d8052f0..d724ceb 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -62,7 +62,7 @@
 
 			/* all seems OK */
 			part = add_partition(disk, partno, start, length,
-					     ADDPART_FLAG_NONE);
+					     ADDPART_FLAG_NONE, NULL);
 			mutex_unlock(&bdev->bd_mutex);
 			return IS_ERR(part) ? PTR_ERR(part) : 0;
 		case BLKPG_DEL_PARTITION:
@@ -116,7 +116,7 @@
 static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
 			     uint64_t len, int secure)
 {
-	unsigned long flags = BLKDEV_IFL_WAIT;
+	unsigned long flags = 0;
 
 	if (start & 511)
 		return -EINVAL;
@@ -128,7 +128,7 @@
 	if (start + len > (bdev->bd_inode->i_size >> 9))
 		return -EINVAL;
 	if (secure)
-		flags |= BLKDEV_IFL_SECURE;
+		flags |= BLKDEV_DISCARD_SECURE;
 	return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags);
 }
 
diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c
index da1228a..de73caf 100644
--- a/drivers/acpi/apei/erst-dbg.c
+++ b/drivers/acpi/apei/erst-dbg.c
@@ -184,6 +184,7 @@
 	.read		= erst_dbg_read,
 	.write		= erst_dbg_write,
 	.unlocked_ioctl	= erst_dbg_ioctl,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice erst_dbg_dev = {
diff --git a/drivers/acpi/debugfs.c b/drivers/acpi/debugfs.c
index 7de27d4..6355b57 100644
--- a/drivers/acpi/debugfs.c
+++ b/drivers/acpi/debugfs.c
@@ -69,6 +69,7 @@
 
 static const struct file_operations cm_fops = {
 	.write = cm_write,
+	.llseek = default_llseek,
 };
 
 int __init acpi_debugfs_init(void)
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
index 0e869b3..411620e 100644
--- a/drivers/acpi/ec_sys.c
+++ b/drivers/acpi/ec_sys.c
@@ -101,6 +101,7 @@
 	.open  = acpi_ec_open_io,
 	.read  = acpi_ec_read_io,
 	.write = acpi_ec_write_io,
+	.llseek = default_llseek,
 };
 
 int acpi_ec_add_debugfs(struct acpi_ec *ec, unsigned int ec_device_count)
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index d439314..85d9089 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -110,6 +110,7 @@
 	.read = acpi_system_read_event,
 	.release = acpi_system_close_event,
 	.poll = acpi_system_poll_event,
+	.llseek = default_llseek,
 };
 #endif	/* CONFIG_ACPI_PROC_EVENT */
 
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 14d18bf..d05387d 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -3335,7 +3335,7 @@
 
 int __init ata_sff_init(void)
 {
-	ata_sff_wq = alloc_workqueue("ata_sff", WQ_RESCUER, WQ_MAX_ACTIVE);
+	ata_sff_wq = alloc_workqueue("ata_sff", WQ_MEM_RECLAIM, WQ_MAX_ACTIVE);
 	if (!ata_sff_wq)
 		return -ENOMEM;
 
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index ef38aff..fd96345 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -71,7 +71,6 @@
 
 config FW_LOADER
 	tristate "Userspace firmware loading support" if EMBEDDED
-	depends on HOTPLUG
 	default y
 	---help---
 	  This option is provided for the case where no in-kernel-tree modules
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index c12c7f2..5f51c3b 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -19,7 +19,5 @@
 endif
 obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
 
-ifeq ($(CONFIG_DEBUG_DRIVER),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index eb1b7fa..33c270a 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -440,22 +440,6 @@
 	}
 }
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-static int make_deprecated_bus_links(struct device *dev)
-{
-	return sysfs_create_link(&dev->kobj,
-				 &dev->bus->p->subsys.kobj, "bus");
-}
-
-static void remove_deprecated_bus_links(struct device *dev)
-{
-	sysfs_remove_link(&dev->kobj, "bus");
-}
-#else
-static inline int make_deprecated_bus_links(struct device *dev) { return 0; }
-static inline void remove_deprecated_bus_links(struct device *dev) { }
-#endif
-
 /**
  * bus_add_device - add device to bus
  * @dev: device being added
@@ -482,15 +466,10 @@
 				&dev->bus->p->subsys.kobj, "subsystem");
 		if (error)
 			goto out_subsys;
-		error = make_deprecated_bus_links(dev);
-		if (error)
-			goto out_deprecated;
 		klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
 	}
 	return 0;
 
-out_deprecated:
-	sysfs_remove_link(&dev->kobj, "subsystem");
 out_subsys:
 	sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
 out_id:
@@ -530,7 +509,6 @@
 {
 	if (dev->bus) {
 		sysfs_remove_link(&dev->kobj, "subsystem");
-		remove_deprecated_bus_links(dev);
 		sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
 				  dev_name(dev));
 		device_remove_attrs(dev->bus, dev);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 8e231d0..9c63a56 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -184,9 +184,9 @@
 	if (!cls->dev_kobj)
 		cls->dev_kobj = sysfs_dev_char_kobj;
 
-#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
+#if defined(CONFIG_BLOCK)
 	/* let the block class directory show up in the root of sysfs */
-	if (cls != &block_class)
+	if (!sysfs_deprecated || cls != &block_class)
 		cp->class_subsys.kobj.kset = class_kset;
 #else
 	cp->class_subsys.kobj.kset = class_kset;
@@ -276,25 +276,6 @@
 	class_unregister(cls);
 }
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-char *make_class_name(const char *name, struct kobject *kobj)
-{
-	char *class_name;
-	int size;
-
-	size = strlen(name) + strlen(kobject_name(kobj)) + 2;
-
-	class_name = kmalloc(size, GFP_KERNEL);
-	if (!class_name)
-		return NULL;
-
-	strcpy(class_name, name);
-	strcat(class_name, ":");
-	strcat(class_name, kobject_name(kobj));
-	return class_name;
-}
-#endif
-
 /**
  * class_dev_iter_init - initialize class device iterator
  * @iter: class iterator to initialize
diff --git a/drivers/base/core.c b/drivers/base/core.c
index d1b2c9a..2cb49a9 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -26,6 +26,19 @@
 #include "base.h"
 #include "power/power.h"
 
+#ifdef CONFIG_SYSFS_DEPRECATED
+#ifdef CONFIG_SYSFS_DEPRECATED_V2
+long sysfs_deprecated = 1;
+#else
+long sysfs_deprecated = 0;
+#endif
+static __init int sysfs_deprecated_setup(char *arg)
+{
+	return strict_strtol(arg, 10, &sysfs_deprecated);
+}
+early_param("sysfs.deprecated", sysfs_deprecated_setup);
+#endif
+
 int (*platform_notify)(struct device *dev) = NULL;
 int (*platform_notify_remove)(struct device *dev) = NULL;
 static struct kobject *dev_kobj;
@@ -203,37 +216,6 @@
 	if (dev->driver)
 		add_uevent_var(env, "DRIVER=%s", dev->driver->name);
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if (dev->class) {
-		struct device *parent = dev->parent;
-
-		/* find first bus device in parent chain */
-		while (parent && !parent->bus)
-			parent = parent->parent;
-		if (parent && parent->bus) {
-			const char *path;
-
-			path = kobject_get_path(&parent->kobj, GFP_KERNEL);
-			if (path) {
-				add_uevent_var(env, "PHYSDEVPATH=%s", path);
-				kfree(path);
-			}
-
-			add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
-
-			if (parent->driver)
-				add_uevent_var(env, "PHYSDEVDRIVER=%s",
-					       parent->driver->name);
-		}
-	} else if (dev->bus) {
-		add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
-
-		if (dev->driver)
-			add_uevent_var(env, "PHYSDEVDRIVER=%s",
-				       dev->driver->name);
-	}
-#endif
-
 	/* have the bus specific function add its stuff */
 	if (dev->bus && dev->bus->uevent) {
 		retval = dev->bus->uevent(dev, env);
@@ -578,24 +560,6 @@
 	set_dev_node(dev, -1);
 }
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-static struct kobject *get_device_parent(struct device *dev,
-					 struct device *parent)
-{
-	/* class devices without a parent live in /sys/class/<classname>/ */
-	if (dev->class && (!parent || parent->class != dev->class))
-		return &dev->class->p->class_subsys.kobj;
-	/* all other devices keep their parent */
-	else if (parent)
-		return &parent->kobj;
-
-	return NULL;
-}
-
-static inline void cleanup_device_parent(struct device *dev) {}
-static inline void cleanup_glue_dir(struct device *dev,
-				    struct kobject *glue_dir) {}
-#else
 static struct kobject *virtual_device_parent(struct device *dev)
 {
 	static struct kobject *virtual_dir = NULL;
@@ -666,6 +630,15 @@
 		struct kobject *parent_kobj;
 		struct kobject *k;
 
+#ifdef CONFIG_BLOCK
+		/* block disks show up in /sys/block */
+		if (sysfs_deprecated && dev->class == &block_class) {
+			if (parent && parent->class == &block_class)
+				return &parent->kobj;
+			return &block_class.p->class_subsys.kobj;
+		}
+#endif
+
 		/*
 		 * If we have no parent, we live in "virtual".
 		 * Class-devices with a non class-device as parent, live
@@ -719,7 +692,6 @@
 {
 	cleanup_glue_dir(dev, dev->kobj.parent);
 }
-#endif
 
 static void setup_parent(struct device *dev, struct device *parent)
 {
@@ -742,70 +714,29 @@
 	if (error)
 		goto out;
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	/* stacked class devices need a symlink in the class directory */
-	if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
-	    device_is_not_partition(dev)) {
-		error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
-					  &dev->kobj, dev_name(dev));
-		if (error)
-			goto out_subsys;
-	}
-
-	if (dev->parent && device_is_not_partition(dev)) {
-		struct device *parent = dev->parent;
-		char *class_name;
-
-		/*
-		 * stacked class devices have the 'device' link
-		 * pointing to the bus device instead of the parent
-		 */
-		while (parent->class && !parent->bus && parent->parent)
-			parent = parent->parent;
-
-		error = sysfs_create_link(&dev->kobj,
-					  &parent->kobj,
-					  "device");
-		if (error)
-			goto out_busid;
-
-		class_name = make_class_name(dev->class->name,
-						&dev->kobj);
-		if (class_name)
-			error = sysfs_create_link(&dev->parent->kobj,
-						&dev->kobj, class_name);
-		kfree(class_name);
-		if (error)
-			goto out_device;
-	}
-	return 0;
-
-out_device:
-	if (dev->parent && device_is_not_partition(dev))
-		sysfs_remove_link(&dev->kobj, "device");
-out_busid:
-	if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
-	    device_is_not_partition(dev))
-		sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
-				  dev_name(dev));
-#else
-	/* link in the class directory pointing to the device */
-	error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
-				  &dev->kobj, dev_name(dev));
-	if (error)
-		goto out_subsys;
-
 	if (dev->parent && device_is_not_partition(dev)) {
 		error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
 					  "device");
 		if (error)
-			goto out_busid;
+			goto out_subsys;
 	}
+
+#ifdef CONFIG_BLOCK
+	/* /sys/block has directories and does not need symlinks */
+	if (sysfs_deprecated && dev->class == &block_class)
+		return 0;
+#endif
+
+	/* link in the class directory pointing to the device */
+	error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
+				  &dev->kobj, dev_name(dev));
+	if (error)
+		goto out_device;
+
 	return 0;
 
-out_busid:
-	sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
-#endif
+out_device:
+	sysfs_remove_link(&dev->kobj, "device");
 
 out_subsys:
 	sysfs_remove_link(&dev->kobj, "subsystem");
@@ -818,30 +749,14 @@
 	if (!dev->class)
 		return;
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if (dev->parent && device_is_not_partition(dev)) {
-		char *class_name;
-
-		class_name = make_class_name(dev->class->name, &dev->kobj);
-		if (class_name) {
-			sysfs_remove_link(&dev->parent->kobj, class_name);
-			kfree(class_name);
-		}
-		sysfs_remove_link(&dev->kobj, "device");
-	}
-
-	if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
-	    device_is_not_partition(dev))
-		sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj,
-				  dev_name(dev));
-#else
 	if (dev->parent && device_is_not_partition(dev))
 		sysfs_remove_link(&dev->kobj, "device");
-
-	sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
-#endif
-
 	sysfs_remove_link(&dev->kobj, "subsystem");
+#ifdef CONFIG_BLOCK
+	if (sysfs_deprecated && dev->class == &block_class)
+		return;
+#endif
+	sysfs_delete_link(&dev->class->p->class_subsys.kobj, &dev->kobj, dev_name(dev));
 }
 
 /**
@@ -1613,41 +1528,23 @@
 	pr_debug("device: '%s': %s: renaming to '%s'\n", dev_name(dev),
 		 __func__, new_name);
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if ((dev->class) && (dev->parent))
-		old_class_name = make_class_name(dev->class->name, &dev->kobj);
-#endif
-
 	old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
 	if (!old_device_name) {
 		error = -ENOMEM;
 		goto out;
 	}
 
-#ifndef CONFIG_SYSFS_DEPRECATED
 	if (dev->class) {
 		error = sysfs_rename_link(&dev->class->p->class_subsys.kobj,
 			&dev->kobj, old_device_name, new_name);
 		if (error)
 			goto out;
 	}
-#endif
+
 	error = kobject_rename(&dev->kobj, new_name);
 	if (error)
 		goto out;
 
-#ifdef CONFIG_SYSFS_DEPRECATED
-	if (old_class_name) {
-		new_class_name = make_class_name(dev->class->name, &dev->kobj);
-		if (new_class_name) {
-			error = sysfs_rename_link(&dev->parent->kobj,
-						  &dev->kobj,
-						  old_class_name,
-						  new_class_name);
-		}
-	}
-#endif
-
 out:
 	put_device(dev);
 
@@ -1664,40 +1561,13 @@
 				   struct device *new_parent)
 {
 	int error = 0;
-#ifdef CONFIG_SYSFS_DEPRECATED
-	char *class_name;
 
-	class_name = make_class_name(dev->class->name, &dev->kobj);
-	if (!class_name) {
-		error = -ENOMEM;
-		goto out;
-	}
-	if (old_parent) {
-		sysfs_remove_link(&dev->kobj, "device");
-		sysfs_remove_link(&old_parent->kobj, class_name);
-	}
-	if (new_parent) {
-		error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
-					  "device");
-		if (error)
-			goto out;
-		error = sysfs_create_link(&new_parent->kobj, &dev->kobj,
-					  class_name);
-		if (error)
-			sysfs_remove_link(&dev->kobj, "device");
-	} else
-		error = 0;
-out:
-	kfree(class_name);
-	return error;
-#else
 	if (old_parent)
 		sysfs_remove_link(&dev->kobj, "device");
 	if (new_parent)
 		error = sysfs_create_link(&dev->kobj, &new_parent->kobj,
 					  "device");
 	return error;
-#endif
 }
 
 /**
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 933442f..cafeaaf 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -27,6 +27,8 @@
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(mem_sysfs_mutex);
+
 #define MEMORY_CLASS_NAME	"memory"
 
 static struct sysdev_class memory_sysdev_class = {
@@ -435,6 +437,45 @@
 	return 0;
 }
 
+struct memory_block *find_memory_block_hinted(struct mem_section *section,
+					      struct memory_block *hint)
+{
+	struct kobject *kobj;
+	struct sys_device *sysdev;
+	struct memory_block *mem;
+	char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+
+	kobj = hint ? &hint->sysdev.kobj : NULL;
+
+	/*
+	 * This only works because we know that section == sysdev->id
+	 * slightly redundant with sysdev_register()
+	 */
+	sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
+
+	kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
+	if (!kobj)
+		return NULL;
+
+	sysdev = container_of(kobj, struct sys_device, kobj);
+	mem = container_of(sysdev, struct memory_block, sysdev);
+
+	return mem;
+}
+
+/*
+ * For now, we have a linear search to go find the appropriate
+ * memory_block corresponding to a particular phys_index. If
+ * this gets to be a real problem, we can always use a radix
+ * tree or something here.
+ *
+ * This could be made generic for all sysdev classes.
+ */
+struct memory_block *find_memory_block(struct mem_section *section)
+{
+	return find_memory_block_hinted(section, NULL);
+}
+
 static int add_memory_block(int nid, struct mem_section *section,
 			unsigned long state, enum mem_add_context context)
 {
@@ -445,8 +486,11 @@
 	if (!mem)
 		return -ENOMEM;
 
+	mutex_lock(&mem_sysfs_mutex);
+
 	mem->phys_index = __section_nr(section);
 	mem->state = state;
+	mem->section_count++;
 	mutex_init(&mem->state_mutex);
 	start_pfn = section_nr_to_pfn(mem->phys_index);
 	mem->phys_device = arch_get_memory_phys_device(start_pfn);
@@ -465,53 +509,29 @@
 			ret = register_mem_sect_under_node(mem, nid);
 	}
 
+	mutex_unlock(&mem_sysfs_mutex);
 	return ret;
 }
 
-/*
- * For now, we have a linear search to go find the appropriate
- * memory_block corresponding to a particular phys_index. If
- * this gets to be a real problem, we can always use a radix
- * tree or something here.
- *
- * This could be made generic for all sysdev classes.
- */
-struct memory_block *find_memory_block(struct mem_section *section)
-{
-	struct kobject *kobj;
-	struct sys_device *sysdev;
-	struct memory_block *mem;
-	char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
-
-	/*
-	 * This only works because we know that section == sysdev->id
-	 * slightly redundant with sysdev_register()
-	 */
-	sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
-
-	kobj = kset_find_obj(&memory_sysdev_class.kset, name);
-	if (!kobj)
-		return NULL;
-
-	sysdev = container_of(kobj, struct sys_device, kobj);
-	mem = container_of(sysdev, struct memory_block, sysdev);
-
-	return mem;
-}
-
 int remove_memory_block(unsigned long node_id, struct mem_section *section,
 		int phys_device)
 {
 	struct memory_block *mem;
 
+	mutex_lock(&mem_sysfs_mutex);
 	mem = find_memory_block(section);
-	unregister_mem_sect_under_nodes(mem);
-	mem_remove_simple_file(mem, phys_index);
-	mem_remove_simple_file(mem, state);
-	mem_remove_simple_file(mem, phys_device);
-	mem_remove_simple_file(mem, removable);
-	unregister_memory(mem, section);
 
+	mem->section_count--;
+	if (mem->section_count == 0) {
+		unregister_mem_sect_under_nodes(mem);
+		mem_remove_simple_file(mem, phys_index);
+		mem_remove_simple_file(mem, state);
+		mem_remove_simple_file(mem, phys_device);
+		mem_remove_simple_file(mem, removable);
+		unregister_memory(mem, section);
+	}
+
+	mutex_unlock(&mem_sysfs_mutex);
 	return 0;
 }
 
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 2872e86..ee53558 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -409,25 +409,27 @@
 	unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
 	unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
 	unsigned long pfn;
+	struct memory_block *mem_blk = NULL;
 	int err = 0;
 
 	for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
 		unsigned long section_nr = pfn_to_section_nr(pfn);
 		struct mem_section *mem_sect;
-		struct memory_block *mem_blk;
 		int ret;
 
 		if (!present_section_nr(section_nr))
 			continue;
 		mem_sect = __nr_to_section(section_nr);
-		mem_blk = find_memory_block(mem_sect);
+		mem_blk = find_memory_block_hinted(mem_sect, mem_blk);
 		ret = register_mem_sect_under_node(mem_blk, nid);
 		if (!err)
 			err = ret;
 
 		/* discard ref obtained in find_memory_block() */
-		kobject_put(&mem_blk->sysdev.kobj);
 	}
+
+	if (mem_blk)
+		kobject_put(&mem_blk->sysdev.kobj);
 	return err;
 }
 
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index c6c933f..3966e62 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -192,6 +192,9 @@
 {
 	struct resource *r;
 
+	if (!res)
+		return 0;
+
 	r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
 	if (r) {
 		pdev->resource = r;
@@ -215,8 +218,12 @@
 int platform_device_add_data(struct platform_device *pdev, const void *data,
 			     size_t size)
 {
-	void *d = kmemdup(data, size, GFP_KERNEL);
+	void *d;
 
+	if (!data)
+		return 0;
+
+	d = kmemdup(data, size, GFP_KERNEL);
 	if (d) {
 		pdev->dev.platform_data = d;
 		return 0;
@@ -373,17 +380,13 @@
 
 	pdev->dev.parent = parent;
 
-	if (res) {
-		ret = platform_device_add_resources(pdev, res, num);
-		if (ret)
-			goto err;
-	}
+	ret = platform_device_add_resources(pdev, res, num);
+	if (ret)
+		goto err;
 
-	if (data) {
-		ret = platform_device_add_data(pdev, data, size);
-		if (ret)
-			goto err;
-	}
+	ret = platform_device_add_data(pdev, data, size);
+	if (ret)
+		goto err;
 
 	ret = platform_device_add(pdev);
 	if (ret) {
@@ -488,12 +491,12 @@
 	 * if the probe was successful, and make sure any forced probes of
 	 * new devices fail.
 	 */
-	spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
+	spin_lock(&drv->driver.bus->p->klist_drivers.k_lock);
 	drv->probe = NULL;
 	if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
 		retval = -ENODEV;
 	drv->driver.probe = platform_drv_probe_fail;
-	spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
+	spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock);
 
 	if (code != retval)
 		platform_driver_unregister(drv);
@@ -530,17 +533,13 @@
 		goto err_out;
 	}
 
-	if (res) {
-		error = platform_device_add_resources(pdev, res, n_res);
-		if (error)
-			goto err_pdev_put;
-	}
+	error = platform_device_add_resources(pdev, res, n_res);
+	if (error)
+		goto err_pdev_put;
 
-	if (data) {
-		error = platform_device_add_data(pdev, data, size);
-		if (error)
-			goto err_pdev_put;
-	}
+	error = platform_device_add_data(pdev, data, size);
+	if (error)
+		goto err_pdev_put;
 
 	error = platform_device_add(pdev);
 	if (error)
@@ -976,6 +975,41 @@
 };
 EXPORT_SYMBOL_GPL(platform_bus_type);
 
+/**
+ * platform_bus_get_pm_ops() - return pointer to busses dev_pm_ops
+ *
+ * This function can be used by platform code to get the current
+ * set of dev_pm_ops functions used by the platform_bus_type.
+ */
+const struct dev_pm_ops * __init platform_bus_get_pm_ops(void)
+{
+	return platform_bus_type.pm;
+}
+
+/**
+ * platform_bus_set_pm_ops() - update dev_pm_ops for the platform_bus_type
+ *
+ * @pm: pointer to new dev_pm_ops struct to be used for platform_bus_type
+ *
+ * Platform code can override the dev_pm_ops methods of
+ * platform_bus_type by using this function.  It is expected that
+ * platform code will first do a platform_bus_get_pm_ops(), then
+ * kmemdup it, then customize selected methods and pass a pointer to
+ * the new struct dev_pm_ops to this function.
+ *
+ * Since platform-specific code is customizing methods for *all*
+ * devices (not just platform-specific devices) it is expected that
+ * any custom overrides of these functions will keep existing behavior
+ * and simply extend it.  For example, any customization of the
+ * runtime PM methods should continue to call the pm_generic_*
+ * functions as the default ones do in addition to the
+ * platform-specific behavior.
+ */
+void __init platform_bus_set_pm_ops(const struct dev_pm_ops *pm)
+{
+	platform_bus_type.pm = pm;
+}
+
 int __init platform_bus_init(void)
 {
 	int error;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 9354dc1..1667aaf 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -432,13 +432,13 @@
 	/* resume current sysdev */
 cls_driver:
 	drv = NULL;
-	printk(KERN_ERR "Class suspend failed for %s\n",
-		kobject_name(&sysdev->kobj));
+	printk(KERN_ERR "Class suspend failed for %s: %d\n",
+		kobject_name(&sysdev->kobj), ret);
 
 aux_driver:
 	if (drv)
-		printk(KERN_ERR "Class driver suspend failed for %s\n",
-				kobject_name(&sysdev->kobj));
+		printk(KERN_ERR "Class driver suspend failed for %s: %d\n",
+				kobject_name(&sysdev->kobj), ret);
 	list_for_each_entry(err_drv, &cls->drivers, entry) {
 		if (err_drv == drv)
 			break;
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 4e2c367..1f286ab 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -36,7 +36,7 @@
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/reboot.h>
@@ -54,6 +54,7 @@
 #define DAC960_GAM_MINOR	252
 
 
+static DEFINE_MUTEX(DAC960_mutex);
 static DAC960_Controller_T *DAC960_Controllers[DAC960_MaxControllers];
 static int DAC960_ControllerCount;
 static struct proc_dir_entry *DAC960_ProcDirectoryEntry;
@@ -81,7 +82,7 @@
 	int drive_nr = (long)disk->private_data;
 	int ret = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&DAC960_mutex);
 	if (p->FirmwareType == DAC960_V1_Controller) {
 		if (p->V1.LogicalDriveInformation[drive_nr].
 		    LogicalDriveState == DAC960_V1_LogicalDrive_Offline)
@@ -99,7 +100,7 @@
 		goto out;
 	ret = 0;
 out:
-	unlock_kernel();
+	mutex_unlock(&DAC960_mutex);
 	return ret;
 }
 
@@ -6625,7 +6626,7 @@
   long ErrorCode = 0;
   if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 
-  lock_kernel();
+  mutex_lock(&DAC960_mutex);
   switch (Request)
     {
     case DAC960_IOCTL_GET_CONTROLLER_COUNT:
@@ -7056,13 +7057,14 @@
       default:
 	ErrorCode = -ENOTTY;
     }
-  unlock_kernel();
+  mutex_unlock(&DAC960_mutex);
   return ErrorCode;
 }
 
 static const struct file_operations DAC960_gam_fops = {
 	.owner		= THIS_MODULE,
-	.unlocked_ioctl	= DAC960_gam_ioctl
+	.unlocked_ioctl	= DAC960_gam_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice DAC960_gam_dev = {
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 76f114f..a1725e6 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -60,7 +60,7 @@
 #include <linux/hdreg.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/amifdreg.h>
 #include <linux/amifd.h>
 #include <linux/buffer_head.h>
@@ -109,13 +109,12 @@
 #define FD_HD_3 	0x55555555  /* high-density 3.5" (1760K) drive */
 #define FD_DD_5 	0xaaaaaaaa  /* double-density 5.25" (440K) drive */
 
+static DEFINE_MUTEX(amiflop_mutex);
 static unsigned long int fd_def_df0 = FD_DD_3;     /* default for df0 if it doesn't identify */
 
 module_param(fd_def_df0, ulong, 0);
 MODULE_LICENSE("GPL");
 
-static struct request_queue *floppy_queue;
-
 /*
  *  Macros
  */
@@ -164,6 +163,7 @@
 static int writepending;
 static int writefromint;
 static char *raw_buf;
+static int fdc_queue;
 
 static DEFINE_SPINLOCK(amiflop_lock);
 
@@ -1334,6 +1334,42 @@
 	return -1;
 }
 
+/*
+ * Round-robin between our available drives, doing one request from each
+ */
+static struct request *set_next_request(void)
+{
+	struct request_queue *q;
+	int cnt = FD_MAX_UNITS;
+	struct request *rq;
+
+	/* Find next queue we can dispatch from */
+	fdc_queue = fdc_queue + 1;
+	if (fdc_queue == FD_MAX_UNITS)
+		fdc_queue = 0;
+
+	for(cnt = FD_MAX_UNITS; cnt > 0; cnt--) {
+
+		if (unit[fdc_queue].type->code == FD_NODRIVE) {
+			if (++fdc_queue == FD_MAX_UNITS)
+				fdc_queue = 0;
+			continue;
+		}
+
+		q = unit[fdc_queue].gendisk->queue;
+		if (q) {
+			rq = blk_fetch_request(q);
+			if (rq)
+				break;
+		}
+
+		if (++fdc_queue == FD_MAX_UNITS)
+			fdc_queue = 0;
+	}
+
+	return rq;
+}
+
 static void redo_fd_request(void)
 {
 	struct request *rq;
@@ -1345,7 +1381,7 @@
 	int err;
 
 next_req:
-	rq = blk_fetch_request(floppy_queue);
+	rq = set_next_request();
 	if (!rq) {
 		/* Nothing left to do */
 		return;
@@ -1506,9 +1542,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&amiflop_mutex);
 	ret = fd_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&amiflop_mutex);
 
 	return ret;
 }
@@ -1555,11 +1591,11 @@
 	int old_dev;
 	unsigned long flags;
 
-	lock_kernel();
+	mutex_lock(&amiflop_mutex);
 	old_dev = fd_device[drive];
 
 	if (fd_ref[drive] && old_dev != system) {
-		unlock_kernel();
+		mutex_unlock(&amiflop_mutex);
 		return -EBUSY;
 	}
 
@@ -1575,7 +1611,7 @@
 			rel_fdc();
 
 			if (wrprot) {
-				unlock_kernel();
+				mutex_unlock(&amiflop_mutex);
 				return -EROFS;
 			}
 		}
@@ -1594,7 +1630,7 @@
 	printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
 	       unit[drive].type->name, data_types[system].name);
 
-	unlock_kernel();
+	mutex_unlock(&amiflop_mutex);
 	return 0;
 }
 
@@ -1603,7 +1639,7 @@
 	struct amiga_floppy_struct *p = disk->private_data;
 	int drive = p - unit;
 
-	lock_kernel();
+	mutex_lock(&amiflop_mutex);
 	if (unit[drive].dirty == 1) {
 		del_timer (flush_track_timer + drive);
 		non_int_flush_track (drive);
@@ -1617,7 +1653,7 @@
 /* the mod_use counter is handled this way */
 	floppy_off (drive | 0x40000000);
 #endif
-	unlock_kernel();
+	mutex_unlock(&amiflop_mutex);
 	return 0;
 }
 
@@ -1682,6 +1718,13 @@
 			continue;
 		}
 		unit[drive].gendisk = disk;
+
+		disk->queue = blk_init_queue(do_fd_request, &amiflop_lock);
+		if (!disk->queue) {
+			unit[drive].type->code = FD_NODRIVE;
+			continue;
+		}
+
 		drives++;
 		if ((unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL)) == NULL) {
 			printk("no mem for ");
@@ -1695,7 +1738,6 @@
 		disk->fops = &floppy_fops;
 		sprintf(disk->disk_name, "fd%d", drive);
 		disk->private_data = &unit[drive];
-		disk->queue = floppy_queue;
 		set_capacity(disk, 880*2);
 		add_disk(disk);
 	}
@@ -1743,11 +1785,6 @@
 		goto out_irq2;
 	}
 
-	ret = -ENOMEM;
-	floppy_queue = blk_init_queue(do_fd_request, &amiflop_lock);
-	if (!floppy_queue)
-		goto out_queue;
-
 	ret = -ENODEV;
 	if (fd_probe_drives() < 1) /* No usable drives */
 		goto out_probe;
@@ -1791,8 +1828,6 @@
 	return 0;
 
 out_probe:
-	blk_cleanup_queue(floppy_queue);
-out_queue:
 	free_irq(IRQ_AMIGA_CIAA_TB, NULL);
 out_irq2:
 	free_irq(IRQ_AMIGA_DSKBLK, NULL);
@@ -1810,9 +1845,12 @@
 
 	for( i = 0; i < FD_MAX_UNITS; i++) {
 		if (unit[i].type->code != FD_NODRIVE) {
+			struct request_queue *q = unit[i].gendisk->queue;
 			del_gendisk(unit[i].gendisk);
 			put_disk(unit[i].gendisk);
 			kfree(unit[i].trackbuf);
+			if (q)
+				blk_cleanup_queue(q);
 		}
 	}
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
@@ -1820,7 +1858,6 @@
 	free_irq(IRQ_AMIGA_DSKBLK, NULL);
 	custom.dmacon = DMAF_DISK; /* disable DMA */
 	amiga_chip_free(raw_buf);
-	blk_cleanup_queue(floppy_queue);
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 }
 #endif
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index a946929..f21c237 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -12,9 +12,10 @@
 #include <linux/slab.h>
 #include <linux/genhd.h>
 #include <linux/netdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include "aoe.h"
 
+static DEFINE_MUTEX(aoeblk_mutex);
 static struct kmem_cache *buf_pool_cache;
 
 static ssize_t aoedisk_show_state(struct device *dev,
@@ -125,16 +126,16 @@
 	struct aoedev *d = bdev->bd_disk->private_data;
 	ulong flags;
 
-	lock_kernel();
+	mutex_lock(&aoeblk_mutex);
 	spin_lock_irqsave(&d->lock, flags);
 	if (d->flags & DEVFL_UP) {
 		d->nopen++;
 		spin_unlock_irqrestore(&d->lock, flags);
-		unlock_kernel();
+		mutex_unlock(&aoeblk_mutex);
 		return 0;
 	}
 	spin_unlock_irqrestore(&d->lock, flags);
-	unlock_kernel();
+	mutex_unlock(&aoeblk_mutex);
 	return -ENODEV;
 }
 
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 4a1b9e74..146296c 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -9,7 +9,7 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/skbuff.h>
 #include "aoe.h"
 
@@ -37,6 +37,7 @@
 	char *msg;
 };
 
+static DEFINE_MUTEX(aoechr_mutex);
 static struct ErrMsg emsgs[NMSG];
 static int emsgs_head_idx, emsgs_tail_idx;
 static struct completion emsgs_comp;
@@ -183,16 +184,16 @@
 {
 	int n, i;
 
-	lock_kernel();
+	mutex_lock(&aoechr_mutex);
 	n = iminor(inode);
 	filp->private_data = (void *) (unsigned long) n;
 
 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
 		if (chardevs[i].minor == n) {
-			unlock_kernel();
+			mutex_unlock(&aoechr_mutex);
 			return 0;
 		}
-	unlock_kernel();
+	mutex_unlock(&aoechr_mutex);
 	return -EINVAL;
 }
 
@@ -265,6 +266,7 @@
 	.open = aoechr_open,
 	.release = aoechr_rel,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static char *aoe_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index aceb964..4e4cc6c 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -67,7 +67,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/atafd.h>
 #include <asm/atafdreg.h>
@@ -79,8 +79,9 @@
 
 #undef DEBUG
 
-static struct request_queue *floppy_queue;
+static DEFINE_MUTEX(ataflop_mutex);
 static struct request *fd_request;
+static int fdc_queue;
 
 /* Disk types: DD, HD, ED */
 static struct atari_disk_type {
@@ -1391,6 +1392,29 @@
 			ReqTrack, ReqSector, (unsigned long)ReqData ));
 }
 
+/*
+ * Round-robin between our available drives, doing one request from each
+ */
+static struct request *set_next_request(void)
+{
+	struct request_queue *q;
+	int old_pos = fdc_queue;
+	struct request *rq;
+
+	do {
+		q = unit[fdc_queue].disk->queue;
+		if (++fdc_queue == FD_MAX_UNITS)
+			fdc_queue = 0;
+		if (q) {
+			rq = blk_fetch_request(q);
+			if (rq)
+				break;
+		}
+	} while (fdc_queue != old_pos);
+
+	return rq;
+}
+
 
 static void redo_fd_request(void)
 {
@@ -1405,7 +1429,7 @@
 
 repeat:
 	if (!fd_request) {
-		fd_request = blk_fetch_request(floppy_queue);
+		fd_request = set_next_request();
 		if (!fd_request)
 			goto the_end;
 	}
@@ -1671,9 +1695,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ataflop_mutex);
 	ret = fd_locked_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ataflop_mutex);
 
 	return ret;
 }
@@ -1854,9 +1878,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ataflop_mutex);
 	ret = floppy_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&ataflop_mutex);
 
 	return ret;
 }
@@ -1864,14 +1888,14 @@
 static int floppy_release(struct gendisk *disk, fmode_t mode)
 {
 	struct atari_floppy_struct *p = disk->private_data;
-	lock_kernel();
+	mutex_lock(&ataflop_mutex);
 	if (p->ref < 0)
 		p->ref = 0;
 	else if (!p->ref--) {
 		printk(KERN_ERR "floppy_release with fd_ref == 0");
 		p->ref = 0;
 	}
-	unlock_kernel();
+	mutex_unlock(&ataflop_mutex);
 	return 0;
 }
 
@@ -1932,10 +1956,6 @@
 	PhysTrackBuffer = virt_to_phys(TrackBuffer);
 	BufferDrive = BufferSide = BufferTrack = -1;
 
-	floppy_queue = blk_init_queue(do_fd_request, &ataflop_lock);
-	if (!floppy_queue)
-		goto Enomem;
-
 	for (i = 0; i < FD_MAX_UNITS; i++) {
 		unit[i].track = -1;
 		unit[i].flags = 0;
@@ -1944,7 +1964,10 @@
 		sprintf(unit[i].disk->disk_name, "fd%d", i);
 		unit[i].disk->fops = &floppy_fops;
 		unit[i].disk->private_data = &unit[i];
-		unit[i].disk->queue = floppy_queue;
+		unit[i].disk->queue = blk_init_queue(do_fd_request,
+					&ataflop_lock);
+		if (!unit[i].disk->queue)
+			goto Enomem;
 		set_capacity(unit[i].disk, MAX_DISK_SIZE * 2);
 		add_disk(unit[i].disk);
 	}
@@ -1959,10 +1982,14 @@
 
 	return 0;
 Enomem:
-	while (i--)
+	while (i--) {
+		struct request_queue *q = unit[i].disk->queue;
+
 		put_disk(unit[i].disk);
-	if (floppy_queue)
-		blk_cleanup_queue(floppy_queue);
+		if (q)
+			blk_cleanup_queue(q);
+	}
+
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 	return -ENOMEM;
 }
@@ -2011,12 +2038,14 @@
 	int i;
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
 	for (i = 0; i < FD_MAX_UNITS; i++) {
+		struct request_queue *q = unit[i].disk->queue;
+
 		del_gendisk(unit[i].disk);
 		put_disk(unit[i].disk);
+		blk_cleanup_queue(q);
 	}
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 
-	blk_cleanup_queue(floppy_queue);
 	del_timer_sync(&fd_timer);
 	atari_stram_free( DMABuffer );
 }
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 1c7f637..b7f51e4 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -15,7 +15,7 @@
 #include <linux/blkdev.h>
 #include <linux/bio.h>
 #include <linux/highmem.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/radix-tree.h>
 #include <linux/buffer_head.h> /* invalidate_bh_lrus() */
 #include <linux/slab.h>
@@ -55,6 +55,7 @@
 /*
  * Look up and return a brd's page for a given sector.
  */
+static DEFINE_MUTEX(brd_mutex);
 static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector)
 {
 	pgoff_t idx;
@@ -402,7 +403,7 @@
 	 * ram device BLKFLSBUF has special semantics, we want to actually
 	 * release and destroy the ramdisk data.
 	 */
-	lock_kernel();
+	mutex_lock(&brd_mutex);
 	mutex_lock(&bdev->bd_mutex);
 	error = -EBUSY;
 	if (bdev->bd_openers <= 1) {
@@ -419,7 +420,7 @@
 		error = 0;
 	}
 	mutex_unlock(&bdev->bd_mutex);
-	unlock_kernel();
+	mutex_unlock(&brd_mutex);
 
 	return error;
 }
@@ -482,7 +483,6 @@
 	if (!brd->brd_queue)
 		goto out_free_dev;
 	blk_queue_make_request(brd->brd_queue, brd_make_request);
-	blk_queue_ordered(brd->brd_queue, QUEUE_ORDERED_TAG);
 	blk_queue_max_hw_sectors(brd->brd_queue, 1024);
 	blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
 
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5e4fadc..f09e6df 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -26,7 +26,6 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -66,6 +65,7 @@
 MODULE_VERSION("3.6.26");
 MODULE_LICENSE("GPL");
 
+static DEFINE_MUTEX(cciss_mutex);
 static int cciss_allow_hpsa;
 module_param(cciss_allow_hpsa, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(cciss_allow_hpsa,
@@ -105,11 +105,12 @@
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3249},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324A},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324B},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3250},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3251},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3252},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3253},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3254},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3350},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3351},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3352},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3353},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3354},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3355},
 	{0,}
 };
 
@@ -149,11 +150,12 @@
 	{0x3249103C, "Smart Array P812", &SA5_access},
 	{0x324A103C, "Smart Array P712m", &SA5_access},
 	{0x324B103C, "Smart Array P711m", &SA5_access},
-	{0x3250103C, "Smart Array", &SA5_access},
-	{0x3251103C, "Smart Array", &SA5_access},
-	{0x3252103C, "Smart Array", &SA5_access},
-	{0x3253103C, "Smart Array", &SA5_access},
-	{0x3254103C, "Smart Array", &SA5_access},
+	{0x3350103C, "Smart Array", &SA5_access},
+	{0x3351103C, "Smart Array", &SA5_access},
+	{0x3352103C, "Smart Array", &SA5_access},
+	{0x3353103C, "Smart Array", &SA5_access},
+	{0x3354103C, "Smart Array", &SA5_access},
+	{0x3355103C, "Smart Array", &SA5_access},
 };
 
 /* How long to wait (in milliseconds) for board to go into simple mode */
@@ -1059,9 +1061,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&cciss_mutex);
 	ret = cciss_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&cciss_mutex);
 
 	return ret;
 }
@@ -1074,13 +1076,13 @@
 	ctlr_info_t *h;
 	drive_info_struct *drv;
 
-	lock_kernel();
+	mutex_lock(&cciss_mutex);
 	h = get_host(disk);
 	drv = get_drv(disk);
 	dev_dbg(&h->pdev->dev, "cciss_release %s\n", disk->disk_name);
 	drv->usage_count--;
 	h->usage_count--;
-	unlock_kernel();
+	mutex_unlock(&cciss_mutex);
 	return 0;
 }
 
@@ -1088,9 +1090,9 @@
 		    unsigned cmd, unsigned long arg)
 {
 	int ret;
-	lock_kernel();
+	mutex_lock(&cciss_mutex);
 	ret = cciss_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&cciss_mutex);
 	return ret;
 }
 
@@ -1232,470 +1234,452 @@
 			c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
 		(void)check_for_unit_attention(h, c);
 }
-/*
- * ioctl
- */
+
+static int cciss_getpciinfo(ctlr_info_t *h, void __user *argp)
+{
+	cciss_pci_info_struct pciinfo;
+
+	if (!argp)
+		return -EINVAL;
+	pciinfo.domain = pci_domain_nr(h->pdev->bus);
+	pciinfo.bus = h->pdev->bus->number;
+	pciinfo.dev_fn = h->pdev->devfn;
+	pciinfo.board_id = h->board_id;
+	if (copy_to_user(argp, &pciinfo, sizeof(cciss_pci_info_struct)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getintinfo(ctlr_info_t *h, void __user *argp)
+{
+	cciss_coalint_struct intinfo;
+
+	if (!argp)
+		return -EINVAL;
+	intinfo.delay = readl(&h->cfgtable->HostWrite.CoalIntDelay);
+	intinfo.count = readl(&h->cfgtable->HostWrite.CoalIntCount);
+	if (copy_to_user
+	    (argp, &intinfo, sizeof(cciss_coalint_struct)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_setintinfo(ctlr_info_t *h, void __user *argp)
+{
+	cciss_coalint_struct intinfo;
+	unsigned long flags;
+	int i;
+
+	if (!argp)
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (copy_from_user(&intinfo, argp, sizeof(intinfo)))
+		return -EFAULT;
+	if ((intinfo.delay == 0) && (intinfo.count == 0))
+		return -EINVAL;
+	spin_lock_irqsave(&h->lock, flags);
+	/* Update the field, and then ring the doorbell */
+	writel(intinfo.delay, &(h->cfgtable->HostWrite.CoalIntDelay));
+	writel(intinfo.count, &(h->cfgtable->HostWrite.CoalIntCount));
+	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+
+	for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+		if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+			break;
+		udelay(1000); /* delay and try again */
+	}
+	spin_unlock_irqrestore(&h->lock, flags);
+	if (i >= MAX_IOCTL_CONFIG_WAIT)
+		return -EAGAIN;
+	return 0;
+}
+
+static int cciss_getnodename(ctlr_info_t *h, void __user *argp)
+{
+	NodeName_type NodeName;
+	int i;
+
+	if (!argp)
+		return -EINVAL;
+	for (i = 0; i < 16; i++)
+		NodeName[i] = readb(&h->cfgtable->ServerName[i]);
+	if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_setnodename(ctlr_info_t *h, void __user *argp)
+{
+	NodeName_type NodeName;
+	unsigned long flags;
+	int i;
+
+	if (!argp)
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (copy_from_user(NodeName, argp, sizeof(NodeName_type)))
+		return -EFAULT;
+	spin_lock_irqsave(&h->lock, flags);
+	/* Update the field, and then ring the doorbell */
+	for (i = 0; i < 16; i++)
+		writeb(NodeName[i], &h->cfgtable->ServerName[i]);
+	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+	for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+		if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+			break;
+		udelay(1000); /* delay and try again */
+	}
+	spin_unlock_irqrestore(&h->lock, flags);
+	if (i >= MAX_IOCTL_CONFIG_WAIT)
+		return -EAGAIN;
+	return 0;
+}
+
+static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
+{
+	Heartbeat_type heartbeat;
+
+	if (!argp)
+		return -EINVAL;
+	heartbeat = readl(&h->cfgtable->HeartBeat);
+	if (copy_to_user(argp, &heartbeat, sizeof(Heartbeat_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getbustypes(ctlr_info_t *h, void __user *argp)
+{
+	BusTypes_type BusTypes;
+
+	if (!argp)
+		return -EINVAL;
+	BusTypes = readl(&h->cfgtable->BusTypes);
+	if (copy_to_user(argp, &BusTypes, sizeof(BusTypes_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getfirmver(ctlr_info_t *h, void __user *argp)
+{
+	FirmwareVer_type firmware;
+
+	if (!argp)
+		return -EINVAL;
+	memcpy(firmware, h->firm_ver, 4);
+
+	if (copy_to_user
+	    (argp, firmware, sizeof(FirmwareVer_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getdrivver(ctlr_info_t *h, void __user *argp)
+{
+	DriverVer_type DriverVer = DRIVER_VERSION;
+
+	if (!argp)
+		return -EINVAL;
+	if (copy_to_user(argp, &DriverVer, sizeof(DriverVer_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_getluninfo(ctlr_info_t *h,
+	struct gendisk *disk, void __user *argp)
+{
+	LogvolInfo_struct luninfo;
+	drive_info_struct *drv = get_drv(disk);
+
+	if (!argp)
+		return -EINVAL;
+	memcpy(&luninfo.LunID, drv->LunID, sizeof(luninfo.LunID));
+	luninfo.num_opens = drv->usage_count;
+	luninfo.num_parts = 0;
+	if (copy_to_user(argp, &luninfo, sizeof(LogvolInfo_struct)))
+		return -EFAULT;
+	return 0;
+}
+
+static int cciss_passthru(ctlr_info_t *h, void __user *argp)
+{
+	IOCTL_Command_struct iocommand;
+	CommandList_struct *c;
+	char *buff = NULL;
+	u64bit temp64;
+	DECLARE_COMPLETION_ONSTACK(wait);
+
+	if (!argp)
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	if (copy_from_user
+	    (&iocommand, argp, sizeof(IOCTL_Command_struct)))
+		return -EFAULT;
+	if ((iocommand.buf_size < 1) &&
+	    (iocommand.Request.Type.Direction != XFER_NONE)) {
+		return -EINVAL;
+	}
+	if (iocommand.buf_size > 0) {
+		buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
+		if (buff == NULL)
+			return -EFAULT;
+	}
+	if (iocommand.Request.Type.Direction == XFER_WRITE) {
+		/* Copy the data into the buffer we created */
+		if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
+			kfree(buff);
+			return -EFAULT;
+		}
+	} else {
+		memset(buff, 0, iocommand.buf_size);
+	}
+	c = cmd_special_alloc(h);
+	if (!c) {
+		kfree(buff);
+		return -ENOMEM;
+	}
+	/* Fill in the command type */
+	c->cmd_type = CMD_IOCTL_PEND;
+	/* Fill in Command Header */
+	c->Header.ReplyQueue = 0;   /* unused in simple mode */
+	if (iocommand.buf_size > 0) { /* buffer to fill */
+		c->Header.SGList = 1;
+		c->Header.SGTotal = 1;
+	} else { /* no buffers to fill */
+		c->Header.SGList = 0;
+		c->Header.SGTotal = 0;
+	}
+	c->Header.LUN = iocommand.LUN_info;
+	/* use the kernel address the cmd block for tag */
+	c->Header.Tag.lower = c->busaddr;
+
+	/* Fill in Request block */
+	c->Request = iocommand.Request;
+
+	/* Fill in the scatter gather information */
+	if (iocommand.buf_size > 0) {
+		temp64.val = pci_map_single(h->pdev, buff,
+			iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+		c->SG[0].Addr.lower = temp64.val32.lower;
+		c->SG[0].Addr.upper = temp64.val32.upper;
+		c->SG[0].Len = iocommand.buf_size;
+		c->SG[0].Ext = 0;  /* we are not chaining */
+	}
+	c->waiting = &wait;
+
+	enqueue_cmd_and_start_io(h, c);
+	wait_for_completion(&wait);
+
+	/* unlock the buffers from DMA */
+	temp64.val32.lower = c->SG[0].Addr.lower;
+	temp64.val32.upper = c->SG[0].Addr.upper;
+	pci_unmap_single(h->pdev, (dma_addr_t) temp64.val, iocommand.buf_size,
+			 PCI_DMA_BIDIRECTIONAL);
+	check_ioctl_unit_attention(h, c);
+
+	/* Copy the error information out */
+	iocommand.error_info = *(c->err_info);
+	if (copy_to_user(argp, &iocommand, sizeof(IOCTL_Command_struct))) {
+		kfree(buff);
+		cmd_special_free(h, c);
+		return -EFAULT;
+	}
+
+	if (iocommand.Request.Type.Direction == XFER_READ) {
+		/* Copy the data out of the buffer we created */
+		if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
+			kfree(buff);
+			cmd_special_free(h, c);
+			return -EFAULT;
+		}
+	}
+	kfree(buff);
+	cmd_special_free(h, c);
+	return 0;
+}
+
+static int cciss_bigpassthru(ctlr_info_t *h, void __user *argp)
+{
+	BIG_IOCTL_Command_struct *ioc;
+	CommandList_struct *c;
+	unsigned char **buff = NULL;
+	int *buff_size = NULL;
+	u64bit temp64;
+	BYTE sg_used = 0;
+	int status = 0;
+	int i;
+	DECLARE_COMPLETION_ONSTACK(wait);
+	__u32 left;
+	__u32 sz;
+	BYTE __user *data_ptr;
+
+	if (!argp)
+		return -EINVAL;
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+	ioc = (BIG_IOCTL_Command_struct *)
+	    kmalloc(sizeof(*ioc), GFP_KERNEL);
+	if (!ioc) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	if (copy_from_user(ioc, argp, sizeof(*ioc))) {
+		status = -EFAULT;
+		goto cleanup1;
+	}
+	if ((ioc->buf_size < 1) &&
+	    (ioc->Request.Type.Direction != XFER_NONE)) {
+		status = -EINVAL;
+		goto cleanup1;
+	}
+	/* Check kmalloc limits  using all SGs */
+	if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
+		status = -EINVAL;
+		goto cleanup1;
+	}
+	if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
+		status = -EINVAL;
+		goto cleanup1;
+	}
+	buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
+	if (!buff) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	buff_size = kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL);
+	if (!buff_size) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	left = ioc->buf_size;
+	data_ptr = ioc->buf;
+	while (left) {
+		sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
+		buff_size[sg_used] = sz;
+		buff[sg_used] = kmalloc(sz, GFP_KERNEL);
+		if (buff[sg_used] == NULL) {
+			status = -ENOMEM;
+			goto cleanup1;
+		}
+		if (ioc->Request.Type.Direction == XFER_WRITE) {
+			if (copy_from_user(buff[sg_used], data_ptr, sz)) {
+				status = -EFAULT;
+				goto cleanup1;
+			}
+		} else {
+			memset(buff[sg_used], 0, sz);
+		}
+		left -= sz;
+		data_ptr += sz;
+		sg_used++;
+	}
+	c = cmd_special_alloc(h);
+	if (!c) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	c->cmd_type = CMD_IOCTL_PEND;
+	c->Header.ReplyQueue = 0;
+	c->Header.SGList = sg_used;
+	c->Header.SGTotal = sg_used;
+	c->Header.LUN = ioc->LUN_info;
+	c->Header.Tag.lower = c->busaddr;
+
+	c->Request = ioc->Request;
+	for (i = 0; i < sg_used; i++) {
+		temp64.val = pci_map_single(h->pdev, buff[i], buff_size[i],
+				    PCI_DMA_BIDIRECTIONAL);
+		c->SG[i].Addr.lower = temp64.val32.lower;
+		c->SG[i].Addr.upper = temp64.val32.upper;
+		c->SG[i].Len = buff_size[i];
+		c->SG[i].Ext = 0;	/* we are not chaining */
+	}
+	c->waiting = &wait;
+	enqueue_cmd_and_start_io(h, c);
+	wait_for_completion(&wait);
+	/* unlock the buffers from DMA */
+	for (i = 0; i < sg_used; i++) {
+		temp64.val32.lower = c->SG[i].Addr.lower;
+		temp64.val32.upper = c->SG[i].Addr.upper;
+		pci_unmap_single(h->pdev,
+			(dma_addr_t) temp64.val, buff_size[i],
+			PCI_DMA_BIDIRECTIONAL);
+	}
+	check_ioctl_unit_attention(h, c);
+	/* Copy the error information out */
+	ioc->error_info = *(c->err_info);
+	if (copy_to_user(argp, ioc, sizeof(*ioc))) {
+		cmd_special_free(h, c);
+		status = -EFAULT;
+		goto cleanup1;
+	}
+	if (ioc->Request.Type.Direction == XFER_READ) {
+		/* Copy the data out of the buffer we created */
+		BYTE __user *ptr = ioc->buf;
+		for (i = 0; i < sg_used; i++) {
+			if (copy_to_user(ptr, buff[i], buff_size[i])) {
+				cmd_special_free(h, c);
+				status = -EFAULT;
+				goto cleanup1;
+			}
+			ptr += buff_size[i];
+		}
+	}
+	cmd_special_free(h, c);
+	status = 0;
+cleanup1:
+	if (buff) {
+		for (i = 0; i < sg_used; i++)
+			kfree(buff[i]);
+		kfree(buff);
+	}
+	kfree(buff_size);
+	kfree(ioc);
+	return status;
+}
+
 static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
-		       unsigned int cmd, unsigned long arg)
+	unsigned int cmd, unsigned long arg)
 {
 	struct gendisk *disk = bdev->bd_disk;
 	ctlr_info_t *h = get_host(disk);
-	drive_info_struct *drv = get_drv(disk);
 	void __user *argp = (void __user *)arg;
 
 	dev_dbg(&h->pdev->dev, "cciss_ioctl: Called with cmd=%x %lx\n",
 		cmd, arg);
 	switch (cmd) {
 	case CCISS_GETPCIINFO:
-		{
-			cciss_pci_info_struct pciinfo;
-
-			if (!arg)
-				return -EINVAL;
-			pciinfo.domain = pci_domain_nr(h->pdev->bus);
-			pciinfo.bus = h->pdev->bus->number;
-			pciinfo.dev_fn = h->pdev->devfn;
-			pciinfo.board_id = h->board_id;
-			if (copy_to_user
-			    (argp, &pciinfo, sizeof(cciss_pci_info_struct)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getpciinfo(h, argp);
 	case CCISS_GETINTINFO:
-		{
-			cciss_coalint_struct intinfo;
-			if (!arg)
-				return -EINVAL;
-			intinfo.delay =
-			    readl(&h->cfgtable->HostWrite.CoalIntDelay);
-			intinfo.count =
-			    readl(&h->cfgtable->HostWrite.CoalIntCount);
-			if (copy_to_user
-			    (argp, &intinfo, sizeof(cciss_coalint_struct)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getintinfo(h, argp);
 	case CCISS_SETINTINFO:
-		{
-			cciss_coalint_struct intinfo;
-			unsigned long flags;
-			int i;
-
-			if (!arg)
-				return -EINVAL;
-			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-			if (copy_from_user
-			    (&intinfo, argp, sizeof(cciss_coalint_struct)))
-				return -EFAULT;
-			if ((intinfo.delay == 0) && (intinfo.count == 0))
-				return -EINVAL;
-			spin_lock_irqsave(&h->lock, flags);
-			/* Update the field, and then ring the doorbell */
-			writel(intinfo.delay,
-			       &(h->cfgtable->HostWrite.CoalIntDelay));
-			writel(intinfo.count,
-			       &(h->cfgtable->HostWrite.CoalIntCount));
-			writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-
-			for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
-				if (!(readl(h->vaddr + SA5_DOORBELL)
-				      & CFGTBL_ChangeReq))
-					break;
-				/* delay and try again */
-				udelay(1000);
-			}
-			spin_unlock_irqrestore(&h->lock, flags);
-			if (i >= MAX_IOCTL_CONFIG_WAIT)
-				return -EAGAIN;
-			return 0;
-		}
+		return cciss_setintinfo(h, argp);
 	case CCISS_GETNODENAME:
-		{
-			NodeName_type NodeName;
-			int i;
-
-			if (!arg)
-				return -EINVAL;
-			for (i = 0; i < 16; i++)
-				NodeName[i] =
-				    readb(&h->cfgtable->ServerName[i]);
-			if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getnodename(h, argp);
 	case CCISS_SETNODENAME:
-		{
-			NodeName_type NodeName;
-			unsigned long flags;
-			int i;
-
-			if (!arg)
-				return -EINVAL;
-			if (!capable(CAP_SYS_ADMIN))
-				return -EPERM;
-
-			if (copy_from_user
-			    (NodeName, argp, sizeof(NodeName_type)))
-				return -EFAULT;
-
-			spin_lock_irqsave(&h->lock, flags);
-
-			/* Update the field, and then ring the doorbell */
-			for (i = 0; i < 16; i++)
-				writeb(NodeName[i],
-				       &h->cfgtable->ServerName[i]);
-
-			writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
-
-			for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
-				if (!(readl(h->vaddr + SA5_DOORBELL)
-				      & CFGTBL_ChangeReq))
-					break;
-				/* delay and try again */
-				udelay(1000);
-			}
-			spin_unlock_irqrestore(&h->lock, flags);
-			if (i >= MAX_IOCTL_CONFIG_WAIT)
-				return -EAGAIN;
-			return 0;
-		}
-
+		return cciss_setnodename(h, argp);
 	case CCISS_GETHEARTBEAT:
-		{
-			Heartbeat_type heartbeat;
-
-			if (!arg)
-				return -EINVAL;
-			heartbeat = readl(&h->cfgtable->HeartBeat);
-			if (copy_to_user
-			    (argp, &heartbeat, sizeof(Heartbeat_type)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getheartbeat(h, argp);
 	case CCISS_GETBUSTYPES:
-		{
-			BusTypes_type BusTypes;
-
-			if (!arg)
-				return -EINVAL;
-			BusTypes = readl(&h->cfgtable->BusTypes);
-			if (copy_to_user
-			    (argp, &BusTypes, sizeof(BusTypes_type)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getbustypes(h, argp);
 	case CCISS_GETFIRMVER:
-		{
-			FirmwareVer_type firmware;
-
-			if (!arg)
-				return -EINVAL;
-			memcpy(firmware, h->firm_ver, 4);
-
-			if (copy_to_user
-			    (argp, firmware, sizeof(FirmwareVer_type)))
-				return -EFAULT;
-			return 0;
-		}
+		return cciss_getfirmver(h, argp);
 	case CCISS_GETDRIVVER:
-		{
-			DriverVer_type DriverVer = DRIVER_VERSION;
-
-			if (!arg)
-				return -EINVAL;
-
-			if (copy_to_user
-			    (argp, &DriverVer, sizeof(DriverVer_type)))
-				return -EFAULT;
-			return 0;
-		}
-
+		return cciss_getdrivver(h, argp);
 	case CCISS_DEREGDISK:
 	case CCISS_REGNEWD:
 	case CCISS_REVALIDVOLS:
 		return rebuild_lun_table(h, 0, 1);
-
-	case CCISS_GETLUNINFO:{
-			LogvolInfo_struct luninfo;
-
-			memcpy(&luninfo.LunID, drv->LunID,
-				sizeof(luninfo.LunID));
-			luninfo.num_opens = drv->usage_count;
-			luninfo.num_parts = 0;
-			if (copy_to_user(argp, &luninfo,
-					 sizeof(LogvolInfo_struct)))
-				return -EFAULT;
-			return 0;
-		}
+	case CCISS_GETLUNINFO:
+		return cciss_getluninfo(h, disk, argp);
 	case CCISS_PASSTHRU:
-		{
-			IOCTL_Command_struct iocommand;
-			CommandList_struct *c;
-			char *buff = NULL;
-			u64bit temp64;
-			DECLARE_COMPLETION_ONSTACK(wait);
-
-			if (!arg)
-				return -EINVAL;
-
-			if (!capable(CAP_SYS_RAWIO))
-				return -EPERM;
-
-			if (copy_from_user
-			    (&iocommand, argp, sizeof(IOCTL_Command_struct)))
-				return -EFAULT;
-			if ((iocommand.buf_size < 1) &&
-			    (iocommand.Request.Type.Direction != XFER_NONE)) {
-				return -EINVAL;
-			}
-#if 0				/* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
-			/* Check kmalloc limits */
-			if (iocommand.buf_size > 128000)
-				return -EINVAL;
-#endif
-			if (iocommand.buf_size > 0) {
-				buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
-				if (buff == NULL)
-					return -EFAULT;
-			}
-			if (iocommand.Request.Type.Direction == XFER_WRITE) {
-				/* Copy the data into the buffer we created */
-				if (copy_from_user
-				    (buff, iocommand.buf, iocommand.buf_size)) {
-					kfree(buff);
-					return -EFAULT;
-				}
-			} else {
-				memset(buff, 0, iocommand.buf_size);
-			}
-			c = cmd_special_alloc(h);
-			if (!c) {
-				kfree(buff);
-				return -ENOMEM;
-			}
-			/* Fill in the command type */
-			c->cmd_type = CMD_IOCTL_PEND;
-			/* Fill in Command Header */
-			c->Header.ReplyQueue = 0;   /* unused in simple mode */
-			if (iocommand.buf_size > 0) /* buffer to fill */
-			{
-				c->Header.SGList = 1;
-				c->Header.SGTotal = 1;
-			} else /* no buffers to fill */
-			{
-				c->Header.SGList = 0;
-				c->Header.SGTotal = 0;
-			}
-			c->Header.LUN = iocommand.LUN_info;
-			/* use the kernel address the cmd block for tag */
-			c->Header.Tag.lower = c->busaddr;
-
-			/* Fill in Request block */
-			c->Request = iocommand.Request;
-
-			/* Fill in the scatter gather information */
-			if (iocommand.buf_size > 0) {
-				temp64.val = pci_map_single(h->pdev, buff,
-					iocommand.buf_size,
-					PCI_DMA_BIDIRECTIONAL);
-				c->SG[0].Addr.lower = temp64.val32.lower;
-				c->SG[0].Addr.upper = temp64.val32.upper;
-				c->SG[0].Len = iocommand.buf_size;
-				c->SG[0].Ext = 0;  /* we are not chaining */
-			}
-			c->waiting = &wait;
-
-			enqueue_cmd_and_start_io(h, c);
-			wait_for_completion(&wait);
-
-			/* unlock the buffers from DMA */
-			temp64.val32.lower = c->SG[0].Addr.lower;
-			temp64.val32.upper = c->SG[0].Addr.upper;
-			pci_unmap_single(h->pdev, (dma_addr_t) temp64.val,
-					 iocommand.buf_size,
-					 PCI_DMA_BIDIRECTIONAL);
-
-			check_ioctl_unit_attention(h, c);
-
-			/* Copy the error information out */
-			iocommand.error_info = *(c->err_info);
-			if (copy_to_user
-			    (argp, &iocommand, sizeof(IOCTL_Command_struct))) {
-				kfree(buff);
-				cmd_special_free(h, c);
-				return -EFAULT;
-			}
-
-			if (iocommand.Request.Type.Direction == XFER_READ) {
-				/* Copy the data out of the buffer we created */
-				if (copy_to_user
-				    (iocommand.buf, buff, iocommand.buf_size)) {
-					kfree(buff);
-					cmd_special_free(h, c);
-					return -EFAULT;
-				}
-			}
-			kfree(buff);
-			cmd_special_free(h, c);
-			return 0;
-		}
-	case CCISS_BIG_PASSTHRU:{
-			BIG_IOCTL_Command_struct *ioc;
-			CommandList_struct *c;
-			unsigned char **buff = NULL;
-			int *buff_size = NULL;
-			u64bit temp64;
-			BYTE sg_used = 0;
-			int status = 0;
-			int i;
-			DECLARE_COMPLETION_ONSTACK(wait);
-			__u32 left;
-			__u32 sz;
-			BYTE __user *data_ptr;
-
-			if (!arg)
-				return -EINVAL;
-			if (!capable(CAP_SYS_RAWIO))
-				return -EPERM;
-			ioc = (BIG_IOCTL_Command_struct *)
-			    kmalloc(sizeof(*ioc), GFP_KERNEL);
-			if (!ioc) {
-				status = -ENOMEM;
-				goto cleanup1;
-			}
-			if (copy_from_user(ioc, argp, sizeof(*ioc))) {
-				status = -EFAULT;
-				goto cleanup1;
-			}
-			if ((ioc->buf_size < 1) &&
-			    (ioc->Request.Type.Direction != XFER_NONE)) {
-				status = -EINVAL;
-				goto cleanup1;
-			}
-			/* Check kmalloc limits  using all SGs */
-			if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
-				status = -EINVAL;
-				goto cleanup1;
-			}
-			if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
-				status = -EINVAL;
-				goto cleanup1;
-			}
-			buff =
-			    kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
-			if (!buff) {
-				status = -ENOMEM;
-				goto cleanup1;
-			}
-			buff_size = kmalloc(MAXSGENTRIES * sizeof(int),
-						   GFP_KERNEL);
-			if (!buff_size) {
-				status = -ENOMEM;
-				goto cleanup1;
-			}
-			left = ioc->buf_size;
-			data_ptr = ioc->buf;
-			while (left) {
-				sz = (left >
-				      ioc->malloc_size) ? ioc->
-				    malloc_size : left;
-				buff_size[sg_used] = sz;
-				buff[sg_used] = kmalloc(sz, GFP_KERNEL);
-				if (buff[sg_used] == NULL) {
-					status = -ENOMEM;
-					goto cleanup1;
-				}
-				if (ioc->Request.Type.Direction == XFER_WRITE) {
-					if (copy_from_user
-					    (buff[sg_used], data_ptr, sz)) {
-						status = -EFAULT;
-						goto cleanup1;
-					}
-				} else {
-					memset(buff[sg_used], 0, sz);
-				}
-				left -= sz;
-				data_ptr += sz;
-				sg_used++;
-			}
-			c = cmd_special_alloc(h);
-			if (!c) {
-				status = -ENOMEM;
-				goto cleanup1;
-			}
-			c->cmd_type = CMD_IOCTL_PEND;
-			c->Header.ReplyQueue = 0;
-
-			if (ioc->buf_size > 0) {
-				c->Header.SGList = sg_used;
-				c->Header.SGTotal = sg_used;
-			} else {
-				c->Header.SGList = 0;
-				c->Header.SGTotal = 0;
-			}
-			c->Header.LUN = ioc->LUN_info;
-			c->Header.Tag.lower = c->busaddr;
-
-			c->Request = ioc->Request;
-			if (ioc->buf_size > 0) {
-				for (i = 0; i < sg_used; i++) {
-					temp64.val =
-					    pci_map_single(h->pdev, buff[i],
-						    buff_size[i],
-						    PCI_DMA_BIDIRECTIONAL);
-					c->SG[i].Addr.lower =
-					    temp64.val32.lower;
-					c->SG[i].Addr.upper =
-					    temp64.val32.upper;
-					c->SG[i].Len = buff_size[i];
-					c->SG[i].Ext = 0;	/* we are not chaining */
-				}
-			}
-			c->waiting = &wait;
-			enqueue_cmd_and_start_io(h, c);
-			wait_for_completion(&wait);
-			/* unlock the buffers from DMA */
-			for (i = 0; i < sg_used; i++) {
-				temp64.val32.lower = c->SG[i].Addr.lower;
-				temp64.val32.upper = c->SG[i].Addr.upper;
-				pci_unmap_single(h->pdev,
-					(dma_addr_t) temp64.val, buff_size[i],
-					PCI_DMA_BIDIRECTIONAL);
-			}
-			check_ioctl_unit_attention(h, c);
-			/* Copy the error information out */
-			ioc->error_info = *(c->err_info);
-			if (copy_to_user(argp, ioc, sizeof(*ioc))) {
-				cmd_special_free(h, c);
-				status = -EFAULT;
-				goto cleanup1;
-			}
-			if (ioc->Request.Type.Direction == XFER_READ) {
-				/* Copy the data out of the buffer we created */
-				BYTE __user *ptr = ioc->buf;
-				for (i = 0; i < sg_used; i++) {
-					if (copy_to_user
-					    (ptr, buff[i], buff_size[i])) {
-						cmd_special_free(h, c);
-						status = -EFAULT;
-						goto cleanup1;
-					}
-					ptr += buff_size[i];
-				}
-			}
-			cmd_special_free(h, c);
-			status = 0;
-		      cleanup1:
-			if (buff) {
-				for (i = 0; i < sg_used; i++)
-					kfree(buff[i]);
-				kfree(buff);
-			}
-			kfree(buff_size);
-			kfree(ioc);
-			return status;
-		}
+		return cciss_passthru(h, argp);
+	case CCISS_BIG_PASSTHRU:
+		return cciss_bigpassthru(h, argp);
 
 	/* scsi_cmd_ioctl handles these, below, though some are not */
 	/* very meaningful for cciss.  SG_IO is the main one people want. */
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index d53b029..946dad4 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -35,7 +35,7 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
@@ -68,6 +68,7 @@
 
 #define CPQARRAY_DMA_MASK	0xFFFFFFFF	/* 32 bit DMA */
 
+static DEFINE_MUTEX(cpqarray_mutex);
 static int nr_ctlr;
 static ctlr_info_t *hba[MAX_CTLR];
 
@@ -845,9 +846,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&cpqarray_mutex);
 	ret = ida_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&cpqarray_mutex);
 
 	return ret;
 }
@@ -859,10 +860,10 @@
 {
 	ctlr_info_t *host;
 
-	lock_kernel();
+	mutex_lock(&cpqarray_mutex);
 	host = get_host(disk);
 	host->usage_count--;
-	unlock_kernel();
+	mutex_unlock(&cpqarray_mutex);
 
 	return 0;
 }
@@ -1217,9 +1218,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&cpqarray_mutex);
 	ret = ida_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&cpqarray_mutex);
 
 	return ret;
 }
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index 9400845..ac04ef9 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -965,29 +965,30 @@
 	 * ok, (capacity & 7) != 0 sometimes, but who cares...
 	 * we count rs_{total,left} in bits, not sectors.
 	 */
-	spin_lock_irqsave(&mdev->al_lock, flags);
 	count = drbd_bm_clear_bits(mdev, sbnr, ebnr);
-	if (count) {
-		/* we need the lock for drbd_try_clear_on_disk_bm */
-		if (jiffies - mdev->rs_mark_time > HZ*10) {
-			/* should be rolling marks,
-			 * but we estimate only anyways. */
-			if (mdev->rs_mark_left != drbd_bm_total_weight(mdev) &&
+	if (count && get_ldev(mdev)) {
+		unsigned long now = jiffies;
+		unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
+		int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
+		if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
+			unsigned long tw = drbd_bm_total_weight(mdev);
+			if (mdev->rs_mark_left[mdev->rs_last_mark] != tw &&
 			    mdev->state.conn != C_PAUSED_SYNC_T &&
 			    mdev->state.conn != C_PAUSED_SYNC_S) {
-				mdev->rs_mark_time = jiffies;
-				mdev->rs_mark_left = drbd_bm_total_weight(mdev);
+				mdev->rs_mark_time[next] = now;
+				mdev->rs_mark_left[next] = tw;
+				mdev->rs_last_mark = next;
 			}
 		}
-		if (get_ldev(mdev)) {
-			drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
-			put_ldev(mdev);
-		}
+		spin_lock_irqsave(&mdev->al_lock, flags);
+		drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
+		spin_unlock_irqrestore(&mdev->al_lock, flags);
+
 		/* just wake_up unconditional now, various lc_chaged(),
 		 * lc_put() in drbd_try_clear_on_disk_bm(). */
 		wake_up = 1;
+		put_ldev(mdev);
 	}
-	spin_unlock_irqrestore(&mdev->al_lock, flags);
 	if (wake_up)
 		wake_up(&mdev->al_wait);
 }
@@ -1118,7 +1119,7 @@
  * @mdev:	DRBD device.
  * @sector:	The sector number.
  *
- * This functions sleeps on al_wait. Returns 1 on success, 0 if interrupted.
+ * This functions sleeps on al_wait. Returns 0 on success, -EINTR if interrupted.
  */
 int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
 {
@@ -1129,10 +1130,10 @@
 	sig = wait_event_interruptible(mdev->al_wait,
 			(bm_ext = _bme_get(mdev, enr)));
 	if (sig)
-		return 0;
+		return -EINTR;
 
 	if (test_bit(BME_LOCKED, &bm_ext->flags))
-		return 1;
+		return 0;
 
 	for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
 		sig = wait_event_interruptible(mdev->al_wait,
@@ -1145,13 +1146,11 @@
 				wake_up(&mdev->al_wait);
 			}
 			spin_unlock_irq(&mdev->al_lock);
-			return 0;
+			return -EINTR;
 		}
 	}
-
 	set_bit(BME_LOCKED, &bm_ext->flags);
-
-	return 1;
+	return 0;
 }
 
 /**
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index e3f88d6..fd42832 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -569,7 +569,7 @@
  *
  * maybe bm_set should be atomic_t ?
  */
-static unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev)
+unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
 	unsigned long s;
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 352441b..9bdcf43 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -337,13 +337,25 @@
  * NOTE that the payload starts at a long aligned offset,
  * regardless of 32 or 64 bit arch!
  */
-struct p_header {
+struct p_header80 {
 	u32	  magic;
 	u16	  command;
 	u16	  length;	/* bytes of data after this header */
 	u8	  payload[0];
 } __packed;
-/* 8 bytes. packet FIXED for the next century! */
+
+/* Header for big packets, Used for data packets exceeding 64kB */
+struct p_header95 {
+	u16	  magic;	/* use DRBD_MAGIC_BIG here */
+	u16	  command;
+	u32	  length;	/* Use only 24 bits of that. Ignore the highest 8 bit. */
+	u8	  payload[0];
+} __packed;
+
+union p_header {
+	struct p_header80 h80;
+	struct p_header95 h95;
+};
 
 /*
  * short commands, packets without payload, plain p_header:
@@ -362,12 +374,16 @@
  */
 
 /* these defines must not be changed without changing the protocol version */
-#define DP_HARDBARRIER	      1
-#define DP_RW_SYNC	      2
+#define DP_HARDBARRIER	      1 /* depricated */
+#define DP_RW_SYNC	      2 /* equals REQ_SYNC    */
 #define DP_MAY_SET_IN_SYNC    4
+#define DP_UNPLUG             8 /* equals REQ_UNPLUG  */
+#define DP_FUA               16 /* equals REQ_FUA     */
+#define DP_FLUSH             32 /* equals REQ_FLUSH   */
+#define DP_DISCARD           64 /* equals REQ_DISCARD */
 
 struct p_data {
-	struct p_header head;
+	union p_header head;
 	u64	    sector;    /* 64 bits sector number */
 	u64	    block_id;  /* to identify the request in protocol B&C */
 	u32	    seq_num;
@@ -383,7 +399,7 @@
  *   P_DATA_REQUEST, P_RS_DATA_REQUEST
  */
 struct p_block_ack {
-	struct p_header head;
+	struct p_header80 head;
 	u64	    sector;
 	u64	    block_id;
 	u32	    blksize;
@@ -392,7 +408,7 @@
 
 
 struct p_block_req {
-	struct p_header head;
+	struct p_header80 head;
 	u64 sector;
 	u64 block_id;
 	u32 blksize;
@@ -409,7 +425,7 @@
  */
 
 struct p_handshake {
-	struct p_header head;	/* 8 bytes */
+	struct p_header80 head;	/* 8 bytes */
 	u32 protocol_min;
 	u32 feature_flags;
 	u32 protocol_max;
@@ -424,19 +440,19 @@
 /* 80 bytes, FIXED for the next century */
 
 struct p_barrier {
-	struct p_header head;
+	struct p_header80 head;
 	u32 barrier;	/* barrier number _handle_ only */
 	u32 pad;	/* to multiple of 8 Byte */
 } __packed;
 
 struct p_barrier_ack {
-	struct p_header head;
+	struct p_header80 head;
 	u32 barrier;
 	u32 set_size;
 } __packed;
 
 struct p_rs_param {
-	struct p_header head;
+	struct p_header80 head;
 	u32 rate;
 
 	      /* Since protocol version 88 and higher. */
@@ -444,20 +460,31 @@
 } __packed;
 
 struct p_rs_param_89 {
-	struct p_header head;
+	struct p_header80 head;
 	u32 rate;
         /* protocol version 89: */
 	char verify_alg[SHARED_SECRET_MAX];
 	char csums_alg[SHARED_SECRET_MAX];
 } __packed;
 
+struct p_rs_param_95 {
+	struct p_header80 head;
+	u32 rate;
+	char verify_alg[SHARED_SECRET_MAX];
+	char csums_alg[SHARED_SECRET_MAX];
+	u32 c_plan_ahead;
+	u32 c_delay_target;
+	u32 c_fill_target;
+	u32 c_max_rate;
+} __packed;
+
 enum drbd_conn_flags {
 	CF_WANT_LOSE = 1,
 	CF_DRY_RUN = 2,
 };
 
 struct p_protocol {
-	struct p_header head;
+	struct p_header80 head;
 	u32 protocol;
 	u32 after_sb_0p;
 	u32 after_sb_1p;
@@ -471,17 +498,17 @@
 } __packed;
 
 struct p_uuids {
-	struct p_header head;
+	struct p_header80 head;
 	u64 uuid[UI_EXTENDED_SIZE];
 } __packed;
 
 struct p_rs_uuid {
-	struct p_header head;
+	struct p_header80 head;
 	u64	    uuid;
 } __packed;
 
 struct p_sizes {
-	struct p_header head;
+	struct p_header80 head;
 	u64	    d_size;  /* size of disk */
 	u64	    u_size;  /* user requested size */
 	u64	    c_size;  /* current exported size */
@@ -491,18 +518,18 @@
 } __packed;
 
 struct p_state {
-	struct p_header head;
+	struct p_header80 head;
 	u32	    state;
 } __packed;
 
 struct p_req_state {
-	struct p_header head;
+	struct p_header80 head;
 	u32	    mask;
 	u32	    val;
 } __packed;
 
 struct p_req_state_reply {
-	struct p_header head;
+	struct p_header80 head;
 	u32	    retcode;
 } __packed;
 
@@ -517,7 +544,7 @@
 } __packed;
 
 struct p_discard {
-	struct p_header head;
+	struct p_header80 head;
 	u64	    block_id;
 	u32	    seq_num;
 	u32	    pad;
@@ -533,7 +560,7 @@
 };
 
 struct p_compressed_bm {
-	struct p_header head;
+	struct p_header80 head;
 	/* (encoding & 0x0f): actual encoding, see enum drbd_bitmap_code
 	 * (encoding & 0x80): polarity (set/unset) of first runlength
 	 * ((encoding >> 4) & 0x07): pad_bits, number of trailing zero bits
@@ -544,10 +571,10 @@
 	u8 code[0];
 } __packed;
 
-struct p_delay_probe {
-	struct p_header head;
-	u32	seq_num; /* sequence number to match the two probe packets */
-	u32	offset;	 /* usecs the probe got sent after the reference time point */
+struct p_delay_probe93 {
+	struct p_header80 head;
+	u32     seq_num; /* sequence number to match the two probe packets */
+	u32     offset;  /* usecs the probe got sent after the reference time point */
 } __packed;
 
 /* DCBP: Drbd Compressed Bitmap Packet ... */
@@ -594,7 +621,7 @@
  * so we need to use the fixed size 4KiB page size
  * most architechtures have used for a long time.
  */
-#define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header))
+#define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header80))
 #define BM_PACKET_WORDS (BM_PACKET_PAYLOAD_BYTES/sizeof(long))
 #define BM_PACKET_VLI_BYTES_MAX (4096 - sizeof(struct p_compressed_bm))
 #if (PAGE_SIZE < 4096)
@@ -603,13 +630,14 @@
 #endif
 
 union p_polymorph {
-        struct p_header          header;
+        union p_header           header;
         struct p_handshake       handshake;
         struct p_data            data;
         struct p_block_ack       block_ack;
         struct p_barrier         barrier;
         struct p_barrier_ack     barrier_ack;
         struct p_rs_param_89     rs_param_89;
+        struct p_rs_param_95     rs_param_95;
         struct p_protocol        protocol;
         struct p_sizes           sizes;
         struct p_uuids           uuids;
@@ -617,6 +645,8 @@
         struct p_req_state       req_state;
         struct p_req_state_reply req_state_reply;
         struct p_block_req       block_req;
+	struct p_delay_probe93   delay_probe93;
+	struct p_rs_uuid         rs_uuid;
 } __packed;
 
 /**********************************************************************/
@@ -697,7 +727,7 @@
 	struct list_head requests; /* requests before */
 	struct drbd_tl_epoch *next; /* pointer to the next barrier */
 	unsigned int br_number;  /* the barriers identifier. */
-	int n_req;	/* number of requests attached before this barrier */
+	int n_writes;	/* number of requests attached before this barrier */
 };
 
 struct drbd_request;
@@ -747,7 +777,7 @@
 struct drbd_epoch_entry {
 	struct drbd_work w;
 	struct hlist_node colision;
-	struct drbd_epoch *epoch;
+	struct drbd_epoch *epoch; /* for writes */
 	struct drbd_conf *mdev;
 	struct page *pages;
 	atomic_t pending_bios;
@@ -755,7 +785,10 @@
 	/* see comments on ee flag bits below */
 	unsigned long flags;
 	sector_t sector;
-	u64 block_id;
+	union {
+		u64 block_id;
+		struct digest_info *digest;
+	};
 };
 
 /* ee flag bits.
@@ -781,12 +814,16 @@
 	 * if any of those fail, we set this flag atomically
 	 * from the endio callback */
 	__EE_WAS_ERROR,
+
+	/* This ee has a pointer to a digest instead of a block id */
+	__EE_HAS_DIGEST,
 };
 #define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO)
 #define EE_MAY_SET_IN_SYNC     (1<<__EE_MAY_SET_IN_SYNC)
 #define EE_IS_BARRIER          (1<<__EE_IS_BARRIER)
 #define	EE_RESUBMITTED         (1<<__EE_RESUBMITTED)
 #define EE_WAS_ERROR           (1<<__EE_WAS_ERROR)
+#define EE_HAS_DIGEST          (1<<__EE_HAS_DIGEST)
 
 /* global flag bits */
 enum {
@@ -794,7 +831,6 @@
 	SIGNAL_ASENDER,		/* whether asender wants to be interrupted */
 	SEND_PING,		/* whether asender should send a ping asap */
 
-	STOP_SYNC_TIMER,	/* tell timer to cancel itself */
 	UNPLUG_QUEUED,		/* only relevant with kernel 2.4 */
 	UNPLUG_REMOTE,		/* sending a "UnplugRemote" could help */
 	MD_DIRTY,		/* current uuids and flags not yet on disk */
@@ -816,6 +852,7 @@
 	BITMAP_IO,		/* suspend application io;
 				   once no more io in flight, start bitmap io */
 	BITMAP_IO_QUEUED,       /* Started bitmap IO */
+	GO_DISKLESS,		/* Disk failed, local_cnt reached zero, we are going diskless */
 	RESYNC_AFTER_NEG,       /* Resync after online grow after the attach&negotiate finished. */
 	NET_CONGESTED,		/* The data socket is congested */
 
@@ -829,6 +866,8 @@
 				 * the peer, if it changed there as well. */
 	CONN_DRY_RUN,		/* Expect disconnect after resync handshake. */
 	GOT_PING_ACK,		/* set when we receive a ping_ack packet, misc wait gets woken */
+	NEW_CUR_UUID,		/* Create new current UUID when thawing IO */
+	AL_SUSPENDED,		/* Activity logging is currently suspended. */
 };
 
 struct drbd_bitmap; /* opaque for drbd_conf */
@@ -838,10 +877,6 @@
 
 /* THINK maybe we actually want to use the default "event/%s" worker threads
  * or similar in linux 2.6, which uses per cpu data and threads.
- *
- * To be general, this might need a spin_lock member.
- * For now, please use the mdev->req_lock to protect list_head,
- * see drbd_queue_work below.
  */
 struct drbd_work_queue {
 	struct list_head q;
@@ -915,6 +950,12 @@
 	WO_bio_barrier
 };
 
+struct fifo_buffer {
+	int *values;
+	unsigned int head_index;
+	unsigned int size;
+};
+
 struct drbd_conf {
 	/* things that are stored as / read from meta data on disk */
 	unsigned long flags;
@@ -936,9 +977,16 @@
 	unsigned int ko_count;
 	struct drbd_work  resync_work,
 			  unplug_work,
+			  go_diskless,
 			  md_sync_work;
 	struct timer_list resync_timer;
 	struct timer_list md_sync_timer;
+#ifdef DRBD_DEBUG_MD_SYNC
+	struct {
+		unsigned int line;
+		const char* func;
+	} last_md_mark_dirty;
+#endif
 
 	/* Used after attach while negotiating new disk state. */
 	union drbd_state new_state_tmp;
@@ -946,6 +994,7 @@
 	union drbd_state state;
 	wait_queue_head_t misc_wait;
 	wait_queue_head_t state_wait;  /* upon each state change. */
+	wait_queue_head_t net_cnt_wait;
 	unsigned int send_cnt;
 	unsigned int recv_cnt;
 	unsigned int read_cnt;
@@ -974,12 +1023,16 @@
 	unsigned long rs_start;
 	/* cumulated time in PausedSyncX state [unit jiffies] */
 	unsigned long rs_paused;
-	/* block not up-to-date at mark [unit BM_BLOCK_SIZE] */
-	unsigned long rs_mark_left;
-	/* marks's time [unit jiffies] */
-	unsigned long rs_mark_time;
-	/* skipped because csum was equeal [unit BM_BLOCK_SIZE] */
+	/* skipped because csum was equal [unit BM_BLOCK_SIZE] */
 	unsigned long rs_same_csum;
+#define DRBD_SYNC_MARKS 8
+#define DRBD_SYNC_MARK_STEP (3*HZ)
+	/* block not up-to-date at mark [unit BM_BLOCK_SIZE] */
+	unsigned long rs_mark_left[DRBD_SYNC_MARKS];
+	/* marks's time [unit jiffies] */
+	unsigned long rs_mark_time[DRBD_SYNC_MARKS];
+	/* current index into rs_mark_{left,time} */
+	int rs_last_mark;
 
 	/* where does the admin want us to start? (sector) */
 	sector_t ov_start_sector;
@@ -1012,10 +1065,10 @@
 	spinlock_t epoch_lock;
 	unsigned int epochs;
 	enum write_ordering_e write_ordering;
-	struct list_head active_ee; /* IO in progress */
-	struct list_head sync_ee;   /* IO in progress */
+	struct list_head active_ee; /* IO in progress (P_DATA gets written to disk) */
+	struct list_head sync_ee;   /* IO in progress (P_RS_DATA_REPLY gets written to disk) */
 	struct list_head done_ee;   /* send ack */
-	struct list_head read_ee;   /* IO in progress */
+	struct list_head read_ee;   /* IO in progress (any read) */
 	struct list_head net_ee;    /* zero-copy network send in progress */
 	struct hlist_head *ee_hash; /* is proteced by req_lock! */
 	unsigned int ee_hash_s;
@@ -1026,7 +1079,8 @@
 	int next_barrier_nr;
 	struct hlist_head *app_reads_hash; /* is proteced by req_lock */
 	struct list_head resync_reads;
-	atomic_t pp_in_use;
+	atomic_t pp_in_use;		/* allocated from page pool */
+	atomic_t pp_in_use_by_net;	/* sendpage()d, still referenced by tcp */
 	wait_queue_head_t ee_wait;
 	struct page *md_io_page;	/* one page buffer for md_io */
 	struct page *md_io_tmpp;	/* for logical_block_size != 512 */
@@ -1054,6 +1108,15 @@
 	u64 ed_uuid; /* UUID of the exposed data */
 	struct mutex state_mutex;
 	char congestion_reason;  /* Why we where congested... */
+	atomic_t rs_sect_in; /* for incoming resync data rate, SyncTarget */
+	atomic_t rs_sect_ev; /* for submitted resync data rate, both */
+	int rs_last_sect_ev; /* counter to compare with */
+	int rs_last_events;  /* counter of read or write "events" (unit sectors)
+			      * on the lower level device when we last looked. */
+	int c_sync_rate; /* current resync rate after syncer throttle magic */
+	struct fifo_buffer rs_plan_s; /* correction values of resync planer */
+	int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
+	int rs_planed;    /* resync sectors already planed */
 };
 
 static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
@@ -1138,6 +1201,8 @@
 extern void tl_release(struct drbd_conf *mdev, unsigned int barrier_nr,
 		       unsigned int set_size);
 extern void tl_clear(struct drbd_conf *mdev);
+enum drbd_req_event;
+extern void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what);
 extern void _tl_add_barrier(struct drbd_conf *, struct drbd_tl_epoch *);
 extern void drbd_free_sock(struct drbd_conf *mdev);
 extern int drbd_send(struct drbd_conf *mdev, struct socket *sock,
@@ -1150,12 +1215,12 @@
 extern int _drbd_send_state(struct drbd_conf *mdev);
 extern int drbd_send_state(struct drbd_conf *mdev);
 extern int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
-			enum drbd_packets cmd, struct p_header *h,
+			enum drbd_packets cmd, struct p_header80 *h,
 			size_t size, unsigned msg_flags);
 #define USE_DATA_SOCKET 1
 #define USE_META_SOCKET 0
 extern int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket,
-			enum drbd_packets cmd, struct p_header *h,
+			enum drbd_packets cmd, struct p_header80 *h,
 			size_t size);
 extern int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd,
 			char *data, size_t size);
@@ -1167,7 +1232,7 @@
 extern int drbd_send_ack_rp(struct drbd_conf *mdev, enum drbd_packets cmd,
 			struct p_block_req *rp);
 extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
-			struct p_data *dp);
+			struct p_data *dp, int data_size);
 extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd,
 			    sector_t sector, int blksize, u64 block_id);
 extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
@@ -1201,7 +1266,13 @@
 extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local);
 extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local);
 extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
+#ifndef DRBD_DEBUG_MD_SYNC
 extern void drbd_md_mark_dirty(struct drbd_conf *mdev);
+#else
+#define drbd_md_mark_dirty(m)	drbd_md_mark_dirty_(m, __LINE__ , __func__ )
+extern void drbd_md_mark_dirty_(struct drbd_conf *mdev,
+		unsigned int line, const char *func);
+#endif
 extern void drbd_queue_bitmap_io(struct drbd_conf *mdev,
 				 int (*io_fn)(struct drbd_conf *),
 				 void (*done)(struct drbd_conf *, int),
@@ -1209,6 +1280,7 @@
 extern int drbd_bmio_set_n_write(struct drbd_conf *mdev);
 extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev);
 extern int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why);
+extern void drbd_go_diskless(struct drbd_conf *mdev);
 
 
 /* Meta data layout
@@ -1264,6 +1336,8 @@
  * Bit 1 ==> local node thinks this block needs to be synced.
  */
 
+#define SLEEP_TIME (HZ/10)
+
 #define BM_BLOCK_SHIFT  12			 /* 4k per bit */
 #define BM_BLOCK_SIZE	 (1<<BM_BLOCK_SHIFT)
 /* (9+3) : 512 bytes @ 8 bits; representing 16M storage
@@ -1335,11 +1409,13 @@
 #endif
 
 /* Sector shift value for the "hash" functions of tl_hash and ee_hash tables.
- * With a value of 6 all IO in one 32K block make it to the same slot of the
+ * With a value of 8 all IO in one 128K block make it to the same slot of the
  * hash table. */
-#define HT_SHIFT 6
+#define HT_SHIFT 8
 #define DRBD_MAX_SEGMENT_SIZE (1U<<(9+HT_SHIFT))
 
+#define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */
+
 /* Number of elements in the app_reads_hash */
 #define APP_R_HSIZE 15
 
@@ -1369,6 +1445,7 @@
 /* bm_find_next variants for use while you hold drbd_bm_lock() */
 extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
 extern unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo);
+extern unsigned long _drbd_bm_total_weight(struct drbd_conf *mdev);
 extern unsigned long drbd_bm_total_weight(struct drbd_conf *mdev);
 extern int drbd_bm_rs_done(struct drbd_conf *mdev);
 /* for receive_bitmap */
@@ -1421,7 +1498,8 @@
 extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local);
 extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role,
 		int force);
-enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev);
+extern enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev);
+extern void drbd_try_outdate_peer_async(struct drbd_conf *mdev);
 extern int drbd_khelper(struct drbd_conf *mdev, char *cmd);
 
 /* drbd_worker.c */
@@ -1467,10 +1545,12 @@
 extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int);
 extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int);
 extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int);
+extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int);
 
 extern void resync_timer_fn(unsigned long data);
 
 /* drbd_receiver.c */
+extern int drbd_rs_should_slow_down(struct drbd_conf *mdev);
 extern int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
 		const unsigned rw, const int fault_type);
 extern int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list);
@@ -1479,7 +1559,10 @@
 					    sector_t sector,
 					    unsigned int data_size,
 					    gfp_t gfp_mask) __must_hold(local);
-extern void drbd_free_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e);
+extern void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
+		int is_net);
+#define drbd_free_ee(m,e)	drbd_free_some_ee(m, e, 0)
+#define drbd_free_net_ee(m,e)	drbd_free_some_ee(m, e, 1)
 extern void drbd_wait_ee_list_empty(struct drbd_conf *mdev,
 		struct list_head *head);
 extern void _drbd_wait_ee_list_empty(struct drbd_conf *mdev,
@@ -1487,6 +1570,7 @@
 extern void drbd_set_recv_tcq(struct drbd_conf *mdev, int tcq_enabled);
 extern void _drbd_clear_done_ee(struct drbd_conf *mdev, struct list_head *to_be_freed);
 extern void drbd_flush_workqueue(struct drbd_conf *mdev);
+extern void drbd_free_tl_hash(struct drbd_conf *mdev);
 
 /* yes, there is kernel_setsockopt, but only since 2.6.18. we don't need to
  * mess with get_fs/set_fs, we know we are KERNEL_DS always. */
@@ -1600,6 +1684,8 @@
 #define susp_MASK 1
 #define user_isp_MASK 1
 #define aftr_isp_MASK 1
+#define susp_nod_MASK 1
+#define susp_fen_MASK 1
 
 #define NS(T, S) \
 	({ union drbd_state mask; mask.i = 0; mask.T = T##_MASK; mask; }), \
@@ -1856,13 +1942,6 @@
 }
 
 static inline void
-_drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
-{
-	list_add_tail(&w->list, &q->q);
-	up(&q->s);
-}
-
-static inline void
 drbd_queue_work_front(struct drbd_work_queue *q, struct drbd_work *w)
 {
 	unsigned long flags;
@@ -1899,19 +1978,19 @@
 static inline int drbd_send_short_cmd(struct drbd_conf *mdev,
 	enum drbd_packets cmd)
 {
-	struct p_header h;
+	struct p_header80 h;
 	return drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd, &h, sizeof(h));
 }
 
 static inline int drbd_send_ping(struct drbd_conf *mdev)
 {
-	struct p_header h;
+	struct p_header80 h;
 	return drbd_send_cmd(mdev, USE_META_SOCKET, P_PING, &h, sizeof(h));
 }
 
 static inline int drbd_send_ping_ack(struct drbd_conf *mdev)
 {
-	struct p_header h;
+	struct p_header80 h;
 	return drbd_send_cmd(mdev, USE_META_SOCKET, P_PING_ACK, &h, sizeof(h));
 }
 
@@ -2013,7 +2092,7 @@
 static inline void put_net_conf(struct drbd_conf *mdev)
 {
 	if (atomic_dec_and_test(&mdev->net_cnt))
-		wake_up(&mdev->misc_wait);
+		wake_up(&mdev->net_cnt_wait);
 }
 
 /**
@@ -2044,10 +2123,14 @@
 
 static inline void put_ldev(struct drbd_conf *mdev)
 {
+	int i = atomic_dec_return(&mdev->local_cnt);
 	__release(local);
-	if (atomic_dec_and_test(&mdev->local_cnt))
+	D_ASSERT(i >= 0);
+	if (i == 0) {
+		if (mdev->state.disk == D_FAILED)
+			drbd_go_diskless(mdev);
 		wake_up(&mdev->misc_wait);
-	D_ASSERT(atomic_read(&mdev->local_cnt) >= 0);
+	}
 }
 
 #ifndef __CHECKER__
@@ -2179,11 +2262,16 @@
 	return 1;
 }
 
+static inline int is_susp(union drbd_state s)
+{
+	return s.susp || s.susp_nod || s.susp_fen;
+}
+
 static inline int __inc_ap_bio_cond(struct drbd_conf *mdev)
 {
 	int mxb = drbd_get_max_buffers(mdev);
 
-	if (mdev->state.susp)
+	if (is_susp(mdev->state))
 		return 0;
 	if (test_bit(SUSPEND_IO, &mdev->flags))
 		return 0;
@@ -2321,8 +2409,7 @@
 	if (test_bit(MD_NO_BARRIER, &mdev->flags))
 		return;
 
-	r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
+	r = blkdev_issue_flush(mdev->ldev->md_bdev, GFP_KERNEL, NULL);
 	if (r) {
 		set_bit(MD_NO_BARRIER, &mdev->flags);
 		dev_err(DEV, "meta data flush failed with status %d, disabling md-flushes\n", r);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index fa650dd..c5dfe64 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -32,7 +32,7 @@
 #include <asm/types.h>
 #include <net/sock.h>
 #include <linux/ctype.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/proc_fs.h>
@@ -64,6 +64,7 @@
 	struct completion *done;
 };
 
+static DEFINE_MUTEX(drbd_main_mutex);
 int drbdd_init(struct drbd_thread *);
 int drbd_worker(struct drbd_thread *);
 int drbd_asender(struct drbd_thread *);
@@ -77,6 +78,7 @@
 static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused);
 static void md_sync_timer_fn(unsigned long data);
 static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused);
+static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused);
 
 MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
 	      "Lars Ellenberg <lars@linbit.com>");
@@ -199,7 +201,7 @@
 	INIT_LIST_HEAD(&b->w.list);
 	b->next = NULL;
 	b->br_number = 4711;
-	b->n_req = 0;
+	b->n_writes = 0;
 	b->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */
 
 	mdev->oldest_tle = b;
@@ -240,7 +242,7 @@
 	INIT_LIST_HEAD(&new->w.list);
 	new->w.cb = NULL; /* if this is != NULL, we need to dec_ap_pending in tl_clear */
 	new->next = NULL;
-	new->n_req = 0;
+	new->n_writes = 0;
 
 	newest_before = mdev->newest_tle;
 	/* never send a barrier number == 0, because that is special-cased
@@ -284,9 +286,9 @@
 			barrier_nr, b->br_number);
 		goto bail;
 	}
-	if (b->n_req != set_size) {
-		dev_err(DEV, "BAD! BarrierAck #%u received with n_req=%u, expected n_req=%u!\n",
-			barrier_nr, set_size, b->n_req);
+	if (b->n_writes != set_size) {
+		dev_err(DEV, "BAD! BarrierAck #%u received with n_writes=%u, expected n_writes=%u!\n",
+			barrier_nr, set_size, b->n_writes);
 		goto bail;
 	}
 
@@ -333,6 +335,82 @@
 	drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
 }
 
+/**
+ * _tl_restart() - Walks the transfer log, and applies an action to all requests
+ * @mdev:	DRBD device.
+ * @what:       The action/event to perform with all request objects
+ *
+ * @what might be one of connection_lost_while_pending, resend, fail_frozen_disk_io,
+ * restart_frozen_disk_io.
+ */
+static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
+{
+	struct drbd_tl_epoch *b, *tmp, **pn;
+	struct list_head *le, *tle, carry_reads;
+	struct drbd_request *req;
+	int rv, n_writes, n_reads;
+
+	b = mdev->oldest_tle;
+	pn = &mdev->oldest_tle;
+	while (b) {
+		n_writes = 0;
+		n_reads = 0;
+		INIT_LIST_HEAD(&carry_reads);
+		list_for_each_safe(le, tle, &b->requests) {
+			req = list_entry(le, struct drbd_request, tl_requests);
+			rv = _req_mod(req, what);
+
+			n_writes += (rv & MR_WRITE) >> MR_WRITE_SHIFT;
+			n_reads  += (rv & MR_READ) >> MR_READ_SHIFT;
+		}
+		tmp = b->next;
+
+		if (n_writes) {
+			if (what == resend) {
+				b->n_writes = n_writes;
+				if (b->w.cb == NULL) {
+					b->w.cb = w_send_barrier;
+					inc_ap_pending(mdev);
+					set_bit(CREATE_BARRIER, &mdev->flags);
+				}
+
+				drbd_queue_work(&mdev->data.work, &b->w);
+			}
+			pn = &b->next;
+		} else {
+			if (n_reads)
+				list_add(&carry_reads, &b->requests);
+			/* there could still be requests on that ring list,
+			 * in case local io is still pending */
+			list_del(&b->requests);
+
+			/* dec_ap_pending corresponding to queue_barrier.
+			 * the newest barrier may not have been queued yet,
+			 * in which case w.cb is still NULL. */
+			if (b->w.cb != NULL)
+				dec_ap_pending(mdev);
+
+			if (b == mdev->newest_tle) {
+				/* recycle, but reinit! */
+				D_ASSERT(tmp == NULL);
+				INIT_LIST_HEAD(&b->requests);
+				list_splice(&carry_reads, &b->requests);
+				INIT_LIST_HEAD(&b->w.list);
+				b->w.cb = NULL;
+				b->br_number = net_random();
+				b->n_writes = 0;
+
+				*pn = b;
+				break;
+			}
+			*pn = tmp;
+			kfree(b);
+		}
+		b = tmp;
+		list_splice(&carry_reads, &b->requests);
+	}
+}
+
 
 /**
  * tl_clear() - Clears all requests and &struct drbd_tl_epoch objects out of the TL
@@ -344,48 +422,12 @@
  */
 void tl_clear(struct drbd_conf *mdev)
 {
-	struct drbd_tl_epoch *b, *tmp;
 	struct list_head *le, *tle;
 	struct drbd_request *r;
-	int new_initial_bnr = net_random();
 
 	spin_lock_irq(&mdev->req_lock);
 
-	b = mdev->oldest_tle;
-	while (b) {
-		list_for_each_safe(le, tle, &b->requests) {
-			r = list_entry(le, struct drbd_request, tl_requests);
-			/* It would be nice to complete outside of spinlock.
-			 * But this is easier for now. */
-			_req_mod(r, connection_lost_while_pending);
-		}
-		tmp = b->next;
-
-		/* there could still be requests on that ring list,
-		 * in case local io is still pending */
-		list_del(&b->requests);
-
-		/* dec_ap_pending corresponding to queue_barrier.
-		 * the newest barrier may not have been queued yet,
-		 * in which case w.cb is still NULL. */
-		if (b->w.cb != NULL)
-			dec_ap_pending(mdev);
-
-		if (b == mdev->newest_tle) {
-			/* recycle, but reinit! */
-			D_ASSERT(tmp == NULL);
-			INIT_LIST_HEAD(&b->requests);
-			INIT_LIST_HEAD(&b->w.list);
-			b->w.cb = NULL;
-			b->br_number = new_initial_bnr;
-			b->n_req = 0;
-
-			mdev->oldest_tle = b;
-			break;
-		}
-		kfree(b);
-		b = tmp;
-	}
+	_tl_restart(mdev, connection_lost_while_pending);
 
 	/* we expect this list to be empty. */
 	D_ASSERT(list_empty(&mdev->out_of_sequence_requests));
@@ -401,6 +443,15 @@
 	/* ensure bit indicating barrier is required is clear */
 	clear_bit(CREATE_BARRIER, &mdev->flags);
 
+	memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *));
+
+	spin_unlock_irq(&mdev->req_lock);
+}
+
+void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
+{
+	spin_lock_irq(&mdev->req_lock);
+	_tl_restart(mdev, what);
 	spin_unlock_irq(&mdev->req_lock);
 }
 
@@ -455,7 +506,7 @@
 static int is_valid_state_transition(struct drbd_conf *,
 				     union drbd_state, union drbd_state);
 static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
-				       union drbd_state ns, int *warn_sync_abort);
+				       union drbd_state ns, const char **warn_sync_abort);
 int drbd_send_state_req(struct drbd_conf *,
 			union drbd_state, union drbd_state);
 
@@ -605,7 +656,7 @@
 	    drbd_role_str(ns.peer),
 	    drbd_disk_str(ns.disk),
 	    drbd_disk_str(ns.pdsk),
-	    ns.susp ? 's' : 'r',
+	    is_susp(ns) ? 's' : 'r',
 	    ns.aftr_isp ? 'a' : '-',
 	    ns.peer_isp ? 'p' : '-',
 	    ns.user_isp ? 'u' : '-'
@@ -763,7 +814,7 @@
  * to D_UNKNOWN. This rule and many more along those lines are in this function.
  */
 static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
-				       union drbd_state ns, int *warn_sync_abort)
+				       union drbd_state ns, const char **warn_sync_abort)
 {
 	enum drbd_fencing_p fp;
 
@@ -778,9 +829,10 @@
 	    os.conn <= C_DISCONNECTING)
 		ns.conn = os.conn;
 
-	/* After a network error (+C_TEAR_DOWN) only C_UNCONNECTED or C_DISCONNECTING can follow */
+	/* After a network error (+C_TEAR_DOWN) only C_UNCONNECTED or C_DISCONNECTING can follow.
+	 * If you try to go into some Sync* state, that shall fail (elsewhere). */
 	if (os.conn >= C_TIMEOUT && os.conn <= C_TEAR_DOWN &&
-	    ns.conn != C_UNCONNECTED && ns.conn != C_DISCONNECTING)
+	    ns.conn != C_UNCONNECTED && ns.conn != C_DISCONNECTING && ns.conn <= C_TEAR_DOWN)
 		ns.conn = os.conn;
 
 	/* After C_DISCONNECTING only C_STANDALONE may follow */
@@ -798,14 +850,13 @@
 	if (ns.conn == C_STANDALONE && ns.disk == D_DISKLESS && ns.role == R_SECONDARY)
 		ns.aftr_isp = 0;
 
-	if (ns.conn <= C_DISCONNECTING && ns.disk == D_DISKLESS)
-		ns.pdsk = D_UNKNOWN;
-
 	/* Abort resync if a disk fails/detaches */
 	if (os.conn > C_CONNECTED && ns.conn > C_CONNECTED &&
 	    (ns.disk <= D_FAILED || ns.pdsk <= D_FAILED)) {
 		if (warn_sync_abort)
-			*warn_sync_abort = 1;
+			*warn_sync_abort =
+				os.conn == C_VERIFY_S || os.conn == C_VERIFY_T ?
+				"Online-verify" : "Resync";
 		ns.conn = C_CONNECTED;
 	}
 
@@ -876,7 +927,12 @@
 	if (fp == FP_STONITH &&
 	    (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) &&
 	    !(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED))
-		ns.susp = 1;
+		ns.susp_fen = 1; /* Suspend IO while fence-peer handler runs (peer lost) */
+
+	if (mdev->sync_conf.on_no_data == OND_SUSPEND_IO &&
+	    (ns.role == R_PRIMARY && ns.disk < D_UP_TO_DATE && ns.pdsk < D_UP_TO_DATE) &&
+	    !(os.role == R_PRIMARY && os.disk < D_UP_TO_DATE && os.pdsk < D_UP_TO_DATE))
+		ns.susp_nod = 1; /* Suspend IO while no data available (no accessible data available) */
 
 	if (ns.aftr_isp || ns.peer_isp || ns.user_isp) {
 		if (ns.conn == C_SYNC_SOURCE)
@@ -912,6 +968,12 @@
 	}
 }
 
+static void drbd_resume_al(struct drbd_conf *mdev)
+{
+	if (test_and_clear_bit(AL_SUSPENDED, &mdev->flags))
+		dev_info(DEV, "Resumed AL updates\n");
+}
+
 /**
  * __drbd_set_state() - Set a new DRBD state
  * @mdev:	DRBD device.
@@ -927,7 +989,7 @@
 {
 	union drbd_state os;
 	int rv = SS_SUCCESS;
-	int warn_sync_abort = 0;
+	const char *warn_sync_abort = NULL;
 	struct after_state_chg_work *ascw;
 
 	os = mdev->state;
@@ -946,14 +1008,8 @@
 			/* If the old state was illegal as well, then let
 			   this happen...*/
 
-			if (is_valid_state(mdev, os) == rv) {
-				dev_err(DEV, "Considering state change from bad state. "
-				    "Error would be: '%s'\n",
-				    drbd_set_st_err_str(rv));
-				print_st(mdev, "old", os);
-				print_st(mdev, "new", ns);
+			if (is_valid_state(mdev, os) == rv)
 				rv = is_valid_state_transition(mdev, ns, os);
-			}
 		} else
 			rv = is_valid_state_transition(mdev, ns, os);
 	}
@@ -965,7 +1021,7 @@
 	}
 
 	if (warn_sync_abort)
-		dev_warn(DEV, "Resync aborted.\n");
+		dev_warn(DEV, "%s aborted.\n", warn_sync_abort);
 
 	{
 		char *pbp, pb[300];
@@ -976,7 +1032,10 @@
 		PSC(conn);
 		PSC(disk);
 		PSC(pdsk);
-		PSC(susp);
+		if (is_susp(ns) != is_susp(os))
+			pbp += sprintf(pbp, "susp( %s -> %s ) ",
+				       drbd_susp_str(is_susp(os)),
+				       drbd_susp_str(is_susp(ns)));
 		PSC(aftr_isp);
 		PSC(peer_isp);
 		PSC(user_isp);
@@ -1001,12 +1060,6 @@
 	wake_up(&mdev->misc_wait);
 	wake_up(&mdev->state_wait);
 
-	/*   post-state-change actions   */
-	if (os.conn >= C_SYNC_SOURCE   && ns.conn <= C_CONNECTED) {
-		set_bit(STOP_SYNC_TIMER, &mdev->flags);
-		mod_timer(&mdev->resync_timer, jiffies);
-	}
-
 	/* aborted verify run. log the last position */
 	if ((os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) &&
 	    ns.conn < C_CONNECTED) {
@@ -1019,41 +1072,42 @@
 	if ((os.conn == C_PAUSED_SYNC_T || os.conn == C_PAUSED_SYNC_S) &&
 	    (ns.conn == C_SYNC_TARGET  || ns.conn == C_SYNC_SOURCE)) {
 		dev_info(DEV, "Syncer continues.\n");
-		mdev->rs_paused += (long)jiffies-(long)mdev->rs_mark_time;
-		if (ns.conn == C_SYNC_TARGET) {
-			if (!test_and_clear_bit(STOP_SYNC_TIMER, &mdev->flags))
-				mod_timer(&mdev->resync_timer, jiffies);
-			/* This if (!test_bit) is only needed for the case
-			   that a device that has ceased to used its timer,
-			   i.e. it is already in drbd_resync_finished() gets
-			   paused and resumed. */
-		}
+		mdev->rs_paused += (long)jiffies
+				  -(long)mdev->rs_mark_time[mdev->rs_last_mark];
+		if (ns.conn == C_SYNC_TARGET)
+			mod_timer(&mdev->resync_timer, jiffies);
 	}
 
 	if ((os.conn == C_SYNC_TARGET  || os.conn == C_SYNC_SOURCE) &&
 	    (ns.conn == C_PAUSED_SYNC_T || ns.conn == C_PAUSED_SYNC_S)) {
 		dev_info(DEV, "Resync suspended\n");
-		mdev->rs_mark_time = jiffies;
-		if (ns.conn == C_PAUSED_SYNC_T)
-			set_bit(STOP_SYNC_TIMER, &mdev->flags);
+		mdev->rs_mark_time[mdev->rs_last_mark] = jiffies;
 	}
 
 	if (os.conn == C_CONNECTED &&
 	    (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T)) {
+		unsigned long now = jiffies;
+		int i;
+
 		mdev->ov_position = 0;
-		mdev->rs_total =
-		mdev->rs_mark_left = drbd_bm_bits(mdev);
+		mdev->rs_total = drbd_bm_bits(mdev);
 		if (mdev->agreed_pro_version >= 90)
 			set_ov_position(mdev, ns.conn);
 		else
 			mdev->ov_start_sector = 0;
 		mdev->ov_left = mdev->rs_total
 			      - BM_SECT_TO_BIT(mdev->ov_position);
-		mdev->rs_start     =
-		mdev->rs_mark_time = jiffies;
+		mdev->rs_start = now;
+		mdev->rs_last_events = 0;
+		mdev->rs_last_sect_ev = 0;
 		mdev->ov_last_oos_size = 0;
 		mdev->ov_last_oos_start = 0;
 
+		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+			mdev->rs_mark_left[i] = mdev->rs_total;
+			mdev->rs_mark_time[i] = now;
+		}
+
 		if (ns.conn == C_VERIFY_S) {
 			dev_info(DEV, "Starting Online Verify from sector %llu\n",
 					(unsigned long long)mdev->ov_position);
@@ -1106,6 +1160,10 @@
 	    ns.conn <= C_TEAR_DOWN && ns.conn >= C_TIMEOUT)
 		drbd_thread_restart_nowait(&mdev->receiver);
 
+	/* Resume AL writing if we get a connection */
+	if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
+		drbd_resume_al(mdev);
+
 	ascw = kmalloc(sizeof(*ascw), GFP_ATOMIC);
 	if (ascw) {
 		ascw->os = os;
@@ -1164,6 +1222,8 @@
 			   union drbd_state ns, enum chg_state_flags flags)
 {
 	enum drbd_fencing_p fp;
+	enum drbd_req_event what = nothing;
+	union drbd_state nsm = (union drbd_state){ .i = -1 };
 
 	if (os.conn != C_CONNECTED && ns.conn == C_CONNECTED) {
 		clear_bit(CRASHED_PRIMARY, &mdev->flags);
@@ -1187,17 +1247,49 @@
 	/* Here we have the actions that are performed after a
 	   state change. This function might sleep */
 
-	if (fp == FP_STONITH && ns.susp) {
-		/* case1: The outdate peer handler is successful:
-		 * case2: The connection was established again: */
-		if ((os.pdsk > D_OUTDATED  && ns.pdsk <= D_OUTDATED) ||
-		    (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)) {
+	nsm.i = -1;
+	if (ns.susp_nod) {
+		if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
+			if (ns.conn == C_CONNECTED)
+				what = resend, nsm.susp_nod = 0;
+			else /* ns.conn > C_CONNECTED */
+				dev_err(DEV, "Unexpected Resynd going on!\n");
+		}
+
+		if (os.disk == D_ATTACHING && ns.disk > D_ATTACHING)
+			what = restart_frozen_disk_io, nsm.susp_nod = 0;
+
+	}
+
+	if (ns.susp_fen) {
+		/* case1: The outdate peer handler is successful: */
+		if (os.pdsk > D_OUTDATED  && ns.pdsk <= D_OUTDATED) {
 			tl_clear(mdev);
+			if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
+				drbd_uuid_new_current(mdev);
+				clear_bit(NEW_CUR_UUID, &mdev->flags);
+				drbd_md_sync(mdev);
+			}
 			spin_lock_irq(&mdev->req_lock);
-			_drbd_set_state(_NS(mdev, susp, 0), CS_VERBOSE, NULL);
+			_drbd_set_state(_NS(mdev, susp_fen, 0), CS_VERBOSE, NULL);
 			spin_unlock_irq(&mdev->req_lock);
 		}
+		/* case2: The connection was established again: */
+		if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
+			clear_bit(NEW_CUR_UUID, &mdev->flags);
+			what = resend;
+			nsm.susp_fen = 0;
+		}
 	}
+
+	if (what != nothing) {
+		spin_lock_irq(&mdev->req_lock);
+		_tl_restart(mdev, what);
+		nsm.i &= mdev->state.i;
+		_drbd_set_state(mdev, nsm, CS_VERBOSE, NULL);
+		spin_unlock_irq(&mdev->req_lock);
+	}
+
 	/* Do not change the order of the if above and the two below... */
 	if (os.pdsk == D_DISKLESS && ns.pdsk > D_DISKLESS) {      /* attach on the peer */
 		drbd_send_uuids(mdev);
@@ -1216,16 +1308,22 @@
 		if (get_ldev(mdev)) {
 			if ((ns.role == R_PRIMARY || ns.peer == R_PRIMARY) &&
 			    mdev->ldev->md.uuid[UI_BITMAP] == 0 && ns.disk >= D_UP_TO_DATE) {
-				drbd_uuid_new_current(mdev);
-				drbd_send_uuids(mdev);
+				if (is_susp(mdev->state)) {
+					set_bit(NEW_CUR_UUID, &mdev->flags);
+				} else {
+					drbd_uuid_new_current(mdev);
+					drbd_send_uuids(mdev);
+				}
 			}
 			put_ldev(mdev);
 		}
 	}
 
 	if (ns.pdsk < D_INCONSISTENT && get_ldev(mdev)) {
-		if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0)
+		if (ns.peer == R_PRIMARY && mdev->ldev->md.uuid[UI_BITMAP] == 0) {
 			drbd_uuid_new_current(mdev);
+			drbd_send_uuids(mdev);
+		}
 
 		/* D_DISKLESS Peer becomes secondary */
 		if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
@@ -1267,42 +1365,51 @@
 	    os.disk > D_INCONSISTENT && ns.disk == D_INCONSISTENT)
 		drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL, "set_n_write from invalidate");
 
+	/* first half of local IO error */
 	if (os.disk > D_FAILED && ns.disk == D_FAILED) {
-		enum drbd_io_error_p eh;
+		enum drbd_io_error_p eh = EP_PASS_ON;
 
-		eh = EP_PASS_ON;
+		if (drbd_send_state(mdev))
+			dev_warn(DEV, "Notified peer that my disk is broken.\n");
+		else
+			dev_err(DEV, "Sending state for drbd_io_error() failed\n");
+
+		drbd_rs_cancel_all(mdev);
+
 		if (get_ldev_if_state(mdev, D_FAILED)) {
 			eh = mdev->ldev->dc.on_io_error;
 			put_ldev(mdev);
 		}
-
-		drbd_rs_cancel_all(mdev);
-		/* since get_ldev() only works as long as disk>=D_INCONSISTENT,
-		   and it is D_DISKLESS here, local_cnt can only go down, it can
-		   not increase... It will reach zero */
-		wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
-		mdev->rs_total = 0;
-		mdev->rs_failed = 0;
-		atomic_set(&mdev->rs_pending_cnt, 0);
-
-		spin_lock_irq(&mdev->req_lock);
-		_drbd_set_state(_NS(mdev, disk, D_DISKLESS), CS_HARD, NULL);
-		spin_unlock_irq(&mdev->req_lock);
-
 		if (eh == EP_CALL_HELPER)
 			drbd_khelper(mdev, "local-io-error");
 	}
 
+
+	/* second half of local IO error handling,
+	 * after local_cnt references have reached zero: */
+	if (os.disk == D_FAILED && ns.disk == D_DISKLESS) {
+		mdev->rs_total = 0;
+		mdev->rs_failed = 0;
+		atomic_set(&mdev->rs_pending_cnt, 0);
+	}
+
 	if (os.disk > D_DISKLESS && ns.disk == D_DISKLESS) {
+		/* We must still be diskless,
+		 * re-attach has to be serialized with this! */
+		if (mdev->state.disk != D_DISKLESS)
+			dev_err(DEV,
+				"ASSERT FAILED: disk is %s while going diskless\n",
+				drbd_disk_str(mdev->state.disk));
 
-		if (os.disk == D_FAILED) /* && ns.disk == D_DISKLESS*/ {
-			if (drbd_send_state(mdev))
-				dev_warn(DEV, "Notified peer that my disk is broken.\n");
-			else
-				dev_err(DEV, "Sending state in drbd_io_error() failed\n");
-		}
+		/* we cannot assert local_cnt == 0 here, as get_ldev_if_state
+		 * will inc/dec it frequently. Since we became D_DISKLESS, no
+		 * one has touched the protected members anymore, though, so we
+		 * are safe to free them here. */
+		if (drbd_send_state(mdev))
+			dev_warn(DEV, "Notified peer that I detached my disk.\n");
+		else
+			dev_err(DEV, "Sending state for detach failed\n");
 
-		wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
 		lc_destroy(mdev->resync);
 		mdev->resync = NULL;
 		lc_destroy(mdev->act_log);
@@ -1311,8 +1418,10 @@
 			drbd_free_bc(mdev->ldev);
 			mdev->ldev = NULL;);
 
-		if (mdev->md_io_tmpp)
+		if (mdev->md_io_tmpp) {
 			__free_page(mdev->md_io_tmpp);
+			mdev->md_io_tmpp = NULL;
+		}
 	}
 
 	/* Disks got bigger while they were detached */
@@ -1328,6 +1437,15 @@
 	    (os.user_isp && !ns.user_isp))
 		resume_next_sg(mdev);
 
+	/* sync target done with resync.  Explicitly notify peer, even though
+	 * it should (at least for non-empty resyncs) already know itself. */
+	if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
+		drbd_send_state(mdev);
+
+	/* free tl_hash if we Got thawed and are C_STANDALONE */
+	if (ns.conn == C_STANDALONE && !is_susp(ns) && mdev->tl_hash)
+		drbd_free_tl_hash(mdev);
+
 	/* Upon network connection, we need to start the receiver */
 	if (os.conn == C_STANDALONE && ns.conn == C_UNCONNECTED)
 		drbd_thread_start(&mdev->receiver);
@@ -1554,7 +1672,7 @@
 
 /* the appropriate socket mutex must be held already */
 int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock,
-			  enum drbd_packets cmd, struct p_header *h,
+			  enum drbd_packets cmd, struct p_header80 *h,
 			  size_t size, unsigned msg_flags)
 {
 	int sent, ok;
@@ -1564,7 +1682,7 @@
 
 	h->magic   = BE_DRBD_MAGIC;
 	h->command = cpu_to_be16(cmd);
-	h->length  = cpu_to_be16(size-sizeof(struct p_header));
+	h->length  = cpu_to_be16(size-sizeof(struct p_header80));
 
 	sent = drbd_send(mdev, sock, h, size, msg_flags);
 
@@ -1579,7 +1697,7 @@
  * when we hold the appropriate socket mutex.
  */
 int drbd_send_cmd(struct drbd_conf *mdev, int use_data_socket,
-		  enum drbd_packets cmd, struct p_header *h, size_t size)
+		  enum drbd_packets cmd, struct p_header80 *h, size_t size)
 {
 	int ok = 0;
 	struct socket *sock;
@@ -1607,7 +1725,7 @@
 int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd, char *data,
 		   size_t size)
 {
-	struct p_header h;
+	struct p_header80 h;
 	int ok;
 
 	h.magic   = BE_DRBD_MAGIC;
@@ -1629,7 +1747,7 @@
 
 int drbd_send_sync_param(struct drbd_conf *mdev, struct syncer_conf *sc)
 {
-	struct p_rs_param_89 *p;
+	struct p_rs_param_95 *p;
 	struct socket *sock;
 	int size, rv;
 	const int apv = mdev->agreed_pro_version;
@@ -1637,7 +1755,8 @@
 	size = apv <= 87 ? sizeof(struct p_rs_param)
 		: apv == 88 ? sizeof(struct p_rs_param)
 			+ strlen(mdev->sync_conf.verify_alg) + 1
-		: /* 89 */    sizeof(struct p_rs_param_89);
+		: apv <= 94 ? sizeof(struct p_rs_param_89)
+		: /* apv >= 95 */ sizeof(struct p_rs_param_95);
 
 	/* used from admin command context and receiver/worker context.
 	 * to avoid kmalloc, grab the socket right here,
@@ -1648,12 +1767,16 @@
 	if (likely(sock != NULL)) {
 		enum drbd_packets cmd = apv >= 89 ? P_SYNC_PARAM89 : P_SYNC_PARAM;
 
-		p = &mdev->data.sbuf.rs_param_89;
+		p = &mdev->data.sbuf.rs_param_95;
 
 		/* initialize verify_alg and csums_alg */
 		memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
 		p->rate = cpu_to_be32(sc->rate);
+		p->c_plan_ahead = cpu_to_be32(sc->c_plan_ahead);
+		p->c_delay_target = cpu_to_be32(sc->c_delay_target);
+		p->c_fill_target = cpu_to_be32(sc->c_fill_target);
+		p->c_max_rate = cpu_to_be32(sc->c_max_rate);
 
 		if (apv >= 88)
 			strcpy(p->verify_alg, mdev->sync_conf.verify_alg);
@@ -1709,7 +1832,7 @@
 		strcpy(p->integrity_alg, mdev->net_conf->integrity_alg);
 
 	rv = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_PROTOCOL,
-			   (struct p_header *)p, size);
+			   (struct p_header80 *)p, size);
 	kfree(p);
 	return rv;
 }
@@ -1735,7 +1858,7 @@
 	put_ldev(mdev);
 
 	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_UUIDS,
-			     (struct p_header *)&p, sizeof(p));
+			     (struct p_header80 *)&p, sizeof(p));
 }
 
 int drbd_send_uuids(struct drbd_conf *mdev)
@@ -1756,7 +1879,7 @@
 	p.uuid = cpu_to_be64(val);
 
 	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SYNC_UUID,
-			     (struct p_header *)&p, sizeof(p));
+			     (struct p_header80 *)&p, sizeof(p));
 }
 
 int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags)
@@ -1786,7 +1909,7 @@
 	p.dds_flags = cpu_to_be16(flags);
 
 	ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SIZES,
-			   (struct p_header *)&p, sizeof(p));
+			   (struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
@@ -1811,7 +1934,7 @@
 
 	if (likely(sock != NULL)) {
 		ok = _drbd_send_cmd(mdev, sock, P_STATE,
-				    (struct p_header *)&p, sizeof(p), 0);
+				    (struct p_header80 *)&p, sizeof(p), 0);
 	}
 
 	mutex_unlock(&mdev->data.mutex);
@@ -1829,7 +1952,7 @@
 	p.val     = cpu_to_be32(val.i);
 
 	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_STATE_CHG_REQ,
-			     (struct p_header *)&p, sizeof(p));
+			     (struct p_header80 *)&p, sizeof(p));
 }
 
 int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode)
@@ -1839,7 +1962,7 @@
 	p.retcode    = cpu_to_be32(retcode);
 
 	return drbd_send_cmd(mdev, USE_META_SOCKET, P_STATE_CHG_REPLY,
-			     (struct p_header *)&p, sizeof(p));
+			     (struct p_header80 *)&p, sizeof(p));
 }
 
 int fill_bitmap_rle_bits(struct drbd_conf *mdev,
@@ -1938,7 +2061,7 @@
 
 enum { OK, FAILED, DONE }
 send_bitmap_rle_or_plain(struct drbd_conf *mdev,
-	struct p_header *h, struct bm_xfer_ctx *c)
+	struct p_header80 *h, struct bm_xfer_ctx *c)
 {
 	struct p_compressed_bm *p = (void*)h;
 	unsigned long num_words;
@@ -1968,12 +2091,12 @@
 		if (len)
 			drbd_bm_get_lel(mdev, c->word_offset, num_words, (unsigned long*)h->payload);
 		ok = _drbd_send_cmd(mdev, mdev->data.socket, P_BITMAP,
-				   h, sizeof(struct p_header) + len, 0);
+				   h, sizeof(struct p_header80) + len, 0);
 		c->word_offset += num_words;
 		c->bit_offset = c->word_offset * BITS_PER_LONG;
 
 		c->packets[1]++;
-		c->bytes[1] += sizeof(struct p_header) + len;
+		c->bytes[1] += sizeof(struct p_header80) + len;
 
 		if (c->bit_offset > c->bm_bits)
 			c->bit_offset = c->bm_bits;
@@ -1989,14 +2112,14 @@
 int _drbd_send_bitmap(struct drbd_conf *mdev)
 {
 	struct bm_xfer_ctx c;
-	struct p_header *p;
+	struct p_header80 *p;
 	int ret;
 
 	ERR_IF(!mdev->bitmap) return FALSE;
 
 	/* maybe we should use some per thread scratch page,
 	 * and allocate that during initial device creation? */
-	p = (struct p_header *) __get_free_page(GFP_NOIO);
+	p = (struct p_header80 *) __get_free_page(GFP_NOIO);
 	if (!p) {
 		dev_err(DEV, "failed to allocate one page buffer in %s\n", __func__);
 		return FALSE;
@@ -2054,7 +2177,7 @@
 	if (mdev->state.conn < C_CONNECTED)
 		return FALSE;
 	ok = drbd_send_cmd(mdev, USE_META_SOCKET, P_BARRIER_ACK,
-			(struct p_header *)&p, sizeof(p));
+			(struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
@@ -2082,17 +2205,18 @@
 	if (!mdev->meta.socket || mdev->state.conn < C_CONNECTED)
 		return FALSE;
 	ok = drbd_send_cmd(mdev, USE_META_SOCKET, cmd,
-				(struct p_header *)&p, sizeof(p));
+				(struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
+/* dp->sector and dp->block_id already/still in network byte order,
+ * data_size is payload size according to dp->head,
+ * and may need to be corrected for digest size. */
 int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd,
-		     struct p_data *dp)
+		     struct p_data *dp, int data_size)
 {
-	const int header_size = sizeof(struct p_data)
-			      - sizeof(struct p_header);
-	int data_size  = ((struct p_header *)dp)->length - header_size;
-
+	data_size -= (mdev->agreed_pro_version >= 87 && mdev->integrity_r_tfm) ?
+		crypto_hash_digestsize(mdev->integrity_r_tfm) : 0;
 	return _drbd_send_ack(mdev, cmd, dp->sector, cpu_to_be32(data_size),
 			      dp->block_id);
 }
@@ -2140,7 +2264,7 @@
 	p.blksize  = cpu_to_be32(size);
 
 	ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, cmd,
-				(struct p_header *)&p, sizeof(p));
+				(struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
@@ -2158,7 +2282,7 @@
 
 	p.head.magic   = BE_DRBD_MAGIC;
 	p.head.command = cpu_to_be16(cmd);
-	p.head.length  = cpu_to_be16(sizeof(p) - sizeof(struct p_header) + digest_size);
+	p.head.length  = cpu_to_be16(sizeof(p) - sizeof(struct p_header80) + digest_size);
 
 	mutex_lock(&mdev->data.mutex);
 
@@ -2180,7 +2304,7 @@
 	p.blksize  = cpu_to_be32(size);
 
 	ok = drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OV_REQUEST,
-			   (struct p_header *)&p, sizeof(p));
+			   (struct p_header80 *)&p, sizeof(p));
 	return ok;
 }
 
@@ -2332,6 +2456,18 @@
 	return 1;
 }
 
+static u32 bio_flags_to_wire(struct drbd_conf *mdev, unsigned long bi_rw)
+{
+	if (mdev->agreed_pro_version >= 95)
+		return  (bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) |
+			(bi_rw & REQ_UNPLUG ? DP_UNPLUG : 0) |
+			(bi_rw & REQ_FUA ? DP_FUA : 0) |
+			(bi_rw & REQ_FLUSH ? DP_FLUSH : 0) |
+			(bi_rw & REQ_DISCARD ? DP_DISCARD : 0);
+	else
+		return bi_rw & (REQ_SYNC | REQ_UNPLUG) ? DP_RW_SYNC : 0;
+}
+
 /* Used to send write requests
  * R_PRIMARY -> Peer	(P_DATA)
  */
@@ -2349,30 +2485,25 @@
 	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ?
 		crypto_hash_digestsize(mdev->integrity_w_tfm) : 0;
 
-	p.head.magic   = BE_DRBD_MAGIC;
-	p.head.command = cpu_to_be16(P_DATA);
-	p.head.length  =
-		cpu_to_be16(sizeof(p) - sizeof(struct p_header) + dgs + req->size);
+	if (req->size <= DRBD_MAX_SIZE_H80_PACKET) {
+		p.head.h80.magic   = BE_DRBD_MAGIC;
+		p.head.h80.command = cpu_to_be16(P_DATA);
+		p.head.h80.length  =
+			cpu_to_be16(sizeof(p) - sizeof(union p_header) + dgs + req->size);
+	} else {
+		p.head.h95.magic   = BE_DRBD_MAGIC_BIG;
+		p.head.h95.command = cpu_to_be16(P_DATA);
+		p.head.h95.length  =
+			cpu_to_be32(sizeof(p) - sizeof(union p_header) + dgs + req->size);
+	}
 
 	p.sector   = cpu_to_be64(req->sector);
 	p.block_id = (unsigned long)req;
 	p.seq_num  = cpu_to_be32(req->seq_num =
 				 atomic_add_return(1, &mdev->packet_seq));
-	dp_flags = 0;
 
-	/* NOTE: no need to check if barriers supported here as we would
-	 *       not pass the test in make_request_common in that case
-	 */
-	if (req->master_bio->bi_rw & REQ_HARDBARRIER) {
-		dev_err(DEV, "ASSERT FAILED would have set DP_HARDBARRIER\n");
-		/* dp_flags |= DP_HARDBARRIER; */
-	}
-	if (req->master_bio->bi_rw & REQ_SYNC)
-		dp_flags |= DP_RW_SYNC;
-	/* for now handle SYNCIO and UNPLUG
-	 * as if they still were one and the same flag */
-	if (req->master_bio->bi_rw & REQ_UNPLUG)
-		dp_flags |= DP_RW_SYNC;
+	dp_flags = bio_flags_to_wire(mdev, req->master_bio->bi_rw);
+
 	if (mdev->state.conn >= C_SYNC_SOURCE &&
 	    mdev->state.conn <= C_PAUSED_SYNC_T)
 		dp_flags |= DP_MAY_SET_IN_SYNC;
@@ -2413,10 +2544,17 @@
 	dgs = (mdev->agreed_pro_version >= 87 && mdev->integrity_w_tfm) ?
 		crypto_hash_digestsize(mdev->integrity_w_tfm) : 0;
 
-	p.head.magic   = BE_DRBD_MAGIC;
-	p.head.command = cpu_to_be16(cmd);
-	p.head.length  =
-		cpu_to_be16(sizeof(p) - sizeof(struct p_header) + dgs + e->size);
+	if (e->size <= DRBD_MAX_SIZE_H80_PACKET) {
+		p.head.h80.magic   = BE_DRBD_MAGIC;
+		p.head.h80.command = cpu_to_be16(cmd);
+		p.head.h80.length  =
+			cpu_to_be16(sizeof(p) - sizeof(struct p_header80) + dgs + e->size);
+	} else {
+		p.head.h95.magic   = BE_DRBD_MAGIC_BIG;
+		p.head.h95.command = cpu_to_be16(cmd);
+		p.head.h95.length  =
+			cpu_to_be32(sizeof(p) - sizeof(struct p_header80) + dgs + e->size);
+	}
 
 	p.sector   = cpu_to_be64(e->sector);
 	p.block_id = e->block_id;
@@ -2429,8 +2567,7 @@
 	if (!drbd_get_data_sock(mdev))
 		return 0;
 
-	ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p,
-					sizeof(p), dgs ? MSG_MORE : 0);
+	ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p, sizeof(p), dgs ? MSG_MORE : 0);
 	if (ok && dgs) {
 		dgb = mdev->int_dig_out;
 		drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb);
@@ -2536,7 +2673,7 @@
 	unsigned long flags;
 	int rv = 0;
 
-	lock_kernel();
+	mutex_lock(&drbd_main_mutex);
 	spin_lock_irqsave(&mdev->req_lock, flags);
 	/* to have a stable mdev->state.role
 	 * and no race with updating open_cnt */
@@ -2551,7 +2688,7 @@
 	if (!rv)
 		mdev->open_cnt++;
 	spin_unlock_irqrestore(&mdev->req_lock, flags);
-	unlock_kernel();
+	mutex_unlock(&drbd_main_mutex);
 
 	return rv;
 }
@@ -2559,9 +2696,9 @@
 static int drbd_release(struct gendisk *gd, fmode_t mode)
 {
 	struct drbd_conf *mdev = gd->private_data;
-	lock_kernel();
+	mutex_lock(&drbd_main_mutex);
 	mdev->open_cnt--;
-	unlock_kernel();
+	mutex_unlock(&drbd_main_mutex);
 	return 0;
 }
 
@@ -2605,7 +2742,13 @@
 		/* .verify_alg = */	{}, 0,
 		/* .cpu_mask = */	{}, 0,
 		/* .csums_alg = */	{}, 0,
-		/* .use_rle = */	0
+		/* .use_rle = */	0,
+		/* .on_no_data = */	DRBD_ON_NO_DATA_DEF,
+		/* .c_plan_ahead = */	DRBD_C_PLAN_AHEAD_DEF,
+		/* .c_delay_target = */	DRBD_C_DELAY_TARGET_DEF,
+		/* .c_fill_target = */	DRBD_C_FILL_TARGET_DEF,
+		/* .c_max_rate = */	DRBD_C_MAX_RATE_DEF,
+		/* .c_min_rate = */	DRBD_C_MIN_RATE_DEF
 	};
 
 	/* Have to use that way, because the layout differs between
@@ -2616,7 +2759,9 @@
 		  .conn = C_STANDALONE,
 		  .disk = D_DISKLESS,
 		  .pdsk = D_UNKNOWN,
-		  .susp = 0
+		  .susp = 0,
+		  .susp_nod = 0,
+		  .susp_fen = 0
 		} };
 }
 
@@ -2640,6 +2785,9 @@
 	atomic_set(&mdev->net_cnt, 0);
 	atomic_set(&mdev->packet_seq, 0);
 	atomic_set(&mdev->pp_in_use, 0);
+	atomic_set(&mdev->pp_in_use_by_net, 0);
+	atomic_set(&mdev->rs_sect_in, 0);
+	atomic_set(&mdev->rs_sect_ev, 0);
 
 	mutex_init(&mdev->md_io_mutex);
 	mutex_init(&mdev->data.mutex);
@@ -2666,11 +2814,13 @@
 	INIT_LIST_HEAD(&mdev->meta.work.q);
 	INIT_LIST_HEAD(&mdev->resync_work.list);
 	INIT_LIST_HEAD(&mdev->unplug_work.list);
+	INIT_LIST_HEAD(&mdev->go_diskless.list);
 	INIT_LIST_HEAD(&mdev->md_sync_work.list);
 	INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
 
 	mdev->resync_work.cb  = w_resync_inactive;
 	mdev->unplug_work.cb  = w_send_write_hint;
+	mdev->go_diskless.cb  = w_go_diskless;
 	mdev->md_sync_work.cb = w_md_sync;
 	mdev->bm_io_work.w.cb = w_bitmap_io;
 	init_timer(&mdev->resync_timer);
@@ -2682,6 +2832,7 @@
 
 	init_waitqueue_head(&mdev->misc_wait);
 	init_waitqueue_head(&mdev->state_wait);
+	init_waitqueue_head(&mdev->net_cnt_wait);
 	init_waitqueue_head(&mdev->ee_wait);
 	init_waitqueue_head(&mdev->al_wait);
 	init_waitqueue_head(&mdev->seq_wait);
@@ -2697,6 +2848,7 @@
 
 void drbd_mdev_cleanup(struct drbd_conf *mdev)
 {
+	int i;
 	if (mdev->receiver.t_state != None)
 		dev_err(DEV, "ASSERT FAILED: receiver t_state == %d expected 0.\n",
 				mdev->receiver.t_state);
@@ -2713,9 +2865,13 @@
 	mdev->p_size       =
 	mdev->rs_start     =
 	mdev->rs_total     =
-	mdev->rs_failed    =
-	mdev->rs_mark_left =
-	mdev->rs_mark_time = 0;
+	mdev->rs_failed    = 0;
+	mdev->rs_last_events = 0;
+	mdev->rs_last_sect_ev = 0;
+	for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+		mdev->rs_mark_left[i] = 0;
+		mdev->rs_mark_time[i] = 0;
+	}
 	D_ASSERT(mdev->net_conf == NULL);
 
 	drbd_set_my_capacity(mdev, 0);
@@ -2726,6 +2882,7 @@
 	}
 
 	drbd_free_resources(mdev);
+	clear_bit(AL_SUSPENDED, &mdev->flags);
 
 	/*
 	 * currently we drbd_init_ee only on module load, so
@@ -2741,6 +2898,7 @@
 	D_ASSERT(list_empty(&mdev->meta.work.q));
 	D_ASSERT(list_empty(&mdev->resync_work.list));
 	D_ASSERT(list_empty(&mdev->unplug_work.list));
+	D_ASSERT(list_empty(&mdev->go_diskless.list));
 
 }
 
@@ -3280,9 +3438,10 @@
 	sector_t sector;
 	int i;
 
+	del_timer(&mdev->md_sync_timer);
+	/* timer may be rearmed by drbd_md_mark_dirty() now. */
 	if (!test_and_clear_bit(MD_DIRTY, &mdev->flags))
 		return;
-	del_timer(&mdev->md_sync_timer);
 
 	/* We use here D_FAILED and not D_ATTACHING because we try to write
 	 * metadata even if we detach due to a disk failure! */
@@ -3310,12 +3469,9 @@
 	D_ASSERT(drbd_md_ss__(mdev, mdev->ldev) == mdev->ldev->md.md_offset);
 	sector = mdev->ldev->md.md_offset;
 
-	if (drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
-		clear_bit(MD_DIRTY, &mdev->flags);
-	} else {
+	if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
 		/* this was a try anyways ... */
 		dev_err(DEV, "meta data update failed!\n");
-
 		drbd_chk_io_error(mdev, 1, TRUE);
 	}
 
@@ -3402,6 +3558,28 @@
 	return rv;
 }
 
+static void debug_drbd_uuid(struct drbd_conf *mdev, enum drbd_uuid_index index)
+{
+	static char *uuid_str[UI_EXTENDED_SIZE] = {
+		[UI_CURRENT] = "CURRENT",
+		[UI_BITMAP] = "BITMAP",
+		[UI_HISTORY_START] = "HISTORY_START",
+		[UI_HISTORY_END] = "HISTORY_END",
+		[UI_SIZE] = "SIZE",
+		[UI_FLAGS] = "FLAGS",
+	};
+
+	if (index >= UI_EXTENDED_SIZE) {
+		dev_warn(DEV, " uuid_index >= EXTENDED_SIZE\n");
+		return;
+	}
+
+	dynamic_dev_dbg(DEV, " uuid[%s] now %016llX\n",
+		 uuid_str[index],
+		 (unsigned long long)mdev->ldev->md.uuid[index]);
+}
+
+
 /**
  * drbd_md_mark_dirty() - Mark meta data super block as dirty
  * @mdev:	DRBD device.
@@ -3410,19 +3588,31 @@
  * the meta-data super block. This function sets MD_DIRTY, and starts a
  * timer that ensures that within five seconds you have to call drbd_md_sync().
  */
+#ifdef DEBUG
+void drbd_md_mark_dirty_(struct drbd_conf *mdev, unsigned int line, const char *func)
+{
+	if (!test_and_set_bit(MD_DIRTY, &mdev->flags)) {
+		mod_timer(&mdev->md_sync_timer, jiffies + HZ);
+		mdev->last_md_mark_dirty.line = line;
+		mdev->last_md_mark_dirty.func = func;
+	}
+}
+#else
 void drbd_md_mark_dirty(struct drbd_conf *mdev)
 {
-	set_bit(MD_DIRTY, &mdev->flags);
-	mod_timer(&mdev->md_sync_timer, jiffies + 5*HZ);
+	if (!test_and_set_bit(MD_DIRTY, &mdev->flags))
+		mod_timer(&mdev->md_sync_timer, jiffies + 5*HZ);
 }
-
+#endif
 
 static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
 {
 	int i;
 
-	for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++)
+	for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++) {
 		mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i];
+		debug_drbd_uuid(mdev, i+1);
+	}
 }
 
 void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
@@ -3437,6 +3627,7 @@
 	}
 
 	mdev->ldev->md.uuid[idx] = val;
+	debug_drbd_uuid(mdev, idx);
 	drbd_md_mark_dirty(mdev);
 }
 
@@ -3446,6 +3637,7 @@
 	if (mdev->ldev->md.uuid[idx]) {
 		drbd_uuid_move_history(mdev);
 		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx];
+		debug_drbd_uuid(mdev, UI_HISTORY_START);
 	}
 	_drbd_uuid_set(mdev, idx, val);
 }
@@ -3464,6 +3656,7 @@
 	dev_info(DEV, "Creating new current UUID\n");
 	D_ASSERT(mdev->ldev->md.uuid[UI_BITMAP] == 0);
 	mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT];
+	debug_drbd_uuid(mdev, UI_BITMAP);
 
 	get_random_bytes(&val, sizeof(u64));
 	_drbd_uuid_set(mdev, UI_CURRENT, val);
@@ -3478,6 +3671,8 @@
 		drbd_uuid_move_history(mdev);
 		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
 		mdev->ldev->md.uuid[UI_BITMAP] = 0;
+		debug_drbd_uuid(mdev, UI_HISTORY_START);
+		debug_drbd_uuid(mdev, UI_BITMAP);
 	} else {
 		if (mdev->ldev->md.uuid[UI_BITMAP])
 			dev_warn(DEV, "bm UUID already set");
@@ -3485,6 +3680,7 @@
 		mdev->ldev->md.uuid[UI_BITMAP] = val;
 		mdev->ldev->md.uuid[UI_BITMAP] &= ~((u64)1);
 
+		debug_drbd_uuid(mdev, UI_BITMAP);
 	}
 	drbd_md_mark_dirty(mdev);
 }
@@ -3527,6 +3723,7 @@
 {
 	int rv = -EIO;
 
+	drbd_resume_al(mdev);
 	if (get_ldev_if_state(mdev, D_ATTACHING)) {
 		drbd_bm_clear_all(mdev);
 		rv = drbd_bm_write(mdev);
@@ -3559,6 +3756,32 @@
 	return 1;
 }
 
+static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused)
+{
+	D_ASSERT(mdev->state.disk == D_FAILED);
+	/* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
+	 * inc/dec it frequently. Once we are D_DISKLESS, no one will touch
+	 * the protected members anymore, though, so in the after_state_ch work
+	 * it will be safe to free them. */
+	drbd_force_state(mdev, NS(disk, D_DISKLESS));
+	/* We need to wait for return of references checked out while we still
+	 * have been D_FAILED, though (drbd_md_sync, bitmap io). */
+	wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt));
+
+	clear_bit(GO_DISKLESS, &mdev->flags);
+	return 1;
+}
+
+void drbd_go_diskless(struct drbd_conf *mdev)
+{
+	D_ASSERT(mdev->state.disk == D_FAILED);
+	if (!test_and_set_bit(GO_DISKLESS, &mdev->flags))
+		drbd_queue_work(&mdev->data.work, &mdev->go_diskless);
+		/* don't drbd_queue_work_front,
+		 * we need to serialize with the after_state_ch work
+		 * of the -> D_FAILED transition. */
+}
+
 /**
  * drbd_queue_bitmap_io() - Queues an IO operation on the whole bitmap
  * @mdev:	DRBD device.
@@ -3655,8 +3878,11 @@
 static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused)
 {
 	dev_warn(DEV, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
+#ifdef DEBUG
+	dev_warn(DEV, "last md_mark_dirty: %s:%u\n",
+		mdev->last_md_mark_dirty.func, mdev->last_md_mark_dirty.line);
+#endif
 	drbd_md_sync(mdev);
-
 	return 1;
 }
 
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 73131c5..87925e9 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -33,10 +33,13 @@
 #include <linux/blkpg.h>
 #include <linux/cpumask.h>
 #include "drbd_int.h"
+#include "drbd_req.h"
 #include "drbd_wrappers.h"
 #include <asm/unaligned.h>
 #include <linux/drbd_tag_magic.h>
 #include <linux/drbd_limits.h>
+#include <linux/compiler.h>
+#include <linux/kthread.h>
 
 static unsigned short *tl_add_blob(unsigned short *, enum drbd_tags, const void *, int);
 static unsigned short *tl_add_str(unsigned short *, enum drbd_tags, const char *);
@@ -169,6 +172,10 @@
 		put_net_conf(mdev);
 	}
 
+	/* The helper may take some time.
+	 * write out any unsynced meta data changes now */
+	drbd_md_sync(mdev);
+
 	dev_info(DEV, "helper command: %s %s %s\n", usermode_helper, cmd, mb);
 
 	drbd_bcast_ev_helper(mdev, cmd);
@@ -202,12 +209,10 @@
 		put_ldev(mdev);
 	} else {
 		dev_warn(DEV, "Not fencing peer, I'm not even Consistent myself.\n");
-		return mdev->state.pdsk;
+		nps = mdev->state.pdsk;
+		goto out;
 	}
 
-	if (fp == FP_STONITH)
-		_drbd_request_state(mdev, NS(susp, 1), CS_WAIT_COMPLETE);
-
 	r = drbd_khelper(mdev, "fence-peer");
 
 	switch ((r>>8) & 0xff) {
@@ -252,9 +257,36 @@
 
 	dev_info(DEV, "fence-peer helper returned %d (%s)\n",
 			(r>>8) & 0xff, ex_to_string);
+
+out:
+	if (mdev->state.susp_fen && nps >= D_UNKNOWN) {
+		/* The handler was not successful... unfreeze here, the
+		   state engine can not unfreeze... */
+		_drbd_request_state(mdev, NS(susp_fen, 0), CS_VERBOSE);
+	}
+
 	return nps;
 }
 
+static int _try_outdate_peer_async(void *data)
+{
+	struct drbd_conf *mdev = (struct drbd_conf *)data;
+	enum drbd_disk_state nps;
+
+	nps = drbd_try_outdate_peer(mdev);
+	drbd_request_state(mdev, NS(pdsk, nps));
+
+	return 0;
+}
+
+void drbd_try_outdate_peer_async(struct drbd_conf *mdev)
+{
+	struct task_struct *opa;
+
+	opa = kthread_run(_try_outdate_peer_async, mdev, "drbd%d_a_helper", mdev_to_minor(mdev));
+	if (IS_ERR(opa))
+		dev_err(DEV, "out of mem, failed to invoke fence-peer helper\n");
+}
 
 int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 {
@@ -394,6 +426,39 @@
 	return r;
 }
 
+static struct drbd_conf *ensure_mdev(int minor, int create)
+{
+	struct drbd_conf *mdev;
+
+	if (minor >= minor_count)
+		return NULL;
+
+	mdev = minor_to_mdev(minor);
+
+	if (!mdev && create) {
+		struct gendisk *disk = NULL;
+		mdev = drbd_new_device(minor);
+
+		spin_lock_irq(&drbd_pp_lock);
+		if (minor_table[minor] == NULL) {
+			minor_table[minor] = mdev;
+			disk = mdev->vdisk;
+			mdev = NULL;
+		} /* else: we lost the race */
+		spin_unlock_irq(&drbd_pp_lock);
+
+		if (disk) /* we won the race above */
+			/* in case we ever add a drbd_delete_device(),
+			 * don't forget the del_gendisk! */
+			add_disk(disk);
+		else /* we lost the race above */
+			drbd_free_mdev(mdev);
+
+		mdev = minor_to_mdev(minor);
+	}
+
+	return mdev;
+}
 
 static int drbd_nl_primary(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
 			   struct drbd_nl_cfg_reply *reply)
@@ -494,6 +559,8 @@
 void drbd_suspend_io(struct drbd_conf *mdev)
 {
 	set_bit(SUSPEND_IO, &mdev->flags);
+	if (is_susp(mdev->state))
+		return;
 	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
 }
 
@@ -713,9 +780,6 @@
 	blk_queue_segment_boundary(q, PAGE_SIZE-1);
 	blk_stack_limits(&q->limits, &b->limits, 0);
 
-	if (b->merge_bvec_fn)
-		dev_warn(DEV, "Backing device's merge_bvec_fn() = %p\n",
-		     b->merge_bvec_fn);
 	dev_info(DEV, "max_segment_size ( = BIO size ) = %u\n", queue_max_segment_size(q));
 
 	if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
@@ -729,14 +793,16 @@
 /* serialize deconfig (worker exiting, doing cleanup)
  * and reconfig (drbdsetup disk, drbdsetup net)
  *
- * wait for a potentially exiting worker, then restart it,
- * or start a new one.
+ * Wait for a potentially exiting worker, then restart it,
+ * or start a new one.  Flush any pending work, there may still be an
+ * after_state_change queued.
  */
 static void drbd_reconfig_start(struct drbd_conf *mdev)
 {
 	wait_event(mdev->state_wait, !test_and_set_bit(CONFIG_PENDING, &mdev->flags));
 	wait_event(mdev->state_wait, !test_bit(DEVICE_DYING, &mdev->flags));
 	drbd_thread_start(&mdev->worker);
+	drbd_flush_workqueue(mdev);
 }
 
 /* if still unconfigured, stops worker again.
@@ -756,6 +822,29 @@
 	wake_up(&mdev->state_wait);
 }
 
+/* Make sure IO is suspended before calling this function(). */
+static void drbd_suspend_al(struct drbd_conf *mdev)
+{
+	int s = 0;
+
+	if (lc_try_lock(mdev->act_log)) {
+		drbd_al_shrink(mdev);
+		lc_unlock(mdev->act_log);
+	} else {
+		dev_warn(DEV, "Failed to lock al in drbd_suspend_al()\n");
+		return;
+	}
+
+	spin_lock_irq(&mdev->req_lock);
+	if (mdev->state.conn < C_CONNECTED)
+		s = !test_and_set_bit(AL_SUSPENDED, &mdev->flags);
+
+	spin_unlock_irq(&mdev->req_lock);
+
+	if (s)
+		dev_info(DEV, "Suspended AL updates\n");
+}
+
 /* does always return 0;
  * interesting return code is in reply->ret_code */
 static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
@@ -769,6 +858,7 @@
 	struct inode *inode, *inode2;
 	struct lru_cache *resync_lru = NULL;
 	union drbd_state ns, os;
+	unsigned int max_seg_s;
 	int rv;
 	int cp_discovered = 0;
 	int logical_block_size;
@@ -803,6 +893,15 @@
 		goto fail;
 	}
 
+	if (get_net_conf(mdev)) {
+		int prot = mdev->net_conf->wire_protocol;
+		put_net_conf(mdev);
+		if (nbc->dc.fencing == FP_STONITH && prot == DRBD_PROT_A) {
+			retcode = ERR_STONITH_AND_PROT_A;
+			goto fail;
+		}
+	}
+
 	nbc->lo_file = filp_open(nbc->dc.backing_dev, O_RDWR, 0);
 	if (IS_ERR(nbc->lo_file)) {
 		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev,
@@ -924,7 +1023,7 @@
 
 	drbd_suspend_io(mdev);
 	/* also wait for the last barrier ack. */
-	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt));
+	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_pending_cnt) || is_susp(mdev->state));
 	/* and for any other previously queued work */
 	drbd_flush_workqueue(mdev);
 
@@ -1021,7 +1120,8 @@
 	else
 		clear_bit(CRASHED_PRIMARY, &mdev->flags);
 
-	if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND)) {
+	if (drbd_md_test_flag(mdev->ldev, MDF_PRIMARY_IND) &&
+	    !(mdev->state.role == R_PRIMARY && mdev->state.susp_nod)) {
 		set_bit(CRASHED_PRIMARY, &mdev->flags);
 		cp_discovered = 1;
 	}
@@ -1031,7 +1131,20 @@
 	mdev->read_cnt = 0;
 	mdev->writ_cnt = 0;
 
-	drbd_setup_queue_param(mdev, DRBD_MAX_SEGMENT_SIZE);
+	max_seg_s = DRBD_MAX_SEGMENT_SIZE;
+	if (mdev->state.conn == C_CONNECTED) {
+		/* We are Primary, Connected, and now attach a new local
+		 * backing store. We must not increase the user visible maximum
+		 * bio size on this device to something the peer may not be
+		 * able to handle. */
+		if (mdev->agreed_pro_version < 94)
+			max_seg_s = queue_max_segment_size(mdev->rq_queue);
+		else if (mdev->agreed_pro_version == 94)
+			max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
+		/* else: drbd 8.3.9 and later, stay with default */
+	}
+
+	drbd_setup_queue_param(mdev, max_seg_s);
 
 	/* If I am currently not R_PRIMARY,
 	 * but meta data primary indicator is set,
@@ -1079,6 +1192,9 @@
 		drbd_al_to_on_disk_bm(mdev);
 	}
 
+	if (_drbd_bm_total_weight(mdev) == drbd_bm_bits(mdev))
+		drbd_suspend_al(mdev); /* IO is still suspended here... */
+
 	spin_lock_irq(&mdev->req_lock);
 	os = mdev->state;
 	ns.i = os.i;
@@ -1235,7 +1351,16 @@
 	    && (new_conf->wire_protocol != DRBD_PROT_C)) {
 		retcode = ERR_NOT_PROTO_C;
 		goto fail;
-	};
+	}
+
+	if (get_ldev(mdev)) {
+		enum drbd_fencing_p fp = mdev->ldev->dc.fencing;
+		put_ldev(mdev);
+		if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH) {
+			retcode = ERR_STONITH_AND_PROT_A;
+			goto fail;
+		}
+	}
 
 	if (mdev->state.role == R_PRIMARY && new_conf->want_lose) {
 		retcode = ERR_DISCARD;
@@ -1350,6 +1475,7 @@
 		}
 	}
 
+	drbd_flush_workqueue(mdev);
 	spin_lock_irq(&mdev->req_lock);
 	if (mdev->net_conf != NULL) {
 		retcode = ERR_NET_CONFIGURED;
@@ -1388,10 +1514,9 @@
 	mdev->int_dig_out=int_dig_out;
 	mdev->int_dig_in=int_dig_in;
 	mdev->int_dig_vv=int_dig_vv;
+	retcode = _drbd_set_state(_NS(mdev, conn, C_UNCONNECTED), CS_VERBOSE, NULL);
 	spin_unlock_irq(&mdev->req_lock);
 
-	retcode = _drbd_request_state(mdev, NS(conn, C_UNCONNECTED), CS_VERBOSE);
-
 	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
 	reply->ret_code = retcode;
 	drbd_reconfig_done(mdev);
@@ -1546,6 +1671,8 @@
 	struct crypto_hash *csums_tfm = NULL;
 	struct syncer_conf sc;
 	cpumask_var_t new_cpu_mask;
+	int *rs_plan_s = NULL;
+	int fifo_size;
 
 	if (!zalloc_cpumask_var(&new_cpu_mask, GFP_KERNEL)) {
 		retcode = ERR_NOMEM;
@@ -1557,6 +1684,12 @@
 		sc.rate       = DRBD_RATE_DEF;
 		sc.after      = DRBD_AFTER_DEF;
 		sc.al_extents = DRBD_AL_EXTENTS_DEF;
+		sc.on_no_data  = DRBD_ON_NO_DATA_DEF;
+		sc.c_plan_ahead = DRBD_C_PLAN_AHEAD_DEF;
+		sc.c_delay_target = DRBD_C_DELAY_TARGET_DEF;
+		sc.c_fill_target = DRBD_C_FILL_TARGET_DEF;
+		sc.c_max_rate = DRBD_C_MAX_RATE_DEF;
+		sc.c_min_rate = DRBD_C_MIN_RATE_DEF;
 	} else
 		memcpy(&sc, &mdev->sync_conf, sizeof(struct syncer_conf));
 
@@ -1634,6 +1767,12 @@
 	}
 #undef AL_MAX
 
+	/* to avoid spurious errors when configuring minors before configuring
+	 * the minors they depend on: if necessary, first create the minor we
+	 * depend on */
+	if (sc.after >= 0)
+		ensure_mdev(sc.after, 1);
+
 	/* most sanity checks done, try to assign the new sync-after
 	 * dependency.  need to hold the global lock in there,
 	 * to avoid a race in the dependency loop check. */
@@ -1641,6 +1780,16 @@
 	if (retcode != NO_ERROR)
 		goto fail;
 
+	fifo_size = (sc.c_plan_ahead * 10 * SLEEP_TIME) / HZ;
+	if (fifo_size != mdev->rs_plan_s.size && fifo_size > 0) {
+		rs_plan_s   = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL);
+		if (!rs_plan_s) {
+			dev_err(DEV, "kmalloc of fifo_buffer failed");
+			retcode = ERR_NOMEM;
+			goto fail;
+		}
+	}
+
 	/* ok, assign the rest of it as well.
 	 * lock against receive_SyncParam() */
 	spin_lock(&mdev->peer_seq_lock);
@@ -1657,6 +1806,15 @@
 		mdev->verify_tfm = verify_tfm;
 		verify_tfm = NULL;
 	}
+
+	if (fifo_size != mdev->rs_plan_s.size) {
+		kfree(mdev->rs_plan_s.values);
+		mdev->rs_plan_s.values = rs_plan_s;
+		mdev->rs_plan_s.size   = fifo_size;
+		mdev->rs_planed = 0;
+		rs_plan_s = NULL;
+	}
+
 	spin_unlock(&mdev->peer_seq_lock);
 
 	if (get_ldev(mdev)) {
@@ -1688,6 +1846,7 @@
 
 	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
 fail:
+	kfree(rs_plan_s);
 	free_cpumask_var(new_cpu_mask);
 	crypto_free_hash(csums_tfm);
 	crypto_free_hash(verify_tfm);
@@ -1721,12 +1880,38 @@
 	return 0;
 }
 
+static int drbd_bmio_set_susp_al(struct drbd_conf *mdev)
+{
+	int rv;
+
+	rv = drbd_bmio_set_n_write(mdev);
+	drbd_suspend_al(mdev);
+	return rv;
+}
+
 static int drbd_nl_invalidate_peer(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
 				   struct drbd_nl_cfg_reply *reply)
 {
+	int retcode;
 
-	reply->ret_code = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S));
+	retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED);
 
+	if (retcode < SS_SUCCESS) {
+		if (retcode == SS_NEED_CONNECTION && mdev->state.role == R_PRIMARY) {
+			/* The peer will get a resync upon connect anyways. Just make that
+			   into a full resync. */
+			retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT));
+			if (retcode >= SS_SUCCESS) {
+				/* open coded drbd_bitmap_io() */
+				if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al,
+						   "set_n_write from invalidate_peer"))
+					retcode = ERR_IO_MD_DISK;
+			}
+		} else
+			retcode = drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S));
+	}
+
+	reply->ret_code = retcode;
 	return 0;
 }
 
@@ -1765,7 +1950,21 @@
 static int drbd_nl_resume_io(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
 			     struct drbd_nl_cfg_reply *reply)
 {
-	reply->ret_code = drbd_request_state(mdev, NS(susp, 0));
+	if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
+		drbd_uuid_new_current(mdev);
+		clear_bit(NEW_CUR_UUID, &mdev->flags);
+		drbd_md_sync(mdev);
+	}
+	drbd_suspend_io(mdev);
+	reply->ret_code = drbd_request_state(mdev, NS3(susp, 0, susp_nod, 0, susp_fen, 0));
+	if (reply->ret_code == SS_SUCCESS) {
+		if (mdev->state.conn < C_CONNECTED)
+			tl_clear(mdev);
+		if (mdev->state.disk == D_DISKLESS || mdev->state.disk == D_FAILED)
+			tl_restart(mdev, fail_frozen_disk_io);
+	}
+	drbd_resume_io(mdev);
+
 	return 0;
 }
 
@@ -1941,40 +2140,6 @@
 	return 0;
 }
 
-static struct drbd_conf *ensure_mdev(struct drbd_nl_cfg_req *nlp)
-{
-	struct drbd_conf *mdev;
-
-	if (nlp->drbd_minor >= minor_count)
-		return NULL;
-
-	mdev = minor_to_mdev(nlp->drbd_minor);
-
-	if (!mdev && (nlp->flags & DRBD_NL_CREATE_DEVICE)) {
-		struct gendisk *disk = NULL;
-		mdev = drbd_new_device(nlp->drbd_minor);
-
-		spin_lock_irq(&drbd_pp_lock);
-		if (minor_table[nlp->drbd_minor] == NULL) {
-			minor_table[nlp->drbd_minor] = mdev;
-			disk = mdev->vdisk;
-			mdev = NULL;
-		} /* else: we lost the race */
-		spin_unlock_irq(&drbd_pp_lock);
-
-		if (disk) /* we won the race above */
-			/* in case we ever add a drbd_delete_device(),
-			 * don't forget the del_gendisk! */
-			add_disk(disk);
-		else /* we lost the race above */
-			drbd_free_mdev(mdev);
-
-		mdev = minor_to_mdev(nlp->drbd_minor);
-	}
-
-	return mdev;
-}
-
 struct cn_handler_struct {
 	int (*function)(struct drbd_conf *,
 			 struct drbd_nl_cfg_req *,
@@ -2035,7 +2200,8 @@
 		goto fail;
 	}
 
-	mdev = ensure_mdev(nlp);
+	mdev = ensure_mdev(nlp->drbd_minor,
+			(nlp->flags & DRBD_NL_CREATE_DEVICE));
 	if (!mdev) {
 		retcode = ERR_MINOR_INVALID;
 		goto fail;
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index be3374b..ad325c5 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -57,6 +57,7 @@
 	unsigned long db, dt, dbdt, rt, rs_left;
 	unsigned int res;
 	int i, x, y;
+	int stalled = 0;
 
 	drbd_get_syncer_progress(mdev, &rs_left, &res);
 
@@ -90,18 +91,17 @@
 	 * db: blocks written from mark until now
 	 * rt: remaining time
 	 */
-	dt = (jiffies - mdev->rs_mark_time) / HZ;
-
-	if (dt > 20) {
-		/* if we made no update to rs_mark_time for too long,
-		 * we are stalled. show that. */
-		seq_printf(seq, "stalled\n");
-		return;
-	}
+	/* Rolling marks. last_mark+1 may just now be modified.  last_mark+2 is
+	 * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
+	 * least DRBD_SYNC_MARK_STEP time before it will be modified. */
+	i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS;
+	dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
+	if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS))
+		stalled = 1;
 
 	if (!dt)
 		dt++;
-	db = mdev->rs_mark_left - rs_left;
+	db = mdev->rs_mark_left[i] - rs_left;
 	rt = (dt * (rs_left / (db/100+1)))/100; /* seconds */
 
 	seq_printf(seq, "finish: %lu:%02lu:%02lu",
@@ -118,7 +118,7 @@
 	/* mean speed since syncer started
 	 * we do account for PausedSync periods */
 	dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
-	if (dt <= 0)
+	if (dt == 0)
 		dt = 1;
 	db = mdev->rs_total - rs_left;
 	dbdt = Bit2KB(db/dt);
@@ -128,7 +128,14 @@
 	else
 		seq_printf(seq, " (%ld)", dbdt);
 
-	seq_printf(seq, " K/sec\n");
+	if (mdev->state.conn == C_SYNC_TARGET) {
+		if (mdev->c_sync_rate > 1000)
+			seq_printf(seq, " want: %d,%03d",
+				   mdev->c_sync_rate / 1000, mdev->c_sync_rate % 1000);
+		else
+			seq_printf(seq, " want: %d", mdev->c_sync_rate);
+	}
+	seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
 }
 
 static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
@@ -196,7 +203,7 @@
 			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
 		} else {
 			seq_printf(seq,
-			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c\n"
+			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
 			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
 			   "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
 			   i, sn,
@@ -206,11 +213,12 @@
 			   drbd_disk_str(mdev->state.pdsk),
 			   (mdev->net_conf == NULL ? ' ' :
 			    (mdev->net_conf->wire_protocol - DRBD_PROT_A+'A')),
-			   mdev->state.susp ? 's' : 'r',
+			   is_susp(mdev->state) ? 's' : 'r',
 			   mdev->state.aftr_isp ? 'a' : '-',
 			   mdev->state.peer_isp ? 'p' : '-',
 			   mdev->state.user_isp ? 'u' : '-',
 			   mdev->congestion_reason ?: '-',
+			   test_bit(AL_SUSPENDED, &mdev->flags) ? 's' : '-',
 			   mdev->send_cnt/2,
 			   mdev->recv_cnt/2,
 			   mdev->writ_cnt/2,
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 081522d..efd6169 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -241,7 +241,7 @@
 	spin_unlock_irq(&mdev->req_lock);
 
 	list_for_each_entry_safe(e, t, &reclaimed, w.list)
-		drbd_free_ee(mdev, e);
+		drbd_free_net_ee(mdev, e);
 }
 
 /**
@@ -298,9 +298,11 @@
  * Is also used from inside an other spin_lock_irq(&mdev->req_lock);
  * Either links the page chain back to the global pool,
  * or returns all pages to the system. */
-static void drbd_pp_free(struct drbd_conf *mdev, struct page *page)
+static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net)
 {
+	atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
 	int i;
+
 	if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count)
 		i = page_chain_free(page);
 	else {
@@ -311,10 +313,10 @@
 		drbd_pp_vacant += i;
 		spin_unlock(&drbd_pp_lock);
 	}
-	atomic_sub(i, &mdev->pp_in_use);
-	i = atomic_read(&mdev->pp_in_use);
+	i = atomic_sub_return(i, a);
 	if (i < 0)
-		dev_warn(DEV, "ASSERTION FAILED: pp_in_use: %d < 0\n", i);
+		dev_warn(DEV, "ASSERTION FAILED: %s: %d < 0\n",
+			is_net ? "pp_in_use_by_net" : "pp_in_use", i);
 	wake_up(&drbd_pp_wait);
 }
 
@@ -365,7 +367,6 @@
 	e->size = data_size;
 	e->flags = 0;
 	e->sector = sector;
-	e->sector = sector;
 	e->block_id = id;
 
 	return e;
@@ -375,9 +376,11 @@
 	return NULL;
 }
 
-void drbd_free_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e)
+void drbd_free_some_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, int is_net)
 {
-	drbd_pp_free(mdev, e->pages);
+	if (e->flags & EE_HAS_DIGEST)
+		kfree(e->digest);
+	drbd_pp_free(mdev, e->pages, is_net);
 	D_ASSERT(atomic_read(&e->pending_bios) == 0);
 	D_ASSERT(hlist_unhashed(&e->colision));
 	mempool_free(e, drbd_ee_mempool);
@@ -388,13 +391,14 @@
 	LIST_HEAD(work_list);
 	struct drbd_epoch_entry *e, *t;
 	int count = 0;
+	int is_net = list == &mdev->net_ee;
 
 	spin_lock_irq(&mdev->req_lock);
 	list_splice_init(list, &work_list);
 	spin_unlock_irq(&mdev->req_lock);
 
 	list_for_each_entry_safe(e, t, &work_list, w.list) {
-		drbd_free_ee(mdev, e);
+		drbd_free_some_ee(mdev, e, is_net);
 		count++;
 	}
 	return count;
@@ -423,7 +427,7 @@
 	spin_unlock_irq(&mdev->req_lock);
 
 	list_for_each_entry_safe(e, t, &reclaimed, w.list)
-		drbd_free_ee(mdev, e);
+		drbd_free_net_ee(mdev, e);
 
 	/* possible callbacks here:
 	 * e_end_block, and e_end_resync_block, e_send_discard_ack.
@@ -719,14 +723,14 @@
 static int drbd_send_fp(struct drbd_conf *mdev,
 	struct socket *sock, enum drbd_packets cmd)
 {
-	struct p_header *h = (struct p_header *) &mdev->data.sbuf.header;
+	struct p_header80 *h = &mdev->data.sbuf.header.h80;
 
 	return _drbd_send_cmd(mdev, sock, cmd, h, sizeof(*h), 0);
 }
 
 static enum drbd_packets drbd_recv_fp(struct drbd_conf *mdev, struct socket *sock)
 {
-	struct p_header *h = (struct p_header *) &mdev->data.sbuf.header;
+	struct p_header80 *h = &mdev->data.rbuf.header.h80;
 	int rr;
 
 	rr = drbd_recv_short(mdev, sock, h, sizeof(*h), 0);
@@ -776,9 +780,6 @@
 
 	D_ASSERT(!mdev->data.socket);
 
-	if (test_and_clear_bit(CREATE_BARRIER, &mdev->flags))
-		dev_err(DEV, "CREATE_BARRIER flag was set in drbd_connect - now cleared!\n");
-
 	if (drbd_request_state(mdev, NS(conn, C_WF_CONNECTION)) < SS_SUCCESS)
 		return -2;
 
@@ -927,6 +928,11 @@
 
 	drbd_thread_start(&mdev->asender);
 
+	if (mdev->agreed_pro_version < 95 && get_ldev(mdev)) {
+		drbd_setup_queue_param(mdev, DRBD_MAX_SIZE_H80_PACKET);
+		put_ldev(mdev);
+	}
+
 	if (!drbd_send_protocol(mdev))
 		return -1;
 	drbd_send_sync_param(mdev, &mdev->sync_conf);
@@ -946,22 +952,28 @@
 	return -1;
 }
 
-static int drbd_recv_header(struct drbd_conf *mdev, struct p_header *h)
+static int drbd_recv_header(struct drbd_conf *mdev, enum drbd_packets *cmd, unsigned int *packet_size)
 {
+	union p_header *h = &mdev->data.rbuf.header;
 	int r;
 
 	r = drbd_recv(mdev, h, sizeof(*h));
-
 	if (unlikely(r != sizeof(*h))) {
 		dev_err(DEV, "short read expecting header on sock: r=%d\n", r);
 		return FALSE;
-	};
-	h->command = be16_to_cpu(h->command);
-	h->length  = be16_to_cpu(h->length);
-	if (unlikely(h->magic != BE_DRBD_MAGIC)) {
-		dev_err(DEV, "magic?? on data m: 0x%lx c: %d l: %d\n",
-		    (long)be32_to_cpu(h->magic),
-		    h->command, h->length);
+	}
+
+	if (likely(h->h80.magic == BE_DRBD_MAGIC)) {
+		*cmd = be16_to_cpu(h->h80.command);
+		*packet_size = be16_to_cpu(h->h80.length);
+	} else if (h->h95.magic == BE_DRBD_MAGIC_BIG) {
+		*cmd = be16_to_cpu(h->h95.command);
+		*packet_size = be32_to_cpu(h->h95.length);
+	} else {
+		dev_err(DEV, "magic?? on data m: 0x%08x c: %d l: %d\n",
+		    be32_to_cpu(h->h80.magic),
+		    be16_to_cpu(h->h80.command),
+		    be16_to_cpu(h->h80.length));
 		return FALSE;
 	}
 	mdev->last_received = jiffies;
@@ -975,7 +987,7 @@
 
 	if (mdev->write_ordering >= WO_bdev_flush && get_ldev(mdev)) {
 		rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL,
-					NULL, BLKDEV_IFL_WAIT);
+					NULL);
 		if (rv) {
 			dev_err(DEV, "local disk flush failed with status %d\n", rv);
 			/* would rather check on EOPNOTSUPP, but that is not reliable.
@@ -1268,17 +1280,12 @@
 	return 1;
 }
 
-static int receive_Barrier(struct drbd_conf *mdev, struct p_header *h)
+static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	int rv, issue_flush;
-	struct p_barrier *p = (struct p_barrier *)h;
+	struct p_barrier *p = &mdev->data.rbuf.barrier;
 	struct drbd_epoch *epoch;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-
-	rv = drbd_recv(mdev, h->payload, h->length);
-	ERR_IF(rv != h->length) return FALSE;
-
 	inc_unacked(mdev);
 
 	if (mdev->net_conf->wire_protocol != DRBD_PROT_C)
@@ -1457,7 +1464,7 @@
 		data_size -= rr;
 	}
 	kunmap(page);
-	drbd_pp_free(mdev, page);
+	drbd_pp_free(mdev, page, 0);
 	return rv;
 }
 
@@ -1562,30 +1569,29 @@
 	list_add(&e->w.list, &mdev->sync_ee);
 	spin_unlock_irq(&mdev->req_lock);
 
+	atomic_add(data_size >> 9, &mdev->rs_sect_ev);
 	if (drbd_submit_ee(mdev, e, WRITE, DRBD_FAULT_RS_WR) == 0)
 		return TRUE;
 
+	/* drbd_submit_ee currently fails for one reason only:
+	 * not being able to allocate enough bios.
+	 * Is dropping the connection going to help? */
+	spin_lock_irq(&mdev->req_lock);
+	list_del(&e->w.list);
+	spin_unlock_irq(&mdev->req_lock);
+
 	drbd_free_ee(mdev, e);
 fail:
 	put_ldev(mdev);
 	return FALSE;
 }
 
-static int receive_DataReply(struct drbd_conf *mdev, struct p_header *h)
+static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	struct drbd_request *req;
 	sector_t sector;
-	unsigned int header_size, data_size;
 	int ok;
-	struct p_data *p = (struct p_data *)h;
-
-	header_size = sizeof(*p) - sizeof(*h);
-	data_size   = h->length  - header_size;
-
-	ERR_IF(data_size == 0) return FALSE;
-
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
-		return FALSE;
+	struct p_data *p = &mdev->data.rbuf.data;
 
 	sector = be64_to_cpu(p->sector);
 
@@ -1611,20 +1617,11 @@
 	return ok;
 }
 
-static int receive_RSDataReply(struct drbd_conf *mdev, struct p_header *h)
+static int receive_RSDataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	sector_t sector;
-	unsigned int header_size, data_size;
 	int ok;
-	struct p_data *p = (struct p_data *)h;
-
-	header_size = sizeof(*p) - sizeof(*h);
-	data_size   = h->length  - header_size;
-
-	ERR_IF(data_size == 0) return FALSE;
-
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
-		return FALSE;
+	struct p_data *p = &mdev->data.rbuf.data;
 
 	sector = be64_to_cpu(p->sector);
 	D_ASSERT(p->block_id == ID_SYNCER);
@@ -1640,9 +1637,11 @@
 
 		ok = drbd_drain_block(mdev, data_size);
 
-		drbd_send_ack_dp(mdev, P_NEG_ACK, p);
+		drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
 	}
 
+	atomic_add(data_size >> 9, &mdev->rs_sect_in);
+
 	return ok;
 }
 
@@ -1765,24 +1764,27 @@
 	return ret;
 }
 
+static unsigned long write_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
+{
+	if (mdev->agreed_pro_version >= 95)
+		return  (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
+			(dpf & DP_UNPLUG ? REQ_UNPLUG : 0) |
+			(dpf & DP_FUA ? REQ_FUA : 0) |
+			(dpf & DP_FLUSH ? REQ_FUA : 0) |
+			(dpf & DP_DISCARD ? REQ_DISCARD : 0);
+	else
+		return dpf & DP_RW_SYNC ? (REQ_SYNC | REQ_UNPLUG) : 0;
+}
+
 /* mirrored write */
-static int receive_Data(struct drbd_conf *mdev, struct p_header *h)
+static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	sector_t sector;
 	struct drbd_epoch_entry *e;
-	struct p_data *p = (struct p_data *)h;
-	int header_size, data_size;
+	struct p_data *p = &mdev->data.rbuf.data;
 	int rw = WRITE;
 	u32 dp_flags;
 
-	header_size = sizeof(*p) - sizeof(*h);
-	data_size   = h->length  - header_size;
-
-	ERR_IF(data_size == 0) return FALSE;
-
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
-		return FALSE;
-
 	if (!get_ldev(mdev)) {
 		if (__ratelimit(&drbd_ratelimit_state))
 			dev_err(DEV, "Can not write mirrored data block "
@@ -1792,7 +1794,7 @@
 			mdev->peer_seq++;
 		spin_unlock(&mdev->peer_seq_lock);
 
-		drbd_send_ack_dp(mdev, P_NEG_ACK, p);
+		drbd_send_ack_dp(mdev, P_NEG_ACK, p, data_size);
 		atomic_inc(&mdev->current_epoch->epoch_size);
 		return drbd_drain_block(mdev, data_size);
 	}
@@ -1839,12 +1841,8 @@
 	spin_unlock(&mdev->epoch_lock);
 
 	dp_flags = be32_to_cpu(p->dp_flags);
-	if (dp_flags & DP_HARDBARRIER) {
-		dev_err(DEV, "ASSERT FAILED would have submitted barrier request\n");
-		/* rw |= REQ_HARDBARRIER; */
-	}
-	if (dp_flags & DP_RW_SYNC)
-		rw |= REQ_SYNC | REQ_UNPLUG;
+	rw |= write_flags_to_bio(mdev, dp_flags);
+
 	if (dp_flags & DP_MAY_SET_IN_SYNC)
 		e->flags |= EE_MAY_SET_IN_SYNC;
 
@@ -2007,6 +2005,16 @@
 	if (drbd_submit_ee(mdev, e, rw, DRBD_FAULT_DT_WR) == 0)
 		return TRUE;
 
+	/* drbd_submit_ee currently fails for one reason only:
+	 * not being able to allocate enough bios.
+	 * Is dropping the connection going to help? */
+	spin_lock_irq(&mdev->req_lock);
+	list_del(&e->w.list);
+	hlist_del_init(&e->colision);
+	spin_unlock_irq(&mdev->req_lock);
+	if (e->flags & EE_CALL_AL_COMPLETE_IO)
+		drbd_al_complete_io(mdev, e->sector);
+
 out_interrupted:
 	/* yes, the epoch_size now is imbalanced.
 	 * but we drop the connection anyways, so we don't have a chance to
@@ -2016,20 +2024,64 @@
 	return FALSE;
 }
 
-static int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h)
+/* We may throttle resync, if the lower device seems to be busy,
+ * and current sync rate is above c_min_rate.
+ *
+ * To decide whether or not the lower device is busy, we use a scheme similar
+ * to MD RAID is_mddev_idle(): if the partition stats reveal "significant"
+ * (more than 64 sectors) of activity we cannot account for with our own resync
+ * activity, it obviously is "busy".
+ *
+ * The current sync rate used here uses only the most recent two step marks,
+ * to have a short time average so we can react faster.
+ */
+int drbd_rs_should_slow_down(struct drbd_conf *mdev)
+{
+	struct gendisk *disk = mdev->ldev->backing_bdev->bd_contains->bd_disk;
+	unsigned long db, dt, dbdt;
+	int curr_events;
+	int throttle = 0;
+
+	/* feature disabled? */
+	if (mdev->sync_conf.c_min_rate == 0)
+		return 0;
+
+	curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
+		      (int)part_stat_read(&disk->part0, sectors[1]) -
+			atomic_read(&mdev->rs_sect_ev);
+	if (!mdev->rs_last_events || curr_events - mdev->rs_last_events > 64) {
+		unsigned long rs_left;
+		int i;
+
+		mdev->rs_last_events = curr_events;
+
+		/* sync speed average over the last 2*DRBD_SYNC_MARK_STEP,
+		 * approx. */
+		i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-2) % DRBD_SYNC_MARKS;
+		rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
+
+		dt = ((long)jiffies - (long)mdev->rs_mark_time[i]) / HZ;
+		if (!dt)
+			dt++;
+		db = mdev->rs_mark_left[i] - rs_left;
+		dbdt = Bit2KB(db/dt);
+
+		if (dbdt > mdev->sync_conf.c_min_rate)
+			throttle = 1;
+	}
+	return throttle;
+}
+
+
+static int receive_DataRequest(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int digest_size)
 {
 	sector_t sector;
 	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
 	struct drbd_epoch_entry *e;
 	struct digest_info *di = NULL;
-	int size, digest_size;
+	int size, verb;
 	unsigned int fault_type;
-	struct p_block_req *p =
-		(struct p_block_req *)h;
-	const int brps = sizeof(*p)-sizeof(*h);
-
-	if (drbd_recv(mdev, h->payload, brps) != brps)
-		return FALSE;
+	struct p_block_req *p =	&mdev->data.rbuf.block_req;
 
 	sector = be64_to_cpu(p->sector);
 	size   = be32_to_cpu(p->blksize);
@@ -2046,12 +2098,31 @@
 	}
 
 	if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) {
-		if (__ratelimit(&drbd_ratelimit_state))
+		verb = 1;
+		switch (cmd) {
+		case P_DATA_REQUEST:
+			drbd_send_ack_rp(mdev, P_NEG_DREPLY, p);
+			break;
+		case P_RS_DATA_REQUEST:
+		case P_CSUM_RS_REQUEST:
+		case P_OV_REQUEST:
+			drbd_send_ack_rp(mdev, P_NEG_RS_DREPLY , p);
+			break;
+		case P_OV_REPLY:
+			verb = 0;
+			dec_rs_pending(mdev);
+			drbd_send_ack_ex(mdev, P_OV_RESULT, sector, size, ID_IN_SYNC);
+			break;
+		default:
+			dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n",
+				cmdname(cmd));
+		}
+		if (verb && __ratelimit(&drbd_ratelimit_state))
 			dev_err(DEV, "Can not satisfy peer's read request, "
 			    "no local data.\n");
-		drbd_send_ack_rp(mdev, h->command == P_DATA_REQUEST ? P_NEG_DREPLY :
-				 P_NEG_RS_DREPLY , p);
-		return drbd_drain_block(mdev, h->length - brps);
+
+		/* drain possibly payload */
+		return drbd_drain_block(mdev, digest_size);
 	}
 
 	/* GFP_NOIO, because we must not cause arbitrary write-out: in a DRBD
@@ -2063,31 +2134,21 @@
 		return FALSE;
 	}
 
-	switch (h->command) {
+	switch (cmd) {
 	case P_DATA_REQUEST:
 		e->w.cb = w_e_end_data_req;
 		fault_type = DRBD_FAULT_DT_RD;
-		break;
+		/* application IO, don't drbd_rs_begin_io */
+		goto submit;
+
 	case P_RS_DATA_REQUEST:
 		e->w.cb = w_e_end_rsdata_req;
 		fault_type = DRBD_FAULT_RS_RD;
-		/* Eventually this should become asynchronously. Currently it
-		 * blocks the whole receiver just to delay the reading of a
-		 * resync data block.
-		 * the drbd_work_queue mechanism is made for this...
-		 */
-		if (!drbd_rs_begin_io(mdev, sector)) {
-			/* we have been interrupted,
-			 * probably connection lost! */
-			D_ASSERT(signal_pending(current));
-			goto out_free_e;
-		}
 		break;
 
 	case P_OV_REPLY:
 	case P_CSUM_RS_REQUEST:
 		fault_type = DRBD_FAULT_RS_RD;
-		digest_size = h->length - brps ;
 		di = kmalloc(sizeof(*di) + digest_size, GFP_NOIO);
 		if (!di)
 			goto out_free_e;
@@ -2095,31 +2156,25 @@
 		di->digest_size = digest_size;
 		di->digest = (((char *)di)+sizeof(struct digest_info));
 
+		e->digest = di;
+		e->flags |= EE_HAS_DIGEST;
+
 		if (drbd_recv(mdev, di->digest, digest_size) != digest_size)
 			goto out_free_e;
 
-		e->block_id = (u64)(unsigned long)di;
-		if (h->command == P_CSUM_RS_REQUEST) {
+		if (cmd == P_CSUM_RS_REQUEST) {
 			D_ASSERT(mdev->agreed_pro_version >= 89);
 			e->w.cb = w_e_end_csum_rs_req;
-		} else if (h->command == P_OV_REPLY) {
+		} else if (cmd == P_OV_REPLY) {
 			e->w.cb = w_e_end_ov_reply;
 			dec_rs_pending(mdev);
-			break;
-		}
-
-		if (!drbd_rs_begin_io(mdev, sector)) {
-			/* we have been interrupted, probably connection lost! */
-			D_ASSERT(signal_pending(current));
-			goto out_free_e;
+			/* drbd_rs_begin_io done when we sent this request,
+			 * but accounting still needs to be done. */
+			goto submit_for_resync;
 		}
 		break;
 
 	case P_OV_REQUEST:
-		if (mdev->state.conn >= C_CONNECTED &&
-		    mdev->state.conn != C_VERIFY_T)
-			dev_warn(DEV, "ASSERT FAILED: got P_OV_REQUEST while being %s\n",
-				drbd_conn_str(mdev->state.conn));
 		if (mdev->ov_start_sector == ~(sector_t)0 &&
 		    mdev->agreed_pro_version >= 90) {
 			mdev->ov_start_sector = sector;
@@ -2130,37 +2185,63 @@
 		}
 		e->w.cb = w_e_end_ov_req;
 		fault_type = DRBD_FAULT_RS_RD;
-		/* Eventually this should become asynchronous. Currently it
-		 * blocks the whole receiver just to delay the reading of a
-		 * resync data block.
-		 * the drbd_work_queue mechanism is made for this...
-		 */
-		if (!drbd_rs_begin_io(mdev, sector)) {
-			/* we have been interrupted,
-			 * probably connection lost! */
-			D_ASSERT(signal_pending(current));
-			goto out_free_e;
-		}
 		break;
 
-
 	default:
 		dev_err(DEV, "unexpected command (%s) in receive_DataRequest\n",
-		    cmdname(h->command));
+		    cmdname(cmd));
 		fault_type = DRBD_FAULT_MAX;
+		goto out_free_e;
 	}
 
-	spin_lock_irq(&mdev->req_lock);
-	list_add(&e->w.list, &mdev->read_ee);
-	spin_unlock_irq(&mdev->req_lock);
+	/* Throttle, drbd_rs_begin_io and submit should become asynchronous
+	 * wrt the receiver, but it is not as straightforward as it may seem.
+	 * Various places in the resync start and stop logic assume resync
+	 * requests are processed in order, requeuing this on the worker thread
+	 * introduces a bunch of new code for synchronization between threads.
+	 *
+	 * Unlimited throttling before drbd_rs_begin_io may stall the resync
+	 * "forever", throttling after drbd_rs_begin_io will lock that extent
+	 * for application writes for the same time.  For now, just throttle
+	 * here, where the rest of the code expects the receiver to sleep for
+	 * a while, anyways.
+	 */
 
+	/* Throttle before drbd_rs_begin_io, as that locks out application IO;
+	 * this defers syncer requests for some time, before letting at least
+	 * on request through.  The resync controller on the receiving side
+	 * will adapt to the incoming rate accordingly.
+	 *
+	 * We cannot throttle here if remote is Primary/SyncTarget:
+	 * we would also throttle its application reads.
+	 * In that case, throttling is done on the SyncTarget only.
+	 */
+	if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev))
+		msleep(100);
+	if (drbd_rs_begin_io(mdev, e->sector))
+		goto out_free_e;
+
+submit_for_resync:
+	atomic_add(size >> 9, &mdev->rs_sect_ev);
+
+submit:
 	inc_unacked(mdev);
+	spin_lock_irq(&mdev->req_lock);
+	list_add_tail(&e->w.list, &mdev->read_ee);
+	spin_unlock_irq(&mdev->req_lock);
 
 	if (drbd_submit_ee(mdev, e, READ, fault_type) == 0)
 		return TRUE;
 
+	/* drbd_submit_ee currently fails for one reason only:
+	 * not being able to allocate enough bios.
+	 * Is dropping the connection going to help? */
+	spin_lock_irq(&mdev->req_lock);
+	list_del(&e->w.list);
+	spin_unlock_irq(&mdev->req_lock);
+	/* no drbd_rs_complete_io(), we are dropping the connection anyways */
+
 out_free_e:
-	kfree(di);
 	put_ldev(mdev);
 	drbd_free_ee(mdev, e);
 	return FALSE;
@@ -2699,20 +2780,13 @@
 	return 1;
 }
 
-static int receive_protocol(struct drbd_conf *mdev, struct p_header *h)
+static int receive_protocol(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_protocol *p = (struct p_protocol *)h;
-	int header_size, data_size;
+	struct p_protocol *p = &mdev->data.rbuf.protocol;
 	int p_proto, p_after_sb_0p, p_after_sb_1p, p_after_sb_2p;
 	int p_want_lose, p_two_primaries, cf;
 	char p_integrity_alg[SHARED_SECRET_MAX] = "";
 
-	header_size = sizeof(*p) - sizeof(*h);
-	data_size   = h->length  - header_size;
-
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
-		return FALSE;
-
 	p_proto		= be32_to_cpu(p->protocol);
 	p_after_sb_0p	= be32_to_cpu(p->after_sb_0p);
 	p_after_sb_1p	= be32_to_cpu(p->after_sb_1p);
@@ -2805,39 +2879,46 @@
 	return tfm;
 }
 
-static int receive_SyncParam(struct drbd_conf *mdev, struct p_header *h)
+static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int packet_size)
 {
 	int ok = TRUE;
-	struct p_rs_param_89 *p = (struct p_rs_param_89 *)h;
+	struct p_rs_param_95 *p = &mdev->data.rbuf.rs_param_95;
 	unsigned int header_size, data_size, exp_max_sz;
 	struct crypto_hash *verify_tfm = NULL;
 	struct crypto_hash *csums_tfm = NULL;
 	const int apv = mdev->agreed_pro_version;
+	int *rs_plan_s = NULL;
+	int fifo_size = 0;
 
 	exp_max_sz  = apv <= 87 ? sizeof(struct p_rs_param)
 		    : apv == 88 ? sizeof(struct p_rs_param)
 					+ SHARED_SECRET_MAX
-		    : /* 89 */    sizeof(struct p_rs_param_89);
+		    : apv <= 94 ? sizeof(struct p_rs_param_89)
+		    : /* apv >= 95 */ sizeof(struct p_rs_param_95);
 
-	if (h->length > exp_max_sz) {
+	if (packet_size > exp_max_sz) {
 		dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n",
-		    h->length, exp_max_sz);
+		    packet_size, exp_max_sz);
 		return FALSE;
 	}
 
 	if (apv <= 88) {
-		header_size = sizeof(struct p_rs_param) - sizeof(*h);
-		data_size   = h->length  - header_size;
-	} else /* apv >= 89 */ {
-		header_size = sizeof(struct p_rs_param_89) - sizeof(*h);
-		data_size   = h->length  - header_size;
+		header_size = sizeof(struct p_rs_param) - sizeof(struct p_header80);
+		data_size   = packet_size  - header_size;
+	} else if (apv <= 94) {
+		header_size = sizeof(struct p_rs_param_89) - sizeof(struct p_header80);
+		data_size   = packet_size  - header_size;
+		D_ASSERT(data_size == 0);
+	} else {
+		header_size = sizeof(struct p_rs_param_95) - sizeof(struct p_header80);
+		data_size   = packet_size  - header_size;
 		D_ASSERT(data_size == 0);
 	}
 
 	/* initialize verify_alg and csums_alg */
 	memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
-	if (drbd_recv(mdev, h->payload, header_size) != header_size)
+	if (drbd_recv(mdev, &p->head.payload, header_size) != header_size)
 		return FALSE;
 
 	mdev->sync_conf.rate	  = be32_to_cpu(p->rate);
@@ -2896,6 +2977,22 @@
 			}
 		}
 
+		if (apv > 94) {
+			mdev->sync_conf.rate	  = be32_to_cpu(p->rate);
+			mdev->sync_conf.c_plan_ahead = be32_to_cpu(p->c_plan_ahead);
+			mdev->sync_conf.c_delay_target = be32_to_cpu(p->c_delay_target);
+			mdev->sync_conf.c_fill_target = be32_to_cpu(p->c_fill_target);
+			mdev->sync_conf.c_max_rate = be32_to_cpu(p->c_max_rate);
+
+			fifo_size = (mdev->sync_conf.c_plan_ahead * 10 * SLEEP_TIME) / HZ;
+			if (fifo_size != mdev->rs_plan_s.size && fifo_size > 0) {
+				rs_plan_s   = kzalloc(sizeof(int) * fifo_size, GFP_KERNEL);
+				if (!rs_plan_s) {
+					dev_err(DEV, "kmalloc of fifo_buffer failed");
+					goto disconnect;
+				}
+			}
+		}
 
 		spin_lock(&mdev->peer_seq_lock);
 		/* lock against drbd_nl_syncer_conf() */
@@ -2913,6 +3010,12 @@
 			mdev->csums_tfm = csums_tfm;
 			dev_info(DEV, "using csums-alg: \"%s\"\n", p->csums_alg);
 		}
+		if (fifo_size != mdev->rs_plan_s.size) {
+			kfree(mdev->rs_plan_s.values);
+			mdev->rs_plan_s.values = rs_plan_s;
+			mdev->rs_plan_s.size   = fifo_size;
+			mdev->rs_planed = 0;
+		}
 		spin_unlock(&mdev->peer_seq_lock);
 	}
 
@@ -2946,19 +3049,15 @@
 		     (unsigned long long)a, (unsigned long long)b);
 }
 
-static int receive_sizes(struct drbd_conf *mdev, struct p_header *h)
+static int receive_sizes(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_sizes *p = (struct p_sizes *)h;
+	struct p_sizes *p = &mdev->data.rbuf.sizes;
 	enum determine_dev_size dd = unchanged;
 	unsigned int max_seg_s;
 	sector_t p_size, p_usize, my_usize;
 	int ldsc = 0; /* local disk size changed */
 	enum dds_flags ddsf;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	p_size = be64_to_cpu(p->d_size);
 	p_usize = be64_to_cpu(p->u_size);
 
@@ -2972,7 +3071,6 @@
 	 * we still need to figure out whether we accept that. */
 	mdev->p_size = p_size;
 
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
 	if (get_ldev(mdev)) {
 		warn_if_differ_considerably(mdev, "lower level device sizes",
 			   p_size, drbd_get_max_capacity(mdev->ldev));
@@ -3029,6 +3127,8 @@
 
 		if (mdev->agreed_pro_version < 94)
 			max_seg_s = be32_to_cpu(p->max_segment_size);
+		else if (mdev->agreed_pro_version == 94)
+			max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
 		else /* drbd 8.3.8 onwards */
 			max_seg_s = DRBD_MAX_SEGMENT_SIZE;
 
@@ -3062,16 +3162,12 @@
 	return TRUE;
 }
 
-static int receive_uuids(struct drbd_conf *mdev, struct p_header *h)
+static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_uuids *p = (struct p_uuids *)h;
+	struct p_uuids *p = &mdev->data.rbuf.uuids;
 	u64 *p_uuid;
 	int i;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO);
 
 	for (i = UI_CURRENT; i < UI_EXTENDED_SIZE; i++)
@@ -3107,6 +3203,11 @@
 			drbd_md_sync(mdev);
 		}
 		put_ldev(mdev);
+	} else if (mdev->state.disk < D_INCONSISTENT &&
+		   mdev->state.role == R_PRIMARY) {
+		/* I am a diskless primary, the peer just created a new current UUID
+		   for me. */
+		drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
 	}
 
 	/* Before we test for the disk state, we should wait until an eventually
@@ -3150,16 +3251,12 @@
 	return ms;
 }
 
-static int receive_req_state(struct drbd_conf *mdev, struct p_header *h)
+static int receive_req_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_req_state *p = (struct p_req_state *)h;
+	struct p_req_state *p = &mdev->data.rbuf.req_state;
 	union drbd_state mask, val;
 	int rv;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	mask.i = be32_to_cpu(p->mask);
 	val.i = be32_to_cpu(p->val);
 
@@ -3180,20 +3277,14 @@
 	return TRUE;
 }
 
-static int receive_state(struct drbd_conf *mdev, struct p_header *h)
+static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_state *p = (struct p_state *)h;
-	enum drbd_conns nconn, oconn;
-	union drbd_state ns, peer_state;
+	struct p_state *p = &mdev->data.rbuf.state;
+	union drbd_state os, ns, peer_state;
 	enum drbd_disk_state real_peer_disk;
+	enum chg_state_flags cs_flags;
 	int rv;
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h)))
-		return FALSE;
-
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	peer_state.i = be32_to_cpu(p->state);
 
 	real_peer_disk = peer_state.disk;
@@ -3204,38 +3295,72 @@
 
 	spin_lock_irq(&mdev->req_lock);
  retry:
-	oconn = nconn = mdev->state.conn;
+	os = ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
 
-	if (nconn == C_WF_REPORT_PARAMS)
-		nconn = C_CONNECTED;
+	/* peer says his disk is uptodate, while we think it is inconsistent,
+	 * and this happens while we think we have a sync going on. */
+	if (os.pdsk == D_INCONSISTENT && real_peer_disk == D_UP_TO_DATE &&
+	    os.conn > C_CONNECTED && os.disk == D_UP_TO_DATE) {
+		/* If we are (becoming) SyncSource, but peer is still in sync
+		 * preparation, ignore its uptodate-ness to avoid flapping, it
+		 * will change to inconsistent once the peer reaches active
+		 * syncing states.
+		 * It may have changed syncer-paused flags, however, so we
+		 * cannot ignore this completely. */
+		if (peer_state.conn > C_CONNECTED &&
+		    peer_state.conn < C_SYNC_SOURCE)
+			real_peer_disk = D_INCONSISTENT;
+
+		/* if peer_state changes to connected at the same time,
+		 * it explicitly notifies us that it finished resync.
+		 * Maybe we should finish it up, too? */
+		else if (os.conn >= C_SYNC_SOURCE &&
+			 peer_state.conn == C_CONNECTED) {
+			if (drbd_bm_total_weight(mdev) <= mdev->rs_failed)
+				drbd_resync_finished(mdev);
+			return TRUE;
+		}
+	}
+
+	/* peer says his disk is inconsistent, while we think it is uptodate,
+	 * and this happens while the peer still thinks we have a sync going on,
+	 * but we think we are already done with the sync.
+	 * We ignore this to avoid flapping pdsk.
+	 * This should not happen, if the peer is a recent version of drbd. */
+	if (os.pdsk == D_UP_TO_DATE && real_peer_disk == D_INCONSISTENT &&
+	    os.conn == C_CONNECTED && peer_state.conn > C_SYNC_SOURCE)
+		real_peer_disk = D_UP_TO_DATE;
+
+	if (ns.conn == C_WF_REPORT_PARAMS)
+		ns.conn = C_CONNECTED;
 
 	if (mdev->p_uuid && peer_state.disk >= D_NEGOTIATING &&
 	    get_ldev_if_state(mdev, D_NEGOTIATING)) {
 		int cr; /* consider resync */
 
 		/* if we established a new connection */
-		cr  = (oconn < C_CONNECTED);
+		cr  = (os.conn < C_CONNECTED);
 		/* if we had an established connection
 		 * and one of the nodes newly attaches a disk */
-		cr |= (oconn == C_CONNECTED &&
+		cr |= (os.conn == C_CONNECTED &&
 		       (peer_state.disk == D_NEGOTIATING ||
-			mdev->state.disk == D_NEGOTIATING));
+			os.disk == D_NEGOTIATING));
 		/* if we have both been inconsistent, and the peer has been
 		 * forced to be UpToDate with --overwrite-data */
 		cr |= test_bit(CONSIDER_RESYNC, &mdev->flags);
 		/* if we had been plain connected, and the admin requested to
 		 * start a sync by "invalidate" or "invalidate-remote" */
-		cr |= (oconn == C_CONNECTED &&
+		cr |= (os.conn == C_CONNECTED &&
 				(peer_state.conn >= C_STARTING_SYNC_S &&
 				 peer_state.conn <= C_WF_BITMAP_T));
 
 		if (cr)
-			nconn = drbd_sync_handshake(mdev, peer_state.role, real_peer_disk);
+			ns.conn = drbd_sync_handshake(mdev, peer_state.role, real_peer_disk);
 
 		put_ldev(mdev);
-		if (nconn == C_MASK) {
-			nconn = C_CONNECTED;
+		if (ns.conn == C_MASK) {
+			ns.conn = C_CONNECTED;
 			if (mdev->state.disk == D_NEGOTIATING) {
 				drbd_force_state(mdev, NS(disk, D_DISKLESS));
 			} else if (peer_state.disk == D_NEGOTIATING) {
@@ -3245,7 +3370,7 @@
 			} else {
 				if (test_and_clear_bit(CONN_DRY_RUN, &mdev->flags))
 					return FALSE;
-				D_ASSERT(oconn == C_WF_REPORT_PARAMS);
+				D_ASSERT(os.conn == C_WF_REPORT_PARAMS);
 				drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
 				return FALSE;
 			}
@@ -3253,18 +3378,28 @@
 	}
 
 	spin_lock_irq(&mdev->req_lock);
-	if (mdev->state.conn != oconn)
+	if (mdev->state.i != os.i)
 		goto retry;
 	clear_bit(CONSIDER_RESYNC, &mdev->flags);
-	ns.i = mdev->state.i;
-	ns.conn = nconn;
 	ns.peer = peer_state.role;
 	ns.pdsk = real_peer_disk;
 	ns.peer_isp = (peer_state.aftr_isp | peer_state.user_isp);
-	if ((nconn == C_CONNECTED || nconn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING)
+	if ((ns.conn == C_CONNECTED || ns.conn == C_WF_BITMAP_S) && ns.disk == D_NEGOTIATING)
 		ns.disk = mdev->new_state_tmp.disk;
-
-	rv = _drbd_set_state(mdev, ns, CS_VERBOSE | CS_HARD, NULL);
+	cs_flags = CS_VERBOSE + (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED ? 0 : CS_HARD);
+	if (ns.pdsk == D_CONSISTENT && is_susp(ns) && ns.conn == C_CONNECTED && os.conn < C_CONNECTED &&
+	    test_bit(NEW_CUR_UUID, &mdev->flags)) {
+		/* Do not allow tl_restart(resend) for a rebooted peer. We can only allow this
+		   for temporal network outages! */
+		spin_unlock_irq(&mdev->req_lock);
+		dev_err(DEV, "Aborting Connect, can not thaw IO with an only Consistent peer\n");
+		tl_clear(mdev);
+		drbd_uuid_new_current(mdev);
+		clear_bit(NEW_CUR_UUID, &mdev->flags);
+		drbd_force_state(mdev, NS2(conn, C_PROTOCOL_ERROR, susp, 0));
+		return FALSE;
+	}
+	rv = _drbd_set_state(mdev, ns, cs_flags, NULL);
 	ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
 
@@ -3273,8 +3408,8 @@
 		return FALSE;
 	}
 
-	if (oconn > C_WF_REPORT_PARAMS) {
-		if (nconn > C_CONNECTED && peer_state.conn <= C_CONNECTED &&
+	if (os.conn > C_WF_REPORT_PARAMS) {
+		if (ns.conn > C_CONNECTED && peer_state.conn <= C_CONNECTED &&
 		    peer_state.disk != D_NEGOTIATING ) {
 			/* we want resync, peer has not yet decided to sync... */
 			/* Nowadays only used when forcing a node into primary role and
@@ -3291,9 +3426,9 @@
 	return TRUE;
 }
 
-static int receive_sync_uuid(struct drbd_conf *mdev, struct p_header *h)
+static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	struct p_rs_uuid *p = (struct p_rs_uuid *)h;
+	struct p_rs_uuid *p = &mdev->data.rbuf.rs_uuid;
 
 	wait_event(mdev->misc_wait,
 		   mdev->state.conn == C_WF_SYNC_UUID ||
@@ -3302,10 +3437,6 @@
 
 	/* D_ASSERT( mdev->state.conn == C_WF_SYNC_UUID ); */
 
-	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
-	if (drbd_recv(mdev, h->payload, h->length) != h->length)
-		return FALSE;
-
 	/* Here the _drbd_uuid_ functions are right, current should
 	   _not_ be rotated into the history */
 	if (get_ldev_if_state(mdev, D_NEGOTIATING)) {
@@ -3324,14 +3455,14 @@
 enum receive_bitmap_ret { OK, DONE, FAILED };
 
 static enum receive_bitmap_ret
-receive_bitmap_plain(struct drbd_conf *mdev, struct p_header *h,
-	unsigned long *buffer, struct bm_xfer_ctx *c)
+receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
+		     unsigned long *buffer, struct bm_xfer_ctx *c)
 {
 	unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset);
 	unsigned want = num_words * sizeof(long);
 
-	if (want != h->length) {
-		dev_err(DEV, "%s:want (%u) != h->length (%u)\n", __func__, want, h->length);
+	if (want != data_size) {
+		dev_err(DEV, "%s:want (%u) != data_size (%u)\n", __func__, want, data_size);
 		return FAILED;
 	}
 	if (want == 0)
@@ -3360,7 +3491,7 @@
 	u64 tmp;
 	unsigned long s = c->bit_offset;
 	unsigned long e;
-	int len = p->head.length - (sizeof(*p) - sizeof(p->head));
+	int len = be16_to_cpu(p->head.length) - (sizeof(*p) - sizeof(p->head));
 	int toggle = DCBP_get_start(p);
 	int have;
 	int bits;
@@ -3429,7 +3560,7 @@
 		const char *direction, struct bm_xfer_ctx *c)
 {
 	/* what would it take to transfer it "plaintext" */
-	unsigned plain = sizeof(struct p_header) *
+	unsigned plain = sizeof(struct p_header80) *
 		((c->bm_words+BM_PACKET_WORDS-1)/BM_PACKET_WORDS+1)
 		+ c->bm_words * sizeof(long);
 	unsigned total = c->bytes[0] + c->bytes[1];
@@ -3467,12 +3598,13 @@
    in order to be agnostic to the 32 vs 64 bits issue.
 
    returns 0 on failure, 1 if we successfully received it. */
-static int receive_bitmap(struct drbd_conf *mdev, struct p_header *h)
+static int receive_bitmap(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	struct bm_xfer_ctx c;
 	void *buffer;
 	enum receive_bitmap_ret ret;
 	int ok = FALSE;
+	struct p_header80 *h = &mdev->data.rbuf.header.h80;
 
 	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
 
@@ -3492,39 +3624,39 @@
 	};
 
 	do {
-		if (h->command == P_BITMAP) {
-			ret = receive_bitmap_plain(mdev, h, buffer, &c);
-		} else if (h->command == P_COMPRESSED_BITMAP) {
+		if (cmd == P_BITMAP) {
+			ret = receive_bitmap_plain(mdev, data_size, buffer, &c);
+		} else if (cmd == P_COMPRESSED_BITMAP) {
 			/* MAYBE: sanity check that we speak proto >= 90,
 			 * and the feature is enabled! */
 			struct p_compressed_bm *p;
 
-			if (h->length > BM_PACKET_PAYLOAD_BYTES) {
+			if (data_size > BM_PACKET_PAYLOAD_BYTES) {
 				dev_err(DEV, "ReportCBitmap packet too large\n");
 				goto out;
 			}
 			/* use the page buff */
 			p = buffer;
 			memcpy(p, h, sizeof(*h));
-			if (drbd_recv(mdev, p->head.payload, h->length) != h->length)
+			if (drbd_recv(mdev, p->head.payload, data_size) != data_size)
 				goto out;
-			if (p->head.length <= (sizeof(*p) - sizeof(p->head))) {
-				dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", p->head.length);
+			if (data_size <= (sizeof(*p) - sizeof(p->head))) {
+				dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", data_size);
 				return FAILED;
 			}
 			ret = decode_bitmap_c(mdev, p, &c);
 		} else {
-			dev_warn(DEV, "receive_bitmap: h->command neither ReportBitMap nor ReportCBitMap (is 0x%x)", h->command);
+			dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", cmd);
 			goto out;
 		}
 
-		c.packets[h->command == P_BITMAP]++;
-		c.bytes[h->command == P_BITMAP] += sizeof(struct p_header) + h->length;
+		c.packets[cmd == P_BITMAP]++;
+		c.bytes[cmd == P_BITMAP] += sizeof(struct p_header80) + data_size;
 
 		if (ret != OK)
 			break;
 
-		if (!drbd_recv_header(mdev, h))
+		if (!drbd_recv_header(mdev, &cmd, &data_size))
 			goto out;
 	} while (ret == OK);
 	if (ret == FAILED)
@@ -3555,17 +3687,16 @@
 	return ok;
 }
 
-static int receive_skip_(struct drbd_conf *mdev, struct p_header *h, int silent)
+static int receive_skip(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	/* TODO zero copy sink :) */
 	static char sink[128];
 	int size, want, r;
 
-	if (!silent)
-		dev_warn(DEV, "skipping unknown optional packet type %d, l: %d!\n",
-		     h->command, h->length);
+	dev_warn(DEV, "skipping unknown optional packet type %d, l: %d!\n",
+		 cmd, data_size);
 
-	size = h->length;
+	size = data_size;
 	while (size > 0) {
 		want = min_t(int, size, sizeof(sink));
 		r = drbd_recv(mdev, sink, want);
@@ -3575,17 +3706,7 @@
 	return size == 0;
 }
 
-static int receive_skip(struct drbd_conf *mdev, struct p_header *h)
-{
-	return receive_skip_(mdev, h, 0);
-}
-
-static int receive_skip_silent(struct drbd_conf *mdev, struct p_header *h)
-{
-	return receive_skip_(mdev, h, 1);
-}
-
-static int receive_UnplugRemote(struct drbd_conf *mdev, struct p_header *h)
+static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	if (mdev->state.disk >= D_INCONSISTENT)
 		drbd_kick_lo(mdev);
@@ -3597,108 +3718,94 @@
 	return TRUE;
 }
 
-typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, struct p_header *);
+typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive);
 
-static drbd_cmd_handler_f drbd_default_handler[] = {
-	[P_DATA]	    = receive_Data,
-	[P_DATA_REPLY]	    = receive_DataReply,
-	[P_RS_DATA_REPLY]   = receive_RSDataReply,
-	[P_BARRIER]	    = receive_Barrier,
-	[P_BITMAP]	    = receive_bitmap,
-	[P_COMPRESSED_BITMAP]    = receive_bitmap,
-	[P_UNPLUG_REMOTE]   = receive_UnplugRemote,
-	[P_DATA_REQUEST]    = receive_DataRequest,
-	[P_RS_DATA_REQUEST] = receive_DataRequest,
-	[P_SYNC_PARAM]	    = receive_SyncParam,
-	[P_SYNC_PARAM89]	   = receive_SyncParam,
-	[P_PROTOCOL]        = receive_protocol,
-	[P_UUIDS]	    = receive_uuids,
-	[P_SIZES]	    = receive_sizes,
-	[P_STATE]	    = receive_state,
-	[P_STATE_CHG_REQ]   = receive_req_state,
-	[P_SYNC_UUID]       = receive_sync_uuid,
-	[P_OV_REQUEST]      = receive_DataRequest,
-	[P_OV_REPLY]        = receive_DataRequest,
-	[P_CSUM_RS_REQUEST]    = receive_DataRequest,
-	[P_DELAY_PROBE]     = receive_skip_silent,
-	/* anything missing from this table is in
-	 * the asender_tbl, see get_asender_cmd */
-	[P_MAX_CMD]	    = NULL,
+struct data_cmd {
+	int expect_payload;
+	size_t pkt_size;
+	drbd_cmd_handler_f function;
 };
 
-static drbd_cmd_handler_f *drbd_cmd_handler = drbd_default_handler;
-static drbd_cmd_handler_f *drbd_opt_cmd_handler;
+static struct data_cmd drbd_cmd_handler[] = {
+	[P_DATA]	    = { 1, sizeof(struct p_data), receive_Data },
+	[P_DATA_REPLY]	    = { 1, sizeof(struct p_data), receive_DataReply },
+	[P_RS_DATA_REPLY]   = { 1, sizeof(struct p_data), receive_RSDataReply } ,
+	[P_BARRIER]	    = { 0, sizeof(struct p_barrier), receive_Barrier } ,
+	[P_BITMAP]	    = { 1, sizeof(struct p_header80), receive_bitmap } ,
+	[P_COMPRESSED_BITMAP] = { 1, sizeof(struct p_header80), receive_bitmap } ,
+	[P_UNPLUG_REMOTE]   = { 0, sizeof(struct p_header80), receive_UnplugRemote },
+	[P_DATA_REQUEST]    = { 0, sizeof(struct p_block_req), receive_DataRequest },
+	[P_RS_DATA_REQUEST] = { 0, sizeof(struct p_block_req), receive_DataRequest },
+	[P_SYNC_PARAM]	    = { 1, sizeof(struct p_header80), receive_SyncParam },
+	[P_SYNC_PARAM89]    = { 1, sizeof(struct p_header80), receive_SyncParam },
+	[P_PROTOCOL]        = { 1, sizeof(struct p_protocol), receive_protocol },
+	[P_UUIDS]	    = { 0, sizeof(struct p_uuids), receive_uuids },
+	[P_SIZES]	    = { 0, sizeof(struct p_sizes), receive_sizes },
+	[P_STATE]	    = { 0, sizeof(struct p_state), receive_state },
+	[P_STATE_CHG_REQ]   = { 0, sizeof(struct p_req_state), receive_req_state },
+	[P_SYNC_UUID]       = { 0, sizeof(struct p_rs_uuid), receive_sync_uuid },
+	[P_OV_REQUEST]      = { 0, sizeof(struct p_block_req), receive_DataRequest },
+	[P_OV_REPLY]        = { 1, sizeof(struct p_block_req), receive_DataRequest },
+	[P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest },
+	[P_DELAY_PROBE]     = { 0, sizeof(struct p_delay_probe93), receive_skip },
+	/* anything missing from this table is in
+	 * the asender_tbl, see get_asender_cmd */
+	[P_MAX_CMD]	    = { 0, 0, NULL },
+};
+
+/* All handler functions that expect a sub-header get that sub-heder in
+   mdev->data.rbuf.header.head.payload.
+
+   Usually in mdev->data.rbuf.header.head the callback can find the usual
+   p_header, but they may not rely on that. Since there is also p_header95 !
+ */
 
 static void drbdd(struct drbd_conf *mdev)
 {
-	drbd_cmd_handler_f handler;
-	struct p_header *header = &mdev->data.rbuf.header;
+	union p_header *header = &mdev->data.rbuf.header;
+	unsigned int packet_size;
+	enum drbd_packets cmd;
+	size_t shs; /* sub header size */
+	int rv;
 
 	while (get_t_state(&mdev->receiver) == Running) {
 		drbd_thread_current_set_cpu(mdev);
-		if (!drbd_recv_header(mdev, header)) {
-			drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-			break;
+		if (!drbd_recv_header(mdev, &cmd, &packet_size))
+			goto err_out;
+
+		if (unlikely(cmd >= P_MAX_CMD || !drbd_cmd_handler[cmd].function)) {
+			dev_err(DEV, "unknown packet type %d, l: %d!\n", cmd, packet_size);
+			goto err_out;
 		}
 
-		if (header->command < P_MAX_CMD)
-			handler = drbd_cmd_handler[header->command];
-		else if (P_MAY_IGNORE < header->command
-		     && header->command < P_MAX_OPT_CMD)
-			handler = drbd_opt_cmd_handler[header->command-P_MAY_IGNORE];
-		else if (header->command > P_MAX_OPT_CMD)
-			handler = receive_skip;
-		else
-			handler = NULL;
-
-		if (unlikely(!handler)) {
-			dev_err(DEV, "unknown packet type %d, l: %d!\n",
-			    header->command, header->length);
-			drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-			break;
+		shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header);
+		rv = drbd_recv(mdev, &header->h80.payload, shs);
+		if (unlikely(rv != shs)) {
+			dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
+			goto err_out;
 		}
-		if (unlikely(!handler(mdev, header))) {
+
+		if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {
+			dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);
+			goto err_out;
+		}
+
+		rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);
+
+		if (unlikely(!rv)) {
 			dev_err(DEV, "error receiving %s, l: %d!\n",
-			    cmdname(header->command), header->length);
-			drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-			break;
+			    cmdname(cmd), packet_size);
+			goto err_out;
 		}
 	}
-}
 
-static void drbd_fail_pending_reads(struct drbd_conf *mdev)
-{
-	struct hlist_head *slot;
-	struct hlist_node *pos;
-	struct hlist_node *tmp;
-	struct drbd_request *req;
-	int i;
-
-	/*
-	 * Application READ requests
-	 */
-	spin_lock_irq(&mdev->req_lock);
-	for (i = 0; i < APP_R_HSIZE; i++) {
-		slot = mdev->app_reads_hash+i;
-		hlist_for_each_entry_safe(req, pos, tmp, slot, colision) {
-			/* it may (but should not any longer!)
-			 * be on the work queue; if that assert triggers,
-			 * we need to also grab the
-			 * spin_lock_irq(&mdev->data.work.q_lock);
-			 * and list_del_init here. */
-			D_ASSERT(list_empty(&req->w.list));
-			/* It would be nice to complete outside of spinlock.
-			 * But this is easier for now. */
-			_req_mod(req, connection_lost_while_pending);
-		}
+	if (0) {
+	err_out:
+		drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
 	}
-	for (i = 0; i < APP_R_HSIZE; i++)
-		if (!hlist_empty(mdev->app_reads_hash+i))
-			dev_warn(DEV, "ASSERT FAILED: app_reads_hash[%d].first: "
-				"%p, should be NULL\n", i, mdev->app_reads_hash[i].first);
-
-	memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *));
-	spin_unlock_irq(&mdev->req_lock);
+	/* If we leave here, we probably want to update at least the
+	 * "Connected" indicator on stable storage. Do so explicitly here. */
+	drbd_md_sync(mdev);
 }
 
 void drbd_flush_workqueue(struct drbd_conf *mdev)
@@ -3711,6 +3818,36 @@
 	wait_for_completion(&barr.done);
 }
 
+void drbd_free_tl_hash(struct drbd_conf *mdev)
+{
+	struct hlist_head *h;
+
+	spin_lock_irq(&mdev->req_lock);
+
+	if (!mdev->tl_hash || mdev->state.conn != C_STANDALONE) {
+		spin_unlock_irq(&mdev->req_lock);
+		return;
+	}
+	/* paranoia code */
+	for (h = mdev->ee_hash; h < mdev->ee_hash + mdev->ee_hash_s; h++)
+		if (h->first)
+			dev_err(DEV, "ASSERT FAILED ee_hash[%u].first == %p, expected NULL\n",
+				(int)(h - mdev->ee_hash), h->first);
+	kfree(mdev->ee_hash);
+	mdev->ee_hash = NULL;
+	mdev->ee_hash_s = 0;
+
+	/* paranoia code */
+	for (h = mdev->tl_hash; h < mdev->tl_hash + mdev->tl_hash_s; h++)
+		if (h->first)
+			dev_err(DEV, "ASSERT FAILED tl_hash[%u] == %p, expected NULL\n",
+				(int)(h - mdev->tl_hash), h->first);
+	kfree(mdev->tl_hash);
+	mdev->tl_hash = NULL;
+	mdev->tl_hash_s = 0;
+	spin_unlock_irq(&mdev->req_lock);
+}
+
 static void drbd_disconnect(struct drbd_conf *mdev)
 {
 	enum drbd_fencing_p fp;
@@ -3728,6 +3865,7 @@
 	drbd_thread_stop(&mdev->asender);
 	drbd_free_sock(mdev);
 
+	/* wait for current activity to cease. */
 	spin_lock_irq(&mdev->req_lock);
 	_drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
 	_drbd_wait_ee_list_empty(mdev, &mdev->sync_ee);
@@ -3752,7 +3890,6 @@
 
 	/* make sure syncer is stopped and w_resume_next_sg queued */
 	del_timer_sync(&mdev->resync_timer);
-	set_bit(STOP_SYNC_TIMER, &mdev->flags);
 	resync_timer_fn((unsigned long)mdev);
 
 	/* wait for all w_e_end_data_req, w_e_end_rsdata_req, w_send_barrier,
@@ -3767,11 +3904,9 @@
 	kfree(mdev->p_uuid);
 	mdev->p_uuid = NULL;
 
-	if (!mdev->state.susp)
+	if (!is_susp(mdev->state))
 		tl_clear(mdev);
 
-	drbd_fail_pending_reads(mdev);
-
 	dev_info(DEV, "Connection closed\n");
 
 	drbd_md_sync(mdev);
@@ -3782,12 +3917,8 @@
 		put_ldev(mdev);
 	}
 
-	if (mdev->state.role == R_PRIMARY) {
-		if (fp >= FP_RESOURCE && mdev->state.pdsk >= D_UNKNOWN) {
-			enum drbd_disk_state nps = drbd_try_outdate_peer(mdev);
-			drbd_request_state(mdev, NS(pdsk, nps));
-		}
-	}
+	if (mdev->state.role == R_PRIMARY && fp >= FP_RESOURCE && mdev->state.pdsk >= D_UNKNOWN)
+		drbd_try_outdate_peer_async(mdev);
 
 	spin_lock_irq(&mdev->req_lock);
 	os = mdev->state;
@@ -3800,32 +3931,14 @@
 	spin_unlock_irq(&mdev->req_lock);
 
 	if (os.conn == C_DISCONNECTING) {
-		struct hlist_head *h;
-		wait_event(mdev->misc_wait, atomic_read(&mdev->net_cnt) == 0);
+		wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0);
 
-		/* we must not free the tl_hash
-		 * while application io is still on the fly */
-		wait_event(mdev->misc_wait, atomic_read(&mdev->ap_bio_cnt) == 0);
-
-		spin_lock_irq(&mdev->req_lock);
-		/* paranoia code */
-		for (h = mdev->ee_hash; h < mdev->ee_hash + mdev->ee_hash_s; h++)
-			if (h->first)
-				dev_err(DEV, "ASSERT FAILED ee_hash[%u].first == %p, expected NULL\n",
-						(int)(h - mdev->ee_hash), h->first);
-		kfree(mdev->ee_hash);
-		mdev->ee_hash = NULL;
-		mdev->ee_hash_s = 0;
-
-		/* paranoia code */
-		for (h = mdev->tl_hash; h < mdev->tl_hash + mdev->tl_hash_s; h++)
-			if (h->first)
-				dev_err(DEV, "ASSERT FAILED tl_hash[%u] == %p, expected NULL\n",
-						(int)(h - mdev->tl_hash), h->first);
-		kfree(mdev->tl_hash);
-		mdev->tl_hash = NULL;
-		mdev->tl_hash_s = 0;
-		spin_unlock_irq(&mdev->req_lock);
+		if (!is_susp(mdev->state)) {
+			/* we must not free the tl_hash
+			 * while application io is still on the fly */
+			wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
+			drbd_free_tl_hash(mdev);
+		}
 
 		crypto_free_hash(mdev->cram_hmac_tfm);
 		mdev->cram_hmac_tfm = NULL;
@@ -3845,6 +3958,9 @@
 	i = drbd_release_ee(mdev, &mdev->net_ee);
 	if (i)
 		dev_info(DEV, "net_ee not empty, killed %u entries\n", i);
+	i = atomic_read(&mdev->pp_in_use_by_net);
+	if (i)
+		dev_info(DEV, "pp_in_use_by_net = %d, expected 0\n", i);
 	i = atomic_read(&mdev->pp_in_use);
 	if (i)
 		dev_info(DEV, "pp_in_use = %d, expected 0\n", i);
@@ -3888,7 +4004,7 @@
 	p->protocol_min = cpu_to_be32(PRO_VERSION_MIN);
 	p->protocol_max = cpu_to_be32(PRO_VERSION_MAX);
 	ok = _drbd_send_cmd( mdev, mdev->data.socket, P_HAND_SHAKE,
-			     (struct p_header *)p, sizeof(*p), 0 );
+			     (struct p_header80 *)p, sizeof(*p), 0 );
 	mutex_unlock(&mdev->data.mutex);
 	return ok;
 }
@@ -3904,27 +4020,28 @@
 {
 	/* ASSERT current == mdev->receiver ... */
 	struct p_handshake *p = &mdev->data.rbuf.handshake;
-	const int expect = sizeof(struct p_handshake)
-			  -sizeof(struct p_header);
+	const int expect = sizeof(struct p_handshake) - sizeof(struct p_header80);
+	unsigned int length;
+	enum drbd_packets cmd;
 	int rv;
 
 	rv = drbd_send_handshake(mdev);
 	if (!rv)
 		return 0;
 
-	rv = drbd_recv_header(mdev, &p->head);
+	rv = drbd_recv_header(mdev, &cmd, &length);
 	if (!rv)
 		return 0;
 
-	if (p->head.command != P_HAND_SHAKE) {
+	if (cmd != P_HAND_SHAKE) {
 		dev_err(DEV, "expected HandShake packet, received: %s (0x%04x)\n",
-		     cmdname(p->head.command), p->head.command);
+		     cmdname(cmd), cmd);
 		return -1;
 	}
 
-	if (p->head.length != expect) {
+	if (length != expect) {
 		dev_err(DEV, "expected HandShake length: %u, received: %u\n",
-		     expect, p->head.length);
+		     expect, length);
 		return -1;
 	}
 
@@ -3982,10 +4099,11 @@
 	char *response = NULL;
 	char *right_response = NULL;
 	char *peers_ch = NULL;
-	struct p_header p;
 	unsigned int key_len = strlen(mdev->net_conf->shared_secret);
 	unsigned int resp_size;
 	struct hash_desc desc;
+	enum drbd_packets cmd;
+	unsigned int length;
 	int rv;
 
 	desc.tfm = mdev->cram_hmac_tfm;
@@ -4005,33 +4123,33 @@
 	if (!rv)
 		goto fail;
 
-	rv = drbd_recv_header(mdev, &p);
+	rv = drbd_recv_header(mdev, &cmd, &length);
 	if (!rv)
 		goto fail;
 
-	if (p.command != P_AUTH_CHALLENGE) {
+	if (cmd != P_AUTH_CHALLENGE) {
 		dev_err(DEV, "expected AuthChallenge packet, received: %s (0x%04x)\n",
-		    cmdname(p.command), p.command);
+		    cmdname(cmd), cmd);
 		rv = 0;
 		goto fail;
 	}
 
-	if (p.length > CHALLENGE_LEN*2) {
+	if (length > CHALLENGE_LEN * 2) {
 		dev_err(DEV, "expected AuthChallenge payload too big.\n");
 		rv = -1;
 		goto fail;
 	}
 
-	peers_ch = kmalloc(p.length, GFP_NOIO);
+	peers_ch = kmalloc(length, GFP_NOIO);
 	if (peers_ch == NULL) {
 		dev_err(DEV, "kmalloc of peers_ch failed\n");
 		rv = -1;
 		goto fail;
 	}
 
-	rv = drbd_recv(mdev, peers_ch, p.length);
+	rv = drbd_recv(mdev, peers_ch, length);
 
-	if (rv != p.length) {
+	if (rv != length) {
 		dev_err(DEV, "short read AuthChallenge: l=%u\n", rv);
 		rv = 0;
 		goto fail;
@@ -4046,7 +4164,7 @@
 	}
 
 	sg_init_table(&sg, 1);
-	sg_set_buf(&sg, peers_ch, p.length);
+	sg_set_buf(&sg, peers_ch, length);
 
 	rv = crypto_hash_digest(&desc, &sg, sg.length, response);
 	if (rv) {
@@ -4059,18 +4177,18 @@
 	if (!rv)
 		goto fail;
 
-	rv = drbd_recv_header(mdev, &p);
+	rv = drbd_recv_header(mdev, &cmd, &length);
 	if (!rv)
 		goto fail;
 
-	if (p.command != P_AUTH_RESPONSE) {
+	if (cmd != P_AUTH_RESPONSE) {
 		dev_err(DEV, "expected AuthResponse packet, received: %s (0x%04x)\n",
-		    cmdname(p.command), p.command);
+			cmdname(cmd), cmd);
 		rv = 0;
 		goto fail;
 	}
 
-	if (p.length != resp_size) {
+	if (length != resp_size) {
 		dev_err(DEV, "expected AuthResponse payload of wrong size\n");
 		rv = 0;
 		goto fail;
@@ -4155,7 +4273,7 @@
 
 /* ********* acknowledge sender ******** */
 
-static int got_RqSReply(struct drbd_conf *mdev, struct p_header *h)
+static int got_RqSReply(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_req_state_reply *p = (struct p_req_state_reply *)h;
 
@@ -4173,13 +4291,13 @@
 	return TRUE;
 }
 
-static int got_Ping(struct drbd_conf *mdev, struct p_header *h)
+static int got_Ping(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	return drbd_send_ping_ack(mdev);
 
 }
 
-static int got_PingAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_PingAck(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	/* restore idle timeout */
 	mdev->meta.socket->sk->sk_rcvtimeo = mdev->net_conf->ping_int*HZ;
@@ -4189,7 +4307,7 @@
 	return TRUE;
 }
 
-static int got_IsInSync(struct drbd_conf *mdev, struct p_header *h)
+static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	sector_t sector = be64_to_cpu(p->sector);
@@ -4199,11 +4317,15 @@
 
 	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
 
-	drbd_rs_complete_io(mdev, sector);
-	drbd_set_in_sync(mdev, sector, blksize);
-	/* rs_same_csums is supposed to count in units of BM_BLOCK_SIZE */
-	mdev->rs_same_csum += (blksize >> BM_BLOCK_SHIFT);
+	if (get_ldev(mdev)) {
+		drbd_rs_complete_io(mdev, sector);
+		drbd_set_in_sync(mdev, sector, blksize);
+		/* rs_same_csums is supposed to count in units of BM_BLOCK_SIZE */
+		mdev->rs_same_csum += (blksize >> BM_BLOCK_SHIFT);
+		put_ldev(mdev);
+	}
 	dec_rs_pending(mdev);
+	atomic_add(blksize >> 9, &mdev->rs_sect_in);
 
 	return TRUE;
 }
@@ -4259,7 +4381,7 @@
 	return TRUE;
 }
 
-static int got_BlockAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	sector_t sector = be64_to_cpu(p->sector);
@@ -4299,7 +4421,7 @@
 		_ack_id_to_req, __func__ , what);
 }
 
-static int got_NegAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_NegAck(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	sector_t sector = be64_to_cpu(p->sector);
@@ -4319,7 +4441,7 @@
 		_ack_id_to_req, __func__ , neg_acked);
 }
 
-static int got_NegDReply(struct drbd_conf *mdev, struct p_header *h)
+static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	sector_t sector = be64_to_cpu(p->sector);
@@ -4332,7 +4454,7 @@
 		_ar_id_to_req, __func__ , neg_acked);
 }
 
-static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header *h)
+static int got_NegRSDReply(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	sector_t sector;
 	int size;
@@ -4354,7 +4476,7 @@
 	return TRUE;
 }
 
-static int got_BarrierAck(struct drbd_conf *mdev, struct p_header *h)
+static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_barrier_ack *p = (struct p_barrier_ack *)h;
 
@@ -4363,7 +4485,7 @@
 	return TRUE;
 }
 
-static int got_OVResult(struct drbd_conf *mdev, struct p_header *h)
+static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	struct drbd_work *w;
@@ -4380,6 +4502,9 @@
 	else
 		ov_oos_print(mdev);
 
+	if (!get_ldev(mdev))
+		return TRUE;
+
 	drbd_rs_complete_io(mdev, sector);
 	dec_rs_pending(mdev);
 
@@ -4394,18 +4519,18 @@
 			drbd_resync_finished(mdev);
 		}
 	}
+	put_ldev(mdev);
 	return TRUE;
 }
 
-static int got_something_to_ignore_m(struct drbd_conf *mdev, struct p_header *h)
+static int got_skip(struct drbd_conf *mdev, struct p_header80 *h)
 {
-	/* IGNORE */
 	return TRUE;
 }
 
 struct asender_cmd {
 	size_t pkt_size;
-	int (*process)(struct drbd_conf *mdev, struct p_header *h);
+	int (*process)(struct drbd_conf *mdev, struct p_header80 *h);
 };
 
 static struct asender_cmd *get_asender_cmd(int cmd)
@@ -4414,8 +4539,8 @@
 		/* anything missing from this table is in
 		 * the drbd_cmd_handler (drbd_default_handler) table,
 		 * see the beginning of drbdd() */
-	[P_PING]	    = { sizeof(struct p_header), got_Ping },
-	[P_PING_ACK]	    = { sizeof(struct p_header), got_PingAck },
+	[P_PING]	    = { sizeof(struct p_header80), got_Ping },
+	[P_PING_ACK]	    = { sizeof(struct p_header80), got_PingAck },
 	[P_RECV_ACK]	    = { sizeof(struct p_block_ack), got_BlockAck },
 	[P_WRITE_ACK]	    = { sizeof(struct p_block_ack), got_BlockAck },
 	[P_RS_WRITE_ACK]    = { sizeof(struct p_block_ack), got_BlockAck },
@@ -4427,7 +4552,7 @@
 	[P_BARRIER_ACK]	    = { sizeof(struct p_barrier_ack), got_BarrierAck },
 	[P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply },
 	[P_RS_IS_IN_SYNC]   = { sizeof(struct p_block_ack), got_IsInSync },
-	[P_DELAY_PROBE]     = { sizeof(struct p_delay_probe), got_something_to_ignore_m },
+	[P_DELAY_PROBE]     = { sizeof(struct p_delay_probe93), got_skip },
 	[P_MAX_CMD]	    = { 0, NULL },
 	};
 	if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL)
@@ -4438,13 +4563,13 @@
 int drbd_asender(struct drbd_thread *thi)
 {
 	struct drbd_conf *mdev = thi->mdev;
-	struct p_header *h = &mdev->meta.rbuf.header;
+	struct p_header80 *h = &mdev->meta.rbuf.header.h80;
 	struct asender_cmd *cmd = NULL;
 
 	int rv, len;
 	void *buf    = h;
 	int received = 0;
-	int expect   = sizeof(struct p_header);
+	int expect   = sizeof(struct p_header80);
 	int empty;
 
 	sprintf(current->comm, "drbd%d_asender", mdev_to_minor(mdev));
@@ -4468,10 +4593,8 @@
 		while (1) {
 			clear_bit(SIGNAL_ASENDER, &mdev->flags);
 			flush_signals(current);
-			if (!drbd_process_done_ee(mdev)) {
-				dev_err(DEV, "process_done_ee() = NOT_OK\n");
+			if (!drbd_process_done_ee(mdev))
 				goto reconnect;
-			}
 			/* to avoid race with newly queued ACKs */
 			set_bit(SIGNAL_ASENDER, &mdev->flags);
 			spin_lock_irq(&mdev->req_lock);
@@ -4530,21 +4653,23 @@
 
 		if (received == expect && cmd == NULL) {
 			if (unlikely(h->magic != BE_DRBD_MAGIC)) {
-				dev_err(DEV, "magic?? on meta m: 0x%lx c: %d l: %d\n",
-				    (long)be32_to_cpu(h->magic),
-				    h->command, h->length);
+				dev_err(DEV, "magic?? on meta m: 0x%08x c: %d l: %d\n",
+				    be32_to_cpu(h->magic),
+				    be16_to_cpu(h->command),
+				    be16_to_cpu(h->length));
 				goto reconnect;
 			}
 			cmd = get_asender_cmd(be16_to_cpu(h->command));
 			len = be16_to_cpu(h->length);
 			if (unlikely(cmd == NULL)) {
-				dev_err(DEV, "unknown command?? on meta m: 0x%lx c: %d l: %d\n",
-				    (long)be32_to_cpu(h->magic),
-				    h->command, h->length);
+				dev_err(DEV, "unknown command?? on meta m: 0x%08x c: %d l: %d\n",
+				    be32_to_cpu(h->magic),
+				    be16_to_cpu(h->command),
+				    be16_to_cpu(h->length));
 				goto disconnect;
 			}
 			expect = cmd->pkt_size;
-			ERR_IF(len != expect-sizeof(struct p_header))
+			ERR_IF(len != expect-sizeof(struct p_header80))
 				goto reconnect;
 		}
 		if (received == expect) {
@@ -4554,7 +4679,7 @@
 
 			buf	 = h;
 			received = 0;
-			expect	 = sizeof(struct p_header);
+			expect	 = sizeof(struct p_header80);
 			cmd	 = NULL;
 		}
 	}
@@ -4562,10 +4687,12 @@
 	if (0) {
 reconnect:
 		drbd_force_state(mdev, NS(conn, C_NETWORK_FAILURE));
+		drbd_md_sync(mdev);
 	}
 	if (0) {
 disconnect:
 		drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
+		drbd_md_sync(mdev);
 	}
 	clear_bit(SIGNAL_ASENDER, &mdev->flags);
 
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index f761d98..9e91a25 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -59,17 +59,19 @@
 static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const int rw)
 {
 	const unsigned long s = req->rq_state;
+
+	/* remove it from the transfer log.
+	 * well, only if it had been there in the first
+	 * place... if it had not (local only or conflicting
+	 * and never sent), it should still be "empty" as
+	 * initialized in drbd_req_new(), so we can list_del() it
+	 * here unconditionally */
+	list_del(&req->tl_requests);
+
 	/* if it was a write, we may have to set the corresponding
 	 * bit(s) out-of-sync first. If it had a local part, we need to
 	 * release the reference to the activity log. */
 	if (rw == WRITE) {
-		/* remove it from the transfer log.
-		 * well, only if it had been there in the first
-		 * place... if it had not (local only or conflicting
-		 * and never sent), it should still be "empty" as
-		 * initialized in drbd_req_new(), so we can list_del() it
-		 * here unconditionally */
-		list_del(&req->tl_requests);
 		/* Set out-of-sync unless both OK flags are set
 		 * (local only or remote failed).
 		 * Other places where we set out-of-sync:
@@ -92,7 +94,8 @@
 		 */
 		if (s & RQ_LOCAL_MASK) {
 			if (get_ldev_if_state(mdev, D_FAILED)) {
-				drbd_al_complete_io(mdev, req->sector);
+				if (s & RQ_IN_ACT_LOG)
+					drbd_al_complete_io(mdev, req->sector);
 				put_ldev(mdev);
 			} else if (__ratelimit(&drbd_ratelimit_state)) {
 				dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu), "
@@ -280,6 +283,14 @@
 	 * protocol A or B, barrier ack still pending... */
 }
 
+static void _req_may_be_done_not_susp(struct drbd_request *req, struct bio_and_error *m)
+{
+	struct drbd_conf *mdev = req->mdev;
+
+	if (!is_susp(mdev->state))
+		_req_may_be_done(req, m);
+}
+
 /*
  * checks whether there was an overlapping request
  * or ee already registered.
@@ -380,10 +391,11 @@
  *  and it enforces that we have to think in a very structured manner
  *  about the "events" that may happen to a request during its life time ...
  */
-void __req_mod(struct drbd_request *req, enum drbd_req_event what,
+int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		struct bio_and_error *m)
 {
 	struct drbd_conf *mdev = req->mdev;
+	int rv = 0;
 	m->bio = NULL;
 
 	switch (what) {
@@ -420,7 +432,7 @@
 		req->rq_state |= (RQ_LOCAL_COMPLETED|RQ_LOCAL_OK);
 		req->rq_state &= ~RQ_LOCAL_PENDING;
 
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		put_ldev(mdev);
 		break;
 
@@ -429,7 +441,7 @@
 		req->rq_state &= ~RQ_LOCAL_PENDING;
 
 		__drbd_chk_io_error(mdev, FALSE);
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		put_ldev(mdev);
 		break;
 
@@ -437,7 +449,7 @@
 		/* it is legal to fail READA */
 		req->rq_state |= RQ_LOCAL_COMPLETED;
 		req->rq_state &= ~RQ_LOCAL_PENDING;
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		put_ldev(mdev);
 		break;
 
@@ -455,7 +467,7 @@
 		/* no point in retrying if there is no good remote data,
 		 * or we have no connection. */
 		if (mdev->state.pdsk != D_UP_TO_DATE) {
-			_req_may_be_done(req, m);
+			_req_may_be_done_not_susp(req, m);
 			break;
 		}
 
@@ -517,11 +529,9 @@
 		D_ASSERT(test_bit(CREATE_BARRIER, &mdev->flags) == 0);
 
 		req->epoch = mdev->newest_tle->br_number;
-		list_add_tail(&req->tl_requests,
-				&mdev->newest_tle->requests);
 
 		/* increment size of current epoch */
-		mdev->newest_tle->n_req++;
+		mdev->newest_tle->n_writes++;
 
 		/* queue work item to send data */
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
@@ -530,7 +540,7 @@
 		drbd_queue_work(&mdev->data.work, &req->w);
 
 		/* close the epoch, in case it outgrew the limit */
-		if (mdev->newest_tle->n_req >= mdev->net_conf->max_epoch_size)
+		if (mdev->newest_tle->n_writes >= mdev->net_conf->max_epoch_size)
 			queue_barrier(mdev);
 
 		break;
@@ -543,7 +553,7 @@
 		req->rq_state &= ~RQ_NET_QUEUED;
 		/* if we did it right, tl_clear should be scheduled only after
 		 * this, so this should not be necessary! */
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		break;
 
 	case handed_over_to_network:
@@ -568,7 +578,7 @@
 		 * "completed_ok" events came in, once we return from
 		 * _drbd_send_zc_bio (drbd_send_dblock), we have to check
 		 * whether it is done already, and end it.  */
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		break;
 
 	case read_retry_remote_canceled:
@@ -584,7 +594,7 @@
 		/* if it is still queued, we may not complete it here.
 		 * it will be canceled soon. */
 		if (!(req->rq_state & RQ_NET_QUEUED))
-			_req_may_be_done(req, m);
+			_req_may_be_done(req, m); /* Allowed while state.susp */
 		break;
 
 	case write_acked_by_peer_and_sis:
@@ -619,7 +629,7 @@
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
 		dec_ap_pending(mdev);
 		req->rq_state &= ~RQ_NET_PENDING;
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		break;
 
 	case neg_acked:
@@ -629,11 +639,50 @@
 		req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING);
 
 		req->rq_state |= RQ_NET_DONE;
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		/* else: done by handed_over_to_network */
 		break;
 
+	case fail_frozen_disk_io:
+		if (!(req->rq_state & RQ_LOCAL_COMPLETED))
+			break;
+
+		_req_may_be_done(req, m); /* Allowed while state.susp */
+		break;
+
+	case restart_frozen_disk_io:
+		if (!(req->rq_state & RQ_LOCAL_COMPLETED))
+			break;
+
+		req->rq_state &= ~RQ_LOCAL_COMPLETED;
+
+		rv = MR_READ;
+		if (bio_data_dir(req->master_bio) == WRITE)
+			rv = MR_WRITE;
+
+		get_ldev(mdev);
+		req->w.cb = w_restart_disk_io;
+		drbd_queue_work(&mdev->data.work, &req->w);
+		break;
+
+	case resend:
+		/* If RQ_NET_OK is already set, we got a P_WRITE_ACK or P_RECV_ACK
+		   before the connection loss (B&C only); only P_BARRIER_ACK was missing.
+		   Trowing them out of the TL here by pretending we got a BARRIER_ACK
+		   We ensure that the peer was not rebooted */
+		if (!(req->rq_state & RQ_NET_OK)) {
+			if (req->w.cb) {
+				drbd_queue_work(&mdev->data.work, &req->w);
+				rv = req->rq_state & RQ_WRITE ? MR_WRITE : MR_READ;
+			}
+			break;
+		}
+		/* else, fall through to barrier_acked */
+
 	case barrier_acked:
+		if (!(req->rq_state & RQ_WRITE))
+			break;
+
 		if (req->rq_state & RQ_NET_PENDING) {
 			/* barrier came in before all requests have been acked.
 			 * this is bad, because if the connection is lost now,
@@ -643,7 +692,7 @@
 		}
 		D_ASSERT(req->rq_state & RQ_NET_SENT);
 		req->rq_state |= RQ_NET_DONE;
-		_req_may_be_done(req, m);
+		_req_may_be_done(req, m); /* Allowed while state.susp */
 		break;
 
 	case data_received:
@@ -651,9 +700,11 @@
 		dec_ap_pending(mdev);
 		req->rq_state &= ~RQ_NET_PENDING;
 		req->rq_state |= (RQ_NET_OK|RQ_NET_DONE);
-		_req_may_be_done(req, m);
+		_req_may_be_done_not_susp(req, m);
 		break;
 	};
+
+	return rv;
 }
 
 /* we may do a local read if:
@@ -752,14 +803,16 @@
 	 * resync extent to finish, and, if necessary, pulls in the target
 	 * extent into the activity log, which involves further disk io because
 	 * of transactional on-disk meta data updates. */
-	if (rw == WRITE && local)
+	if (rw == WRITE && local && !test_bit(AL_SUSPENDED, &mdev->flags)) {
+		req->rq_state |= RQ_IN_ACT_LOG;
 		drbd_al_begin_io(mdev, sector);
+	}
 
 	remote = remote && (mdev->state.pdsk == D_UP_TO_DATE ||
 			    (mdev->state.pdsk == D_INCONSISTENT &&
 			     mdev->state.conn >= C_CONNECTED));
 
-	if (!(local || remote) && !mdev->state.susp) {
+	if (!(local || remote) && !is_susp(mdev->state)) {
 		dev_err(DEV, "IO ERROR: neither local nor remote disk\n");
 		goto fail_free_complete;
 	}
@@ -785,7 +838,7 @@
 	/* GOOD, everything prepared, grab the spin_lock */
 	spin_lock_irq(&mdev->req_lock);
 
-	if (mdev->state.susp) {
+	if (is_susp(mdev->state)) {
 		/* If we got suspended, use the retry mechanism of
 		   generic_make_request() to restart processing of this
 		   bio. In the next call to drbd_make_request_26
@@ -867,30 +920,10 @@
 	/* check this request on the collision detection hash tables.
 	 * if we have a conflict, just complete it here.
 	 * THINK do we want to check reads, too? (I don't think so...) */
-	if (rw == WRITE && _req_conflicts(req)) {
-		/* this is a conflicting request.
-		 * even though it may have been only _partially_
-		 * overlapping with one of the currently pending requests,
-		 * without even submitting or sending it, we will
-		 * pretend that it was successfully served right now.
-		 */
-		if (local) {
-			bio_put(req->private_bio);
-			req->private_bio = NULL;
-			drbd_al_complete_io(mdev, req->sector);
-			put_ldev(mdev);
-			local = 0;
-		}
-		if (remote)
-			dec_ap_pending(mdev);
-		_drbd_end_io_acct(mdev, req);
-		/* THINK: do we want to fail it (-EIO), or pretend success? */
-		bio_endio(req->master_bio, 0);
-		req->master_bio = NULL;
-		dec_ap_bio(mdev);
-		drbd_req_free(req);
-		remote = 0;
-	}
+	if (rw == WRITE && _req_conflicts(req))
+		goto fail_conflicting;
+
+	list_add_tail(&req->tl_requests, &mdev->newest_tle->requests);
 
 	/* NOTE remote first: to get the concurrent write detection right,
 	 * we must register the request before start of local IO.  */
@@ -923,6 +956,21 @@
 
 	return 0;
 
+fail_conflicting:
+	/* this is a conflicting request.
+	 * even though it may have been only _partially_
+	 * overlapping with one of the currently pending requests,
+	 * without even submitting or sending it, we will
+	 * pretend that it was successfully served right now.
+	 */
+	_drbd_end_io_acct(mdev, req);
+	spin_unlock_irq(&mdev->req_lock);
+	if (remote)
+		dec_ap_pending(mdev);
+	/* THINK: do we want to fail it (-EIO), or pretend success?
+	 * this pretends success. */
+	err = 0;
+
 fail_free_complete:
 	if (rw == WRITE && local)
 		drbd_al_complete_io(mdev, sector);
@@ -961,21 +1009,6 @@
 		return 1;
 	}
 
-	/*
-	 * Paranoia: we might have been primary, but sync target, or
-	 * even diskless, then lost the connection.
-	 * This should have been handled (panic? suspend?) somewhere
-	 * else. But maybe it was not, so check again here.
-	 * Caution: as long as we do not have a read/write lock on mdev,
-	 * to serialize state changes, this is racy, since we may lose
-	 * the connection *after* we test for the cstate.
-	 */
-	if (mdev->state.disk < D_UP_TO_DATE && mdev->state.pdsk < D_UP_TO_DATE) {
-		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "Sorry, I have no access to good data anymore.\n");
-		return 1;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 02d575d..181ea03 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -104,6 +104,9 @@
 	read_ahead_completed_with_error,
 	write_completed_with_error,
 	completed_ok,
+	resend,
+	fail_frozen_disk_io,
+	restart_frozen_disk_io,
 	nothing, /* for tracing only */
 };
 
@@ -183,6 +186,12 @@
 
 	/* keep this last, its for the RQ_NET_MASK */
 	__RQ_NET_MAX,
+
+	/* Set when this is a write, clear for a read */
+	__RQ_WRITE,
+
+	/* Should call drbd_al_complete_io() for this request... */
+	__RQ_IN_ACT_LOG,
 };
 
 #define RQ_LOCAL_PENDING   (1UL << __RQ_LOCAL_PENDING)
@@ -201,6 +210,16 @@
 /* 0x1f8 */
 #define RQ_NET_MASK        (((1UL << __RQ_NET_MAX)-1) & ~RQ_LOCAL_MASK)
 
+#define RQ_WRITE           (1UL << __RQ_WRITE)
+#define RQ_IN_ACT_LOG      (1UL << __RQ_IN_ACT_LOG)
+
+/* For waking up the frozen transfer log mod_req() has to return if the request
+   should be counted in the epoch object*/
+#define MR_WRITE_SHIFT 0
+#define MR_WRITE       (1 << MR_WRITE_SHIFT)
+#define MR_READ_SHIFT  1
+#define MR_READ        (1 << MR_READ_SHIFT)
+
 /* epoch entries */
 static inline
 struct hlist_head *ee_hash_slot(struct drbd_conf *mdev, sector_t sector)
@@ -244,30 +263,36 @@
 	return NULL;
 }
 
+static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bio *bio_src)
+{
+	struct bio *bio;
+	bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */
+
+	req->private_bio = bio;
+
+	bio->bi_private  = req;
+	bio->bi_end_io   = drbd_endio_pri;
+	bio->bi_next     = NULL;
+}
+
 static inline struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
 	struct bio *bio_src)
 {
-	struct bio *bio;
 	struct drbd_request *req =
 		mempool_alloc(drbd_request_mempool, GFP_NOIO);
 	if (likely(req)) {
-		bio = bio_clone(bio_src, GFP_NOIO); /* XXX cannot fail?? */
+		drbd_req_make_private_bio(req, bio_src);
 
-		req->rq_state    = 0;
+		req->rq_state    = bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0;
 		req->mdev        = mdev;
 		req->master_bio  = bio_src;
-		req->private_bio = bio;
 		req->epoch       = 0;
-		req->sector      = bio->bi_sector;
-		req->size        = bio->bi_size;
+		req->sector      = bio_src->bi_sector;
+		req->size        = bio_src->bi_size;
 		req->start_time  = jiffies;
 		INIT_HLIST_NODE(&req->colision);
 		INIT_LIST_HEAD(&req->tl_requests);
 		INIT_LIST_HEAD(&req->w.list);
-
-		bio->bi_private  = req;
-		bio->bi_end_io   = drbd_endio_pri;
-		bio->bi_next     = NULL;
 	}
 	return req;
 }
@@ -292,36 +317,43 @@
 
 extern void _req_may_be_done(struct drbd_request *req,
 		struct bio_and_error *m);
-extern void __req_mod(struct drbd_request *req, enum drbd_req_event what,
+extern int __req_mod(struct drbd_request *req, enum drbd_req_event what,
 		struct bio_and_error *m);
 extern void complete_master_bio(struct drbd_conf *mdev,
 		struct bio_and_error *m);
 
 /* use this if you don't want to deal with calling complete_master_bio()
  * outside the spinlock, e.g. when walking some list on cleanup. */
-static inline void _req_mod(struct drbd_request *req, enum drbd_req_event what)
+static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
 {
 	struct drbd_conf *mdev = req->mdev;
 	struct bio_and_error m;
+	int rv;
 
 	/* __req_mod possibly frees req, do not touch req after that! */
-	__req_mod(req, what, &m);
+	rv = __req_mod(req, what, &m);
 	if (m.bio)
 		complete_master_bio(mdev, &m);
+
+	return rv;
 }
 
 /* completion of master bio is outside of spinlock.
  * If you need it irqsave, do it your self! */
-static inline void req_mod(struct drbd_request *req,
+static inline int req_mod(struct drbd_request *req,
 		enum drbd_req_event what)
 {
 	struct drbd_conf *mdev = req->mdev;
 	struct bio_and_error m;
+	int rv;
+
 	spin_lock_irq(&mdev->req_lock);
-	__req_mod(req, what, &m);
+	rv = __req_mod(req, what, &m);
 	spin_unlock_irq(&mdev->req_lock);
 
 	if (m.bio)
 		complete_master_bio(mdev, &m);
+
+	return rv;
 }
 #endif
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index ca4a16c..108d580 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -39,8 +39,6 @@
 #include "drbd_int.h"
 #include "drbd_req.h"
 
-#define SLEEP_TIME (HZ/10)
-
 static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int cancel);
 
 
@@ -217,10 +215,8 @@
  */
 void drbd_endio_pri(struct bio *bio, int error)
 {
-	unsigned long flags;
 	struct drbd_request *req = bio->bi_private;
 	struct drbd_conf *mdev = req->mdev;
-	struct bio_and_error m;
 	enum drbd_req_event what;
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
@@ -246,12 +242,7 @@
 	bio_put(req->private_bio);
 	req->private_bio = ERR_PTR(error);
 
-	spin_lock_irqsave(&mdev->req_lock, flags);
-	__req_mod(req, what, &m);
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
-
-	if (m.bio)
-		complete_master_bio(mdev, &m);
+	req_mod(req, what);
 }
 
 int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
@@ -376,54 +367,145 @@
 	struct drbd_epoch_entry *e;
 
 	if (!get_ldev(mdev))
-		return 0;
+		return -EIO;
+
+	if (drbd_rs_should_slow_down(mdev))
+		goto defer;
 
 	/* GFP_TRY, because if there is no memory available right now, this may
 	 * be rescheduled for later. It is "only" background resync, after all. */
 	e = drbd_alloc_ee(mdev, DRBD_MAGIC+0xbeef, sector, size, GFP_TRY);
 	if (!e)
-		goto fail;
+		goto defer;
 
+	e->w.cb = w_e_send_csum;
 	spin_lock_irq(&mdev->req_lock);
 	list_add(&e->w.list, &mdev->read_ee);
 	spin_unlock_irq(&mdev->req_lock);
 
-	e->w.cb = w_e_send_csum;
+	atomic_add(size >> 9, &mdev->rs_sect_ev);
 	if (drbd_submit_ee(mdev, e, READ, DRBD_FAULT_RS_RD) == 0)
-		return 1;
+		return 0;
+
+	/* drbd_submit_ee currently fails for one reason only:
+	 * not being able to allocate enough bios.
+	 * Is dropping the connection going to help? */
+	spin_lock_irq(&mdev->req_lock);
+	list_del(&e->w.list);
+	spin_unlock_irq(&mdev->req_lock);
 
 	drbd_free_ee(mdev, e);
-fail:
+defer:
 	put_ldev(mdev);
-	return 2;
+	return -EAGAIN;
 }
 
 void resync_timer_fn(unsigned long data)
 {
-	unsigned long flags;
 	struct drbd_conf *mdev = (struct drbd_conf *) data;
 	int queue;
 
-	spin_lock_irqsave(&mdev->req_lock, flags);
-
-	if (likely(!test_and_clear_bit(STOP_SYNC_TIMER, &mdev->flags))) {
-		queue = 1;
-		if (mdev->state.conn == C_VERIFY_S)
-			mdev->resync_work.cb = w_make_ov_request;
-		else
-			mdev->resync_work.cb = w_make_resync_request;
-	} else {
+	queue = 1;
+	switch (mdev->state.conn) {
+	case C_VERIFY_S:
+		mdev->resync_work.cb = w_make_ov_request;
+		break;
+	case C_SYNC_TARGET:
+		mdev->resync_work.cb = w_make_resync_request;
+		break;
+	default:
 		queue = 0;
 		mdev->resync_work.cb = w_resync_inactive;
 	}
 
-	spin_unlock_irqrestore(&mdev->req_lock, flags);
-
 	/* harmless race: list_empty outside data.work.q_lock */
 	if (list_empty(&mdev->resync_work.list) && queue)
 		drbd_queue_work(&mdev->data.work, &mdev->resync_work);
 }
 
+static void fifo_set(struct fifo_buffer *fb, int value)
+{
+	int i;
+
+	for (i = 0; i < fb->size; i++)
+		fb->values[i] = value;
+}
+
+static int fifo_push(struct fifo_buffer *fb, int value)
+{
+	int ov;
+
+	ov = fb->values[fb->head_index];
+	fb->values[fb->head_index++] = value;
+
+	if (fb->head_index >= fb->size)
+		fb->head_index = 0;
+
+	return ov;
+}
+
+static void fifo_add_val(struct fifo_buffer *fb, int value)
+{
+	int i;
+
+	for (i = 0; i < fb->size; i++)
+		fb->values[i] += value;
+}
+
+int drbd_rs_controller(struct drbd_conf *mdev)
+{
+	unsigned int sect_in;  /* Number of sectors that came in since the last turn */
+	unsigned int want;     /* The number of sectors we want in the proxy */
+	int req_sect; /* Number of sectors to request in this turn */
+	int correction; /* Number of sectors more we need in the proxy*/
+	int cps; /* correction per invocation of drbd_rs_controller() */
+	int steps; /* Number of time steps to plan ahead */
+	int curr_corr;
+	int max_sect;
+
+	sect_in = atomic_xchg(&mdev->rs_sect_in, 0); /* Number of sectors that came in */
+	mdev->rs_in_flight -= sect_in;
+
+	spin_lock(&mdev->peer_seq_lock); /* get an atomic view on mdev->rs_plan_s */
+
+	steps = mdev->rs_plan_s.size; /* (mdev->sync_conf.c_plan_ahead * 10 * SLEEP_TIME) / HZ; */
+
+	if (mdev->rs_in_flight + sect_in == 0) { /* At start of resync */
+		want = ((mdev->sync_conf.rate * 2 * SLEEP_TIME) / HZ) * steps;
+	} else { /* normal path */
+		want = mdev->sync_conf.c_fill_target ? mdev->sync_conf.c_fill_target :
+			sect_in * mdev->sync_conf.c_delay_target * HZ / (SLEEP_TIME * 10);
+	}
+
+	correction = want - mdev->rs_in_flight - mdev->rs_planed;
+
+	/* Plan ahead */
+	cps = correction / steps;
+	fifo_add_val(&mdev->rs_plan_s, cps);
+	mdev->rs_planed += cps * steps;
+
+	/* What we do in this step */
+	curr_corr = fifo_push(&mdev->rs_plan_s, 0);
+	spin_unlock(&mdev->peer_seq_lock);
+	mdev->rs_planed -= curr_corr;
+
+	req_sect = sect_in + curr_corr;
+	if (req_sect < 0)
+		req_sect = 0;
+
+	max_sect = (mdev->sync_conf.c_max_rate * 2 * SLEEP_TIME) / HZ;
+	if (req_sect > max_sect)
+		req_sect = max_sect;
+
+	/*
+	dev_warn(DEV, "si=%u if=%d wa=%u co=%d st=%d cps=%d pl=%d cc=%d rs=%d\n",
+		 sect_in, mdev->rs_in_flight, want, correction,
+		 steps, cps, mdev->rs_planed, curr_corr, req_sect);
+	*/
+
+	return req_sect;
+}
+
 int w_make_resync_request(struct drbd_conf *mdev,
 		struct drbd_work *w, int cancel)
 {
@@ -431,8 +513,9 @@
 	sector_t sector;
 	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
 	int max_segment_size;
-	int number, i, size, pe, mx;
+	int number, rollback_i, size, pe, mx;
 	int align, queued, sndbuf;
+	int i = 0;
 
 	if (unlikely(cancel))
 		return 1;
@@ -446,6 +529,12 @@
 		dev_err(DEV, "%s in w_make_resync_request\n",
 			drbd_conn_str(mdev->state.conn));
 
+	if (mdev->rs_total == 0) {
+		/* empty resync? */
+		drbd_resync_finished(mdev);
+		return 1;
+	}
+
 	if (!get_ldev(mdev)) {
 		/* Since we only need to access mdev->rsync a
 		   get_ldev_if_state(mdev,D_FAILED) would be sufficient, but
@@ -458,11 +547,25 @@
 
 	/* starting with drbd 8.3.8, we can handle multi-bio EEs,
 	 * if it should be necessary */
-	max_segment_size = mdev->agreed_pro_version < 94 ?
-		queue_max_segment_size(mdev->rq_queue) : DRBD_MAX_SEGMENT_SIZE;
+	max_segment_size =
+		mdev->agreed_pro_version < 94 ? queue_max_segment_size(mdev->rq_queue) :
+		mdev->agreed_pro_version < 95 ?	DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_SEGMENT_SIZE;
 
-	number = SLEEP_TIME * mdev->sync_conf.rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
-	pe = atomic_read(&mdev->rs_pending_cnt);
+	if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */
+		number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
+		mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
+	} else {
+		mdev->c_sync_rate = mdev->sync_conf.rate;
+		number = SLEEP_TIME * mdev->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
+	}
+
+	/* Throttle resync on lower level disk activity, which may also be
+	 * caused by application IO on Primary/SyncTarget.
+	 * Keep this after the call to drbd_rs_controller, as that assumes
+	 * to be called as precisely as possible every SLEEP_TIME,
+	 * and would be confused otherwise. */
+	if (drbd_rs_should_slow_down(mdev))
+		goto requeue;
 
 	mutex_lock(&mdev->data.mutex);
 	if (mdev->data.socket)
@@ -476,6 +579,7 @@
 		mx = number;
 
 	/* Limit the number of pending RS requests to no more than the peer's receive buffer */
+	pe = atomic_read(&mdev->rs_pending_cnt);
 	if ((pe + number) > mx) {
 		number = mx - pe;
 	}
@@ -526,6 +630,7 @@
 		 * be prepared for all stripe sizes of software RAIDs.
 		 */
 		align = 1;
+		rollback_i = i;
 		for (;;) {
 			if (size + BM_BLOCK_SIZE > max_segment_size)
 				break;
@@ -561,14 +666,19 @@
 			size = (capacity-sector)<<9;
 		if (mdev->agreed_pro_version >= 89 && mdev->csums_tfm) {
 			switch (read_for_csum(mdev, sector, size)) {
-			case 0: /* Disk failure*/
+			case -EIO: /* Disk failure */
 				put_ldev(mdev);
 				return 0;
-			case 2: /* Allocation failed */
+			case -EAGAIN: /* allocation failed, or ldev busy */
 				drbd_rs_complete_io(mdev, sector);
 				mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
+				i = rollback_i;
 				goto requeue;
-			/* case 1: everything ok */
+			case 0:
+				/* everything ok */
+				break;
+			default:
+				BUG();
 			}
 		} else {
 			inc_rs_pending(mdev);
@@ -595,6 +705,7 @@
 	}
 
  requeue:
+	mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
 	mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
 	put_ldev(mdev);
 	return 1;
@@ -670,6 +781,14 @@
 	return 1;
 }
 
+static void ping_peer(struct drbd_conf *mdev)
+{
+	clear_bit(GOT_PING_ACK, &mdev->flags);
+	request_ping(mdev);
+	wait_event(mdev->misc_wait,
+		   test_bit(GOT_PING_ACK, &mdev->flags) || mdev->state.conn < C_CONNECTED);
+}
+
 int drbd_resync_finished(struct drbd_conf *mdev)
 {
 	unsigned long db, dt, dbdt;
@@ -709,6 +828,8 @@
 	if (!get_ldev(mdev))
 		goto out;
 
+	ping_peer(mdev);
+
 	spin_lock_irq(&mdev->req_lock);
 	os = mdev->state;
 
@@ -801,6 +922,8 @@
 	mdev->rs_paused = 0;
 	mdev->ov_start_sector = 0;
 
+	drbd_md_sync(mdev);
+
 	if (test_and_clear_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags)) {
 		dev_warn(DEV, "Writing the whole bitmap, due to failed kmalloc\n");
 		drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished");
@@ -817,9 +940,13 @@
 {
 	if (drbd_ee_has_active_page(e)) {
 		/* This might happen if sendpage() has not finished */
+		int i = (e->size + PAGE_SIZE -1) >> PAGE_SHIFT;
+		atomic_add(i, &mdev->pp_in_use_by_net);
+		atomic_sub(i, &mdev->pp_in_use);
 		spin_lock_irq(&mdev->req_lock);
 		list_add_tail(&e->w.list, &mdev->net_ee);
 		spin_unlock_irq(&mdev->req_lock);
+		wake_up(&drbd_pp_wait);
 	} else
 		drbd_free_ee(mdev, e);
 }
@@ -926,9 +1053,12 @@
 		return 1;
 	}
 
-	drbd_rs_complete_io(mdev, e->sector);
+	if (get_ldev(mdev)) {
+		drbd_rs_complete_io(mdev, e->sector);
+		put_ldev(mdev);
+	}
 
-	di = (struct digest_info *)(unsigned long)e->block_id;
+	di = e->digest;
 
 	if (likely((e->flags & EE_WAS_ERROR) == 0)) {
 		/* quick hack to try to avoid a race against reconfiguration.
@@ -952,7 +1082,9 @@
 			ok = drbd_send_ack(mdev, P_RS_IS_IN_SYNC, e);
 		} else {
 			inc_rs_pending(mdev);
-			e->block_id = ID_SYNCER;
+			e->block_id = ID_SYNCER; /* By setting block_id, digest pointer becomes invalid! */
+			e->flags &= ~EE_HAS_DIGEST; /* This e no longer has a digest pointer */
+			kfree(di);
 			ok = drbd_send_block(mdev, P_RS_DATA_REPLY, e);
 		}
 	} else {
@@ -962,9 +1094,6 @@
 	}
 
 	dec_unacked(mdev);
-
-	kfree(di);
-
 	move_to_net_ee_or_free(mdev, e);
 
 	if (unlikely(!ok))
@@ -1034,9 +1163,12 @@
 
 	/* after "cancel", because after drbd_disconnect/drbd_rs_cancel_all
 	 * the resync lru has been cleaned up already */
-	drbd_rs_complete_io(mdev, e->sector);
+	if (get_ldev(mdev)) {
+		drbd_rs_complete_io(mdev, e->sector);
+		put_ldev(mdev);
+	}
 
-	di = (struct digest_info *)(unsigned long)e->block_id;
+	di = e->digest;
 
 	if (likely((e->flags & EE_WAS_ERROR) == 0)) {
 		digest_size = crypto_hash_digestsize(mdev->verify_tfm);
@@ -1055,9 +1187,6 @@
 	}
 
 	dec_unacked(mdev);
-
-	kfree(di);
-
 	if (!eq)
 		drbd_ov_oos_found(mdev, e->sector, e->size);
 	else
@@ -1108,7 +1237,7 @@
 	 * dec_ap_pending will be done in got_BarrierAck
 	 * or (on connection loss) in w_clear_epoch.  */
 	ok = _drbd_send_cmd(mdev, mdev->data.socket, P_BARRIER,
-				(struct p_header *)p, sizeof(*p), 0);
+				(struct p_header80 *)p, sizeof(*p), 0);
 	drbd_put_data_sock(mdev);
 
 	return ok;
@@ -1173,6 +1302,24 @@
 	return ok;
 }
 
+int w_restart_disk_io(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+{
+	struct drbd_request *req = container_of(w, struct drbd_request, w);
+
+	if (bio_data_dir(req->master_bio) == WRITE && req->rq_state & RQ_IN_ACT_LOG)
+		drbd_al_begin_io(mdev, req->sector);
+	/* Calling drbd_al_begin_io() out of the worker might deadlocks
+	   theoretically. Practically it can not deadlock, since this is
+	   only used when unfreezing IOs. All the extents of the requests
+	   that made it into the TL are already active */
+
+	drbd_req_make_private_bio(req, req->master_bio);
+	req->private_bio->bi_bdev = mdev->ldev->backing_bdev;
+	generic_make_request(req->private_bio);
+
+	return 1;
+}
+
 static int _drbd_may_sync_now(struct drbd_conf *mdev)
 {
 	struct drbd_conf *odev = mdev;
@@ -1298,14 +1445,6 @@
 	return retcode;
 }
 
-static void ping_peer(struct drbd_conf *mdev)
-{
-	clear_bit(GOT_PING_ACK, &mdev->flags);
-	request_ping(mdev);
-	wait_event(mdev->misc_wait,
-		   test_bit(GOT_PING_ACK, &mdev->flags) || mdev->state.conn < C_CONNECTED);
-}
-
 /**
  * drbd_start_resync() - Start the resync process
  * @mdev:	DRBD device.
@@ -1379,13 +1518,21 @@
 		r = SS_UNKNOWN_ERROR;
 
 	if (r == SS_SUCCESS) {
-		mdev->rs_total     =
-		mdev->rs_mark_left = drbd_bm_total_weight(mdev);
+		unsigned long tw = drbd_bm_total_weight(mdev);
+		unsigned long now = jiffies;
+		int i;
+
 		mdev->rs_failed    = 0;
 		mdev->rs_paused    = 0;
-		mdev->rs_start     =
-		mdev->rs_mark_time = jiffies;
 		mdev->rs_same_csum = 0;
+		mdev->rs_last_events = 0;
+		mdev->rs_last_sect_ev = 0;
+		mdev->rs_total     = tw;
+		mdev->rs_start     = now;
+		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+			mdev->rs_mark_left[i] = tw;
+			mdev->rs_mark_time[i] = now;
+		}
 		_drbd_pause_after(mdev);
 	}
 	write_unlock_irq(&global_state_lock);
@@ -1397,12 +1544,31 @@
 		     (unsigned long) mdev->rs_total << (BM_BLOCK_SHIFT-10),
 		     (unsigned long) mdev->rs_total);
 
-		if (mdev->rs_total == 0) {
-			/* Peer still reachable? Beware of failing before-resync-target handlers! */
-			ping_peer(mdev);
+		if (mdev->agreed_pro_version < 95 && mdev->rs_total == 0) {
+			/* This still has a race (about when exactly the peers
+			 * detect connection loss) that can lead to a full sync
+			 * on next handshake. In 8.3.9 we fixed this with explicit
+			 * resync-finished notifications, but the fix
+			 * introduces a protocol change.  Sleeping for some
+			 * time longer than the ping interval + timeout on the
+			 * SyncSource, to give the SyncTarget the chance to
+			 * detect connection loss, then waiting for a ping
+			 * response (implicit in drbd_resync_finished) reduces
+			 * the race considerably, but does not solve it. */
+			if (side == C_SYNC_SOURCE)
+				schedule_timeout_interruptible(
+					mdev->net_conf->ping_int * HZ +
+					mdev->net_conf->ping_timeo*HZ/9);
 			drbd_resync_finished(mdev);
 		}
 
+		atomic_set(&mdev->rs_sect_in, 0);
+		atomic_set(&mdev->rs_sect_ev, 0);
+		mdev->rs_in_flight = 0;
+		mdev->rs_planed = 0;
+		spin_lock(&mdev->peer_seq_lock);
+		fifo_set(&mdev->rs_plan_s, 0);
+		spin_unlock(&mdev->peer_seq_lock);
 		/* ns.conn may already be != mdev->state.conn,
 		 * we may have been paused in between, or become paused until
 		 * the timer triggers.
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index cf04c1b..767107c 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -178,7 +178,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/bio.h>
-#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/jiffies.h>
 #include <linux/fcntl.h>
@@ -199,6 +198,7 @@
  * It's been recommended that take about 1/4 of the default speed
  * in some more extreme cases.
  */
+static DEFINE_MUTEX(floppy_mutex);
 static int slow_floppy;
 
 #include <asm/dma.h>
@@ -258,8 +258,8 @@
 #include <linux/completion.h>
 
 static struct request *current_req;
-static struct request_queue *floppy_queue;
 static void do_fd_request(struct request_queue *q);
+static int set_next_request(void);
 
 #ifndef fd_get_dma_residue
 #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
@@ -413,6 +413,7 @@
 static struct block_device *opened_bdev[N_DRIVE];
 static DEFINE_MUTEX(open_lock);
 static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
+static int fdc_queue;
 
 /*
  * This struct defines the different floppy types.
@@ -890,8 +891,8 @@
 	del_timer(&fd_timeout);
 	cont = NULL;
 	clear_bit(0, &fdc_busy);
-	if (current_req || blk_peek_request(floppy_queue))
-		do_fd_request(floppy_queue);
+	if (current_req || set_next_request())
+		do_fd_request(current_req->q);
 	spin_unlock_irqrestore(&floppy_lock, flags);
 	wake_up(&fdc_wait);
 }
@@ -2243,8 +2244,8 @@
  * logical buffer */
 static void request_done(int uptodate)
 {
-	struct request_queue *q = floppy_queue;
 	struct request *req = current_req;
+	struct request_queue *q;
 	unsigned long flags;
 	int block;
 	char msg[sizeof("request done ") + sizeof(int) * 3];
@@ -2258,6 +2259,8 @@
 		return;
 	}
 
+	q = req->q;
+
 	if (uptodate) {
 		/* maintain values for invalidation on geometry
 		 * change */
@@ -2811,6 +2814,28 @@
 	return 2;
 }
 
+/*
+ * Round-robin between our available drives, doing one request from each
+ */
+static int set_next_request(void)
+{
+	struct request_queue *q;
+	int old_pos = fdc_queue;
+
+	do {
+		q = disks[fdc_queue]->queue;
+		if (++fdc_queue == N_DRIVE)
+			fdc_queue = 0;
+		if (q) {
+			current_req = blk_fetch_request(q);
+			if (current_req)
+				break;
+		}
+	} while (fdc_queue != old_pos);
+
+	return current_req != NULL;
+}
+
 static void redo_fd_request(void)
 {
 	int drive;
@@ -2822,17 +2847,17 @@
 
 do_request:
 	if (!current_req) {
-		struct request *req;
+		int pending;
 
-		spin_lock_irq(floppy_queue->queue_lock);
-		req = blk_fetch_request(floppy_queue);
-		spin_unlock_irq(floppy_queue->queue_lock);
-		if (!req) {
+		spin_lock_irq(&floppy_lock);
+		pending = set_next_request();
+		spin_unlock_irq(&floppy_lock);
+
+		if (!pending) {
 			do_floppy = NULL;
 			unlock_fdc();
 			return;
 		}
-		current_req = req;
 	}
 	drive = (long)current_req->rq_disk->private_data;
 	set_fdc(drive);
@@ -3553,9 +3578,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&floppy_mutex);
 	ret = fd_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&floppy_mutex);
 
 	return ret;
 }
@@ -3616,7 +3641,7 @@
 {
 	int drive = (long)disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&floppy_mutex);
 	mutex_lock(&open_lock);
 	if (UDRS->fd_ref < 0)
 		UDRS->fd_ref = 0;
@@ -3627,7 +3652,7 @@
 	if (!UDRS->fd_ref)
 		opened_bdev[drive] = NULL;
 	mutex_unlock(&open_lock);
-	unlock_kernel();
+	mutex_unlock(&floppy_mutex);
 
 	return 0;
 }
@@ -3645,7 +3670,7 @@
 	int res = -EBUSY;
 	char *tmp;
 
-	lock_kernel();
+	mutex_lock(&floppy_mutex);
 	mutex_lock(&open_lock);
 	old_dev = UDRS->fd_device;
 	if (opened_bdev[drive] && opened_bdev[drive] != bdev)
@@ -3722,7 +3747,7 @@
 			goto out;
 	}
 	mutex_unlock(&open_lock);
-	unlock_kernel();
+	mutex_unlock(&floppy_mutex);
 	return 0;
 out:
 	if (UDRS->fd_ref < 0)
@@ -3733,7 +3758,7 @@
 		opened_bdev[drive] = NULL;
 out2:
 	mutex_unlock(&open_lock);
-	unlock_kernel();
+	mutex_unlock(&floppy_mutex);
 	return res;
 }
 
@@ -4165,6 +4190,13 @@
 			goto out_put_disk;
 		}
 
+		disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+		if (!disks[dr]->queue) {
+			err = -ENOMEM;
+			goto out_put_disk;
+		}
+
+		blk_queue_max_hw_sectors(disks[dr]->queue, 64);
 		disks[dr]->major = FLOPPY_MAJOR;
 		disks[dr]->first_minor = TOMINOR(dr);
 		disks[dr]->fops = &floppy_fops;
@@ -4183,13 +4215,6 @@
 	if (err)
 		goto out_unreg_blkdev;
 
-	floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
-	if (!floppy_queue) {
-		err = -ENOMEM;
-		goto out_unreg_driver;
-	}
-	blk_queue_max_hw_sectors(floppy_queue, 64);
-
 	blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
 			    floppy_find, NULL, NULL);
 
@@ -4317,7 +4342,6 @@
 
 		/* to be cleaned up... */
 		disks[drive]->private_data = (void *)(long)drive;
-		disks[drive]->queue = floppy_queue;
 		disks[drive]->flags |= GENHD_FL_REMOVABLE;
 		disks[drive]->driverfs_dev = &floppy_device[drive].dev;
 		add_disk(disks[drive]);
@@ -4333,8 +4357,6 @@
 		floppy_release_irq_and_dma();
 out_unreg_region:
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
-	blk_cleanup_queue(floppy_queue);
-out_unreg_driver:
 	platform_driver_unregister(&floppy_driver);
 out_unreg_blkdev:
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
@@ -4342,6 +4364,8 @@
 	while (dr--) {
 		del_timer(&motor_off_timer[dr]);
 		put_disk(disks[dr]);
+		if (disks[dr]->queue)
+			blk_cleanup_queue(disks[dr]->queue);
 	}
 	return err;
 }
@@ -4550,11 +4574,11 @@
 			platform_device_unregister(&floppy_device[drive]);
 		}
 		put_disk(disks[drive]);
+		blk_cleanup_queue(disks[drive]->queue);
 	}
 
 	del_timer_sync(&fd_timeout);
 	del_timer_sync(&fd_timer);
-	blk_cleanup_queue(floppy_queue);
 
 	if (atomic_read(&usage_count))
 		floppy_release_irq_and_dma();
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 91797bb..6c48b35 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -67,16 +67,18 @@
 #include <linux/compat.h>
 #include <linux/suspend.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>		/* for invalidate_bdev() */
 #include <linux/completion.h>
 #include <linux/highmem.h>
 #include <linux/kthread.h>
 #include <linux/splice.h>
+#include <linux/sysfs.h>
 
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(loop_mutex);
 static LIST_HEAD(loop_devices);
 static DEFINE_MUTEX(loop_devices_mutex);
 
@@ -477,17 +479,17 @@
 	pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
 
 	if (bio_rw(bio) == WRITE) {
-		bool barrier = !!(bio->bi_rw & REQ_HARDBARRIER);
 		struct file *file = lo->lo_backing_file;
 
-		if (barrier) {
-			if (unlikely(!file->f_op->fsync)) {
-				ret = -EOPNOTSUPP;
-				goto out;
-			}
+		/* REQ_HARDBARRIER is deprecated */
+		if (bio->bi_rw & REQ_HARDBARRIER) {
+			ret = -EOPNOTSUPP;
+			goto out;
+		}
 
+		if (bio->bi_rw & REQ_FLUSH) {
 			ret = vfs_fsync(file, 0);
-			if (unlikely(ret)) {
+			if (unlikely(ret && ret != -EINVAL)) {
 				ret = -EIO;
 				goto out;
 			}
@@ -495,9 +497,9 @@
 
 		ret = lo_send(lo, bio, pos);
 
-		if (barrier && !ret) {
+		if ((bio->bi_rw & REQ_FUA) && !ret) {
 			ret = vfs_fsync(file, 0);
-			if (unlikely(ret))
+			if (unlikely(ret && ret != -EINVAL))
 				ret = -EIO;
 		}
 	} else
@@ -737,6 +739,103 @@
 	return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
 }
 
+/* loop sysfs attributes */
+
+static ssize_t loop_attr_show(struct device *dev, char *page,
+			      ssize_t (*callback)(struct loop_device *, char *))
+{
+	struct loop_device *l, *lo = NULL;
+
+	mutex_lock(&loop_devices_mutex);
+	list_for_each_entry(l, &loop_devices, lo_list)
+		if (disk_to_dev(l->lo_disk) == dev) {
+			lo = l;
+			break;
+		}
+	mutex_unlock(&loop_devices_mutex);
+
+	return lo ? callback(lo, page) : -EIO;
+}
+
+#define LOOP_ATTR_RO(_name)						\
+static ssize_t loop_attr_##_name##_show(struct loop_device *, char *);	\
+static ssize_t loop_attr_do_show_##_name(struct device *d,		\
+				struct device_attribute *attr, char *b)	\
+{									\
+	return loop_attr_show(d, b, loop_attr_##_name##_show);		\
+}									\
+static struct device_attribute loop_attr_##_name =			\
+	__ATTR(_name, S_IRUGO, loop_attr_do_show_##_name, NULL);
+
+static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf)
+{
+	ssize_t ret;
+	char *p = NULL;
+
+	mutex_lock(&lo->lo_ctl_mutex);
+	if (lo->lo_backing_file)
+		p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1);
+	mutex_unlock(&lo->lo_ctl_mutex);
+
+	if (IS_ERR_OR_NULL(p))
+		ret = PTR_ERR(p);
+	else {
+		ret = strlen(p);
+		memmove(buf, p, ret);
+		buf[ret++] = '\n';
+		buf[ret] = 0;
+	}
+
+	return ret;
+}
+
+static ssize_t loop_attr_offset_show(struct loop_device *lo, char *buf)
+{
+	return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_offset);
+}
+
+static ssize_t loop_attr_sizelimit_show(struct loop_device *lo, char *buf)
+{
+	return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_sizelimit);
+}
+
+static ssize_t loop_attr_autoclear_show(struct loop_device *lo, char *buf)
+{
+	int autoclear = (lo->lo_flags & LO_FLAGS_AUTOCLEAR);
+
+	return sprintf(buf, "%s\n", autoclear ? "1" : "0");
+}
+
+LOOP_ATTR_RO(backing_file);
+LOOP_ATTR_RO(offset);
+LOOP_ATTR_RO(sizelimit);
+LOOP_ATTR_RO(autoclear);
+
+static struct attribute *loop_attrs[] = {
+	&loop_attr_backing_file.attr,
+	&loop_attr_offset.attr,
+	&loop_attr_sizelimit.attr,
+	&loop_attr_autoclear.attr,
+	NULL,
+};
+
+static struct attribute_group loop_attribute_group = {
+	.name = "loop",
+	.attrs= loop_attrs,
+};
+
+static int loop_sysfs_init(struct loop_device *lo)
+{
+	return sysfs_create_group(&disk_to_dev(lo->lo_disk)->kobj,
+				  &loop_attribute_group);
+}
+
+static void loop_sysfs_exit(struct loop_device *lo)
+{
+	sysfs_remove_group(&disk_to_dev(lo->lo_disk)->kobj,
+			   &loop_attribute_group);
+}
+
 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		       struct block_device *bdev, unsigned int arg)
 {
@@ -832,10 +931,11 @@
 	lo->lo_queue->unplug_fn = loop_unplug;
 
 	if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
-		blk_queue_ordered(lo->lo_queue, QUEUE_ORDERED_DRAIN);
+		blk_queue_flush(lo->lo_queue, REQ_FLUSH);
 
 	set_capacity(lo->lo_disk, size);
 	bd_set_size(bdev, size << 9);
+	loop_sysfs_init(lo);
 	/* let user-space know about the new size */
 	kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
 
@@ -854,6 +954,7 @@
 	return 0;
 
 out_clr:
+	loop_sysfs_exit(lo);
 	lo->lo_thread = NULL;
 	lo->lo_device = NULL;
 	lo->lo_backing_file = NULL;
@@ -950,6 +1051,7 @@
 	set_capacity(lo->lo_disk, 0);
 	if (bdev) {
 		bd_set_size(bdev, 0);
+		loop_sysfs_exit(lo);
 		/* let user-space know about this change */
 		kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
 	}
@@ -1409,11 +1511,11 @@
 {
 	struct loop_device *lo = bdev->bd_disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&loop_mutex);
 	mutex_lock(&lo->lo_ctl_mutex);
 	lo->lo_refcnt++;
 	mutex_unlock(&lo->lo_ctl_mutex);
-	unlock_kernel();
+	mutex_unlock(&loop_mutex);
 
 	return 0;
 }
@@ -1423,7 +1525,7 @@
 	struct loop_device *lo = disk->private_data;
 	int err;
 
-	lock_kernel();
+	mutex_lock(&loop_mutex);
 	mutex_lock(&lo->lo_ctl_mutex);
 
 	if (--lo->lo_refcnt)
@@ -1448,7 +1550,7 @@
 out:
 	mutex_unlock(&lo->lo_ctl_mutex);
 out_unlocked:
-	lock_kernel();
+	mutex_unlock(&loop_mutex);
 	return 0;
 }
 
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 0daa422..a32fb41 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -24,7 +24,7 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/ioctl.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compiler.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
@@ -53,6 +53,7 @@
 #define DBG_BLKDEV      0x0100
 #define DBG_RX          0x0200
 #define DBG_TX          0x0400
+static DEFINE_MUTEX(nbd_mutex);
 static unsigned int debugflags;
 #endif /* NDEBUG */
 
@@ -717,11 +718,11 @@
 	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
 			lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
 
-	lock_kernel();
+	mutex_lock(&nbd_mutex);
 	mutex_lock(&lo->tx_lock);
 	error = __nbd_ioctl(bdev, lo, cmd, arg);
 	mutex_unlock(&lo->tx_lock);
-	unlock_kernel();
+	mutex_unlock(&nbd_mutex);
 
 	return error;
 }
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
index 2284b4f..87311eb 100644
--- a/drivers/block/osdblk.c
+++ b/drivers/block/osdblk.c
@@ -310,8 +310,7 @@
 			break;
 
 		/* filter out block requests we don't understand */
-		if (rq->cmd_type != REQ_TYPE_FS &&
-		    !(rq->cmd_flags & REQ_HARDBARRIER)) {
+		if (rq->cmd_type != REQ_TYPE_FS) {
 			blk_end_request_all(rq, 0);
 			continue;
 		}
@@ -439,7 +438,7 @@
 	blk_queue_stack_limits(q, osd_request_queue(osdev->osd));
 
 	blk_queue_prep_rq(q, blk_queue_start_tag);
-	blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH);
+	blk_queue_flush(q, REQ_FLUSH);
 
 	disk->queue = q;
 
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 76f8565..62cec6a 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -138,9 +138,10 @@
 #include <linux/cdrom.h>
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(pcd_mutex);
 static DEFINE_SPINLOCK(pcd_lock);
 
 module_param(verbose, bool, 0644);
@@ -227,9 +228,9 @@
 	struct pcd_unit *cd = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pcd_mutex);
 	ret = cdrom_open(&cd->info, bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&pcd_mutex);
 
 	return ret;
 }
@@ -237,9 +238,9 @@
 static int pcd_block_release(struct gendisk *disk, fmode_t mode)
 {
 	struct pcd_unit *cd = disk->private_data;
-	lock_kernel();
+	mutex_lock(&pcd_mutex);
 	cdrom_release(&cd->info, mode);
-	unlock_kernel();
+	mutex_unlock(&pcd_mutex);
 	return 0;
 }
 
@@ -249,9 +250,9 @@
 	struct pcd_unit *cd = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pcd_mutex);
 	ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pcd_mutex);
 
 	return ret;
 }
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 985f0d4..c0ee155 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -153,10 +153,11 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/workqueue.h>
 
+static DEFINE_MUTEX(pd_mutex);
 static DEFINE_SPINLOCK(pd_lock);
 
 module_param(verbose, bool, 0);
@@ -736,14 +737,14 @@
 {
 	struct pd_unit *disk = bdev->bd_disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&pd_mutex);
 	disk->access++;
 
 	if (disk->removable) {
 		pd_special_command(disk, pd_media_check);
 		pd_special_command(disk, pd_door_lock);
 	}
-	unlock_kernel();
+	mutex_unlock(&pd_mutex);
 	return 0;
 }
 
@@ -771,10 +772,10 @@
 
 	switch (cmd) {
 	case CDROMEJECT:
-		lock_kernel();
+		mutex_lock(&pd_mutex);
 		if (disk->access == 1)
 			pd_special_command(disk, pd_eject);
-		unlock_kernel();
+		mutex_unlock(&pd_mutex);
 		return 0;
 	default:
 		return -EINVAL;
@@ -785,10 +786,10 @@
 {
 	struct pd_unit *disk = p->private_data;
 
-	lock_kernel();
+	mutex_lock(&pd_mutex);
 	if (!--disk->access && disk->removable)
 		pd_special_command(disk, pd_door_unlock);
-	unlock_kernel();
+	mutex_unlock(&pd_mutex);
 
 	return 0;
 }
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 4457b49..635f25d 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -152,9 +152,10 @@
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
+static DEFINE_MUTEX(pf_mutex);
 static DEFINE_SPINLOCK(pf_spin_lock);
 
 module_param(verbose, bool, 0644);
@@ -302,7 +303,7 @@
 	struct pf_unit *pf = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pf_mutex);
 	pf_identify(pf);
 
 	ret = -ENODEV;
@@ -318,7 +319,7 @@
 	if (pf->removable)
 		pf_lock(pf, 1);
 out:
-	unlock_kernel();
+	mutex_unlock(&pf_mutex);
 	return ret;
 }
 
@@ -349,9 +350,9 @@
 
 	if (pf->access != 1)
 		return -EBUSY;
-	lock_kernel();
+	mutex_lock(&pf_mutex);
 	pf_eject(pf);
-	unlock_kernel();
+	mutex_unlock(&pf_mutex);
 
 	return 0;
 }
@@ -360,9 +361,9 @@
 {
 	struct pf_unit *pf = disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&pf_mutex);
 	if (pf->access <= 0) {
-		unlock_kernel();
+		mutex_unlock(&pf_mutex);
 		return -EINVAL;
 	}
 
@@ -371,7 +372,7 @@
 	if (!pf->access && pf->removable)
 		pf_lock(pf, 0);
 
-	unlock_kernel();
+	mutex_unlock(&pf_mutex);
 	return 0;
 
 }
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index c397b3d..6b9a200 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -162,7 +162,7 @@
 #include <linux/pg.h>
 #include <linux/device.h>
 #include <linux/sched.h>	/* current, TASK_* */
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
@@ -193,6 +193,7 @@
 
 #define ATAPI_IDENTIFY		0x12
 
+static DEFINE_MUTEX(pg_mutex);
 static int pg_open(struct inode *inode, struct file *file);
 static int pg_release(struct inode *inode, struct file *file);
 static ssize_t pg_read(struct file *filp, char __user *buf,
@@ -234,6 +235,7 @@
 	.write = pg_write,
 	.open = pg_open,
 	.release = pg_release,
+	.llseek = noop_llseek,
 };
 
 static void pg_init_units(void)
@@ -518,7 +520,7 @@
 	struct pg *dev = &devices[unit];
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&pg_mutex);
 	if ((unit >= PG_UNITS) || (!dev->present)) {
 		ret = -ENODEV;
 		goto out;
@@ -547,7 +549,7 @@
 	file->private_data = dev;
 
 out:
-	unlock_kernel();
+	mutex_unlock(&pg_mutex);
 	return ret;
 }
 
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index bc5825f..7179f79 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -146,7 +146,7 @@
 #include <linux/mtio.h>
 #include <linux/device.h>
 #include <linux/sched.h>	/* current, TASK_*, schedule_timeout() */
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 
@@ -189,6 +189,7 @@
 #define ATAPI_MODE_SENSE	0x1a
 #define ATAPI_LOG_SENSE		0x4d
 
+static DEFINE_MUTEX(pt_mutex);
 static int pt_open(struct inode *inode, struct file *file);
 static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 static int pt_release(struct inode *inode, struct file *file);
@@ -239,6 +240,7 @@
 	.unlocked_ioctl = pt_ioctl,
 	.open = pt_open,
 	.release = pt_release,
+	.llseek = noop_llseek,
 };
 
 /* sysfs class support */
@@ -650,9 +652,9 @@
 	struct pt_unit *tape = pt + unit;
 	int err;
 
-	lock_kernel();
+	mutex_lock(&pt_mutex);
 	if (unit >= PT_UNITS || (!tape->present)) {
-		unlock_kernel();
+		mutex_unlock(&pt_mutex);
 		return -ENODEV;
 	}
 
@@ -681,12 +683,12 @@
 	}
 
 	file->private_data = tape;
-	unlock_kernel();
+	mutex_unlock(&pt_mutex);
 	return 0;
 
 out:
 	atomic_inc(&tape->available);
-	unlock_kernel();
+	mutex_unlock(&pt_mutex);
 	return err;
 }
 
@@ -704,15 +706,15 @@
 		switch (mtop.mt_op) {
 
 		case MTREW:
-			lock_kernel();
+			mutex_lock(&pt_mutex);
 			pt_rewind(tape);
-			unlock_kernel();
+			mutex_unlock(&pt_mutex);
 			return 0;
 
 		case MTWEOF:
-			lock_kernel();
+			mutex_lock(&pt_mutex);
 			pt_write_fm(tape);
-			unlock_kernel();
+			mutex_unlock(&pt_mutex);
 			return 0;
 
 		default:
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 37a2bb5..19b3568 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -57,7 +57,6 @@
 #include <linux/seq_file.h>
 #include <linux/miscdevice.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <scsi/scsi_cmnd.h>
@@ -86,6 +85,7 @@
 
 #define ZONE(sector, pd) (((sector) + (pd)->offset) & ~((pd)->settings.size - 1))
 
+static DEFINE_MUTEX(pktcdvd_mutex);
 static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
 static struct proc_dir_entry *pkt_proc;
 static int pktdev_major;
@@ -753,7 +753,6 @@
 
 	rq->timeout = 60*HZ;
 	rq->cmd_type = REQ_TYPE_BLOCK_PC;
-	rq->cmd_flags |= REQ_HARDBARRIER;
 	if (cgc->quiet)
 		rq->cmd_flags |= REQ_QUIET;
 
@@ -2383,7 +2382,7 @@
 
 	VPRINTK(DRIVER_NAME": entering open\n");
 
-	lock_kernel();
+	mutex_lock(&pktcdvd_mutex);
 	mutex_lock(&ctl_mutex);
 	pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev));
 	if (!pd) {
@@ -2411,7 +2410,7 @@
 	}
 
 	mutex_unlock(&ctl_mutex);
-	unlock_kernel();
+	mutex_unlock(&pktcdvd_mutex);
 	return 0;
 
 out_dec:
@@ -2419,7 +2418,7 @@
 out:
 	VPRINTK(DRIVER_NAME": failed open (%d)\n", ret);
 	mutex_unlock(&ctl_mutex);
-	unlock_kernel();
+	mutex_unlock(&pktcdvd_mutex);
 	return ret;
 }
 
@@ -2428,7 +2427,7 @@
 	struct pktcdvd_device *pd = disk->private_data;
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&pktcdvd_mutex);
 	mutex_lock(&ctl_mutex);
 	pd->refcnt--;
 	BUG_ON(pd->refcnt < 0);
@@ -2437,7 +2436,7 @@
 		pkt_release_dev(pd, flush);
 	}
 	mutex_unlock(&ctl_mutex);
-	unlock_kernel();
+	mutex_unlock(&pktcdvd_mutex);
 	return ret;
 }
 
@@ -2773,7 +2772,7 @@
 	VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd,
 		MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
 
-	lock_kernel();
+	mutex_lock(&pktcdvd_mutex);
 	switch (cmd) {
 	case CDROMEJECT:
 		/*
@@ -2798,7 +2797,7 @@
 		VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd);
 		ret = -ENOTTY;
 	}
-	unlock_kernel();
+	mutex_unlock(&pktcdvd_mutex);
 
 	return ret;
 }
@@ -3046,6 +3045,7 @@
 	.compat_ioctl	= pkt_ctl_compat_ioctl,
 #endif
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice pkt_misc = {
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index 03688c2..8e1ce2e 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -468,7 +468,7 @@
 	blk_queue_dma_alignment(queue, dev->blk_size-1);
 	blk_queue_logical_block_size(queue, dev->blk_size);
 
-	blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH);
+	blk_queue_flush(queue, REQ_FLUSH);
 
 	blk_queue_max_segments(queue, -1);
 	blk_queue_max_segment_size(queue, dev->bounce_size);
diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index 2e46815..75333d0 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -20,7 +20,7 @@
 #include <linux/fd.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/hdreg.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -222,6 +222,7 @@
 extern int swim_read_sector_data(struct swim __iomem *base,
 				 unsigned char *data);
 
+static DEFINE_MUTEX(swim_mutex);
 static inline void set_swim_mode(struct swim __iomem *base, int enable)
 {
 	struct iwm __iomem *iwm_base;
@@ -666,9 +667,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&swim_mutex);
 	ret = floppy_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&swim_mutex);
 
 	return ret;
 }
@@ -678,7 +679,7 @@
 	struct floppy_state *fs = disk->private_data;
 	struct swim __iomem *base = fs->swd->base;
 
-	lock_kernel();
+	mutex_lock(&swim_mutex);
 	if (fs->ref_count < 0)
 		fs->ref_count = 0;
 	else if (fs->ref_count > 0)
@@ -686,7 +687,7 @@
 
 	if (fs->ref_count == 0)
 		swim_motor(base, OFF);
-	unlock_kernel();
+	mutex_unlock(&swim_mutex);
 
 	return 0;
 }
@@ -704,9 +705,9 @@
 	case FDEJECT:
 		if (fs->ref_count != 1)
 			return -EBUSY;
-		lock_kernel();
+		mutex_lock(&swim_mutex);
 		err = floppy_eject(fs);
-		unlock_kernel();
+		mutex_unlock(&swim_mutex);
 		return err;
 
 	case FDGETPRM:
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index cc6a386..bf3a5b8 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -25,7 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
@@ -36,6 +36,7 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 
+static DEFINE_MUTEX(swim3_mutex);
 static struct request_queue *swim3_queue;
 static struct gendisk *disks[2];
 static struct request *fd_req;
@@ -873,9 +874,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&swim3_mutex);
 	ret = floppy_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&swim3_mutex);
 
 	return ret;
 }
@@ -953,9 +954,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&swim3_mutex);
 	ret = floppy_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&swim3_mutex);
 
 	return ret;
 }
@@ -964,13 +965,13 @@
 {
 	struct floppy_state *fs = disk->private_data;
 	struct swim3 __iomem *sw = fs->swim3;
-	lock_kernel();
+	mutex_lock(&swim3_mutex);
 	if (fs->ref_count > 0 && --fs->ref_count == 0) {
 		swim3_action(fs, MOTOR_OFF);
 		out_8(&sw->control_bic, 0xff);
 		swim3_select(fs, RELAX);
 	}
-	unlock_kernel();
+	mutex_unlock(&swim3_mutex);
 	return 0;
 }
 
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index c48e148..9ae3bb7 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -28,7 +28,7 @@
 #include <linux/timer.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <scsi/scsi.h>
 
 #define DRV_NAME "ub"
@@ -248,6 +248,7 @@
 	spinlock_t lock;
 };
 
+static DEFINE_MUTEX(ub_mutex);
 static inline void ub_init_completion(struct ub_completion *x)
 {
 	x->done = 0;
@@ -396,7 +397,7 @@
 #else
 
 static const struct usb_device_id ub_usb_ids[] = {
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
 	{ }
 };
 
@@ -1715,9 +1716,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ub_mutex);
 	ret = ub_bd_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&ub_mutex);
 
 	return ret;
 }
@@ -1730,9 +1731,9 @@
 	struct ub_lun *lun = disk->private_data;
 	struct ub_dev *sc = lun->udev;
 
-	lock_kernel();
+	mutex_lock(&ub_mutex);
 	ub_put(sc);
-	unlock_kernel();
+	mutex_unlock(&ub_mutex);
 
 	return 0;
 }
@@ -1747,9 +1748,9 @@
 	void __user *usermem = (void __user *) arg;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ub_mutex);
 	ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem);
-	unlock_kernel();
+	mutex_unlock(&ub_mutex);
 
 	return ret;
 }
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index f651e51..e2ff697 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -41,7 +41,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/dma-mapping.h>
 #include <linux/completion.h>
 #include <linux/device.h>
@@ -73,6 +73,7 @@
 	MAX_DISK_NAME = FIELD_SIZEOF(struct gendisk, disk_name)
 };
 
+static DEFINE_MUTEX(viodasd_mutex);
 static DEFINE_SPINLOCK(viodasd_spinlock);
 
 #define VIOMAXREQ		16
@@ -180,9 +181,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&viodasd_mutex);
 	ret = viodasd_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&viodasd_mutex);
 
 	return ret;
 }
@@ -196,7 +197,7 @@
 	struct viodasd_device *d = disk->private_data;
 	HvLpEvent_Rc hvrc;
 
-	lock_kernel();
+	mutex_lock(&viodasd_mutex);
 	/* Send the event to OS/400.  We DON'T expect a response */
 	hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
 			HvLpEvent_Type_VirtualIo,
@@ -210,7 +211,7 @@
 	if (hvrc != 0)
 		pr_warning("HV close call failed %d\n", (int)hvrc);
 
-	unlock_kernel();
+	mutex_unlock(&viodasd_mutex);
 
 	return 0;
 }
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 8320490..6ecf89c 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -127,9 +127,6 @@
 		}
 	}
 
-	if (vbr->req->cmd_flags & REQ_HARDBARRIER)
-		vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER;
-
 	sg_set_buf(&vblk->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
 
 	/*
@@ -379,31 +376,9 @@
 	vblk->disk->driverfs_dev = &vdev->dev;
 	index++;
 
-	if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) {
-		/*
-		 * If the FLUSH feature is supported we do have support for
-		 * flushing a volatile write cache on the host.  Use that
-		 * to implement write barrier support.
-		 */
-		blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH);
-	} else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) {
-		/*
-		 * If the BARRIER feature is supported the host expects us
-		 * to order request by tags.  This implies there is not
-		 * volatile write cache on the host, and that the host
-		 * never re-orders outstanding I/O.  This feature is not
-		 * useful for real life scenarious and deprecated.
-		 */
-		blk_queue_ordered(q, QUEUE_ORDERED_TAG);
-	} else {
-		/*
-		 * If the FLUSH feature is not supported we must assume that
-		 * the host does not perform any kind of volatile write
-		 * caching. We still need to drain the queue to provider
-		 * proper barrier semantics.
-		 */
-		blk_queue_ordered(q, QUEUE_ORDERED_DRAIN);
-	}
+	/* configure queue flush support */
+	if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
+		blk_queue_flush(q, REQ_FLUSH);
 
 	/* If disk is read-only in the host, the guest should obey */
 	if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
@@ -522,9 +497,9 @@
 };
 
 static unsigned int features[] = {
-	VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
-	VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
-	VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY
+	VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
+	VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
+	VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY
 };
 
 /*
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index d5a3cd7..4abd2bc 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -46,7 +46,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/blkpg.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -58,6 +58,7 @@
 
 #include "xd.h"
 
+static DEFINE_MUTEX(xd_mutex);
 static void __init do_xd_setup (int *integers);
 #ifdef MODULE
 static int xd[5] = { -1,-1,-1,-1, };
@@ -381,9 +382,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&xd_mutex);
 	ret = xd_locked_ioctl(bdev, mode, cmd, param);
-	unlock_kernel();
+	mutex_unlock(&xd_mutex);
 
 	return ret;
 }
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index ab735a6..4b33a18 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -41,7 +41,7 @@
 #include <linux/cdrom.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/scatterlist.h>
 
 #include <xen/xen.h>
@@ -69,6 +69,7 @@
 	unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
 
+static DEFINE_MUTEX(blkfront_mutex);
 static const struct block_device_operations xlvbd_block_fops;
 
 #define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
@@ -95,7 +96,7 @@
 	struct gnttab_free_callback callback;
 	struct blk_shadow shadow[BLK_RING_SIZE];
 	unsigned long shadow_free;
-	int feature_barrier;
+	unsigned int feature_flush;
 	int is_ready;
 };
 
@@ -418,26 +419,12 @@
 }
 
 
-static int xlvbd_barrier(struct blkfront_info *info)
+static void xlvbd_flush(struct blkfront_info *info)
 {
-	int err;
-	const char *barrier;
-
-	switch (info->feature_barrier) {
-	case QUEUE_ORDERED_DRAIN:	barrier = "enabled (drain)"; break;
-	case QUEUE_ORDERED_TAG:		barrier = "enabled (tag)"; break;
-	case QUEUE_ORDERED_NONE:	barrier = "disabled"; break;
-	default:			return -EINVAL;
-	}
-
-	err = blk_queue_ordered(info->rq, info->feature_barrier);
-
-	if (err)
-		return err;
-
+	blk_queue_flush(info->rq, info->feature_flush);
 	printk(KERN_INFO "blkfront: %s: barriers %s\n",
-	       info->gd->disk_name, barrier);
-	return 0;
+	       info->gd->disk_name,
+	       info->feature_flush ? "enabled" : "disabled");
 }
 
 
@@ -516,7 +503,7 @@
 	info->rq = gd->queue;
 	info->gd = gd;
 
-	xlvbd_barrier(info);
+	xlvbd_flush(info);
 
 	if (vdisk_info & VDISK_READONLY)
 		set_disk_ro(gd, 1);
@@ -662,8 +649,8 @@
 				printk(KERN_WARNING "blkfront: %s: write barrier op failed\n",
 				       info->gd->disk_name);
 				error = -EOPNOTSUPP;
-				info->feature_barrier = QUEUE_ORDERED_NONE;
-				xlvbd_barrier(info);
+				info->feature_flush = 0;
+				xlvbd_flush(info);
 			}
 			/* fall through */
 		case BLKIF_OP_READ:
@@ -1076,20 +1063,20 @@
 	/*
 	 * If there's no "feature-barrier" defined, then it means
 	 * we're dealing with a very old backend which writes
-	 * synchronously; draining will do what needs to get done.
+	 * synchronously; nothing to do.
 	 *
-	 * If there are barriers, then we can do full queued writes
-	 * with tagged barriers.
-	 *
-	 * If barriers are not supported, then there's no much we can
-	 * do, so just set ordering to NONE.
+	 * If there are barriers, then we use flush.
 	 */
-	if (err)
-		info->feature_barrier = QUEUE_ORDERED_DRAIN;
-	else if (barrier)
-		info->feature_barrier = QUEUE_ORDERED_TAG;
-	else
-		info->feature_barrier = QUEUE_ORDERED_NONE;
+	info->feature_flush = 0;
+
+	/*
+	 * The driver doesn't properly handled empty flushes, so
+	 * lets disable barrier support for now.
+	 */
+#if 0
+	if (!err && barrier)
+		info->feature_flush = REQ_FLUSH;
+#endif
 
 	err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
 	if (err) {
@@ -1201,7 +1188,7 @@
 	struct blkfront_info *info;
 	int err = 0;
 
-	lock_kernel();
+	mutex_lock(&blkfront_mutex);
 
 	info = disk->private_data;
 	if (!info) {
@@ -1219,7 +1206,7 @@
 	mutex_unlock(&info->mutex);
 
 out:
-	unlock_kernel();
+	mutex_unlock(&blkfront_mutex);
 	return err;
 }
 
@@ -1229,7 +1216,7 @@
 	struct block_device *bdev;
 	struct xenbus_device *xbdev;
 
-	lock_kernel();
+	mutex_lock(&blkfront_mutex);
 
 	bdev = bdget_disk(disk, 0);
 	bdput(bdev);
@@ -1263,7 +1250,7 @@
 	}
 
 out:
-	unlock_kernel();
+	mutex_unlock(&blkfront_mutex);
 	return 0;
 }
 
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 057413b..6e968cd 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -89,7 +89,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/ata.h>
 #include <linux/hdreg.h>
 #include <linux/platform_device.h>
@@ -214,6 +214,7 @@
 	u16 cf_id[ATA_ID_WORDS];
 };
 
+static DEFINE_MUTEX(xsysace_mutex);
 static int ace_major;
 
 /* ---------------------------------------------------------------------
@@ -903,13 +904,13 @@
 
 	dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
 
-	lock_kernel();
+	mutex_lock(&xsysace_mutex);
 	spin_lock_irqsave(&ace->lock, flags);
 	ace->users++;
 	spin_unlock_irqrestore(&ace->lock, flags);
 
 	check_disk_change(bdev);
-	unlock_kernel();
+	mutex_unlock(&xsysace_mutex);
 
 	return 0;
 }
@@ -922,7 +923,7 @@
 
 	dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1);
 
-	lock_kernel();
+	mutex_lock(&xsysace_mutex);
 	spin_lock_irqsave(&ace->lock, flags);
 	ace->users--;
 	if (ace->users == 0) {
@@ -930,7 +931,7 @@
 		ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ);
 	}
 	spin_unlock_irqrestore(&ace->lock, flags);
-	unlock_kernel();
+	mutex_unlock(&xsysace_mutex);
 	return 0;
 }
 
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index d75b2bb..dcd4cfc 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -33,7 +33,7 @@
 #include <linux/module.h>
 #include <linux/blkdev.h>
 #include <linux/bitops.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include <asm/setup.h>
@@ -57,6 +57,7 @@
 
 #define Z2RAM_CHUNK1024       ( Z2RAM_CHUNKSIZE >> 10 )
 
+static DEFINE_MUTEX(z2ram_mutex);
 static u_long *z2ram_map    = NULL;
 static u_long z2ram_size    = 0;
 static int z2_count         = 0;
@@ -154,7 +155,7 @@
 
     device = MINOR(bdev->bd_dev);
 
-    lock_kernel();
+    mutex_lock(&z2ram_mutex);
     if ( current_device != -1 && current_device != device )
     {
 	rc = -EBUSY;
@@ -296,25 +297,25 @@
 	set_capacity(z2ram_gendisk, z2ram_size >> 9);
     }
 
-    unlock_kernel();
+    mutex_unlock(&z2ram_mutex);
     return 0;
 
 err_out_kfree:
     kfree(z2ram_map);
 err_out:
-    unlock_kernel();
+    mutex_unlock(&z2ram_mutex);
     return rc;
 }
 
 static int
 z2_release(struct gendisk *disk, fmode_t mode)
 {
-    lock_kernel();
+    mutex_lock(&z2ram_mutex);
     if ( current_device == -1 ) {
-    	unlock_kernel();
+    	mutex_unlock(&z2ram_mutex);
     	return 0;
     }
-    unlock_kernel();
+    mutex_unlock(&z2ram_mutex);
     /*
      * FIXME: unmap memory
      */
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c
index 54739b0..fd6305b 100644
--- a/drivers/bluetooth/btmrvl_debugfs.c
+++ b/drivers/bluetooth/btmrvl_debugfs.c
@@ -92,6 +92,7 @@
 	.read	= btmrvl_hscfgcmd_read,
 	.write	= btmrvl_hscfgcmd_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
@@ -130,6 +131,7 @@
 	.read	= btmrvl_psmode_read,
 	.write	= btmrvl_psmode_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
@@ -173,6 +175,7 @@
 	.read = btmrvl_pscmd_read,
 	.write = btmrvl_pscmd_write,
 	.open = btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
@@ -211,6 +214,7 @@
 	.read	= btmrvl_gpiogap_read,
 	.write	= btmrvl_gpiogap_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
@@ -252,6 +256,7 @@
 	.read	= btmrvl_hscmd_read,
 	.write	= btmrvl_hscmd_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
@@ -289,6 +294,7 @@
 	.read	= btmrvl_hsmode_read,
 	.write	= btmrvl_hsmode_write,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
@@ -306,6 +312,7 @@
 static const struct file_operations btmrvl_curpsmode_fops = {
 	.read	= btmrvl_curpsmode_read,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
@@ -323,6 +330,7 @@
 static const struct file_operations btmrvl_psstate_fops = {
 	.read	= btmrvl_psstate_read,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
@@ -340,6 +348,7 @@
 static const struct file_operations btmrvl_hsstate_fops = {
 	.read	= btmrvl_hsstate_read,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
@@ -358,6 +367,7 @@
 static const struct file_operations btmrvl_txdnldready_fops = {
 	.read	= btmrvl_txdnldready_read,
 	.open	= btmrvl_open_generic,
+	.llseek = default_llseek,
 };
 
 void btmrvl_debugfs_init(struct hci_dev *hdev)
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 998833d..17361ba 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -256,9 +256,16 @@
 
 	BT_DBG("tty %p", tty);
 
+	/* FIXME: This btw is bogus, nothing requires the old ldisc to clear
+	   the pointer */
 	if (hu)
 		return -EEXIST;
 
+	/* Error if the tty has no write op instead of leaving an exploitable
+	   hole */
+	if (tty->ops->write == NULL)
+		return -EOPNOTSUPP;
+
 	if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
 		BT_ERR("Can't allocate control structure");
 		return -ENFILE;
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 3aa7b2a..67c180c 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -282,6 +282,7 @@
 	.poll		= vhci_poll,
 	.open		= vhci_open,
 	.release	= vhci_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice vhci_miscdev= {
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 261107d..3af6516 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -34,7 +34,7 @@
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
@@ -81,6 +81,7 @@
 
 #define GDROM_DEFAULT_TIMEOUT	(HZ * 7)
 
+static DEFINE_MUTEX(gdrom_mutex);
 static const struct {
 	int sense_key;
 	const char * const text;
@@ -494,17 +495,17 @@
 static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode)
 {
 	int ret;
-	lock_kernel();
+	mutex_lock(&gdrom_mutex);
 	ret = cdrom_open(gd.cd_info, bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&gdrom_mutex);
 	return ret;
 }
 
 static int gdrom_bdops_release(struct gendisk *disk, fmode_t mode)
 {
-	lock_kernel();
+	mutex_lock(&gdrom_mutex);
 	cdrom_release(gd.cd_info, mode);
-	unlock_kernel();
+	mutex_unlock(&gdrom_mutex);
 	return 0;
 }
 
@@ -518,9 +519,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&gdrom_mutex);
 	ret = cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&gdrom_mutex);
 
 	return ret;
 }
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 56bf9f4..be73a9b 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -42,7 +42,7 @@
 #include <linux/module.h>
 #include <linux/completion.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/seq_file.h>
 #include <linux/scatterlist.h>
 
@@ -61,6 +61,7 @@
  */
 #define VIOCD_MAX_CD	HVMAXARCHITECTEDVIRTUALCDROMS
 
+static DEFINE_MUTEX(viocd_mutex);
 static const struct vio_error_entry viocd_err_table[] = {
 	{0x0201, EINVAL, "Invalid Range"},
 	{0x0202, EINVAL, "Invalid Token"},
@@ -156,9 +157,9 @@
 	struct disk_info *di = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&viocd_mutex);
 	ret = cdrom_open(&di->viocd_info, bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&viocd_mutex);
 
 	return ret;
 }
@@ -166,9 +167,9 @@
 static int viocd_blk_release(struct gendisk *disk, fmode_t mode)
 {
 	struct disk_info *di = disk->private_data;
-	lock_kernel();
+	mutex_lock(&viocd_mutex);
 	cdrom_release(&di->viocd_info, mode);
-	unlock_kernel();
+	mutex_unlock(&viocd_mutex);
 	return 0;
 }
 
@@ -178,9 +179,9 @@
 	struct disk_info *di = bdev->bd_disk->private_data;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&viocd_mutex);
 	ret = cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&viocd_mutex);
 
 	return ret;
 }
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3d44ec7..43d3395 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -493,6 +493,21 @@
 	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
 	  architectures and 24 bytes on 64-bit architectures.
 
+config TTY_PRINTK
+	bool "TTY driver to output user messages via printk"
+	depends on EMBEDDED
+	default n
+	---help---
+	  If you say Y here, the support for writing user messages (i.e.
+	  console messages) via printk is available.
+
+	  The feature is useful to inline user messages with kernel
+	  messages.
+	  In order to use this feature, you should output user messages
+	  to /dev/ttyprintk or redirect console to this TTY.
+
+	  If unsure, say N.
+
 config BRIQ_PANEL
 	tristate 'Total Impact briQ front panel driver'
 	depends on PPC_CHRP
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index dc96416..3a9c014 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -12,6 +12,7 @@
 obj-y				+= tty_mutex.o
 obj-$(CONFIG_LEGACY_PTYS)	+= pty.o
 obj-$(CONFIG_UNIX98_PTYS)	+= pty.o
+obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
 obj-$(CONFIG_VT)		+= vt_ioctl.o vc_screen.o selection.o keyboard.o
 obj-$(CONFIG_BFIN_JTAG_COMM)	+= bfin_jtag_comm.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index a11c8c9..b0a7046 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1263,6 +1263,36 @@
 	return 0;
 }
 
+/*
+ * 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.
+ */
+static int rs_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct async_struct *info = tty->driver_data;
+	struct async_icount cnow;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	cnow = info->state->icount;
+	local_irq_restore(flags);
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
 
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
@@ -1332,31 +1362,6 @@
 			}
 			/* 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:
-			local_irq_save(flags);
-			cnow = info->state->icount;
-			local_irq_restore(flags);
-			icount.cts = cnow.cts;
-			icount.dsr = cnow.dsr;
-			icount.rng = cnow.rng;
-			icount.dcd = cnow.dcd;
-			icount.rx = cnow.rx;
-			icount.tx = cnow.tx;
-			icount.frame = cnow.frame;
-			icount.overrun = cnow.overrun;
-			icount.parity = cnow.parity;
-			icount.brk = cnow.brk;
-			icount.buf_overrun = cnow.buf_overrun;
-
-			if (copy_to_user(argp, &icount, sizeof(icount)))
-				return -EFAULT;
-			return 0;
 		case TIOCSERGWILD:
 		case TIOCSERSWILD:
 			/* "setserial -W" is called in Debian boot */
@@ -1958,6 +1963,7 @@
 	.wait_until_sent = rs_wait_until_sent,
 	.tiocmget = rs_tiocmget,
 	.tiocmset = rs_tiocmset,
+	.get_icount = rs_get_icount,
 	.proc_fops = &rs_proc_fops,
 };
 
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 033e150..3022801 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/miscdevice.h>
@@ -126,6 +126,7 @@
 /*
  * Local variables
  */
+static DEFINE_MUTEX(apm_mutex);
 static atomic_t suspend_acks_pending = ATOMIC_INIT(0);
 static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0);
 static int apm_disabled;
@@ -274,7 +275,7 @@
 	if (!as->suser || !as->writer)
 		return -EPERM;
 
-	lock_kernel();
+	mutex_lock(&apm_mutex);
 	switch (cmd) {
 	case APM_IOC_SUSPEND:
 		mutex_lock(&state_lock);
@@ -335,7 +336,7 @@
 		mutex_unlock(&state_lock);
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&apm_mutex);
 
 	return err;
 }
@@ -370,7 +371,7 @@
 {
 	struct apm_user *as;
 
-	lock_kernel();
+	mutex_lock(&apm_mutex);
 	as = kzalloc(sizeof(*as), GFP_KERNEL);
 	if (as) {
 		/*
@@ -390,7 +391,7 @@
 
 		filp->private_data = as;
 	}
-	unlock_kernel();
+	mutex_unlock(&apm_mutex);
 
 	return as ? 0 : -ENOMEM;
 }
@@ -402,6 +403,7 @@
 	.unlocked_ioctl	= apm_ioctl,
 	.open		= apm_open,
 	.release	= apm_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice apm_device = {
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index f4ae0e0..e7ba774 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -26,7 +26,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/wait.h>
@@ -60,6 +60,7 @@
 #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB     0x0003
 #endif
 
+static DEFINE_MUTEX(ac_mutex);
 static char *applicom_pci_devnames[] = {
 	"PCI board",
 	"PCI2000IBS / PCI2000CAN",
@@ -707,7 +708,7 @@
 	if (IS_ERR(adgl))
 		return PTR_ERR(adgl);
 
-	lock_kernel();	
+	mutex_lock(&ac_mutex);	
 	IndexCard = adgl->num_card-1;
 	 
 	if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
@@ -717,7 +718,7 @@
 			warncount--;
 		}
 		kfree(adgl);
-		unlock_kernel();
+		mutex_unlock(&ac_mutex);
 		return -EINVAL;
 	}
 
@@ -835,7 +836,7 @@
 	}
 	Dummy = readb(apbs[IndexCard].RamIO + VERS);
 	kfree(adgl);
-	unlock_kernel();
+	mutex_unlock(&ac_mutex);
 	return 0;
 }
 
diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
index 836d4f0..44660f1 100644
--- a/drivers/char/bfin-otp.c
+++ b/drivers/char/bfin-otp.c
@@ -222,6 +222,7 @@
 	.unlocked_ioctl = bfin_otp_ioctl,
 	.read           = bfin_otp_read,
 	.write          = bfin_otp_write,
+	.llseek		= default_llseek,
 };
 
 static struct miscdevice bfin_otp_misc_device = {
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index d5fa113..f6718f0 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -186,6 +186,7 @@
 	.write		= briq_panel_write,
 	.open		= briq_panel_open,
 	.release	= briq_panel_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice briq_panel_miscdev = {
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 9191713..a4a6c2f 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -155,6 +155,7 @@
 	.owner = THIS_MODULE,
 	.mmap  = bsr_mmap,
 	.open  = bsr_open,
+	.llseek = noop_llseek,
 };
 
 static void bsr_cleanup_devs(void)
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
index 4d830dc..0cf1e5f 100644
--- a/drivers/char/cs5535_gpio.c
+++ b/drivers/char/cs5535_gpio.c
@@ -169,7 +169,8 @@
 	.owner	= THIS_MODULE,
 	.write	= cs5535_gpio_write,
 	.read	= cs5535_gpio_read,
-	.open	= cs5535_gpio_open
+	.open	= cs5535_gpio_open,
+	.llseek = no_llseek,
 };
 
 static int __init cs5535_gpio_init(void)
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 27aad94..4f152c2 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2790,29 +2790,6 @@
 		 * NB: both 1->0 and 0->1 transitions are counted except for
 		 *     RI where only 0->1 is counted.
 		 */
-	case TIOCGICOUNT: {
-		struct serial_icounter_struct sic = { };
-
-		spin_lock_irqsave(&info->card->card_lock, flags);
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->card->card_lock, flags);
-
-		sic.cts = cnow.cts;
-		sic.dsr = cnow.dsr;
-		sic.rng = cnow.rng;
-		sic.dcd = cnow.dcd;
-		sic.rx = cnow.rx;
-		sic.tx = cnow.tx;
-		sic.frame = cnow.frame;
-		sic.overrun = cnow.overrun;
-		sic.parity = cnow.parity;
-		sic.brk = cnow.brk;
-		sic.buf_overrun = cnow.buf_overrun;
-
-		if (copy_to_user(argp, &sic, sizeof(sic)))
-			ret_val = -EFAULT;
-		break;
-	}
 	default:
 		ret_val = -ENOIOCTLCMD;
 	}
@@ -2823,6 +2800,31 @@
 	return ret_val;
 }				/* cy_ioctl */
 
+static int cy_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *sic)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_icount cnow;	/* Used to snapshot */
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->card->card_lock, flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->card->card_lock, flags);
+
+	sic->cts = cnow.cts;
+	sic->dsr = cnow.dsr;
+	sic->rng = cnow.rng;
+	sic->dcd = cnow.dcd;
+	sic->rx = cnow.rx;
+	sic->tx = cnow.tx;
+	sic->frame = cnow.frame;
+	sic->overrun = cnow.overrun;
+	sic->parity = cnow.parity;
+	sic->brk = cnow.brk;
+	sic->buf_overrun = cnow.buf_overrun;
+	return 0;
+}
+
 /*
  * This routine allows the tty driver to be notified when
  * device's termios settings have changed.  Note that a
@@ -4084,6 +4086,7 @@
 	.wait_until_sent = cy_wait_until_sent,
 	.tiocmget = cy_tiocmget,
 	.tiocmset = cy_tiocmset,
+	.get_icount = cy_get_icount,
 	.proc_fops = &cyclades_proc_fops,
 };
 
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c
index 170693c..ed8303f9 100644
--- a/drivers/char/ds1302.c
+++ b/drivers/char/ds1302.c
@@ -20,7 +20,7 @@
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
 #include <linux/bcd.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
@@ -32,6 +32,7 @@
 
 #define RTC_MAJOR_NR 121 /* local major, change later */
 
+static DEFINE_MUTEX(rtc_mutex);
 static const char ds1302_name[] = "ds1302";
 
 /* Send 8 bits. */
@@ -164,9 +165,9 @@
 			struct rtc_time rtc_tm;
 
 			memset(&rtc_tm, 0, sizeof (struct rtc_time));
-			lock_kernel();
+			mutex_lock(&rtc_mutex);
 			get_rtc_time(&rtc_tm);
-			unlock_kernel();
+			mutex_unlock(&rtc_mutex);
 			if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
 				return -EFAULT;
 			return 0;
@@ -218,7 +219,7 @@
 			mon = bin2bcd(mon);
 			yrs = bin2bcd(yrs);
 
-			lock_kernel();
+			mutex_lock(&rtc_mutex);
 			local_irq_save(flags);
 			CMOS_WRITE(yrs, RTC_YEAR);
 			CMOS_WRITE(mon, RTC_MONTH);
@@ -227,7 +228,7 @@
 			CMOS_WRITE(min, RTC_MINUTES);
 			CMOS_WRITE(sec, RTC_SECONDS);
 			local_irq_restore(flags);
-			unlock_kernel();
+			mutex_unlock(&rtc_mutex);
 
 			/* Notice that at this point, the RTC is updated but
 			 * the kernel is still running with the old time.
@@ -247,10 +248,10 @@
 			if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
 				return -EFAULT;
 
-			lock_kernel();
+			mutex_lock(&rtc_mutex);
 			tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
 			ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
-			unlock_kernel();
+			mutex_unlock(&rtc_mutex);
 			return 0;
 		}
 		default:
@@ -288,6 +289,7 @@
 static const struct file_operations rtc_fops = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= rtc_ioctl,
+	.llseek		= noop_llseek,
 };
 
 /* Probe for the chip by writing something to its RAM and try reading it back. */
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index dbee868..aab9605 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -8,7 +8,7 @@
 #include <linux/proc_fs.h>
 #include <linux/capability.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -34,6 +34,7 @@
 #define CFG_CPU			2
 #define CFG_1SHOT		1
 
+static DEFINE_MUTEX(ds1620_mutex);
 static const char *fan_state[] = { "off", "on", "on (hardwired)" };
 
 /*
@@ -210,7 +211,6 @@
 
 static int ds1620_open(struct inode *inode, struct file *file)
 {
-	cycle_kernel_lock();
 	return nonseekable_open(inode, file);
 }
 
@@ -321,9 +321,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ds1620_mutex);
 	ret = ds1620_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ds1620_mutex);
 
 	return ret;
 }
@@ -357,6 +357,7 @@
 	.open		= ds1620_open,
 	.read		= ds1620_read,
 	.unlocked_ioctl	= ds1620_unlocked_ioctl,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice ds1620_miscdev = {
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 8a1b28a..052797b 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -32,7 +32,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>	/* For put_user and get_user */
@@ -94,6 +94,7 @@
 	} \
 }
 
+static DEFINE_MUTEX(dsp56k_mutex);
 static struct dsp56k_device {
 	unsigned long in_use;
 	long maxio, timeout;
@@ -330,9 +331,9 @@
 			if (len > DSP56K_MAX_BINARY_LENGTH) {
 				return -EINVAL;
 			}
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			r = dsp56k_upload(bin, len);
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			if (r < 0) {
 				return r;
 			}
@@ -342,16 +343,16 @@
 		case DSP56K_SET_TX_WSIZE:
 			if (arg > 4 || arg < 1)
 				return -EINVAL;
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			dsp56k.tx_wsize = (int) arg;
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			break;
 		case DSP56K_SET_RX_WSIZE:
 			if (arg > 4 || arg < 1)
 				return -EINVAL;
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			dsp56k.rx_wsize = (int) arg;
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			break;
 		case DSP56K_HOST_FLAGS:
 		{
@@ -363,7 +364,7 @@
 			if(get_user(out, &hf->out) < 0)
 				return -EFAULT;
 
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			if ((dir & 0x1) && (out & 0x1))
 				dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
 			else if (dir & 0x1)
@@ -378,16 +379,16 @@
 			if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2;
 			if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4;
 			if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8;
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			return put_user(status, &hf->status);
 		}
 		case DSP56K_HOST_CMD:
 			if (arg > 31 || arg < 0)
 				return -EINVAL;
-			lock_kernel();
+			mutex_lock(&dsp56k_mutex);
 			dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
 							     DSP56K_CVR_HC);
-			unlock_kernel();
+			mutex_unlock(&dsp56k_mutex);
 			break;
 		default:
 			return -EINVAL;
@@ -427,7 +428,7 @@
 	int dev = iminor(inode) & 0x0f;
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&dsp56k_mutex);
 	switch(dev)
 	{
 	case DSP56K_DEV_56001:
@@ -454,7 +455,7 @@
 		ret = -ENODEV;
 	}
 out:
-	unlock_kernel();
+	mutex_unlock(&dsp56k_mutex);
 	return ret;
 }
 
@@ -482,6 +483,7 @@
 	.unlocked_ioctl	= dsp56k_ioctl,
 	.open		= dsp56k_open,
 	.release	= dsp56k_release,
+	.llseek		= noop_llseek,
 };
 
 
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index e3859d4..85156dd 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -57,7 +57,7 @@
 #include <linux/ioport.h>	/* for request_region */
 #include <linux/delay.h>	/* for loops_per_jiffy */
 #include <linux/sched.h>
-#include <linux/smp_lock.h>	/* cycle_kernel_lock() */
+#include <linux/mutex.h>
 #include <asm/io.h>		/* for inb_p, outb_p, inb, outb, etc. */
 #include <asm/uaccess.h>	/* for get_user, etc. */
 #include <linux/wait.h>		/* for wait_queue */
@@ -73,6 +73,7 @@
 #define TRACE_RET ((void) 0)
 #endif				/* TRACING */
 
+static DEFINE_MUTEX(dtlk_mutex);
 static void dtlk_timer_tick(unsigned long data);
 
 static int dtlk_major;
@@ -105,6 +106,7 @@
 	.unlocked_ioctl	= dtlk_ioctl,
 	.open		= dtlk_open,
 	.release	= dtlk_release,
+	.llseek		= no_llseek,
 };
 
 /* local prototypes */
@@ -275,9 +277,9 @@
 	switch (cmd) {
 
 	case DTLK_INTERROGATE:
-		lock_kernel();
+		mutex_lock(&dtlk_mutex);
 		sp = dtlk_interrogate();
-		unlock_kernel();
+		mutex_unlock(&dtlk_mutex);
 		if (copy_to_user(argp, sp, sizeof(struct dtlk_settings)))
 			return -EINVAL;
 		return 0;
@@ -296,7 +298,6 @@
 {
 	TRACE_TEXT("(dtlk_open");
 
-	cycle_kernel_lock();
 	nonseekable_open(inode, file);
 	switch (iminor(inode)) {
 	case DTLK_MINOR:
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 82b5a88..0e941b5 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -19,7 +19,7 @@
 #include <linux/miscdevice.h>
 #include <linux/fcntl.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #ifdef CONFIG_PPC_PMAC
@@ -28,6 +28,7 @@
 
 #define NVRAM_SIZE	8192
 
+static DEFINE_MUTEX(nvram_mutex);
 static ssize_t nvram_len;
 
 static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
@@ -120,9 +121,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&nvram_mutex);
 	ret = nvram_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&nvram_mutex);
 
 	return ret;
 }
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index b6c2cc1..f773a9d 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -52,7 +52,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
@@ -66,6 +66,7 @@
  *	ioctls.
  */
 
+static DEFINE_MUTEX(gen_rtc_mutex);
 static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
 
 /*
@@ -337,9 +338,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&gen_rtc_mutex);
 	ret = gen_rtc_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&gen_rtc_mutex);
 
 	return ret;
 }
@@ -352,16 +353,16 @@
 
 static int gen_rtc_open(struct inode *inode, struct file *file)
 {
-	lock_kernel();
+	mutex_lock(&gen_rtc_mutex);
 	if (gen_rtc_status & RTC_IS_OPEN) {
-		unlock_kernel();
+		mutex_unlock(&gen_rtc_mutex);
 		return -EBUSY;
 	}
 
 	gen_rtc_status |= RTC_IS_OPEN;
 	gen_rtc_irq_data = 0;
 	irq_active = 0;
-	unlock_kernel();
+	mutex_unlock(&gen_rtc_mutex);
 
 	return 0;
 }
@@ -497,6 +498,7 @@
 	.unlocked_ioctl	= gen_rtc_unlocked_ioctl,
 	.open		= gen_rtc_open,
 	.release	= gen_rtc_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice rtc_gen_dev =
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index a0a1829..a4eee32 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -30,6 +30,7 @@
 #include <linux/bcd.h>
 #include <linux/seq_file.h>
 #include <linux/bitops.h>
+#include <linux/compat.h>
 #include <linux/clocksource.h>
 #include <linux/slab.h>
 
@@ -67,6 +68,7 @@
 #define	read_counter(MC)	readl(MC)
 #endif
 
+static DEFINE_MUTEX(hpet_mutex); /* replaces BKL */
 static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
 
 /* This clocksource driver currently only works on ia64 */
@@ -250,7 +252,7 @@
 	if (file->f_mode & FMODE_WRITE)
 		return -EINVAL;
 
-	lock_kernel();
+	mutex_lock(&hpet_mutex);
 	spin_lock_irq(&hpet_lock);
 
 	for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
@@ -264,7 +266,7 @@
 
 	if (!devp) {
 		spin_unlock_irq(&hpet_lock);
-		unlock_kernel();
+		mutex_unlock(&hpet_mutex);
 		return -EBUSY;
 	}
 
@@ -272,7 +274,7 @@
 	devp->hd_irqdata = 0;
 	devp->hd_flags |= HPET_OPEN;
 	spin_unlock_irq(&hpet_lock);
-	unlock_kernel();
+	mutex_unlock(&hpet_mutex);
 
 	hpet_timer_set_irq(devp);
 
@@ -429,22 +431,6 @@
 	return 0;
 }
 
-static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int);
-
-static long hpet_ioctl(struct file *file, unsigned int cmd,
-			unsigned long arg)
-{
-	struct hpet_dev *devp;
-	int ret;
-
-	devp = file->private_data;
-	lock_kernel();
-	ret = hpet_ioctl_common(devp, cmd, arg, 0);
-	unlock_kernel();
-
-	return ret;
-}
-
 static int hpet_ioctl_ieon(struct hpet_dev *devp)
 {
 	struct hpet_timer __iomem *timer;
@@ -553,7 +539,8 @@
 }
 
 static int
-hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
+hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg,
+		  struct hpet_info *info)
 {
 	struct hpet_timer __iomem *timer;
 	struct hpet __iomem *hpet;
@@ -594,23 +581,15 @@
 		break;
 	case HPET_INFO:
 		{
-			struct hpet_info info;
-
 			if (devp->hd_ireqfreq)
-				info.hi_ireqfreq =
+				info->hi_ireqfreq =
 					hpet_time_div(hpetp, devp->hd_ireqfreq);
 			else
-				info.hi_ireqfreq = 0;
-			info.hi_flags =
+				info->hi_ireqfreq = 0;
+			info->hi_flags =
 			    readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
-			info.hi_hpet = hpetp->hp_which;
-			info.hi_timer = devp - hpetp->hp_dev;
-			if (kernel)
-				memcpy((void *)arg, &info, sizeof(info));
-			else
-				if (copy_to_user((void __user *)arg, &info,
-						 sizeof(info)))
-					err = -EFAULT;
+			info->hi_hpet = hpetp->hp_which;
+			info->hi_timer = devp - hpetp->hp_dev;
 			break;
 		}
 	case HPET_EPI:
@@ -636,7 +615,7 @@
 		devp->hd_flags &= ~HPET_PERIODIC;
 		break;
 	case HPET_IRQFREQ:
-		if (!kernel && (arg > hpet_max_freq) &&
+		if ((arg > hpet_max_freq) &&
 		    !capable(CAP_SYS_RESOURCE)) {
 			err = -EACCES;
 			break;
@@ -653,12 +632,63 @@
 	return err;
 }
 
+static long
+hpet_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct hpet_info info;
+	int err;
+
+	mutex_lock(&hpet_mutex);
+	err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+	mutex_unlock(&hpet_mutex);
+
+	if ((cmd == HPET_INFO) && !err &&
+	    (copy_to_user((void __user *)arg, &info, sizeof(info))))
+		err = -EFAULT;
+
+	return err;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_hpet_info {
+	compat_ulong_t hi_ireqfreq;	/* Hz */
+	compat_ulong_t hi_flags;	/* information */
+	unsigned short hi_hpet;
+	unsigned short hi_timer;
+};
+
+static long
+hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct hpet_info info;
+	int err;
+
+	mutex_lock(&hpet_mutex);
+	err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+	mutex_unlock(&hpet_mutex);
+
+	if ((cmd == HPET_INFO) && !err) {
+		struct compat_hpet_info __user *u = compat_ptr(arg);
+		if (put_user(info.hi_ireqfreq, &u->hi_ireqfreq) ||
+		    put_user(info.hi_flags, &u->hi_flags) ||
+		    put_user(info.hi_hpet, &u->hi_hpet) ||
+		    put_user(info.hi_timer, &u->hi_timer))
+			err = -EFAULT;
+	}
+
+	return err;
+}
+#endif
+
 static const struct file_operations hpet_fops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 	.read = hpet_read,
 	.poll = hpet_poll,
 	.unlocked_ioctl = hpet_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = hpet_compat_ioctl,
+#endif
 	.open = hpet_open,
 	.release = hpet_release,
 	.fasync = hpet_fasync,
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 3d9c61e..788da05 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -170,6 +170,7 @@
 	.owner		= THIS_MODULE,
 	.open		= rng_dev_open,
 	.read		= rng_dev_read,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice rng_miscdev = {
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index 4cd8b22..3bc0eef 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -23,7 +23,7 @@
 #include <linux/seq_file.h>
 #include <linux/dmi.h>
 #include <linux/capability.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
@@ -56,6 +56,7 @@
 
 #define I8K_TEMPERATURE_BUG	1
 
+static DEFINE_MUTEX(i8k_mutex);
 static char bios_version[4];
 
 MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
@@ -399,9 +400,9 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&i8k_mutex);
 	ret = i8k_ioctl_unlocked(fp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&i8k_mutex);
 
 	return ret;
 }
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index d4b71e8..fcd02ba 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -98,7 +98,7 @@
 #include <linux/major.h>
 #include <linux/wait.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 
@@ -138,6 +138,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
+static DEFINE_MUTEX(ip2_mutex);
 static const struct file_operations ip2mem_proc_fops;
 static const struct file_operations ip2_proc_fops;
 
@@ -183,6 +184,8 @@
 static int  ip2_tiocmget(struct tty_struct *tty, struct file *file);
 static int  ip2_tiocmset(struct tty_struct *tty, struct file *file,
 			 unsigned int set, unsigned int clear);
+static int ip2_get_icount(struct tty_struct *tty,
+		struct serial_icounter_struct *icount);
 
 static void set_irq(int, int);
 static void ip2_interrupt_bh(struct work_struct *work);
@@ -236,6 +239,7 @@
 	.write		= ip2_ipl_write,
 	.unlocked_ioctl	= ip2_ipl_ioctl,
 	.open		= ip2_ipl_open,
+	.llseek		= noop_llseek,
 }; 
 
 static unsigned long irq_counter;
@@ -454,6 +458,7 @@
 	.hangup          = ip2_hangup,
 	.tiocmget	 = ip2_tiocmget,
 	.tiocmset	 = ip2_tiocmset,
+	.get_icount	 = ip2_get_icount,
 	.proc_fops	 = &ip2_proc_fops,
 };
 
@@ -2128,7 +2133,6 @@
 	i2ChanStrPtr pCh = DevTable[tty->index];
 	i2eBordStrPtr pB;
 	struct async_icount cprev, cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;
 	int rc = 0;
 	unsigned long flags;
 	void __user *argp = (void __user *)arg;
@@ -2297,34 +2301,6 @@
 		break;
 
 	/*
-	 * 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. The controller is quite capable of counting
-	 * both, but this done to preserve compatibility with the standard
-	 * serial driver.
-	 */
-	case TIOCGICOUNT:
-		ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
-
-		write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-		cnow = pCh->icount;
-		write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-		p_cuser = argp;
-		rc = put_user(cnow.cts, &p_cuser->cts);
-		rc = put_user(cnow.dsr, &p_cuser->dsr);
-		rc = put_user(cnow.rng, &p_cuser->rng);
-		rc = put_user(cnow.dcd, &p_cuser->dcd);
-		rc = put_user(cnow.rx, &p_cuser->rx);
-		rc = put_user(cnow.tx, &p_cuser->tx);
-		rc = put_user(cnow.frame, &p_cuser->frame);
-		rc = put_user(cnow.overrun, &p_cuser->overrun);
-		rc = put_user(cnow.parity, &p_cuser->parity);
-		rc = put_user(cnow.brk, &p_cuser->brk);
-		rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
-		break;
-
-	/*
 	 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
 	 * will be passed to the line discipline for it to handle.
 	 */
@@ -2348,6 +2324,46 @@
 	return rc;
 }
 
+static int ip2_get_icount(struct tty_struct *tty,
+		struct serial_icounter_struct *icount)
+{
+	i2ChanStrPtr pCh = DevTable[tty->index];
+	i2eBordStrPtr pB;
+	struct async_icount cnow;	/* kernel counter temp */
+	unsigned long flags;
+
+	if ( pCh == NULL )
+		return -ENODEV;
+
+	pB = pCh->pMyBord;
+
+	/*
+	 * 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. The controller is quite capable of counting
+	 * both, but this done to preserve compatibility with the standard
+	 * serial driver.
+	 */
+
+	write_lock_irqsave(&pB->read_fifo_spinlock, flags);
+	cnow = pCh->icount;
+	write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+	return 0;
+}
+
 /******************************************************************************/
 /* Function:   GetSerialInfo()                                                */
 /* Parameters: Pointer to channel structure                                   */
@@ -2897,7 +2913,7 @@
 	printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
 #endif
 
-	lock_kernel();
+	mutex_lock(&ip2_mutex);
 
 	switch ( iplminor ) {
 	case 0:	    // IPL device
@@ -2961,7 +2977,7 @@
 		rc = -ENODEV;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&ip2_mutex);
 	return rc;
 }
 
@@ -2982,7 +2998,6 @@
 #ifdef IP2DEBUG_IPL
 	printk (KERN_DEBUG "IP2IPL: open\n" );
 #endif
-	cycle_kernel_lock();
 	return 0;
 }
 
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index d8ec92a..1fc8876 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -44,7 +44,6 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/compat.h>
-#include <linux/smp_lock.h>
 
 struct ipmi_file_private
 {
@@ -59,6 +58,7 @@
 	unsigned int         default_retry_time_ms;
 };
 
+static DEFINE_MUTEX(ipmi_mutex);
 static void file_receive_handler(struct ipmi_recv_msg *msg,
 				 void                 *handler_data)
 {
@@ -102,9 +102,9 @@
 	struct ipmi_file_private *priv = file->private_data;
 	int                      result;
 
-	lock_kernel(); /* could race against open() otherwise */
+	mutex_lock(&ipmi_mutex); /* could race against open() otherwise */
 	result = fasync_helper(fd, file, on, &priv->fasync_queue);
-	unlock_kernel();
+	mutex_unlock(&ipmi_mutex);
 
 	return (result);
 }
@@ -125,7 +125,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&ipmi_mutex);
 	priv->file = file;
 
 	rv = ipmi_create_user(if_num,
@@ -150,7 +150,7 @@
 	priv->default_retry_time_ms = 0;
 
 out:
-	unlock_kernel();
+	mutex_unlock(&ipmi_mutex);
 	return rv;
 }
 
@@ -639,9 +639,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ipmi_mutex);
 	ret = ipmi_ioctl(file, cmd, data);
-	unlock_kernel();
+	mutex_unlock(&ipmi_mutex);
 
 	return ret;
 }
@@ -850,6 +850,7 @@
 	.release	= ipmi_release,
 	.fasync		= ipmi_fasync,
 	.poll		= ipmi_poll,
+	.llseek		= noop_llseek,
 };
 
 #define DEVICE_NAME     "ipmidev"
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 654d566..f4d334f 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -35,7 +35,7 @@
 #include <linux/moduleparam.h>
 #include <linux/ipmi.h>
 #include <linux/ipmi_smi.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
@@ -149,6 +149,7 @@
 #define	WDIOC_GET_PRETIMEOUT     _IOW(WATCHDOG_IOCTL_BASE, 22, int)
 #endif
 
+static DEFINE_MUTEX(ipmi_watchdog_mutex);
 static int nowayout = WATCHDOG_NOWAYOUT;
 
 static ipmi_user_t watchdog_user;
@@ -748,9 +749,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ipmi_watchdog_mutex);
 	ret = ipmi_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ipmi_watchdog_mutex);
 
 	return ret;
 }
@@ -844,7 +845,6 @@
 		if (test_and_set_bit(0, &ipmi_wdog_open))
 			return -EBUSY;
 
-		cycle_kernel_lock();
 
 		/*
 		 * Don't start the timer now, let it start on the
@@ -909,6 +909,7 @@
 	.open    = ipmi_open,
 	.release = ipmi_close,
 	.fasync  = ipmi_fasync,
+	.llseek  = no_llseek,
 };
 
 static struct miscdevice ipmi_wdog_miscdev = {
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index be28391..667abd23 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -704,6 +704,7 @@
 	.read		= stli_memread,
 	.write		= stli_memwrite,
 	.unlocked_ioctl	= stli_memioctl,
+	.llseek		= default_llseek,
 };
 
 /*****************************************************************************/
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 938a3a2..97c3edb 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -126,7 +126,7 @@
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/jiffies.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 
 #include <linux/parport.h>
@@ -140,6 +140,7 @@
 /* if you have more than 8 printers, remember to increase LP_NO */
 #define LP_NO 8
 
+static DEFINE_MUTEX(lp_mutex);
 static struct lp_struct lp_table[LP_NO];
 
 static unsigned int lp_count = 0;
@@ -493,7 +494,7 @@
 	unsigned int minor = iminor(inode);
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&lp_mutex);
 	if (minor >= LP_NO) {
 		ret = -ENXIO;
 		goto out;
@@ -554,7 +555,7 @@
 	lp_release_parport (&lp_table[minor]);
 	lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
 out:
-	unlock_kernel();
+	mutex_unlock(&lp_mutex);
 	return ret;
 }
 
@@ -680,7 +681,7 @@
 	int ret;
 
 	minor = iminor(file->f_path.dentry->d_inode);
-	lock_kernel();
+	mutex_lock(&lp_mutex);
 	switch (cmd) {
 	case LPSETTIMEOUT:
 		if (copy_from_user(&par_timeout, (void __user *)arg,
@@ -694,7 +695,7 @@
 		ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&lp_mutex);
 
 	return ret;
 }
@@ -709,7 +710,7 @@
 	int ret;
 
 	minor = iminor(file->f_path.dentry->d_inode);
-	lock_kernel();
+	mutex_lock(&lp_mutex);
 	switch (cmd) {
 	case LPSETTIMEOUT:
 		tc = compat_ptr(arg);
@@ -730,7 +731,7 @@
 		ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg));
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&lp_mutex);
 
 	return ret;
 }
@@ -748,6 +749,7 @@
 #ifdef CONFIG_PARPORT_1284
 	.read		= lp_read,
 #endif
+	.llseek		= noop_llseek,
 };
 
 /* --- support for console on the line printer ----------------- */
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 83bef4e..1aeaaba 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -25,7 +25,6 @@
 #include <linux/mm.h>
 #include <linux/uio.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -42,6 +41,7 @@
 #else
 #define DBG(fmt...)
 #endif
+static DEFINE_MUTEX(mbcs_mutex);
 static int mbcs_major;
 
 static LIST_HEAD(soft_list);
@@ -385,19 +385,19 @@
 	struct mbcs_soft *soft;
 	int minor;
 
-	lock_kernel();
+	mutex_lock(&mbcs_mutex);
 	minor = iminor(ip);
 
 	/* Nothing protects access to this list... */
 	list_for_each_entry(soft, &soft_list, list) {
 		if (soft->nasid == minor) {
 			fp->private_data = soft->cxdev;
-			unlock_kernel();
+			mutex_unlock(&mbcs_mutex);
 			return 0;
 		}
 	}
 
-	unlock_kernel();
+	mutex_unlock(&mbcs_mutex);
 	return -ENODEV;
 }
 
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 1f528fa..e985b1c 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -805,6 +805,7 @@
 static const struct file_operations oldmem_fops = {
 	.read	= read_oldmem,
 	.open	= open_oldmem,
+	.llseek = default_llseek,
 };
 #endif
 
@@ -831,6 +832,7 @@
 
 static const struct file_operations kmsg_fops = {
 	.write = kmsg_write,
+	.llseek = noop_llseek,
 };
 
 static const struct memdev {
@@ -882,6 +884,7 @@
 
 static const struct file_operations memory_fops = {
 	.open = memory_open,
+	.llseek = noop_llseek,
 };
 
 static char *mem_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index abdafd4..778273c 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -162,6 +162,7 @@
 static const struct file_operations misc_fops = {
 	.owner		= THIS_MODULE,
 	.open		= misc_open,
+	.llseek		= noop_llseek,
 };
 
 /**
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index ea7c99f..c070b53 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -32,7 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/math64.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
@@ -59,6 +59,7 @@
 
 #define rtc_time()              (*RTC_COUNTER_ADDR)
 
+static DEFINE_MUTEX(mmtimer_mutex);
 static long mmtimer_ioctl(struct file *file, unsigned int cmd,
 						unsigned long arg);
 static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
@@ -72,6 +73,7 @@
 	.owner = THIS_MODULE,
 	.mmap =	mmtimer_mmap,
 	.unlocked_ioctl = mmtimer_ioctl,
+	.llseek = noop_llseek,
 };
 
 /*
@@ -371,7 +373,7 @@
 {
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&mmtimer_mutex);
 
 	switch (cmd) {
 	case MMTIMER_GETOFFSET:	/* offset of the counter */
@@ -414,7 +416,7 @@
 		ret = -ENOTTY;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&mmtimer_mutex);
 	return ret;
 }
 
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index ecb89d7..966a95b 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -316,7 +316,8 @@
 
 static const struct file_operations fetchop_fops = {
 	.owner = THIS_MODULE,
-	.mmap = fetchop_mmap
+	.mmap = fetchop_mmap,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice fetchop_miscdev = {
@@ -327,7 +328,8 @@
 
 static const struct file_operations cached_fops = {
 	.owner = THIS_MODULE,
-	.mmap = cached_mmap
+	.mmap = cached_mmap,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice cached_miscdev = {
@@ -338,7 +340,8 @@
 
 static const struct file_operations uncached_fops = {
 	.owner = THIS_MODULE,
-	.mmap = uncached_mmap
+	.mmap = uncached_mmap,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice uncached_miscdev = {
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index a4ec50c..1d82d58 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -56,7 +56,7 @@
 #include <linux/serial.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/serial_8250.h>
 #include "smapi.h"
@@ -73,6 +73,7 @@
 * checks are made against other devices (ie. superio) for conflicts.
 * We'll depend on users using the tpctl utility to do that for now
 */
+static DEFINE_MUTEX(mwave_mutex);
 int mwave_debug = 0;
 int mwave_3780i_irq = 0;
 int mwave_3780i_io = 0;
@@ -101,7 +102,6 @@
 	PRINTK_2(TRACE_MWAVE,
 		"mwavedd::mwave_open, exit return retval %x\n", retval);
 
-	cycle_kernel_lock();
 	return retval;
 }
 
@@ -136,9 +136,9 @@
 			PRINTK_1(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
 				" calling tp3780I_ResetDSP\n");
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ResetDSP(&pDrvData->rBDData);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 			PRINTK_2(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
 				" retval %x from tp3780I_ResetDSP\n",
@@ -149,9 +149,9 @@
 			PRINTK_1(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
 				" calling tp3780I_StartDSP\n");
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_StartDSP(&pDrvData->rBDData);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 			PRINTK_2(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
 				" retval %x from tp3780I_StartDSP\n",
@@ -165,10 +165,10 @@
 				"mwavedd::mwave_ioctl,"
 				" IOCTL_MW_DSP_ABILITIES calling"
 				" tp3780I_QueryAbilities\n");
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
 					&rAbilities);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 			PRINTK_2(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
 				" retval %x from tp3780I_QueryAbilities\n",
@@ -199,13 +199,13 @@
 				"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
 				" size %lx, ioarg %lx pusBuffer %p\n",
 				rReadData.ulDataLength, ioarg, pusBuffer);
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
 					iocmd,
 					pusBuffer,
 					rReadData.ulDataLength,
 					rReadData.usDspAddress);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -223,12 +223,12 @@
 				" size %lx, ioarg %lx pusBuffer %p\n",
 				rReadData.ulDataLength / 2, ioarg,
 				pusBuffer);
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
 				iocmd, pusBuffer,
 				rReadData.ulDataLength / 2,
 				rReadData.usDspAddress);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -246,12 +246,12 @@
 				" size %lx, ioarg %lx pusBuffer %p\n",
 				rWriteData.ulDataLength, ioarg,
 				pusBuffer);
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
 					iocmd, pusBuffer,
 					rWriteData.ulDataLength,
 					rWriteData.usDspAddress);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -269,12 +269,12 @@
 				" size %lx, ioarg %lx pusBuffer %p\n",
 				rWriteData.ulDataLength, ioarg,
 				pusBuffer);
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
 					iocmd, pusBuffer,
 					rWriteData.ulDataLength,
 					rWriteData.usDspAddress);
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -295,10 +295,10 @@
 				ipcnum,
 				pDrvData->IPCs[ipcnum].usIntCount);
 
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			pDrvData->IPCs[ipcnum].bIsHere = FALSE;
 			pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 	
 			PRINTK_2(TRACE_MWAVE,
 				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
@@ -323,7 +323,7 @@
 				ipcnum,
 				pDrvData->IPCs[ipcnum].usIntCount);
 	
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
 				DECLARE_WAITQUEUE(wait, current);
 
@@ -364,7 +364,7 @@
 					" processing\n",
 					ipcnum);
 			}
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -383,14 +383,14 @@
 						ipcnum);
 				return -EINVAL;
 			}
-			lock_kernel();
+			mutex_lock(&mwave_mutex);
 			if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
 				pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
 				if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) {
 					wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
 				}
 			}
-			unlock_kernel();
+			mutex_unlock(&mwave_mutex);
 		}
 			break;
 	
@@ -479,7 +479,8 @@
 	.write		= mwave_write,
 	.unlocked_ioctl	= mwave_ioctl,
 	.open		= mwave_open,
-	.release	= mwave_close
+	.release	= mwave_close,
+	.llseek		= default_llseek,
 };
 
 
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 3fc89da..463df27 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1700,7 +1700,7 @@
 		return 0;
 	}
 
-	if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
+	if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
 			test_bit(TTY_IO_ERROR, &tty->flags))
 		return -EIO;
 
@@ -1730,32 +1730,6 @@
 
 		return wait_event_interruptible(info->port.delta_msr_wait,
 				mxser_cflags_changed(info, arg, &cnow));
-	/*
-	 * 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: {
-		struct serial_icounter_struct icnt = { 0 };
-		spin_lock_irqsave(&info->slock, flags);
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		icnt.frame = cnow.frame;
-		icnt.brk = cnow.brk;
-		icnt.overrun = cnow.overrun;
-		icnt.buf_overrun = cnow.buf_overrun;
-		icnt.parity = cnow.parity;
-		icnt.rx = cnow.rx;
-		icnt.tx = cnow.tx;
-		icnt.cts = cnow.cts;
-		icnt.dsr = cnow.dsr;
-		icnt.rng = cnow.rng;
-		icnt.dcd = cnow.dcd;
-
-		return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
-	}
 	case MOXA_HighSpeedOn:
 		return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
 	case MOXA_SDS_RSTICOUNTER:
@@ -1828,6 +1802,39 @@
 	return 0;
 }
 
+	/*
+	 * 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.
+	 */
+
+static int mxser_get_icount(struct tty_struct *tty,
+		struct serial_icounter_struct *icount)
+
+{
+	struct mxser_port *info = tty->driver_data;
+	struct async_icount cnow;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->slock, flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->slock, flags);
+
+	icount->frame = cnow.frame;
+	icount->brk = cnow.brk;
+	icount->overrun = cnow.overrun;
+	icount->buf_overrun = cnow.buf_overrun;
+	icount->parity = cnow.parity;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	return 0;
+}
+
 static void mxser_stoprx(struct tty_struct *tty)
 {
 	struct mxser_port *info = tty->driver_data;
@@ -2326,6 +2333,7 @@
 	.wait_until_sent = mxser_wait_until_sent,
 	.tiocmget = mxser_tiocmget,
 	.tiocmset = mxser_tiocmset,
+	.get_icount = mxser_get_icount,
 };
 
 struct tty_port_operations mxser_port_ops = {
@@ -2339,20 +2347,11 @@
  * The MOXA Smartio/Industio serial driver boot-time initialization code!
  */
 
-static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
-		unsigned int irq)
+static void mxser_release_ISA_res(struct mxser_board *brd)
 {
-	if (irq)
-		free_irq(brd->irq, brd);
-	if (pdev != NULL) {	/* PCI */
-#ifdef CONFIG_PCI
-		pci_release_region(pdev, 2);
-		pci_release_region(pdev, 3);
-#endif
-	} else {
-		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-		release_region(brd->vector, 1);
-	}
+	free_irq(brd->irq, brd);
+	release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+	release_region(brd->vector, 1);
 }
 
 static int __devinit mxser_initbrd(struct mxser_board *brd,
@@ -2397,13 +2396,11 @@
 
 	retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
 			brd);
-	if (retval) {
+	if (retval)
 		printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
 			"conflict with another device.\n",
 			brd->info->name, brd->irq);
-		/* We hold resources, we need to release them. */
-		mxser_release_res(brd, pdev, 0);
-	}
+
 	return retval;
 }
 
@@ -2555,7 +2552,7 @@
 	ioaddress = pci_resource_start(pdev, 2);
 	retval = pci_request_region(pdev, 2, "mxser(IO)");
 	if (retval)
-		goto err;
+		goto err_dis;
 
 	brd->info = &mxser_cards[ent->driver_data];
 	for (i = 0; i < brd->info->nports; i++)
@@ -2565,7 +2562,7 @@
 	ioaddress = pci_resource_start(pdev, 3);
 	retval = pci_request_region(pdev, 3, "mxser(vector)");
 	if (retval)
-		goto err_relio;
+		goto err_zero;
 	brd->vector = ioaddress;
 
 	/* irq */
@@ -2608,7 +2605,7 @@
 	/* mxser_initbrd will hook ISR. */
 	retval = mxser_initbrd(brd, pdev);
 	if (retval)
-		goto err_null;
+		goto err_rel3;
 
 	for (i = 0; i < brd->info->nports; i++)
 		tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
@@ -2616,10 +2613,13 @@
 	pci_set_drvdata(pdev, brd);
 
 	return 0;
-err_relio:
-	pci_release_region(pdev, 2);
-err_null:
+err_rel3:
+	pci_release_region(pdev, 3);
+err_zero:
 	brd->info = NULL;
+	pci_release_region(pdev, 2);
+err_dis:
+	pci_disable_device(pdev);
 err:
 	return retval;
 #else
@@ -2629,14 +2629,19 @@
 
 static void __devexit mxser_remove(struct pci_dev *pdev)
 {
+#ifdef CONFIG_PCI
 	struct mxser_board *brd = pci_get_drvdata(pdev);
 	unsigned int i;
 
 	for (i = 0; i < brd->info->nports; i++)
 		tty_unregister_device(mxvar_sdriver, brd->idx + i);
 
-	mxser_release_res(brd, pdev, 1);
+	free_irq(pdev->irq, brd);
+	pci_release_region(pdev, 2);
+	pci_release_region(pdev, 3);
+	pci_disable_device(pdev);
 	brd->info = NULL;
+#endif
 }
 
 static struct pci_driver mxser_driver = {
@@ -2741,7 +2746,7 @@
 
 	for (i = 0; i < MXSER_BOARDS; i++)
 		if (mxser_boards[i].info != NULL)
-			mxser_release_res(&mxser_boards[i], NULL, 1);
+			mxser_release_ISA_res(&mxser_boards[i]);
 }
 
 module_init(mxser_module_init);
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 817169c..dd3f9b1 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -1804,24 +1804,24 @@
 	return ret;
 }
 
-static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
+static int ntty_tiocgicount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
 {
+	struct port *port = tty->driver_data;
 	const struct async_icount cnow = port->tty_icount;
-	struct serial_icounter_struct icount;
 
-	icount.cts = cnow.cts;
-	icount.dsr = cnow.dsr;
-	icount.rng = cnow.rng;
-	icount.dcd = cnow.dcd;
-	icount.rx = cnow.rx;
-	icount.tx = cnow.tx;
-	icount.frame = cnow.frame;
-	icount.overrun = cnow.overrun;
-	icount.parity = cnow.parity;
-	icount.brk = cnow.brk;
-	icount.buf_overrun = cnow.buf_overrun;
-
-	return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+	return 0;
 }
 
 static int ntty_ioctl(struct tty_struct *tty, struct file *file,
@@ -1840,9 +1840,7 @@
 		rval = wait_event_interruptible(port->tty_wait,
 				ntty_cflags_changed(port, arg, &cprev));
 		break;
-	} case TIOCGICOUNT:
-		rval = ntty_ioctl_tiocgicount(port, argp);
-		break;
+	}
 	default:
 		DBG1("ERR: 0x%08X, %d", cmd, cmd);
 		break;
@@ -1922,6 +1920,7 @@
 	.chars_in_buffer = ntty_chars_in_buffer,
 	.tiocmget = ntty_tiocmget,
 	.tiocmset = ntty_tiocmset,
+	.get_icount = ntty_tiocgicount,
 	.install = ntty_install,
 	.cleanup = ntty_cleanup,
 };
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 66d2917..166f1e7 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -109,10 +109,11 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/system.h>
 
+static DEFINE_MUTEX(nvram_mutex);
 static DEFINE_SPINLOCK(nvram_state_lock);
 static int nvram_open_cnt;	/* #times opened */
 static int nvram_open_mode;	/* special open modes */
@@ -308,7 +309,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
 
-		lock_kernel();
+		mutex_lock(&nvram_mutex);
 		spin_lock_irq(&rtc_lock);
 
 		for (i = 0; i < NVRAM_BYTES; ++i)
@@ -316,7 +317,7 @@
 		__nvram_set_checksum();
 
 		spin_unlock_irq(&rtc_lock);
-		unlock_kernel();
+		mutex_unlock(&nvram_mutex);
 		return 0;
 
 	case NVRAM_SETCKS:
@@ -325,11 +326,11 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
 
-		lock_kernel();
+		mutex_lock(&nvram_mutex);
 		spin_lock_irq(&rtc_lock);
 		__nvram_set_checksum();
 		spin_unlock_irq(&rtc_lock);
-		unlock_kernel();
+		mutex_unlock(&nvram_mutex);
 		return 0;
 
 	default:
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index 2604246..8994ce3 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -182,6 +182,7 @@
 static const struct file_operations button_fops = {
 	.owner		= THIS_MODULE,
 	.read		= button_read,
+	.llseek		= noop_llseek,
 };
 
 /* 
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index 043a1c7..a12f524 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -25,7 +25,6 @@
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
 
@@ -41,6 +40,7 @@
 
 #define	NWFLASH_VERSION "6.4"
 
+static DEFINE_MUTEX(flash_mutex);
 static void kick_open(void);
 static int get_flash_id(void);
 static int erase_block(int nBlock);
@@ -96,7 +96,7 @@
 
 static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
-	lock_kernel();
+	mutex_lock(&flash_mutex);
 	switch (cmd) {
 	case CMD_WRITE_DISABLE:
 		gbWriteBase64Enable = 0;
@@ -114,10 +114,10 @@
 	default:
 		gbWriteBase64Enable = 0;
 		gbWriteEnable = 0;
-		unlock_kernel();
+		mutex_unlock(&flash_mutex);
 		return -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&flash_mutex);
 	return 0;
 }
 
@@ -282,7 +282,7 @@
 {
 	loff_t ret;
 
-	lock_kernel();
+	mutex_lock(&flash_mutex);
 	if (flashdebug)
 		printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n",
 		       (unsigned int) offset, orig);
@@ -317,7 +317,7 @@
 	default:
 		ret = -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&flash_mutex);
 	return ret;
 }
 
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 8ecbcc1..b304ec0 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -234,6 +234,7 @@
 	.open	= pc8736x_gpio_open,
 	.write	= nsc_gpio_write,
 	.read	= nsc_gpio_read,
+	.llseek = no_llseek,
 };
 
 static void __init pc8736x_init_shadow(void)
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index c7b482d..6835c23 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -30,7 +30,7 @@
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/bitrev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
@@ -54,6 +54,8 @@
 			   __func__ , ## args);		\
 	} while (0)
 
+static DEFINE_MUTEX(cmm_mutex);
+
 #define	T_1SEC		(HZ)
 #define	T_10MSEC	msecs_to_jiffies(10)
 #define	T_20MSEC	msecs_to_jiffies(20)
@@ -1415,7 +1417,7 @@
 	       iminor(inode), ioctl_names[_IOC_NR(cmd)]);
 #endif
 
-	lock_kernel();
+	mutex_lock(&cmm_mutex);
 	rc = -ENODEV;
 	link = dev_table[iminor(inode)];
 	if (!pcmcia_dev_present(link)) {
@@ -1623,7 +1625,7 @@
 		rc = -ENOTTY;
 	}
 out:
-	unlock_kernel();
+	mutex_unlock(&cmm_mutex);
 	return rc;
 }
 
@@ -1637,7 +1639,7 @@
 	if (minor >= CM4000_MAX_DEV)
 		return -ENODEV;
 
-	lock_kernel();
+	mutex_lock(&cmm_mutex);
 	link = dev_table[minor];
 	if (link == NULL || !pcmcia_dev_present(link)) {
 		ret = -ENODEV;
@@ -1682,7 +1684,7 @@
 	DEBUGP(2, dev, "<- cmm_open\n");
 	ret = nonseekable_open(inode, filp);
 out:
-	unlock_kernel();
+	mutex_unlock(&cmm_mutex);
 	return ret;
 }
 
@@ -1864,6 +1866,7 @@
 	.unlocked_ioctl	= cmm_ioctl,
 	.open	= cmm_open,
 	.release= cmm_close,
+	.llseek = no_llseek,
 };
 
 static struct pcmcia_device_id cm4000_ids[] = {
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index bf2f046..5d8d59e 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -24,7 +24,7 @@
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -48,6 +48,8 @@
 			   __func__ , ## args);		\
 	} while (0)
 
+static DEFINE_MUTEX(cm4040_mutex);
+
 #define	CCID_DRIVER_BULK_DEFAULT_TIMEOUT  	(150*HZ)
 #define	CCID_DRIVER_ASYNC_POWERUP_TIMEOUT 	(35*HZ)
 #define	CCID_DRIVER_MINIMUM_TIMEOUT 		(3*HZ)
@@ -440,7 +442,7 @@
 	if (minor >= CM_MAX_DEV)
 		return -ENODEV;
 
-	lock_kernel();
+	mutex_lock(&cm4040_mutex);
 	link = dev_table[minor];
 	if (link == NULL || !pcmcia_dev_present(link)) {
 		ret = -ENODEV;
@@ -469,7 +471,7 @@
 	DEBUGP(2, dev, "<- cm4040_open (successfully)\n");
 	ret = nonseekable_open(inode, filp);
 out:
-	unlock_kernel();
+	mutex_unlock(&cm4040_mutex);
 	return ret;
 }
 
@@ -628,6 +630,7 @@
 	.open		= cm4040_open,
 	.release	= cm4040_close,
 	.poll		= cm4040_poll,
+	.llseek		= no_llseek,
 };
 
 static struct pcmcia_device_id cm4040_ids[] = {
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index be18100..bfc10f8 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2191,6 +2191,32 @@
 	return 0;
 }
 
+static int mgslpc_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
+	struct mgsl_icount cnow;	/* kernel counter temps */
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
+
 /* Service an IOCTL request
  *
  * Arguments:
@@ -2206,11 +2232,7 @@
 			unsigned int cmd, unsigned long arg)
 {
 	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
-	int error;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
 	void __user *argp = (void __user *)arg;
-	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@@ -2220,7 +2242,7 @@
 		return -ENODEV;
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -2250,34 +2272,6 @@
 		return wait_events(info, argp);
 	case TIOCMIWAIT:
 		return modem_input_wait(info,(int)arg);
-	case TIOCGICOUNT:
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->lock,flags);
-		p_cuser = argp;
-		PUT_USER(error,cnow.cts, &p_cuser->cts);
-		if (error) return error;
-		PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-		if (error) return error;
-		PUT_USER(error,cnow.rng, &p_cuser->rng);
-		if (error) return error;
-		PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-		if (error) return error;
-		PUT_USER(error,cnow.rx, &p_cuser->rx);
-		if (error) return error;
-		PUT_USER(error,cnow.tx, &p_cuser->tx);
-		if (error) return error;
-		PUT_USER(error,cnow.frame, &p_cuser->frame);
-		if (error) return error;
-		PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-		if (error) return error;
-		PUT_USER(error,cnow.parity, &p_cuser->parity);
-		if (error) return error;
-		PUT_USER(error,cnow.brk, &p_cuser->brk);
-		if (error) return error;
-		PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-		if (error) return error;
-		return 0;
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 02abfdd..723152d 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -67,7 +67,7 @@
 #include <linux/slab.h>
 #include <linux/major.h>
 #include <linux/ppdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 
 #define PP_VERSION "ppdev: user-space parallel port driver"
@@ -97,6 +97,7 @@
 /* ROUND_UP macro from fs/select.c */
 #define ROUND_UP(x,y) (((x)+(y)-1)/(y))
 
+static DEFINE_MUTEX(pp_do_mutex);
 static inline void pp_enable_irq (struct pp_struct *pp)
 {
 	struct parport *port = pp->pdev->port;
@@ -630,9 +631,9 @@
 static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&pp_do_mutex);
 	ret = pp_do_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pp_do_mutex);
 	return ret;
 }
 
@@ -641,7 +642,6 @@
 	unsigned int minor = iminor(inode);
 	struct pp_struct *pp;
 
-	cycle_kernel_lock();
 	if (minor >= PARPORT_MAX)
 		return -ENXIO;
 
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index c350d01..923a485 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -676,7 +676,9 @@
 
 	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
 
-	tty_add_file(tty, filp);
+	retval = tty_add_file(tty, filp);
+	if (retval)
+		goto out;
 
 	retval = devpts_pty_new(inode, tty->link);
 	if (retval)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index caef35a..5a1aa64 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1165,6 +1165,7 @@
 	.poll  = random_poll,
 	.unlocked_ioctl = random_ioctl,
 	.fasync = random_fasync,
+	.llseek = noop_llseek,
 };
 
 const struct file_operations urandom_fops = {
@@ -1172,6 +1173,7 @@
 	.write = random_write,
 	.unlocked_ioctl = random_ioctl,
 	.fasync = random_fasync,
+	.llseek = noop_llseek,
 };
 
 /***************************************************************
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index b38942f..bfe25ea 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -19,8 +19,8 @@
 #include <linux/cdev.h>
 #include <linux/device.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/gfp.h>
+#include <linux/compat.h>
 
 #include <asm/uaccess.h>
 
@@ -55,7 +55,6 @@
 		return 0;
 	}
 
-	lock_kernel();
 	mutex_lock(&raw_mutex);
 
 	/*
@@ -82,7 +81,6 @@
 			bdev->bd_inode->i_mapping;
 	filp->private_data = bdev;
 	mutex_unlock(&raw_mutex);
-	unlock_kernel();
 	return 0;
 
 out2:
@@ -91,7 +89,6 @@
 	blkdev_put(bdev, filp->f_mode);
 out:
 	mutex_unlock(&raw_mutex);
-	unlock_kernel();
 	return err;
 }
 
@@ -125,20 +122,84 @@
 raw_ioctl(struct file *filp, unsigned int command, unsigned long arg)
 {
 	struct block_device *bdev = filp->private_data;
-	int ret;
-
-	lock_kernel();
-	ret = blkdev_ioctl(bdev, 0, command, arg);
-	unlock_kernel();
-
-	return ret;
+	return blkdev_ioctl(bdev, 0, command, arg);
 }
 
-static void bind_device(struct raw_config_request *rq)
+static int bind_set(int number, u64 major, u64 minor)
 {
-	device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
-	device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL,
-		      "raw%d", rq->raw_minor);
+	dev_t dev = MKDEV(major, minor);
+	struct raw_device_data *rawdev;
+	int err = 0;
+
+	if (number <= 0 || number >= MAX_RAW_MINORS)
+		return -EINVAL;
+
+	if (MAJOR(dev) != major || MINOR(dev) != minor)
+		return -EINVAL;
+
+	rawdev = &raw_devices[number];
+
+	/*
+	 * This is like making block devices, so demand the
+	 * same capability
+	 */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	/*
+	 * For now, we don't need to check that the underlying
+	 * block device is present or not: we can do that when
+	 * the raw device is opened.  Just check that the
+	 * major/minor numbers make sense.
+	 */
+
+	if (MAJOR(dev) == 0 && dev != 0)
+		return -EINVAL;
+
+	mutex_lock(&raw_mutex);
+	if (rawdev->inuse) {
+		mutex_unlock(&raw_mutex);
+		return -EBUSY;
+	}
+	if (rawdev->binding) {
+		bdput(rawdev->binding);
+		module_put(THIS_MODULE);
+	}
+	if (!dev) {
+		/* unbind */
+		rawdev->binding = NULL;
+		device_destroy(raw_class, MKDEV(RAW_MAJOR, number));
+	} else {
+		rawdev->binding = bdget(dev);
+		if (rawdev->binding == NULL) {
+			err = -ENOMEM;
+		} else {
+			dev_t raw = MKDEV(RAW_MAJOR, number);
+			__module_get(THIS_MODULE);
+			device_destroy(raw_class, raw);
+			device_create(raw_class, NULL, raw, NULL,
+				      "raw%d", number);
+		}
+	}
+	mutex_unlock(&raw_mutex);
+	return err;
+}
+
+static int bind_get(int number, dev_t *dev)
+{
+	struct raw_device_data *rawdev;
+	struct block_device *bdev;
+
+	if (number <= 0 || number >= MAX_RAW_MINORS)
+		return -EINVAL;
+
+	rawdev = &raw_devices[number];
+
+	mutex_lock(&raw_mutex);
+	bdev = rawdev->binding;
+	*dev = bdev ? bdev->bd_dev : 0;
+	mutex_unlock(&raw_mutex);
+	return 0;
 }
 
 /*
@@ -149,106 +210,79 @@
 			  unsigned long arg)
 {
 	struct raw_config_request rq;
-	struct raw_device_data *rawdev;
-	int err = 0;
+	dev_t dev;
+	int err;
 
-	lock_kernel();
 	switch (command) {
 	case RAW_SETBIND:
+		if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+			return -EFAULT;
+
+		return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
 	case RAW_GETBIND:
+		if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+			return -EFAULT;
 
-		/* First, find out which raw minor we want */
+		err = bind_get(rq.raw_minor, &dev);
+		if (err)
+			return err;
 
-		if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) {
-			err = -EFAULT;
-			goto out;
-		}
+		rq.block_major = MAJOR(dev);
+		rq.block_minor = MINOR(dev);
 
-		if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) {
-			err = -EINVAL;
-			goto out;
-		}
-		rawdev = &raw_devices[rq.raw_minor];
+		if (copy_to_user((void __user *)arg, &rq, sizeof(rq)))
+			return -EFAULT;
 
-		if (command == RAW_SETBIND) {
-			dev_t dev;
-
-			/*
-			 * This is like making block devices, so demand the
-			 * same capability
-			 */
-			if (!capable(CAP_SYS_ADMIN)) {
-				err = -EPERM;
-				goto out;
-			}
-
-			/*
-			 * For now, we don't need to check that the underlying
-			 * block device is present or not: we can do that when
-			 * the raw device is opened.  Just check that the
-			 * major/minor numbers make sense.
-			 */
-
-			dev = MKDEV(rq.block_major, rq.block_minor);
-			if ((rq.block_major == 0 && rq.block_minor != 0) ||
-					MAJOR(dev) != rq.block_major ||
-					MINOR(dev) != rq.block_minor) {
-				err = -EINVAL;
-				goto out;
-			}
-
-			mutex_lock(&raw_mutex);
-			if (rawdev->inuse) {
-				mutex_unlock(&raw_mutex);
-				err = -EBUSY;
-				goto out;
-			}
-			if (rawdev->binding) {
-				bdput(rawdev->binding);
-				module_put(THIS_MODULE);
-			}
-			if (rq.block_major == 0 && rq.block_minor == 0) {
-				/* unbind */
-				rawdev->binding = NULL;
-				device_destroy(raw_class,
-						MKDEV(RAW_MAJOR, rq.raw_minor));
-			} else {
-				rawdev->binding = bdget(dev);
-				if (rawdev->binding == NULL)
-					err = -ENOMEM;
-				else {
-					__module_get(THIS_MODULE);
-					bind_device(&rq);
-				}
-			}
-			mutex_unlock(&raw_mutex);
-		} else {
-			struct block_device *bdev;
-
-			mutex_lock(&raw_mutex);
-			bdev = rawdev->binding;
-			if (bdev) {
-				rq.block_major = MAJOR(bdev->bd_dev);
-				rq.block_minor = MINOR(bdev->bd_dev);
-			} else {
-				rq.block_major = rq.block_minor = 0;
-			}
-			mutex_unlock(&raw_mutex);
-			if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) {
-				err = -EFAULT;
-				goto out;
-			}
-		}
-		break;
-	default:
-		err = -EINVAL;
-		break;
+		return 0;
 	}
-out:
-	unlock_kernel();
-	return err;
+
+	return -EINVAL;
 }
 
+#ifdef CONFIG_COMPAT
+struct raw32_config_request {
+	compat_int_t	raw_minor;
+	compat_u64	block_major;
+	compat_u64	block_minor;
+};
+
+static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct raw32_config_request __user *user_req = compat_ptr(arg);
+	struct raw32_config_request rq;
+	dev_t dev;
+	int err = 0;
+
+	switch (cmd) {
+	case RAW_SETBIND:
+		if (copy_from_user(&rq, user_req, sizeof(rq)))
+			return -EFAULT;
+
+		return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
+	case RAW_GETBIND:
+		if (copy_from_user(&rq, user_req, sizeof(rq)))
+			return -EFAULT;
+
+		err = bind_get(rq.raw_minor, &dev);
+		if (err)
+			return err;
+
+		rq.block_major = MAJOR(dev);
+		rq.block_minor = MINOR(dev);
+
+		if (copy_to_user(user_req, &rq, sizeof(rq)))
+			return -EFAULT;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+#endif
+
 static const struct file_operations raw_fops = {
 	.read		= do_sync_read,
 	.aio_read	= generic_file_aio_read,
@@ -258,13 +292,18 @@
 	.open		= raw_open,
 	.release	= raw_release,
 	.unlocked_ioctl = raw_ioctl,
+	.llseek		= default_llseek,
 	.owner		= THIS_MODULE,
 };
 
 static const struct file_operations raw_ctl_fops = {
 	.unlocked_ioctl = raw_ctl_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= raw_ctl_compat_ioctl,
+#endif
 	.open		= raw_open,
 	.owner		= THIS_MODULE,
+	.llseek		= noop_llseek,
 };
 
 static struct cdev raw_cdev;
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index d58c2eb..5e33293 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -44,7 +44,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 
@@ -122,6 +122,7 @@
 
 
 /* These constants are derived from SCO Source */
+static DEFINE_MUTEX(rio_fw_mutex);
 static struct Conf
  RIOConf = {
 	/* locator */ "RIO Config here",
@@ -241,6 +242,7 @@
 static const struct file_operations rio_fw_fops = {
 	.owner = THIS_MODULE,
 	.unlocked_ioctl = rio_fw_ioctl,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice rio_fw_device = {
@@ -566,9 +568,9 @@
 	func_enter();
 
 	/* The "dev" argument isn't used. */
-	lock_kernel();
+	mutex_lock(&rio_fw_mutex);
 	rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
-	unlock_kernel();
+	mutex_unlock(&rio_fw_mutex);
 
 	func_exit();
 	return rc;
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c
index 99e5272..0bc135b 100644
--- a/drivers/char/scx200_gpio.c
+++ b/drivers/char/scx200_gpio.c
@@ -67,6 +67,7 @@
 	.read    = nsc_gpio_read,
 	.open    = scx200_gpio_open,
 	.release = scx200_gpio_release,
+	.llseek  = no_llseek,
 };
 
 static struct cdev scx200_gpio_cdev;  /* use 1 cdev for all pins */
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 32b74de..5816b39 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -21,7 +21,7 @@
 #include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/sn/io.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/module.h>
@@ -34,6 +34,7 @@
 #define SCDRV_BUFSZ	2048
 #define SCDRV_TIMEOUT	1000
 
+static DEFINE_MUTEX(scdrv_mutex);
 static irqreturn_t
 scdrv_interrupt(int irq, void *subch_data)
 {
@@ -105,7 +106,7 @@
 	file->private_data = sd;
 
 	/* hook this subchannel up to the system controller interrupt */
-	lock_kernel();
+	mutex_lock(&scdrv_mutex);
 	rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
 			 IRQF_SHARED | IRQF_DISABLED,
 			 SYSCTL_BASENAME, sd);
@@ -113,10 +114,10 @@
 		ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
 		kfree(sd);
 		printk("%s: irq request failed (%d)\n", __func__, rv);
-		unlock_kernel();
+		mutex_unlock(&scdrv_mutex);
 		return -EBUSY;
 	}
-	unlock_kernel();
+	mutex_unlock(&scdrv_mutex);
 	return 0;
 }
 
@@ -357,6 +358,7 @@
 	.poll =		scdrv_poll,
 	.open =		scdrv_open,
 	.release =	scdrv_release,
+	.llseek =	noop_llseek,
 };
 
 static struct class *snsc_class;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index f2167f8..8ef1649 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -608,6 +608,7 @@
 static const struct file_operations	stl_fsiomem = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= stl_memioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct class *stallion_class;
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 5b24db4..e53f168 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -397,6 +397,7 @@
 static const struct file_operations sx_fw_fops = {
 	.owner = THIS_MODULE,
 	.unlocked_ioctl = sx_fw_ioctl,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice sx_fw_device = {
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index a2a5800..3a6824f 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2925,6 +2925,38 @@
 	
 }	/* end of mgsl_break() */
 
+/*
+ * 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.
+ */
+static int msgl_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+
+{
+	struct mgsl_struct * info = tty->driver_data;
+	struct mgsl_icount cnow;	/* kernel counter temps */
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+	return 0;
+}
+
 /* mgsl_ioctl()	Service an IOCTL request
  * 	
  * Arguments:
@@ -2949,7 +2981,7 @@
 		return -ENODEV;
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -2959,11 +2991,7 @@
 
 static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
 {
-	int error;
-	struct mgsl_icount cnow;	/* kernel counter temps */
 	void __user *argp = (void __user *)arg;
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
-	unsigned long flags;
 	
 	switch (cmd) {
 		case MGSL_IOCGPARAMS:
@@ -2992,40 +3020,6 @@
 		case TIOCMIWAIT:
 			return modem_input_wait(info,(int)arg);
 
-		/* 
-		 * 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->irq_spinlock,flags);
-			cnow = info->icount;
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			p_cuser = argp;
-			PUT_USER(error,cnow.cts, &p_cuser->cts);
-			if (error) return error;
-			PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-			if (error) return error;
-			PUT_USER(error,cnow.rng, &p_cuser->rng);
-			if (error) return error;
-			PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-			if (error) return error;
-			PUT_USER(error,cnow.rx, &p_cuser->rx);
-			if (error) return error;
-			PUT_USER(error,cnow.tx, &p_cuser->tx);
-			if (error) return error;
-			PUT_USER(error,cnow.frame, &p_cuser->frame);
-			if (error) return error;
-			PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-			if (error) return error;
-			PUT_USER(error,cnow.parity, &p_cuser->parity);
-			if (error) return error;
-			PUT_USER(error,cnow.brk, &p_cuser->brk);
-			if (error) return error;
-			PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-			if (error) return error;
-			return 0;
 		default:
 			return -ENOIOCTLCMD;
 	}
@@ -4328,6 +4322,7 @@
 	.hangup = mgsl_hangup,
 	.tiocmget = tiocmget,
 	.tiocmset = tiocmset,
+	.get_icount = msgl_get_icount,
 	.proc_fops = &mgsl_proc_fops,
 };
 
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index e63b830..1746d91 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1032,9 +1032,6 @@
 		 unsigned int cmd, unsigned long arg)
 {
 	struct slgt_info *info = tty->driver_data;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
-	unsigned long flags;
 	void __user *argp = (void __user *)arg;
 	int ret;
 
@@ -1043,7 +1040,7 @@
 	DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -1053,24 +1050,6 @@
 		return wait_mgsl_event(info, argp);
 	case TIOCMIWAIT:
 		return modem_input_wait(info,(int)arg);
-	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) ||
-		    put_user(cnow.rx, &p_cuser->rx) ||
-		    put_user(cnow.tx, &p_cuser->tx) ||
-		    put_user(cnow.frame, &p_cuser->frame) ||
-		    put_user(cnow.overrun, &p_cuser->overrun) ||
-		    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;
 	case MGSL_IOCSGPIO:
 		return set_gpio(info, argp);
 	case MGSL_IOCGGPIO:
@@ -1117,6 +1096,33 @@
 	return ret;
 }
 
+static int get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+
+{
+	struct slgt_info *info = tty->driver_data;
+	struct mgsl_icount cnow;	/* kernel counter temps */
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
+
 /*
  * support for 32 bit ioctl calls on 64 bit systems
  */
@@ -1206,10 +1212,6 @@
 	case MGSL_IOCSGPIO:
 	case MGSL_IOCGGPIO:
 	case MGSL_IOCWAITGPIO:
-	case TIOCGICOUNT:
-		rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
-		break;
-
 	case MGSL_IOCSTXIDLE:
 	case MGSL_IOCTXENABLE:
 	case MGSL_IOCRXENABLE:
@@ -3642,6 +3644,7 @@
 	.hangup = hangup,
 	.tiocmget = tiocmget,
 	.tiocmset = tiocmset,
+	.get_icount = get_icount,
 	.proc_fops = &synclink_gt_proc_fops,
 };
 
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index e56caf7..2f9eb4b 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1258,10 +1258,6 @@
 		 unsigned int cmd, unsigned long arg)
 {
 	SLMP_INFO *info = tty->driver_data;
-	int error;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	struct serial_icounter_struct __user *p_cuser;	/* user space */
-	unsigned long flags;
 	void __user *argp = (void __user *)arg;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1272,7 +1268,7 @@
 		return -ENODEV;
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	    (cmd != TIOCMIWAIT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -1310,40 +1306,38 @@
 		 * 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;
-		PUT_USER(error,cnow.cts, &p_cuser->cts);
-		if (error) return error;
-		PUT_USER(error,cnow.dsr, &p_cuser->dsr);
-		if (error) return error;
-		PUT_USER(error,cnow.rng, &p_cuser->rng);
-		if (error) return error;
-		PUT_USER(error,cnow.dcd, &p_cuser->dcd);
-		if (error) return error;
-		PUT_USER(error,cnow.rx, &p_cuser->rx);
-		if (error) return error;
-		PUT_USER(error,cnow.tx, &p_cuser->tx);
-		if (error) return error;
-		PUT_USER(error,cnow.frame, &p_cuser->frame);
-		if (error) return error;
-		PUT_USER(error,cnow.overrun, &p_cuser->overrun);
-		if (error) return error;
-		PUT_USER(error,cnow.parity, &p_cuser->parity);
-		if (error) return error;
-		PUT_USER(error,cnow.brk, &p_cuser->brk);
-		if (error) return error;
-		PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
-		if (error) return error;
-		return 0;
 	default:
 		return -ENOIOCTLCMD;
 	}
 	return 0;
 }
 
+static int get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	SLMP_INFO *info = tty->driver_data;
+	struct mgsl_icount cnow;	/* kernel counter temps */
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
+
 /*
  * /proc fs routines....
  */
@@ -3909,6 +3903,7 @@
 	.hangup = hangup,
 	.tiocmget = tiocmget,
 	.tiocmset = tiocmset,
+	.get_icount = get_icount,
 	.proc_fops = &synclinkmp_proc_fops,
 };
 
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index ef31bb8..f3019f5 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -772,6 +772,7 @@
 
 static const struct file_operations proc_sysrq_trigger_operations = {
 	.write		= write_sysrq_trigger,
+	.llseek		= noop_llseek,
 };
 
 static void sysrq_init_procfs(void)
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index cad4eb6..ad26418 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -261,6 +261,7 @@
 	.write		= tanbac_tb0219_write,
 	.open		= tanbac_tb0219_open,
 	.release	= tanbac_tb0219_release,
+	.llseek		= no_llseek,
 };
 
 static void tb0219_restart(char *command)
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 80ea6bc..0c964cd 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -37,7 +37,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/timer.h>
 #include <linux/sysfs.h>
 #include <linux/device.h>
@@ -206,7 +206,7 @@
 {
 	int result;
 
-	lock_kernel();
+	mutex_lock(&tlclk_mutex);
 	if (test_and_set_bit(0, &useflags)) {
 		result = -EBUSY;
 		/* this legacy device is always one per system and it doesn't
@@ -229,7 +229,7 @@
 		inb(TLCLK_REG6);	/* Clear interrupt events */
 
 out:
-	unlock_kernel();
+	mutex_unlock(&tlclk_mutex);
 	return result;
 }
 
@@ -267,6 +267,7 @@
 	.read = tlclk_read,
 	.open = tlclk_open,
 	.release = tlclk_release,
+	.llseek = noop_llseek,
 
 };
 
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index f8bc79f..014c9d9 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -68,7 +68,7 @@
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/toshiba.h>
 
 #define TOSH_MINOR_DEV 181
@@ -78,6 +78,7 @@
 MODULE_DESCRIPTION("Toshiba laptop SMM driver");
 MODULE_SUPPORTED_DEVICE("toshiba");
 
+static DEFINE_MUTEX(tosh_mutex);
 static int tosh_fn;
 module_param_named(fn, tosh_fn, int, 0);
 MODULE_PARM_DESC(fn, "User specified Fn key detection port");
@@ -95,6 +96,7 @@
 static const struct file_operations tosh_fops = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= tosh_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice tosh_device = {
@@ -274,16 +276,16 @@
 				return -EINVAL;
 
 			/* do we need to emulate the fan ? */
-			lock_kernel();
+			mutex_lock(&tosh_mutex);
 			if (tosh_fan==1) {
 				if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) {
 					err = tosh_emulate_fan(&regs);
-					unlock_kernel();
+					mutex_unlock(&tosh_mutex);
 					break;
 				}
 			}
 			err = tosh_smm(&regs);
-			unlock_kernel();
+			mutex_unlock(&tosh_mutex);
 			break;
 		default:
 			return -EINVAL;
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 613c852..c05c5af 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -96,6 +96,7 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
+#include <linux/serial.h>
 
 #include <linux/uaccess.h>
 #include <asm/system.h>
@@ -183,6 +184,8 @@
 
 void free_tty_struct(struct tty_struct *tty)
 {
+	if (tty->dev)
+		put_device(tty->dev);
 	kfree(tty->write_buf);
 	tty_buffer_free_all(tty);
 	kfree(tty);
@@ -194,12 +197,13 @@
 }
 
 /* Associate a new file with the tty structure */
-void tty_add_file(struct tty_struct *tty, struct file *file)
+int tty_add_file(struct tty_struct *tty, struct file *file)
 {
 	struct tty_file_private *priv;
 
-	/* XXX: must implement proper error handling in callers */
-	priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL);
+	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 
 	priv->tty = tty;
 	priv->file = file;
@@ -208,6 +212,8 @@
 	spin_lock(&tty_files_lock);
 	list_add(&priv->list, &tty->tty_files);
 	spin_unlock(&tty_files_lock);
+
+	return 0;
 }
 
 /* Delete file from its tty */
@@ -1875,7 +1881,11 @@
 		return PTR_ERR(tty);
 	}
 
-	tty_add_file(tty, filp);
+	retval = tty_add_file(tty, filp);
+	if (retval) {
+		tty_unlock();
+		return retval;
+	}
 
 	check_tty_count(tty, "tty_open");
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2502,6 +2512,20 @@
 	return tty->ops->tiocmset(tty, file, set, clear);
 }
 
+static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
+{
+	int retval = -EINVAL;
+	struct serial_icounter_struct icount;
+	memset(&icount, 0, sizeof(icount));
+	if (tty->ops->get_icount)
+		retval = tty->ops->get_icount(tty, &icount);
+	if (retval != 0)
+		return retval;
+	if (copy_to_user(arg, &icount, sizeof(icount)))
+		return -EFAULT;
+	return 0;
+}
+
 struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
 {
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2622,6 +2646,12 @@
 	case TIOCMBIC:
 	case TIOCMBIS:
 		return tty_tiocmset(tty, file, cmd, p);
+	case TIOCGICOUNT:
+		retval = tty_tiocgicount(tty, p);
+		/* For the moment allow fall through to the old method */
+        	if (retval != -EINVAL)
+			return retval;
+		break;
 	case TCFLSH:
 		switch (arg) {
 		case TCIFLUSH:
@@ -2783,6 +2813,20 @@
 
 EXPORT_SYMBOL(do_SAK);
 
+static int dev_match_devt(struct device *dev, void *data)
+{
+	dev_t *devt = data;
+	return dev->devt == *devt;
+}
+
+/* Must put_device() after it's unused! */
+static struct device *tty_get_device(struct tty_struct *tty)
+{
+	dev_t devt = tty_devnum(tty);
+	return class_find_device(tty_class, NULL, &devt, dev_match_devt);
+}
+
+
 /**
  *	initialize_tty_struct
  *	@tty: tty to initialize
@@ -2823,6 +2867,7 @@
 	tty->ops = driver->ops;
 	tty->index = idx;
 	tty_line_name(driver, idx, tty->name);
+	tty->dev = tty_get_device(tty);
 }
 
 /**
@@ -2980,6 +3025,7 @@
 	int i;
 	dev_t dev;
 	void **p = NULL;
+	struct device *d;
 
 	if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
 		p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
@@ -3027,12 +3073,31 @@
 	mutex_unlock(&tty_mutex);
 
 	if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
-		for (i = 0; i < driver->num; i++)
-		    tty_register_device(driver, i, NULL);
+		for (i = 0; i < driver->num; i++) {
+			d = tty_register_device(driver, i, NULL);
+			if (IS_ERR(d)) {
+				error = PTR_ERR(d);
+				goto err;
+			}
+		}
 	}
 	proc_tty_register_driver(driver);
 	driver->flags |= TTY_DRIVER_INSTALLED;
 	return 0;
+
+err:
+	for (i--; i >= 0; i--)
+		tty_unregister_device(driver, i);
+
+	mutex_lock(&tty_mutex);
+	list_del(&driver->tty_drivers);
+	mutex_unlock(&tty_mutex);
+
+	unregister_chrdev_region(dev, driver->num);
+	driver->ttys = NULL;
+	driver->termios = NULL;
+	kfree(p);
+	return error;
 }
 
 EXPORT_SYMBOL(tty_register_driver);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
new file mode 100644
index 0000000..c40c161
--- /dev/null
+++ b/drivers/char/ttyprintk.c
@@ -0,0 +1,225 @@
+/*
+ *  linux/drivers/char/ttyprintk.c
+ *
+ *  Copyright (C) 2010  Samo Pogacnik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+/*
+ * This pseudo device allows user to make printk messages. It is possible
+ * to store "console" messages inline with kernel messages for better analyses
+ * of the boot process, for example.
+ */
+
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+
+struct ttyprintk_port {
+	struct tty_port port;
+	struct mutex port_write_mutex;
+};
+
+static struct ttyprintk_port tpk_port;
+
+/*
+ * Our simple preformatting supports transparent output of (time-stamped)
+ * printk messages (also suitable for logging service):
+ * - any cr is replaced by nl
+ * - adds a ttyprintk source tag in front of each line
+ * - too long message is fragmeted, with '\'nl between fragments
+ * - TPK_STR_SIZE isn't really the write_room limiting factor, bcause
+ *   it is emptied on the fly during preformatting.
+ */
+#define TPK_STR_SIZE 508 /* should be bigger then max expected line length */
+#define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */
+static const char *tpk_tag = "[U] "; /* U for User */
+static int tpk_curr;
+
+static int tpk_printk(const unsigned char *buf, int count)
+{
+	static char tmp[TPK_STR_SIZE + 4];
+	int i = tpk_curr;
+
+	if (buf == NULL) {
+		/* flush tmp[] */
+		if (tpk_curr > 0) {
+			/* non nl or cr terminated message - add nl */
+			tmp[tpk_curr + 0] = '\n';
+			tmp[tpk_curr + 1] = '\0';
+			printk(KERN_INFO "%s%s", tpk_tag, tmp);
+			tpk_curr = 0;
+		}
+		return i;
+	}
+
+	for (i = 0; i < count; i++) {
+		tmp[tpk_curr] = buf[i];
+		if (tpk_curr < TPK_STR_SIZE) {
+			switch (buf[i]) {
+			case '\r':
+				/* replace cr with nl */
+				tmp[tpk_curr + 0] = '\n';
+				tmp[tpk_curr + 1] = '\0';
+				printk(KERN_INFO "%s%s", tpk_tag, tmp);
+				tpk_curr = 0;
+				if (buf[i + 1] == '\n')
+					i++;
+				break;
+			case '\n':
+				tmp[tpk_curr + 1] = '\0';
+				printk(KERN_INFO "%s%s", tpk_tag, tmp);
+				tpk_curr = 0;
+				break;
+			default:
+				tpk_curr++;
+			}
+		} else {
+			/* end of tmp buffer reached: cut the message in two */
+			tmp[tpk_curr + 1] = '\\';
+			tmp[tpk_curr + 2] = '\n';
+			tmp[tpk_curr + 3] = '\0';
+			printk(KERN_INFO "%s%s", tpk_tag, tmp);
+			tpk_curr = 0;
+		}
+	}
+
+	return count;
+}
+
+/*
+ * TTY operations open function.
+ */
+static int tpk_open(struct tty_struct *tty, struct file *filp)
+{
+	tty->driver_data = &tpk_port;
+
+	return tty_port_open(&tpk_port.port, tty, filp);
+}
+
+/*
+ * TTY operations close function.
+ */
+static void tpk_close(struct tty_struct *tty, struct file *filp)
+{
+	struct ttyprintk_port *tpkp = tty->driver_data;
+
+	mutex_lock(&tpkp->port_write_mutex);
+	/* flush tpk_printk buffer */
+	tpk_printk(NULL, 0);
+	mutex_unlock(&tpkp->port_write_mutex);
+
+	tty_port_close(&tpkp->port, tty, filp);
+}
+
+/*
+ * TTY operations write function.
+ */
+static int tpk_write(struct tty_struct *tty,
+		const unsigned char *buf, int count)
+{
+	struct ttyprintk_port *tpkp = tty->driver_data;
+	int ret;
+
+
+	/* exclusive use of tpk_printk within this tty */
+	mutex_lock(&tpkp->port_write_mutex);
+	ret = tpk_printk(buf, count);
+	mutex_unlock(&tpkp->port_write_mutex);
+
+	return ret;
+}
+
+/*
+ * TTY operations write_room function.
+ */
+static int tpk_write_room(struct tty_struct *tty)
+{
+	return TPK_MAX_ROOM;
+}
+
+/*
+ * TTY operations ioctl function.
+ */
+static int tpk_ioctl(struct tty_struct *tty, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	struct ttyprintk_port *tpkp = tty->driver_data;
+
+	if (!tpkp)
+		return -EINVAL;
+
+	switch (cmd) {
+	/* Stop TIOCCONS */
+	case TIOCCONS:
+		return -EOPNOTSUPP;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static const struct tty_operations ttyprintk_ops = {
+	.open = tpk_open,
+	.close = tpk_close,
+	.write = tpk_write,
+	.write_room = tpk_write_room,
+	.ioctl = tpk_ioctl,
+};
+
+struct tty_port_operations null_ops = { };
+
+static struct tty_driver *ttyprintk_driver;
+
+static int __init ttyprintk_init(void)
+{
+	int ret = -ENOMEM;
+	void *rp;
+
+	ttyprintk_driver = alloc_tty_driver(1);
+	if (!ttyprintk_driver)
+		return ret;
+
+	ttyprintk_driver->owner = THIS_MODULE;
+	ttyprintk_driver->driver_name = "ttyprintk";
+	ttyprintk_driver->name = "ttyprintk";
+	ttyprintk_driver->major = TTYAUX_MAJOR;
+	ttyprintk_driver->minor_start = 3;
+	ttyprintk_driver->num = 1;
+	ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
+	ttyprintk_driver->init_termios = tty_std_termios;
+	ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
+	ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
+		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
+
+	ret = tty_register_driver(ttyprintk_driver);
+	if (ret < 0) {
+		printk(KERN_ERR "Couldn't register ttyprintk driver\n");
+		goto error;
+	}
+
+	/* create our unnumbered device */
+	rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
+				ttyprintk_driver->name);
+	if (IS_ERR(rp)) {
+		printk(KERN_ERR "Couldn't create ttyprintk device\n");
+		ret = PTR_ERR(rp);
+		goto error;
+	}
+
+	tty_port_init(&tpk_port.port);
+	tpk_port.port.ops = &null_ops;
+	mutex_init(&tpk_port.port_write_mutex);
+
+	return 0;
+
+error:
+	put_tty_driver(ttyprintk_driver);
+	ttyprintk_driver = NULL;
+	return ret;
+}
+module_init(ttyprintk_init);
diff --git a/drivers/char/uv_mmtimer.c b/drivers/char/uv_mmtimer.c
index c7072ba..493b47a 100644
--- a/drivers/char/uv_mmtimer.c
+++ b/drivers/char/uv_mmtimer.c
@@ -52,6 +52,7 @@
 	.owner = THIS_MODULE,
 	.mmap =	uv_mmtimer_mmap,
 	.unlocked_ioctl = uv_mmtimer_ioctl,
+	.llseek = noop_llseek,
 };
 
 /**
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index bcce46c..273ab44 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -35,6 +35,12 @@
 #include <linux/console.h>
 #include <linux/device.h>
 #include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/notifier.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -45,6 +51,86 @@
 #undef addr
 #define HEADER_SIZE	4
 
+struct vcs_poll_data {
+	struct notifier_block notifier;
+	unsigned int cons_num;
+	bool seen_last_update;
+	wait_queue_head_t waitq;
+	struct fasync_struct *fasync;
+};
+
+static int
+vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
+{
+	struct vt_notifier_param *param = _param;
+	struct vc_data *vc = param->vc;
+	struct vcs_poll_data *poll =
+		container_of(nb, struct vcs_poll_data, notifier);
+	int currcons = poll->cons_num;
+
+	if (code != VT_UPDATE)
+		return NOTIFY_DONE;
+
+	if (currcons == 0)
+		currcons = fg_console;
+	else
+		currcons--;
+	if (currcons != vc->vc_num)
+		return NOTIFY_DONE;
+
+	poll->seen_last_update = false;
+	wake_up_interruptible(&poll->waitq);
+	kill_fasync(&poll->fasync, SIGIO, POLL_IN);
+	return NOTIFY_OK;
+}
+
+static void
+vcs_poll_data_free(struct vcs_poll_data *poll)
+{
+	unregister_vt_notifier(&poll->notifier);
+	kfree(poll);
+}
+
+static struct vcs_poll_data *
+vcs_poll_data_get(struct file *file)
+{
+	struct vcs_poll_data *poll = file->private_data;
+
+	if (poll)
+		return poll;
+
+	poll = kzalloc(sizeof(*poll), GFP_KERNEL);
+	if (!poll)
+		return NULL;
+	poll->cons_num = iminor(file->f_path.dentry->d_inode) & 127;
+	init_waitqueue_head(&poll->waitq);
+	poll->notifier.notifier_call = vcs_notifier;
+	if (register_vt_notifier(&poll->notifier) != 0) {
+		kfree(poll);
+		return NULL;
+	}
+
+	/*
+	 * This code may be called either through ->poll() or ->fasync().
+	 * If we have two threads using the same file descriptor, they could
+	 * both enter this function, both notice that the structure hasn't
+	 * been allocated yet and go ahead allocating it in parallel, but
+	 * only one of them must survive and be shared otherwise we'd leak
+	 * memory with a dangling notifier callback.
+	 */
+	spin_lock(&file->f_lock);
+	if (!file->private_data) {
+		file->private_data = poll;
+	} else {
+		/* someone else raced ahead of us */
+		vcs_poll_data_free(poll);
+		poll = file->private_data;
+	}
+	spin_unlock(&file->f_lock);
+
+	return poll;
+}
+
 static int
 vcs_size(struct inode *inode)
 {
@@ -102,6 +188,7 @@
 	struct inode *inode = file->f_path.dentry->d_inode;
 	unsigned int currcons = iminor(inode);
 	struct vc_data *vc;
+	struct vcs_poll_data *poll;
 	long pos;
 	long viewed, attr, read;
 	int col, maxcol;
@@ -134,6 +221,9 @@
 	ret = -EINVAL;
 	if (pos < 0)
 		goto unlock_out;
+	poll = file->private_data;
+	if (count && poll)
+		poll->seen_last_update = true;
 	read = 0;
 	ret = 0;
 	while (count) {
@@ -448,6 +538,8 @@
 	}
 	*ppos += written;
 	ret = written;
+	if (written)
+		vcs_scr_updated(vc);
 
 unlock_out:
 	release_console_sem();
@@ -457,6 +549,37 @@
 	return ret;
 }
 
+static unsigned int
+vcs_poll(struct file *file, poll_table *wait)
+{
+	struct vcs_poll_data *poll = vcs_poll_data_get(file);
+	int ret = 0;
+
+	if (poll) {
+		poll_wait(file, &poll->waitq, wait);
+		if (!poll->seen_last_update)
+			ret = POLLIN | POLLRDNORM;
+	}
+	return ret;
+}
+
+static int
+vcs_fasync(int fd, struct file *file, int on)
+{
+	struct vcs_poll_data *poll = file->private_data;
+
+	if (!poll) {
+		/* don't allocate anything if all we want is disable fasync */
+		if (!on)
+			return 0;
+		poll = vcs_poll_data_get(file);
+		if (!poll)
+			return -ENOMEM;
+	}
+
+	return fasync_helper(fd, file, on, &poll->fasync);
+}
+
 static int
 vcs_open(struct inode *inode, struct file *filp)
 {
@@ -470,11 +593,23 @@
 	return ret;
 }
 
+static int vcs_release(struct inode *inode, struct file *file)
+{
+	struct vcs_poll_data *poll = file->private_data;
+
+	if (poll)
+		vcs_poll_data_free(poll);
+	return 0;
+}
+
 static const struct file_operations vcs_fops = {
 	.llseek		= vcs_lseek,
 	.read		= vcs_read,
 	.write		= vcs_write,
+	.poll		= vcs_poll,
+	.fasync		= vcs_fasync,
 	.open		= vcs_open,
+	.release	= vcs_release,
 };
 
 static struct class *vc_class;
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 42f7fa4..ad6e64a 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -46,7 +46,7 @@
 #include <linux/completion.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #include <asm/uaccess.h>
@@ -64,6 +64,7 @@
 #define VIOTAPE_KERN_WARN	KERN_WARNING "viotape: "
 #define VIOTAPE_KERN_INFO	KERN_INFO "viotape: "
 
+static DEFINE_MUTEX(proc_viotape_mutex);
 static int viotape_numdev;
 
 /*
@@ -684,9 +685,9 @@
 {
 	long rc;
 
-	lock_kernel();
+	mutex_lock(&proc_viotape_mutex);
 	rc = viotap_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&proc_viotape_mutex);
 	return rc;
 }
 
@@ -700,7 +701,7 @@
 	if (op == NULL)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&proc_viotape_mutex);
 	get_dev_info(file->f_path.dentry->d_inode, &devi);
 
 	/* Note: We currently only support one mode! */
@@ -731,7 +732,7 @@
 
 free_op:
 	free_op_struct(op);
-	unlock_kernel();
+	mutex_unlock(&proc_viotape_mutex);
 	return ret;
 }
 
@@ -804,6 +805,7 @@
 	.unlocked_ioctl =	viotap_unlocked_ioctl,
 	.open =			viotap_open,
 	.release =		viotap_release,
+	.llseek = 		noop_llseek,
 };
 
 /* Handle interrupt events for tape */
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 281aada..a8ec48e 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -4182,6 +4182,11 @@
 	}
 }
 
+void vcs_scr_updated(struct vc_data *vc)
+{
+	notify_update(vc);
+}
+
 /*
  *	Visible symbols for modules
  */
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index b663d57..9f2272e 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -81,7 +81,6 @@
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/sysctl.h>
 #include <linux/fs.h>
 #include <linux/cdev.h>
@@ -112,6 +111,7 @@
 #define HWICAP_DEVICES 1
 
 /* An array, which is set to true when the device is registered. */
+static DEFINE_MUTEX(hwicap_mutex);
 static bool probed_devices[HWICAP_DEVICES];
 static struct mutex icap_sem;
 
@@ -502,7 +502,7 @@
 	struct hwicap_drvdata *drvdata;
 	int status;
 
-	lock_kernel();
+	mutex_lock(&hwicap_mutex);
 	drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
 
 	status = mutex_lock_interruptible(&drvdata->sem);
@@ -528,7 +528,7 @@
  error:
 	mutex_unlock(&drvdata->sem);
  out:
-	unlock_kernel();
+	mutex_unlock(&hwicap_mutex);
 	return status;
 }
 
@@ -567,6 +567,7 @@
 	.read = hwicap_read,
 	.open = hwicap_open,
 	.release = hwicap_release,
+	.llseek = noop_llseek,
 };
 
 static int __devinit hwicap_setup(struct device *dev, int id,
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 557e227..ae2b871 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -157,6 +157,7 @@
 	.owner		= THIS_MODULE,
 	.open		= coh901318_debugfs_open,
 	.read		= coh901318_debugfs_read,
+	.llseek		= default_llseek,
 };
 
 
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index 8528b10..bf184fb 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -405,6 +405,7 @@
 	.poll =			nosy_poll,
 	.open =			nosy_open,
 	.release =		nosy_release,
+	.llseek =		noop_llseek,
 };
 
 #define PHY_PACKET_SIZE 12 /* 1 payload, 1 inverse, 1 ack = 3 quadlets */
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 4cab0c6..7af4436 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -73,7 +73,8 @@
 
 config DRM_I810
 	tristate "Intel I810"
-	depends on DRM && AGP && AGP_INTEL
+	# BKL usage in order to avoid AB-BA deadlocks, may become BROKEN_ON_SMP
+	depends on DRM && AGP && AGP_INTEL && BKL
 	help
 	  Choose this option if you have an Intel I810 graphics card.  If M is
 	  selected, the module will be called i810.  AGP support is required
@@ -86,6 +87,8 @@
 
 config DRM_I830
 	tristate "i830 driver"
+	# BKL usage in order to avoid AB-BA deadlocks, i830 may get removed
+	depends on BKL
 	help
 	  Choose this option if you have a system that has Intel 830M, 845G,
 	  852GM, 855GM or 865G integrated graphics.  If M is selected, the
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 84da748..ff6690f 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -284,7 +284,8 @@
 /** File operations structure */
 static const struct file_operations drm_stub_fops = {
 	.owner = THIS_MODULE,
-	.open = drm_stub_open
+	.open = drm_stub_open,
+	.llseek = noop_llseek,
 };
 
 static int __init drm_core_init(void)
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index fb07e73..ff33e53 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -119,6 +119,7 @@
 	.unlocked_ioctl = i810_ioctl,
 	.mmap = i810_mmap_buffers,
 	.fasync = drm_fasync,
+	.llseek = noop_llseek,
 };
 
 static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c
index b4250b2..fe69914c 100644
--- a/drivers/gpu/drm/i810/i810_drv.c
+++ b/drivers/gpu/drm/i810/i810_drv.c
@@ -63,6 +63,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c
index cc92c7e..ca6f31f 100644
--- a/drivers/gpu/drm/i830/i830_dma.c
+++ b/drivers/gpu/drm/i830/i830_dma.c
@@ -121,6 +121,7 @@
 	.unlocked_ioctl = i830_ioctl,
 	.mmap = i830_mmap_buffers,
 	.fasync = drm_fasync,
+	.llseek = noop_llseek,
 };
 
 static int i830_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c
index a5c66aa..5b6298b 100644
--- a/drivers/gpu/drm/i830/i830_drv.c
+++ b/drivers/gpu/drm/i830/i830_drv.c
@@ -74,6 +74,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 5e43d70..0481497 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -782,6 +782,7 @@
 	.open = i915_wedged_open,
 	.read = i915_wedged_read,
 	.write = i915_wedged_write,
+	.llseek = default_llseek,
 };
 
 /* As the drm_debugfs_init() routines are called before dev->dev_private is
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 6dbe14c..895ab89 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -548,6 +548,7 @@
 #ifdef CONFIG_COMPAT
 		 .compat_ioctl = i915_compat_ioctl,
 #endif
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c
index 26d0d8c..ac64f0b 100644
--- a/drivers/gpu/drm/mga/mga_drv.c
+++ b/drivers/gpu/drm/mga/mga_drv.c
@@ -75,6 +75,7 @@
 #ifdef CONFIG_COMPAT
 		.compat_ioctl = mga_compat_ioctl,
 #endif
+		.llseek = noop_llseek,
 	},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 1de5eb5..eb15345 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -393,6 +393,7 @@
 #if defined(CONFIG_COMPAT)
 		.compat_ioctl = nouveau_compat_ioctl,
 #endif
+		.llseek = noop_llseek,
 	},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
index 1e2971f..d42c76c 100644
--- a/drivers/gpu/drm/r128/r128_drv.c
+++ b/drivers/gpu/drm/r128/r128_drv.c
@@ -71,6 +71,7 @@
 #ifdef CONFIG_COMPAT
 		.compat_ioctl = r128_compat_ioctl,
 #endif
+		.llseek = noop_llseek,
 	},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 795403b..29c1237 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -219,6 +219,7 @@
 #ifdef CONFIG_COMPAT
 		 .compat_ioctl = radeon_compat_ioctl,
 #endif
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c
index 021de44..2a2830f 100644
--- a/drivers/gpu/drm/savage/savage_drv.c
+++ b/drivers/gpu/drm/savage/savage_drv.c
@@ -54,6 +54,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 
 	.pci_driver = {
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
index 776bf9e..4bb10ef 100644
--- a/drivers/gpu/drm/sis/sis_drv.c
+++ b/drivers/gpu/drm/sis/sis_drv.c
@@ -83,6 +83,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 	.pci_driver = {
 		 .name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c
index ec5a43e..640567e 100644
--- a/drivers/gpu/drm/tdfx/tdfx_drv.c
+++ b/drivers/gpu/drm/tdfx/tdfx_drv.c
@@ -52,6 +52,7 @@
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
+		 .llseek = noop_llseek,
 	},
 	.pci_driver = {
 		 .name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index 7a1b210..b8984a5 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -62,6 +62,7 @@
 		.mmap = drm_mmap,
 		.poll = drm_poll,
 		.fasync = drm_fasync,
+		.llseek = noop_llseek,
 		},
 	.pci_driver = {
 		.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index a96ed6d..2ef93df 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -820,6 +820,7 @@
 #if defined(CONFIG_COMPAT)
 		 .compat_ioctl = drm_compat_ioctl,
 #endif
+		 .llseek = noop_llseek,
 		 },
 	.pci_driver = {
 		       .name = VMWGFX_DRIVER_NAME,
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index f366f96..c380c65 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -1211,6 +1211,7 @@
 	.poll = vga_arb_fpoll,
 	.open = vga_arb_open,
 	.release = vga_arb_release,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice vga_arb_device = {
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index a0dea3d..3cb6632 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1662,6 +1662,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_YUREX) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 850d02a..61a3e57 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -1051,6 +1051,7 @@
 	.read           = hid_debug_events_read,
 	.poll		= hid_debug_events_poll,
 	.release        = hid_debug_events_release,
+	.llseek		= noop_llseek,
 };
 
 
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index c5ae5f1..855aa8e 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -304,6 +304,9 @@
 #define USB_VENDOR_ID_IMATION		0x0718
 #define USB_DEVICE_ID_DISC_STAKKA	0xd000
 
+#define USB_VENDOR_ID_JESS		0x0c45
+#define USB_DEVICE_ID_JESS_YUREX	0x1010
+
 #define USB_VENDOR_ID_KBGEAR		0x084e
 #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO	0x1001
 
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index f6e80c7..5a6879e 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -384,6 +384,7 @@
 	.poll = roccat_poll,
 	.open = roccat_open,
 	.release = roccat_release,
+	.llseek = noop_llseek,
 };
 
 static int __init roccat_init(void)
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index a3866b5..925992f 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -340,6 +340,7 @@
 	.open =         hidraw_open,
 	.release =      hidraw_release,
 	.unlocked_ioctl = hidraw_ioctl,
+	.llseek =	noop_llseek,
 };
 
 void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 681e620..dfcb276 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -847,6 +847,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= hiddev_compat_ioctl,
 #endif
+	.llseek		= noop_llseek,
 };
 
 static char *hiddev_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 653db1b..23b8555 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -762,6 +762,7 @@
 	.read		= atk_debugfs_ggrp_read,
 	.open		= atk_debugfs_ggrp_open,
 	.release	= atk_debugfs_ggrp_release,
+	.llseek		= no_llseek,
 };
 
 static void atk_debugfs_init(struct atk_data *data)
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index b7ca2a9..d4d4ca6 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -38,7 +38,6 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
-#include <linux/smp_lock.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
@@ -50,6 +49,7 @@
 #include <linux/kref.h>
 
 /* Addresses to scan */
+static DEFINE_MUTEX(watchdog_mutex);
 static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
 
 /* Insmod parameters */
@@ -858,7 +858,7 @@
 	int i, ret = 0;
 	struct fschmd_data *data = filp->private_data;
 
-	lock_kernel();
+	mutex_lock(&watchdog_mutex);
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
 		ident.firmware_version = data->revision;
@@ -915,7 +915,7 @@
 	default:
 		ret = -ENOTTY;
 	}
-	unlock_kernel();
+	mutex_unlock(&watchdog_mutex);
 	return ret;
 }
 
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 697202e..8e540ad 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -35,7 +35,6 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
-#include <linux/smp_lock.h>
 #include <linux/hwmon-vid.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
@@ -52,6 +51,7 @@
 #define WATCHDOG_TIMEOUT 2	/* 2 minute default timeout */
 
 /* Addresses to scan */
+static DEFINE_MUTEX(watchdog_mutex);
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
 						I2C_CLIENT_END };
 
@@ -1333,7 +1333,7 @@
 	int val, ret = 0;
 	struct w83793_data *data = filp->private_data;
 
-	lock_kernel();
+	mutex_lock(&watchdog_mutex);
 	switch (cmd) {
 	case WDIOC_GETSUPPORT:
 		if (!nowayout)
@@ -1387,7 +1387,7 @@
 	default:
 		ret = -ENOTTY;
 	}
-	unlock_kernel();
+	mutex_unlock(&watchdog_mutex);
 	return ret;
 }
 
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 31fc769..0c73fe3 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -31,7 +31,6 @@
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
@@ -52,6 +51,7 @@
 
 #include "ide-cd.h"
 
+static DEFINE_MUTEX(ide_cd_mutex);
 static DEFINE_MUTEX(idecd_ref_mutex);
 
 static void ide_cd_release(struct device *);
@@ -1602,7 +1602,7 @@
 	struct cdrom_info *info;
 	int rc = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&ide_cd_mutex);
 	info = ide_cd_get(bdev->bd_disk);
 	if (!info)
 		goto out;
@@ -1611,7 +1611,7 @@
 	if (rc < 0)
 		ide_cd_put(info);
 out:
-	unlock_kernel();
+	mutex_unlock(&ide_cd_mutex);
 	return rc;
 }
 
@@ -1619,11 +1619,11 @@
 {
 	struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
 
-	lock_kernel();
+	mutex_lock(&ide_cd_mutex);
 	cdrom_release(&info->devinfo, mode);
 
 	ide_cd_put(info);
-	unlock_kernel();
+	mutex_unlock(&ide_cd_mutex);
 
 	return 0;
 }
@@ -1694,9 +1694,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ide_cd_mutex);
 	ret = idecd_locked_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ide_cd_mutex);
 
 	return ret;
 }
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7433e07..7c5b01c 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -516,10 +516,10 @@
 	return ide_no_data_taskfile(drive, &cmd);
 }
 
-static void update_ordered(ide_drive_t *drive)
+static void update_flush(ide_drive_t *drive)
 {
 	u16 *id = drive->id;
-	unsigned ordered = QUEUE_ORDERED_NONE;
+	unsigned flush = 0;
 
 	if (drive->dev_flags & IDE_DFLAG_WCACHE) {
 		unsigned long long capacity;
@@ -543,13 +543,12 @@
 		       drive->name, barrier ? "" : "not ");
 
 		if (barrier) {
-			ordered = QUEUE_ORDERED_DRAIN_FLUSH;
+			flush = REQ_FLUSH;
 			blk_queue_prep_rq(drive->queue, idedisk_prep_fn);
 		}
-	} else
-		ordered = QUEUE_ORDERED_DRAIN;
+	}
 
-	blk_queue_ordered(drive->queue, ordered);
+	blk_queue_flush(drive->queue, flush);
 }
 
 ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
@@ -572,7 +571,7 @@
 		}
 	}
 
-	update_ordered(drive);
+	update_flush(drive);
 
 	return err;
 }
diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c
index ec94c66..da36f72 100644
--- a/drivers/ide/ide-disk_ioctl.c
+++ b/drivers/ide/ide-disk_ioctl.c
@@ -1,10 +1,11 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 #include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include "ide-disk.h"
 
+static DEFINE_MUTEX(ide_disk_ioctl_mutex);
 static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
 { HDIO_GET_ADDRESS,	HDIO_SET_ADDRESS,   &ide_devset_address   },
 { HDIO_GET_MULTCOUNT,	HDIO_SET_MULTCOUNT, &ide_devset_multcount },
@@ -19,13 +20,13 @@
 {
 	int err;
 
-	lock_kernel();
+	mutex_lock(&ide_disk_ioctl_mutex);
 	err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
 	if (err != -EOPNOTSUPP)
 		goto out;
 
 	err = generic_ide_ioctl(drive, bdev, cmd, arg);
 out:
-	unlock_kernel();
+	mutex_unlock(&ide_disk_ioctl_mutex);
 	return err;
 }
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index fd3d05a..d267b7a 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -5,7 +5,7 @@
 #include <linux/kernel.h>
 #include <linux/ide.h>
 #include <linux/cdrom.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/unaligned.h>
 
@@ -32,6 +32,7 @@
  * On exit we set nformats to the number of records we've actually initialized.
  */
 
+static DEFINE_MUTEX(ide_floppy_ioctl_mutex);
 static int ide_floppy_get_format_capacities(ide_drive_t *drive,
 					    struct ide_atapi_pc *pc,
 					    int __user *arg)
@@ -276,7 +277,7 @@
 	void __user *argp = (void __user *)arg;
 	int err;
 
-	lock_kernel();
+	mutex_lock(&ide_floppy_ioctl_mutex);
 	if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) {
 		err = ide_floppy_lockdoor(drive, &pc, arg, cmd);
 		goto out;
@@ -298,6 +299,6 @@
 		err = generic_ide_ioctl(drive, bdev, cmd, arg);
 
 out:
-	unlock_kernel();
+	mutex_unlock(&ide_floppy_ioctl_mutex);
 	return err;
 }
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index 70aeeb1..35c4b43 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -1,4 +1,3 @@
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -23,6 +22,7 @@
 #define IDE_GD_VERSION	"1.18"
 
 /* module parameters */
+static DEFINE_MUTEX(ide_gd_mutex);
 static unsigned long debug_mask;
 module_param(debug_mask, ulong, 0644);
 
@@ -242,9 +242,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ide_gd_mutex);
 	ret = ide_gd_open(bdev, mode);
-	unlock_kernel();
+	mutex_unlock(&ide_gd_mutex);
 
 	return ret;
 }
@@ -257,7 +257,7 @@
 
 	ide_debug_log(IDE_DBG_FUNC, "enter");
 
-	lock_kernel();
+	mutex_lock(&ide_gd_mutex);
 	if (idkp->openers == 1)
 		drive->disk_ops->flush(drive);
 
@@ -269,7 +269,7 @@
 	idkp->openers--;
 
 	ide_disk_put(idkp);
-	unlock_kernel();
+	mutex_unlock(&ide_gd_mutex);
 
 	return 0;
 }
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index a381be8..999dac0 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -441,19 +441,6 @@
 	struct request	*rq = NULL;
 	ide_startstop_t	startstop;
 
-	/*
-	 * drive is doing pre-flush, ordered write, post-flush sequence. even
-	 * though that is 3 requests, it must be seen as a single transaction.
-	 * we must not preempt this drive until that is complete
-	 */
-	if (blk_queue_flushing(q))
-		/*
-		 * small race where queue could get replugged during
-		 * the 3-request flush cycle, just yank the plug since
-		 * we want it to finish asap
-		 */
-		blk_remove_plug(q);
-
 	spin_unlock_irq(q->queue_lock);
 
 	/* HLD do_request() callback might sleep, make sure it's okay */
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 6d622cb..7ecb1ad 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -32,11 +32,9 @@
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
@@ -220,6 +218,7 @@
 	char write_prot;
 } idetape_tape_t;
 
+static DEFINE_MUTEX(ide_tape_mutex);
 static DEFINE_MUTEX(idetape_ref_mutex);
 
 static DEFINE_MUTEX(idetape_chrdev_mutex);
@@ -1426,9 +1425,9 @@
 				unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&ide_tape_mutex);
 	ret = do_idetape_chrdev_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ide_tape_mutex);
 	return ret;
 }
 
@@ -1903,15 +1902,16 @@
 	.unlocked_ioctl	= idetape_chrdev_ioctl,
 	.open		= idetape_chrdev_open,
 	.release	= idetape_chrdev_release,
+	.llseek		= noop_llseek,
 };
 
 static int idetape_open(struct block_device *bdev, fmode_t mode)
 {
 	struct ide_tape_obj *tape;
 
-	lock_kernel();
+	mutex_lock(&ide_tape_mutex);
 	tape = ide_tape_get(bdev->bd_disk, false, 0);
-	unlock_kernel();
+	mutex_unlock(&ide_tape_mutex);
 
 	if (!tape)
 		return -ENXIO;
@@ -1923,9 +1923,9 @@
 {
 	struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
 
-	lock_kernel();
+	mutex_lock(&ide_tape_mutex);
 	ide_tape_put(tape);
-	unlock_kernel();
+	mutex_unlock(&ide_tape_mutex);
 
 	return 0;
 }
@@ -1937,11 +1937,11 @@
 	ide_drive_t *drive = tape->drive;
 	int err;
 
-	lock_kernel();
+	mutex_lock(&ide_tape_mutex);
 	err = generic_ide_ioctl(drive, bdev, cmd, arg);
 	if (err == -EINVAL)
 		err = idetape_blkdev_ioctl(drive, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ide_tape_mutex);
 
 	return err;
 }
diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c
index 15341fc..c976285 100644
--- a/drivers/idle/i7300_idle.c
+++ b/drivers/idle/i7300_idle.c
@@ -536,6 +536,7 @@
 static const struct file_operations idle_fops = {
 	.open	= stats_open_generic,
 	.read	= stats_read_ul,
+	.llseek = default_llseek,
 };
 
 struct debugfs_file_info {
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index d4ce8b6..daef61d 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -65,7 +65,8 @@
 	.write = ipath_diag_write,
 	.read = ipath_diag_read,
 	.open = ipath_diag_open,
-	.release = ipath_diag_release
+	.release = ipath_diag_release,
+	.llseek = default_llseek,
 };
 
 static ssize_t ipath_diagpkt_write(struct file *fp,
@@ -75,6 +76,7 @@
 static const struct file_operations diagpkt_file_ops = {
 	.owner = THIS_MODULE,
 	.write = ipath_diagpkt_write,
+	.llseek = noop_llseek,
 };
 
 static atomic_t diagpkt_count = ATOMIC_INIT(0);
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 65eb892..6078992 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -63,7 +63,8 @@
 	.open = ipath_open,
 	.release = ipath_close,
 	.poll = ipath_poll,
-	.mmap = ipath_mmap
+	.mmap = ipath_mmap,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 2fca708..d13e726 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -103,6 +103,7 @@
 
 static const struct file_operations atomic_stats_ops = {
 	.read = atomic_stats_read,
+	.llseek = default_llseek,
 };
 
 static ssize_t atomic_counters_read(struct file *file, char __user *buf,
@@ -120,6 +121,7 @@
 
 static const struct file_operations atomic_counters_ops = {
 	.read = atomic_counters_read,
+	.llseek = default_llseek,
 };
 
 static ssize_t flash_read(struct file *file, char __user *buf,
@@ -224,6 +226,7 @@
 static const struct file_operations flash_ops = {
 	.read = flash_read,
 	.write = flash_write,
+	.llseek = default_llseek,
 };
 
 static int create_device_files(struct super_block *sb,
diff --git a/drivers/infiniband/hw/qib/qib_diag.c b/drivers/infiniband/hw/qib/qib_diag.c
index 05dcf0d..204c4dd 100644
--- a/drivers/infiniband/hw/qib/qib_diag.c
+++ b/drivers/infiniband/hw/qib/qib_diag.c
@@ -136,7 +136,8 @@
 	.write = qib_diag_write,
 	.read = qib_diag_read,
 	.open = qib_diag_open,
-	.release = qib_diag_release
+	.release = qib_diag_release,
+	.llseek = default_llseek,
 };
 
 static atomic_t diagpkt_count = ATOMIC_INIT(0);
@@ -149,6 +150,7 @@
 static const struct file_operations diagpkt_file_ops = {
 	.owner = THIS_MODULE,
 	.write = qib_diagpkt_write,
+	.llseek = noop_llseek,
 };
 
 int qib_diag_add(struct qib_devdata *dd)
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index 6b11645..aa2be21 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -63,7 +63,8 @@
 	.open = qib_open,
 	.release = qib_close,
 	.poll = qib_poll,
-	.mmap = qib_mmapf
+	.mmap = qib_mmapf,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index 9f989c0..a0e6613 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -367,6 +367,7 @@
 static const struct file_operations flash_ops = {
 	.read = flash_read,
 	.write = flash_write,
+	.llseek = default_llseek,
 };
 
 static int add_cntr_files(struct super_block *sb, struct qib_devdata *dd)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index af9ee31..535fea4 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -767,7 +767,8 @@
 	.compat_ioctl	= evdev_ioctl_compat,
 #endif
 	.fasync		= evdev_fasync,
-	.flush		= evdev_flush
+	.flush		= evdev_flush,
+	.llseek		= no_llseek,
 };
 
 static int evdev_install_chrdev(struct evdev *evdev)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ab69820..7919c25 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2047,6 +2047,7 @@
 static const struct file_operations input_fops = {
 	.owner = THIS_MODULE,
 	.open = input_open_file,
+	.llseek = noop_llseek,
 };
 
 static int __init input_init(void)
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 22239e9..9d424ceb 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -739,6 +739,7 @@
 	.compat_ioctl	= joydev_compat_ioctl,
 #endif
 	.fasync		= joydev_fasync,
+	.llseek		= no_llseek,
 };
 
 static int joydev_install_chrdev(struct joydev *joydev)
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 7e2c12a..0b4f542 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -43,7 +43,7 @@
 #include <linux/proc_fs.h>
 #include <linux/poll.h>
 #include <linux/rtc.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/semaphore.h>
 
 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
@@ -52,6 +52,7 @@
 
 #define RTC_VERSION "1.10d"
 
+static DEFINE_MUTEX(hp_sdc_rtc_mutex);
 static unsigned long epoch = 2000;
 
 static struct semaphore i8042tregs;
@@ -665,9 +666,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&hp_sdc_rtc_mutex);
 	ret = hp_sdc_rtc_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&hp_sdc_rtc_mutex);
 
 	return ret;
 }
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 3606985..b941078 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -811,6 +811,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= uinput_compat_ioctl,
 #endif
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice uinput_misc = {
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index d528a2d..31ec726 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -792,6 +792,7 @@
 	.open =		mousedev_open,
 	.release =	mousedev_release,
 	.fasync =	mousedev_fasync,
+	.llseek = noop_llseek,
 };
 
 static int mousedev_install_chrdev(struct mousedev *mousedev)
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 9986648..cd82bb1 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -243,6 +243,7 @@
 	.write =	serio_raw_write,
 	.poll =		serio_raw_poll,
 	.fasync =	serio_raw_fasync,
+	.llseek = noop_llseek,
 };
 
 
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 6d345112..6e362de 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -165,6 +165,7 @@
 	serio->open = serport_serio_open;
 	serio->close = serport_serio_close;
 	serio->port_data = serport;
+	serio->dev.parent = tty->dev;
 
 	serio_register_port(serport->serio);
 	printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index ed9c555..f332b60 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -15,7 +15,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/ioport.h>
-#include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
@@ -546,7 +545,6 @@
 		void *mem;
 
 		tasklet_kill(&pdpc->divas_task);
-		flush_scheduled_work();
 		mem = psoft_isr->object;
 		psoft_isr->object = NULL;
 		diva_os_free(0, mem);
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c
index de43c8c..859c81e 100644
--- a/drivers/isdn/mISDN/timerdev.c
+++ b/drivers/isdn/mISDN/timerdev.c
@@ -267,6 +267,7 @@
 	.unlocked_ioctl	= mISDN_ioctl,
 	.open		= mISDN_open,
 	.release	= mISDN_close,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice mISDNtimer = {
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 85b714d..3c781cd 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -514,6 +514,7 @@
 	.release = close,
 	.write	 = write,
 	.read	 = read,
+	.llseek  = default_llseek,
 };
 
 /*
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index bf64e49..75049e7 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -24,7 +24,6 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/pmu.h>
@@ -55,6 +54,7 @@
 extern struct adb_driver via_pmu_driver;
 extern struct adb_driver macio_adb_driver;
 
+static DEFINE_MUTEX(adb_mutex);
 static struct adb_driver *adb_driver_list[] = {
 #ifdef CONFIG_ADB_MACII
 	&via_macii_driver,
@@ -647,7 +647,7 @@
 	struct adbdev_state *state;
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&adb_mutex);
 	if (iminor(inode) > 0 || adb_controller == NULL) {
 		ret = -ENXIO;
 		goto out;
@@ -665,7 +665,7 @@
 	state->inuse = 1;
 
 out:
-	unlock_kernel();
+	mutex_unlock(&adb_mutex);
 	return ret;
 }
 
@@ -674,7 +674,7 @@
 	struct adbdev_state *state = file->private_data;
 	unsigned long flags;
 
-	lock_kernel();
+	mutex_lock(&adb_mutex);
 	if (state) {
 		file->private_data = NULL;
 		spin_lock_irqsave(&state->lock, flags);
@@ -687,7 +687,7 @@
 			spin_unlock_irqrestore(&state->lock, flags);
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&adb_mutex);
 	return 0;
 }
 
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index a3d25da..1a57e88 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -137,6 +137,7 @@
 	.write		= anslcd_write,
 	.unlocked_ioctl	= anslcd_ioctl,
 	.open		= anslcd_open,
+	.llseek		= default_llseek,
 };
 
 static struct miscdevice anslcd_dev = {
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index e58c3d3..290cb32 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -19,7 +19,6 @@
  *    the userland interface
  */
 
-#include <linux/smp_lock.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -97,6 +96,7 @@
  * I don't think there will ever be more than one SMU, so
  * for now, just hard code that
  */
+static DEFINE_MUTEX(smu_mutex);
 static struct smu_device	*smu;
 static DEFINE_MUTEX(smu_part_access);
 static int smu_irq_inited;
@@ -1095,12 +1095,12 @@
 	pp->mode = smu_file_commands;
 	init_waitqueue_head(&pp->wait);
 
-	lock_kernel();
+	mutex_lock(&smu_mutex);
 	spin_lock_irqsave(&smu_clist_lock, flags);
 	list_add(&pp->list, &smu_clist);
 	spin_unlock_irqrestore(&smu_clist_lock, flags);
 	file->private_data = pp;
-	unlock_kernel();
+	mutex_unlock(&smu_mutex);
 
 	return 0;
 }
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 2d17e76..cd29c82 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -18,7 +18,7 @@
  *
  */
 #include <stdarg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -73,6 +73,7 @@
 /* How many iterations between battery polls */
 #define BATTERY_POLLING_COUNT	2
 
+static DEFINE_MUTEX(pmu_info_proc_mutex);
 static volatile unsigned char __iomem *via;
 
 /* VIA registers - spaced 0x200 bytes apart */
@@ -2078,7 +2079,7 @@
 	pp->rb_get = pp->rb_put = 0;
 	spin_lock_init(&pp->lock);
 	init_waitqueue_head(&pp->wait);
-	lock_kernel();
+	mutex_lock(&pmu_info_proc_mutex);
 	spin_lock_irqsave(&all_pvt_lock, flags);
 #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
 	pp->backlight_locker = 0;
@@ -2086,7 +2087,7 @@
 	list_add(&pp->list, &all_pmu_pvt);
 	spin_unlock_irqrestore(&all_pvt_lock, flags);
 	file->private_data = pp;
-	unlock_kernel();
+	mutex_unlock(&pmu_info_proc_mutex);
 	return 0;
 }
 
@@ -2343,9 +2344,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&pmu_info_proc_mutex);
 	ret = pmu_ioctl(filp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&pmu_info_proc_mutex);
 
 	return ret;
 }
@@ -2398,6 +2399,7 @@
 #endif
 	.open		= pmu_open,
 	.release	= pmu_release,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice pmu_device = {
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 368e8e9..d5b0e4c 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1278,7 +1278,7 @@
 	struct dm_crypt_io *io;
 	struct crypt_config *cc;
 
-	if (unlikely(bio_empty_barrier(bio))) {
+	if (bio->bi_rw & REQ_FLUSH) {
 		cc = ti->private;
 		bio->bi_bdev = cc->dev->bdev;
 		return DM_MAPIO_REMAPPED;
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 0590c75..136d4f7 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -31,7 +31,6 @@
  */
 struct io {
 	unsigned long error_bits;
-	unsigned long eopnotsupp_bits;
 	atomic_t count;
 	struct task_struct *sleeper;
 	struct dm_io_client *client;
@@ -130,11 +129,8 @@
  *---------------------------------------------------------------*/
 static void dec_count(struct io *io, unsigned int region, int error)
 {
-	if (error) {
+	if (error)
 		set_bit(region, &io->error_bits);
-		if (error == -EOPNOTSUPP)
-			set_bit(region, &io->eopnotsupp_bits);
-	}
 
 	if (atomic_dec_and_test(&io->count)) {
 		if (io->sleeper)
@@ -310,8 +306,8 @@
 	sector_t remaining = where->count;
 
 	/*
-	 * where->count may be zero if rw holds a write barrier and we
-	 * need to send a zero-sized barrier.
+	 * where->count may be zero if rw holds a flush and we need to
+	 * send a zero-sized flush.
 	 */
 	do {
 		/*
@@ -364,7 +360,7 @@
 	 */
 	for (i = 0; i < num_regions; i++) {
 		*dp = old_pages;
-		if (where[i].count || (rw & REQ_HARDBARRIER))
+		if (where[i].count || (rw & REQ_FLUSH))
 			do_region(rw, i, where + i, dp, io);
 	}
 
@@ -393,9 +389,7 @@
 		return -EIO;
 	}
 
-retry:
 	io->error_bits = 0;
-	io->eopnotsupp_bits = 0;
 	atomic_set(&io->count, 1); /* see dispatch_io() */
 	io->sleeper = current;
 	io->client = client;
@@ -412,11 +406,6 @@
 	}
 	set_current_state(TASK_RUNNING);
 
-	if (io->eopnotsupp_bits && (rw & REQ_HARDBARRIER)) {
-		rw &= ~REQ_HARDBARRIER;
-		goto retry;
-	}
-
 	if (error_bits)
 		*error_bits = io->error_bits;
 
@@ -437,7 +426,6 @@
 
 	io = mempool_alloc(client->pool, GFP_NOIO);
 	io->error_bits = 0;
-	io->eopnotsupp_bits = 0;
 	atomic_set(&io->count, 1); /* see dispatch_io() */
 	io->sleeper = NULL;
 	io->client = client;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 3e39193..4b54618 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1596,6 +1596,7 @@
 	.unlocked_ioctl	 = dm_ctl_ioctl,
 	.compat_ioctl = dm_compat_ctl_ioctl,
 	.owner	 = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice _dm_misc = {
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 5a08be0..33420e6 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -300,7 +300,7 @@
 		.count = 0,
 	};
 
-	lc->io_req.bi_rw = WRITE_BARRIER;
+	lc->io_req.bi_rw = WRITE_FLUSH;
 
 	return dm_io(&lc->io_req, 1, &null_location, NULL);
 }
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 7c081bc..19a59b0 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -259,7 +259,7 @@
 	struct dm_io_region io[ms->nr_mirrors];
 	struct mirror *m;
 	struct dm_io_request io_req = {
-		.bi_rw = WRITE_BARRIER,
+		.bi_rw = WRITE_FLUSH,
 		.mem.type = DM_IO_KMEM,
 		.mem.ptr.bvec = NULL,
 		.client = ms->io_client,
@@ -629,7 +629,7 @@
 	struct dm_io_region io[ms->nr_mirrors], *dest = io;
 	struct mirror *m;
 	struct dm_io_request io_req = {
-		.bi_rw = WRITE | (bio->bi_rw & WRITE_BARRIER),
+		.bi_rw = WRITE | (bio->bi_rw & WRITE_FLUSH_FUA),
 		.mem.type = DM_IO_BVEC,
 		.mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx,
 		.notify.fn = write_callback,
@@ -670,7 +670,7 @@
 	bio_list_init(&requeue);
 
 	while ((bio = bio_list_pop(writes))) {
-		if (unlikely(bio_empty_barrier(bio))) {
+		if (bio->bi_rw & REQ_FLUSH) {
 			bio_list_add(&sync, bio);
 			continue;
 		}
@@ -1203,7 +1203,7 @@
 	 * We need to dec pending if this was a write.
 	 */
 	if (rw == WRITE) {
-		if (likely(!bio_empty_barrier(bio)))
+		if (!(bio->bi_rw & REQ_FLUSH))
 			dm_rh_dec(ms->rh, map_context->ll);
 		return error;
 	}
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index bd5c58b..dad011a 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -81,9 +81,9 @@
 	struct list_head failed_recovered_regions;
 
 	/*
-	 * If there was a barrier failure no regions can be marked clean.
+	 * If there was a flush failure no regions can be marked clean.
 	 */
-	int barrier_failure;
+	int flush_failure;
 
 	void *context;
 	sector_t target_begin;
@@ -217,7 +217,7 @@
 	INIT_LIST_HEAD(&rh->quiesced_regions);
 	INIT_LIST_HEAD(&rh->recovered_regions);
 	INIT_LIST_HEAD(&rh->failed_recovered_regions);
-	rh->barrier_failure = 0;
+	rh->flush_failure = 0;
 
 	rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
 						      sizeof(struct dm_region));
@@ -399,8 +399,8 @@
 	region_t region = dm_rh_bio_to_region(rh, bio);
 	int recovering = 0;
 
-	if (bio_empty_barrier(bio)) {
-		rh->barrier_failure = 1;
+	if (bio->bi_rw & REQ_FLUSH) {
+		rh->flush_failure = 1;
 		return;
 	}
 
@@ -524,7 +524,7 @@
 	struct bio *bio;
 
 	for (bio = bios->head; bio; bio = bio->bi_next) {
-		if (bio_empty_barrier(bio))
+		if (bio->bi_rw & REQ_FLUSH)
 			continue;
 		rh_inc(rh, dm_rh_bio_to_region(rh, bio));
 	}
@@ -555,9 +555,9 @@
 		 */
 
 		/* do nothing for DM_RH_NOSYNC */
-		if (unlikely(rh->barrier_failure)) {
+		if (unlikely(rh->flush_failure)) {
 			/*
-			 * If a write barrier failed some time ago, we
+			 * If a write flush failed some time ago, we
 			 * don't know whether or not this write made it
 			 * to the disk, so we must resync the device.
 			 */
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index cc2bdb8..0b61792 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -687,7 +687,7 @@
 	/*
 	 * Commit exceptions to disk.
 	 */
-	if (ps->valid && area_io(ps, WRITE_BARRIER))
+	if (ps->valid && area_io(ps, WRITE_FLUSH_FUA))
 		ps->valid = 0;
 
 	/*
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 5974d30..53cf79d 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -706,8 +706,6 @@
 	return 0;
 }
 
-#define min_not_zero(l, r) (((l) == 0) ? (r) : (((r) == 0) ? (l) : min(l, r)))
-
 /*
  * Return a minimum chunk size of all snapshots that have the specified origin.
  * Return zero if the origin has no snapshots.
@@ -1587,7 +1585,7 @@
 	chunk_t chunk;
 	struct dm_snap_pending_exception *pe = NULL;
 
-	if (unlikely(bio_empty_barrier(bio))) {
+	if (bio->bi_rw & REQ_FLUSH) {
 		bio->bi_bdev = s->cow->bdev;
 		return DM_MAPIO_REMAPPED;
 	}
@@ -1691,7 +1689,7 @@
 	int r = DM_MAPIO_REMAPPED;
 	chunk_t chunk;
 
-	if (unlikely(bio_empty_barrier(bio))) {
+	if (bio->bi_rw & REQ_FLUSH) {
 		if (!map_context->target_request_nr)
 			bio->bi_bdev = s->origin->bdev;
 		else
@@ -2135,7 +2133,7 @@
 	struct dm_dev *dev = ti->private;
 	bio->bi_bdev = dev->bdev;
 
-	if (unlikely(bio_empty_barrier(bio)))
+	if (bio->bi_rw & REQ_FLUSH)
 		return DM_MAPIO_REMAPPED;
 
 	/* Only tell snapshots if this is a write */
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index c297f6d..f0371b4 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -271,7 +271,7 @@
 	uint32_t stripe;
 	unsigned target_request_nr;
 
-	if (unlikely(bio_empty_barrier(bio))) {
+	if (bio->bi_rw & REQ_FLUSH) {
 		target_request_nr = map_context->target_request_nr;
 		BUG_ON(target_request_nr >= sc->stripes);
 		bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index f9fc07d..90267f8 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -486,11 +486,6 @@
 	return 0;
 }
 
-/*
- * Returns the minimum that is _not_ zero, unless both are zero.
- */
-#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
-
 int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
 			 sector_t start, sector_t len, void *data)
 {
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index ac384b2..7cb1352 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -15,7 +15,6 @@
 #include <linux/blkpg.h>
 #include <linux/bio.h>
 #include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
 #include <linux/mempool.h>
 #include <linux/slab.h>
 #include <linux/idr.h>
@@ -33,6 +32,7 @@
 #define DM_COOKIE_ENV_VAR_NAME "DM_COOKIE"
 #define DM_COOKIE_LENGTH 24
 
+static DEFINE_MUTEX(dm_mutex);
 static const char *_name = DM_NAME;
 
 static unsigned int major = 0;
@@ -110,7 +110,6 @@
 #define DMF_FREEING 3
 #define DMF_DELETING 4
 #define DMF_NOFLUSH_SUSPENDING 5
-#define DMF_QUEUE_IO_TO_THREAD 6
 
 /*
  * Work processed by per-device workqueue.
@@ -144,24 +143,9 @@
 	spinlock_t deferred_lock;
 
 	/*
-	 * An error from the barrier request currently being processed.
-	 */
-	int barrier_error;
-
-	/*
-	 * Protect barrier_error from concurrent endio processing
-	 * in request-based dm.
-	 */
-	spinlock_t barrier_error_lock;
-
-	/*
-	 * Processing queue (flush/barriers)
+	 * Processing queue (flush)
 	 */
 	struct workqueue_struct *wq;
-	struct work_struct barrier_work;
-
-	/* A pointer to the currently processing pre/post flush request */
-	struct request *flush_request;
 
 	/*
 	 * The current mapping.
@@ -200,8 +184,8 @@
 	/* sysfs handle */
 	struct kobject kobj;
 
-	/* zero-length barrier that will be cloned and submitted to targets */
-	struct bio barrier_bio;
+	/* zero-length flush that will be cloned and submitted to targets */
+	struct bio flush_bio;
 };
 
 /*
@@ -344,7 +328,7 @@
 {
 	struct mapped_device *md;
 
-	lock_kernel();
+	mutex_lock(&dm_mutex);
 	spin_lock(&_minor_lock);
 
 	md = bdev->bd_disk->private_data;
@@ -362,7 +346,7 @@
 
 out:
 	spin_unlock(&_minor_lock);
-	unlock_kernel();
+	mutex_unlock(&dm_mutex);
 
 	return md ? 0 : -ENXIO;
 }
@@ -371,10 +355,10 @@
 {
 	struct mapped_device *md = disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&dm_mutex);
 	atomic_dec(&md->open_count);
 	dm_put(md);
-	unlock_kernel();
+	mutex_unlock(&dm_mutex);
 
 	return 0;
 }
@@ -512,7 +496,7 @@
 
 	/*
 	 * After this is decremented the bio must not be touched if it is
-	 * a barrier.
+	 * a flush.
 	 */
 	dm_disk(md)->part0.in_flight[rw] = pending =
 		atomic_dec_return(&md->pending[rw]);
@@ -528,16 +512,12 @@
  */
 static void queue_io(struct mapped_device *md, struct bio *bio)
 {
-	down_write(&md->io_lock);
+	unsigned long flags;
 
-	spin_lock_irq(&md->deferred_lock);
+	spin_lock_irqsave(&md->deferred_lock, flags);
 	bio_list_add(&md->deferred, bio);
-	spin_unlock_irq(&md->deferred_lock);
-
-	if (!test_and_set_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags))
-		queue_work(md->wq, &md->work);
-
-	up_write(&md->io_lock);
+	spin_unlock_irqrestore(&md->deferred_lock, flags);
+	queue_work(md->wq, &md->work);
 }
 
 /*
@@ -625,11 +605,9 @@
 			 * Target requested pushing back the I/O.
 			 */
 			spin_lock_irqsave(&md->deferred_lock, flags);
-			if (__noflush_suspending(md)) {
-				if (!(io->bio->bi_rw & REQ_HARDBARRIER))
-					bio_list_add_head(&md->deferred,
-							  io->bio);
-			} else
+			if (__noflush_suspending(md))
+				bio_list_add_head(&md->deferred, io->bio);
+			else
 				/* noflush suspend was interrupted. */
 				io->error = -EIO;
 			spin_unlock_irqrestore(&md->deferred_lock, flags);
@@ -637,32 +615,23 @@
 
 		io_error = io->error;
 		bio = io->bio;
+		end_io_acct(io);
+		free_io(md, io);
 
-		if (bio->bi_rw & REQ_HARDBARRIER) {
+		if (io_error == DM_ENDIO_REQUEUE)
+			return;
+
+		if ((bio->bi_rw & REQ_FLUSH) && bio->bi_size) {
 			/*
-			 * There can be just one barrier request so we use
-			 * a per-device variable for error reporting.
-			 * Note that you can't touch the bio after end_io_acct
-			 *
-			 * We ignore -EOPNOTSUPP for empty flush reported by
-			 * underlying devices. We assume that if the device
-			 * doesn't support empty barriers, it doesn't need
-			 * cache flushing commands.
+			 * Preflush done for flush with data, reissue
+			 * without REQ_FLUSH.
 			 */
-			if (!md->barrier_error &&
-			    !(bio_empty_barrier(bio) && io_error == -EOPNOTSUPP))
-				md->barrier_error = io_error;
-			end_io_acct(io);
-			free_io(md, io);
+			bio->bi_rw &= ~REQ_FLUSH;
+			queue_io(md, bio);
 		} else {
-			end_io_acct(io);
-			free_io(md, io);
-
-			if (io_error != DM_ENDIO_REQUEUE) {
-				trace_block_bio_complete(md->queue, bio);
-
-				bio_endio(bio, io_error);
-			}
+			/* done with normal IO or empty flush */
+			trace_block_bio_complete(md->queue, bio);
+			bio_endio(bio, io_error);
 		}
 	}
 }
@@ -755,23 +724,6 @@
 	blk_update_request(tio->orig, 0, nr_bytes);
 }
 
-static void store_barrier_error(struct mapped_device *md, int error)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&md->barrier_error_lock, flags);
-	/*
-	 * Basically, the first error is taken, but:
-	 *   -EOPNOTSUPP supersedes any I/O error.
-	 *   Requeue request supersedes any I/O error but -EOPNOTSUPP.
-	 */
-	if (!md->barrier_error || error == -EOPNOTSUPP ||
-	    (md->barrier_error != -EOPNOTSUPP &&
-	     error == DM_ENDIO_REQUEUE))
-		md->barrier_error = error;
-	spin_unlock_irqrestore(&md->barrier_error_lock, flags);
-}
-
 /*
  * Don't touch any member of the md after calling this function because
  * the md may be freed in dm_put() at the end of this function.
@@ -809,13 +761,11 @@
 static void dm_end_request(struct request *clone, int error)
 {
 	int rw = rq_data_dir(clone);
-	int run_queue = 1;
-	bool is_barrier = clone->cmd_flags & REQ_HARDBARRIER;
 	struct dm_rq_target_io *tio = clone->end_io_data;
 	struct mapped_device *md = tio->md;
 	struct request *rq = tio->orig;
 
-	if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !is_barrier) {
+	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		rq->errors = clone->errors;
 		rq->resid_len = clone->resid_len;
 
@@ -829,15 +779,8 @@
 	}
 
 	free_rq_clone(clone);
-
-	if (unlikely(is_barrier)) {
-		if (unlikely(error))
-			store_barrier_error(md, error);
-		run_queue = 0;
-	} else
-		blk_end_request_all(rq, error);
-
-	rq_completed(md, rw, run_queue);
+	blk_end_request_all(rq, error);
+	rq_completed(md, rw, true);
 }
 
 static void dm_unprep_request(struct request *rq)
@@ -862,16 +805,6 @@
 	struct request_queue *q = rq->q;
 	unsigned long flags;
 
-	if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) {
-		/*
-		 * Barrier clones share an original request.
-		 * Leave it to dm_end_request(), which handles this special
-		 * case.
-		 */
-		dm_end_request(clone, DM_ENDIO_REQUEUE);
-		return;
-	}
-
 	dm_unprep_request(rq);
 
 	spin_lock_irqsave(q->queue_lock, flags);
@@ -961,19 +894,6 @@
 	struct dm_rq_target_io *tio = clone->end_io_data;
 	struct request *rq = tio->orig;
 
-	if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) {
-		/*
-		 * Barrier clones share an original request.  So can't use
-		 * softirq_done with the original.
-		 * Pass the clone to dm_done() directly in this special case.
-		 * It is safe (even if clone->q->queue_lock is held here)
-		 * because there is no I/O dispatching during the completion
-		 * of barrier clone.
-		 */
-		dm_done(clone, error, true);
-		return;
-	}
-
 	tio->error = error;
 	rq->completion_data = clone;
 	blk_complete_request(rq);
@@ -990,17 +910,6 @@
 	struct dm_rq_target_io *tio = clone->end_io_data;
 	struct request *rq = tio->orig;
 
-	if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) {
-		/*
-		 * Barrier clones share an original request.
-		 * Leave it to dm_end_request(), which handles this special
-		 * case.
-		 */
-		BUG_ON(error > 0);
-		dm_end_request(clone, error);
-		return;
-	}
-
 	rq->cmd_flags |= REQ_FAILED;
 	dm_complete_request(clone, error);
 }
@@ -1119,7 +1028,7 @@
 }
 
 /*
- * Creates a little bio that is just does part of a bvec.
+ * Creates a little bio that just does part of a bvec.
  */
 static struct bio *split_bvec(struct bio *bio, sector_t sector,
 			      unsigned short idx, unsigned int offset,
@@ -1134,7 +1043,7 @@
 
 	clone->bi_sector = sector;
 	clone->bi_bdev = bio->bi_bdev;
-	clone->bi_rw = bio->bi_rw & ~REQ_HARDBARRIER;
+	clone->bi_rw = bio->bi_rw;
 	clone->bi_vcnt = 1;
 	clone->bi_size = to_bytes(len);
 	clone->bi_io_vec->bv_offset = offset;
@@ -1161,7 +1070,6 @@
 
 	clone = bio_alloc_bioset(GFP_NOIO, bio->bi_max_vecs, bs);
 	__bio_clone(clone, bio);
-	clone->bi_rw &= ~REQ_HARDBARRIER;
 	clone->bi_destructor = dm_bio_destructor;
 	clone->bi_sector = sector;
 	clone->bi_idx = idx;
@@ -1225,16 +1133,15 @@
 		__issue_target_request(ci, ti, request_nr, len);
 }
 
-static int __clone_and_map_empty_barrier(struct clone_info *ci)
+static int __clone_and_map_empty_flush(struct clone_info *ci)
 {
 	unsigned target_nr = 0;
 	struct dm_target *ti;
 
+	BUG_ON(bio_has_data(ci->bio));
 	while ((ti = dm_table_get_target(ci->map, target_nr++)))
 		__issue_target_requests(ci, ti, ti->num_flush_requests, 0);
 
-	ci->sector_count = 0;
-
 	return 0;
 }
 
@@ -1289,9 +1196,6 @@
 	sector_t len = 0, max;
 	struct dm_target_io *tio;
 
-	if (unlikely(bio_empty_barrier(bio)))
-		return __clone_and_map_empty_barrier(ci);
-
 	if (unlikely(bio->bi_rw & REQ_DISCARD))
 		return __clone_and_map_discard(ci);
 
@@ -1383,16 +1287,11 @@
 
 	ci.map = dm_get_live_table(md);
 	if (unlikely(!ci.map)) {
-		if (!(bio->bi_rw & REQ_HARDBARRIER))
-			bio_io_error(bio);
-		else
-			if (!md->barrier_error)
-				md->barrier_error = -EIO;
+		bio_io_error(bio);
 		return;
 	}
 
 	ci.md = md;
-	ci.bio = bio;
 	ci.io = alloc_io(md);
 	ci.io->error = 0;
 	atomic_set(&ci.io->io_count, 1);
@@ -1400,14 +1299,20 @@
 	ci.io->md = md;
 	spin_lock_init(&ci.io->endio_lock);
 	ci.sector = bio->bi_sector;
-	ci.sector_count = bio_sectors(bio);
-	if (unlikely(bio_empty_barrier(bio)))
-		ci.sector_count = 1;
 	ci.idx = bio->bi_idx;
 
 	start_io_acct(ci.io);
-	while (ci.sector_count && !error)
-		error = __clone_and_map(&ci);
+	if (bio->bi_rw & REQ_FLUSH) {
+		ci.bio = &ci.md->flush_bio;
+		ci.sector_count = 0;
+		error = __clone_and_map_empty_flush(&ci);
+		/* dec_pending submits any data associated with flush */
+	} else {
+		ci.bio = bio;
+		ci.sector_count = bio_sectors(bio);
+		while (ci.sector_count && !error)
+			error = __clone_and_map(&ci);
+	}
 
 	/* drop the extra reference count */
 	dec_pending(ci.io, error);
@@ -1491,22 +1396,14 @@
 	part_stat_add(cpu, &dm_disk(md)->part0, sectors[rw], bio_sectors(bio));
 	part_stat_unlock();
 
-	/*
-	 * If we're suspended or the thread is processing barriers
-	 * we have to queue this io for later.
-	 */
-	if (unlikely(test_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags)) ||
-	    unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
+	/* if we're suspended, we have to queue this io for later */
+	if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) {
 		up_read(&md->io_lock);
 
-		if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) &&
-		    bio_rw(bio) == READA) {
+		if (bio_rw(bio) != READA)
+			queue_io(md, bio);
+		else
 			bio_io_error(bio);
-			return 0;
-		}
-
-		queue_io(md, bio);
-
 		return 0;
 	}
 
@@ -1537,14 +1434,6 @@
 	return _dm_request(q, bio);
 }
 
-static bool dm_rq_is_flush_request(struct request *rq)
-{
-	if (rq->cmd_flags & REQ_FLUSH)
-		return true;
-	else
-		return false;
-}
-
 void dm_dispatch_request(struct request *rq)
 {
 	int r;
@@ -1592,22 +1481,15 @@
 {
 	int r;
 
-	if (dm_rq_is_flush_request(rq)) {
-		blk_rq_init(NULL, clone);
-		clone->cmd_type = REQ_TYPE_FS;
-		clone->cmd_flags |= (REQ_HARDBARRIER | WRITE);
-	} else {
-		r = blk_rq_prep_clone(clone, rq, tio->md->bs, GFP_ATOMIC,
-				      dm_rq_bio_constructor, tio);
-		if (r)
-			return r;
+	r = blk_rq_prep_clone(clone, rq, tio->md->bs, GFP_ATOMIC,
+			      dm_rq_bio_constructor, tio);
+	if (r)
+		return r;
 
-		clone->cmd = rq->cmd;
-		clone->cmd_len = rq->cmd_len;
-		clone->sense = rq->sense;
-		clone->buffer = rq->buffer;
-	}
-
+	clone->cmd = rq->cmd;
+	clone->cmd_len = rq->cmd_len;
+	clone->sense = rq->sense;
+	clone->buffer = rq->buffer;
 	clone->end_io = end_clone_request;
 	clone->end_io_data = tio;
 
@@ -1648,9 +1530,6 @@
 	struct mapped_device *md = q->queuedata;
 	struct request *clone;
 
-	if (unlikely(dm_rq_is_flush_request(rq)))
-		return BLKPREP_OK;
-
 	if (unlikely(rq->special)) {
 		DMWARN("Already has something in rq->special.");
 		return BLKPREP_KILL;
@@ -1727,6 +1606,7 @@
 	struct dm_table *map = dm_get_live_table(md);
 	struct dm_target *ti;
 	struct request *rq, *clone;
+	sector_t pos;
 
 	/*
 	 * For suspend, check blk_queue_stopped() and increment
@@ -1739,15 +1619,14 @@
 		if (!rq)
 			goto plug_and_out;
 
-		if (unlikely(dm_rq_is_flush_request(rq))) {
-			BUG_ON(md->flush_request);
-			md->flush_request = rq;
-			blk_start_request(rq);
-			queue_work(md->wq, &md->barrier_work);
-			goto out;
-		}
+		/* always use block 0 to find the target for flushes for now */
+		pos = 0;
+		if (!(rq->cmd_flags & REQ_FLUSH))
+			pos = blk_rq_pos(rq);
 
-		ti = dm_table_find_target(map, blk_rq_pos(rq));
+		ti = dm_table_find_target(map, pos);
+		BUG_ON(!dm_target_is_valid(ti));
+
 		if (ti->type->busy && ti->type->busy(ti))
 			goto plug_and_out;
 
@@ -1918,7 +1797,6 @@
 static const struct block_device_operations dm_blk_dops;
 
 static void dm_wq_work(struct work_struct *work);
-static void dm_rq_barrier_work(struct work_struct *work);
 
 static void dm_init_md_queue(struct mapped_device *md)
 {
@@ -1940,6 +1818,7 @@
 	blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
 	md->queue->unplug_fn = dm_unplug_all;
 	blk_queue_merge_bvec(md->queue, dm_merge_bvec);
+	blk_queue_flush(md->queue, REQ_FLUSH | REQ_FUA);
 }
 
 /*
@@ -1972,7 +1851,6 @@
 	mutex_init(&md->suspend_lock);
 	mutex_init(&md->type_lock);
 	spin_lock_init(&md->deferred_lock);
-	spin_lock_init(&md->barrier_error_lock);
 	rwlock_init(&md->map_lock);
 	atomic_set(&md->holders, 1);
 	atomic_set(&md->open_count, 0);
@@ -1995,7 +1873,6 @@
 	atomic_set(&md->pending[1], 0);
 	init_waitqueue_head(&md->wait);
 	INIT_WORK(&md->work, dm_wq_work);
-	INIT_WORK(&md->barrier_work, dm_rq_barrier_work);
 	init_waitqueue_head(&md->eventq);
 
 	md->disk->major = _major;
@@ -2015,6 +1892,10 @@
 	if (!md->bdev)
 		goto bad_bdev;
 
+	bio_init(&md->flush_bio);
+	md->flush_bio.bi_bdev = md->bdev;
+	md->flush_bio.bi_rw = WRITE_FLUSH;
+
 	/* Populate the mapping, nobody knows we exist yet */
 	spin_lock(&_minor_lock);
 	old_md = idr_replace(&_minor_idr, md, minor);
@@ -2245,7 +2126,6 @@
 	blk_queue_softirq_done(md->queue, dm_softirq_done);
 	blk_queue_prep_rq(md->queue, dm_prep_fn);
 	blk_queue_lld_busy(md->queue, dm_lld_busy);
-	blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH);
 
 	elv_register_queue(md->queue);
 
@@ -2406,43 +2286,6 @@
 	return r;
 }
 
-static void dm_flush(struct mapped_device *md)
-{
-	dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
-
-	bio_init(&md->barrier_bio);
-	md->barrier_bio.bi_bdev = md->bdev;
-	md->barrier_bio.bi_rw = WRITE_BARRIER;
-	__split_and_process_bio(md, &md->barrier_bio);
-
-	dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
-}
-
-static void process_barrier(struct mapped_device *md, struct bio *bio)
-{
-	md->barrier_error = 0;
-
-	dm_flush(md);
-
-	if (!bio_empty_barrier(bio)) {
-		__split_and_process_bio(md, bio);
-		/*
-		 * If the request isn't supported, don't waste time with
-		 * the second flush.
-		 */
-		if (md->barrier_error != -EOPNOTSUPP)
-			dm_flush(md);
-	}
-
-	if (md->barrier_error != DM_ENDIO_REQUEUE)
-		bio_endio(bio, md->barrier_error);
-	else {
-		spin_lock_irq(&md->deferred_lock);
-		bio_list_add_head(&md->deferred, bio);
-		spin_unlock_irq(&md->deferred_lock);
-	}
-}
-
 /*
  * Process the deferred bios
  */
@@ -2452,33 +2295,27 @@
 						work);
 	struct bio *c;
 
-	down_write(&md->io_lock);
+	down_read(&md->io_lock);
 
 	while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
 		spin_lock_irq(&md->deferred_lock);
 		c = bio_list_pop(&md->deferred);
 		spin_unlock_irq(&md->deferred_lock);
 
-		if (!c) {
-			clear_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags);
+		if (!c)
 			break;
-		}
 
-		up_write(&md->io_lock);
+		up_read(&md->io_lock);
 
 		if (dm_request_based(md))
 			generic_make_request(c);
-		else {
-			if (c->bi_rw & REQ_HARDBARRIER)
-				process_barrier(md, c);
-			else
-				__split_and_process_bio(md, c);
-		}
+		else
+			__split_and_process_bio(md, c);
 
-		down_write(&md->io_lock);
+		down_read(&md->io_lock);
 	}
 
-	up_write(&md->io_lock);
+	up_read(&md->io_lock);
 }
 
 static void dm_queue_flush(struct mapped_device *md)
@@ -2488,73 +2325,6 @@
 	queue_work(md->wq, &md->work);
 }
 
-static void dm_rq_set_target_request_nr(struct request *clone, unsigned request_nr)
-{
-	struct dm_rq_target_io *tio = clone->end_io_data;
-
-	tio->info.target_request_nr = request_nr;
-}
-
-/* Issue barrier requests to targets and wait for their completion. */
-static int dm_rq_barrier(struct mapped_device *md)
-{
-	int i, j;
-	struct dm_table *map = dm_get_live_table(md);
-	unsigned num_targets = dm_table_get_num_targets(map);
-	struct dm_target *ti;
-	struct request *clone;
-
-	md->barrier_error = 0;
-
-	for (i = 0; i < num_targets; i++) {
-		ti = dm_table_get_target(map, i);
-		for (j = 0; j < ti->num_flush_requests; j++) {
-			clone = clone_rq(md->flush_request, md, GFP_NOIO);
-			dm_rq_set_target_request_nr(clone, j);
-			atomic_inc(&md->pending[rq_data_dir(clone)]);
-			map_request(ti, clone, md);
-		}
-	}
-
-	dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
-	dm_table_put(map);
-
-	return md->barrier_error;
-}
-
-static void dm_rq_barrier_work(struct work_struct *work)
-{
-	int error;
-	struct mapped_device *md = container_of(work, struct mapped_device,
-						barrier_work);
-	struct request_queue *q = md->queue;
-	struct request *rq;
-	unsigned long flags;
-
-	/*
-	 * Hold the md reference here and leave it at the last part so that
-	 * the md can't be deleted by device opener when the barrier request
-	 * completes.
-	 */
-	dm_get(md);
-
-	error = dm_rq_barrier(md);
-
-	rq = md->flush_request;
-	md->flush_request = NULL;
-
-	if (error == DM_ENDIO_REQUEUE) {
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_requeue_request(q, rq);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-	} else
-		blk_end_request_all(rq, error);
-
-	blk_run_queue(q);
-
-	dm_put(md);
-}
-
 /*
  * Swap in a new table, returning the old one for the caller to destroy.
  */
@@ -2677,23 +2447,17 @@
 	 *
 	 * To get all processes out of __split_and_process_bio in dm_request,
 	 * we take the write lock. To prevent any process from reentering
-	 * __split_and_process_bio from dm_request, we set
-	 * DMF_QUEUE_IO_TO_THREAD.
-	 *
-	 * To quiesce the thread (dm_wq_work), we set DMF_BLOCK_IO_FOR_SUSPEND
-	 * and call flush_workqueue(md->wq). flush_workqueue will wait until
-	 * dm_wq_work exits and DMF_BLOCK_IO_FOR_SUSPEND will prevent any
-	 * further calls to __split_and_process_bio from dm_wq_work.
+	 * __split_and_process_bio from dm_request and quiesce the thread
+	 * (dm_wq_work), we set BMF_BLOCK_IO_FOR_SUSPEND and call
+	 * flush_workqueue(md->wq).
 	 */
 	down_write(&md->io_lock);
 	set_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
-	set_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags);
 	up_write(&md->io_lock);
 
 	/*
-	 * Request-based dm uses md->wq for barrier (dm_rq_barrier_work) which
-	 * can be kicked until md->queue is stopped.  So stop md->queue before
-	 * flushing md->wq.
+	 * Stop md->queue before flushing md->wq in case request-based
+	 * dm defers requests to md->wq from md->queue.
 	 */
 	if (dm_request_based(md))
 		stop_queue(md->queue);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index ba19060..8a2f767 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -294,8 +294,8 @@
 	dev_info_t *tmp_dev;
 	sector_t start_sector;
 
-	if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
-		md_barrier_request(mddev, bio);
+	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bio);
 		return 0;
 	}
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index f20d13e..2258151 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -36,7 +36,7 @@
 #include <linux/blkdev.h>
 #include <linux/sysctl.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/buffer_head.h> /* for invalidate_bdev */
 #include <linux/poll.h>
 #include <linux/ctype.h>
@@ -57,6 +57,7 @@
 #define DEBUG 0
 #define dprintk(x...) ((void)(DEBUG && printk(x)))
 
+static DEFINE_MUTEX(md_mutex);
 
 #ifndef MODULE
 static void autostart_arrays(int part);
@@ -226,12 +227,12 @@
 		return 0;
 	}
 	rcu_read_lock();
-	if (mddev->suspended || mddev->barrier) {
+	if (mddev->suspended) {
 		DEFINE_WAIT(__wait);
 		for (;;) {
 			prepare_to_wait(&mddev->sb_wait, &__wait,
 					TASK_UNINTERRUPTIBLE);
-			if (!mddev->suspended && !mddev->barrier)
+			if (!mddev->suspended)
 				break;
 			rcu_read_unlock();
 			schedule();
@@ -282,40 +283,29 @@
 
 int mddev_congested(mddev_t *mddev, int bits)
 {
-	if (mddev->barrier)
-		return 1;
 	return mddev->suspended;
 }
 EXPORT_SYMBOL(mddev_congested);
 
 /*
- * Generic barrier handling for md
+ * Generic flush handling for md
  */
 
-#define POST_REQUEST_BARRIER ((void*)1)
-
-static void md_end_barrier(struct bio *bio, int err)
+static void md_end_flush(struct bio *bio, int err)
 {
 	mdk_rdev_t *rdev = bio->bi_private;
 	mddev_t *mddev = rdev->mddev;
-	if (err == -EOPNOTSUPP && mddev->barrier != POST_REQUEST_BARRIER)
-		set_bit(BIO_EOPNOTSUPP, &mddev->barrier->bi_flags);
 
 	rdev_dec_pending(rdev, mddev);
 
 	if (atomic_dec_and_test(&mddev->flush_pending)) {
-		if (mddev->barrier == POST_REQUEST_BARRIER) {
-			/* This was a post-request barrier */
-			mddev->barrier = NULL;
-			wake_up(&mddev->sb_wait);
-		} else
-			/* The pre-request barrier has finished */
-			schedule_work(&mddev->barrier_work);
+		/* The pre-request flush has finished */
+		schedule_work(&mddev->flush_work);
 	}
 	bio_put(bio);
 }
 
-static void submit_barriers(mddev_t *mddev)
+static void submit_flushes(mddev_t *mddev)
 {
 	mdk_rdev_t *rdev;
 
@@ -332,60 +322,56 @@
 			atomic_inc(&rdev->nr_pending);
 			rcu_read_unlock();
 			bi = bio_alloc(GFP_KERNEL, 0);
-			bi->bi_end_io = md_end_barrier;
+			bi->bi_end_io = md_end_flush;
 			bi->bi_private = rdev;
 			bi->bi_bdev = rdev->bdev;
 			atomic_inc(&mddev->flush_pending);
-			submit_bio(WRITE_BARRIER, bi);
+			submit_bio(WRITE_FLUSH, bi);
 			rcu_read_lock();
 			rdev_dec_pending(rdev, mddev);
 		}
 	rcu_read_unlock();
 }
 
-static void md_submit_barrier(struct work_struct *ws)
+static void md_submit_flush_data(struct work_struct *ws)
 {
-	mddev_t *mddev = container_of(ws, mddev_t, barrier_work);
-	struct bio *bio = mddev->barrier;
+	mddev_t *mddev = container_of(ws, mddev_t, flush_work);
+	struct bio *bio = mddev->flush_bio;
 
 	atomic_set(&mddev->flush_pending, 1);
 
-	if (test_bit(BIO_EOPNOTSUPP, &bio->bi_flags))
-		bio_endio(bio, -EOPNOTSUPP);
-	else if (bio->bi_size == 0)
+	if (bio->bi_size == 0)
 		/* an empty barrier - all done */
 		bio_endio(bio, 0);
 	else {
-		bio->bi_rw &= ~REQ_HARDBARRIER;
+		bio->bi_rw &= ~REQ_FLUSH;
 		if (mddev->pers->make_request(mddev, bio))
 			generic_make_request(bio);
-		mddev->barrier = POST_REQUEST_BARRIER;
-		submit_barriers(mddev);
 	}
 	if (atomic_dec_and_test(&mddev->flush_pending)) {
-		mddev->barrier = NULL;
+		mddev->flush_bio = NULL;
 		wake_up(&mddev->sb_wait);
 	}
 }
 
-void md_barrier_request(mddev_t *mddev, struct bio *bio)
+void md_flush_request(mddev_t *mddev, struct bio *bio)
 {
 	spin_lock_irq(&mddev->write_lock);
 	wait_event_lock_irq(mddev->sb_wait,
-			    !mddev->barrier,
+			    !mddev->flush_bio,
 			    mddev->write_lock, /*nothing*/);
-	mddev->barrier = bio;
+	mddev->flush_bio = bio;
 	spin_unlock_irq(&mddev->write_lock);
 
 	atomic_set(&mddev->flush_pending, 1);
-	INIT_WORK(&mddev->barrier_work, md_submit_barrier);
+	INIT_WORK(&mddev->flush_work, md_submit_flush_data);
 
-	submit_barriers(mddev);
+	submit_flushes(mddev);
 
 	if (atomic_dec_and_test(&mddev->flush_pending))
-		schedule_work(&mddev->barrier_work);
+		schedule_work(&mddev->flush_work);
 }
-EXPORT_SYMBOL(md_barrier_request);
+EXPORT_SYMBOL(md_flush_request);
 
 /* Support for plugging.
  * This mirrors the plugging support in request_queue, but does not
@@ -696,31 +682,6 @@
 	bio_put(bio);
 }
 
-static void super_written_barrier(struct bio *bio, int error)
-{
-	struct bio *bio2 = bio->bi_private;
-	mdk_rdev_t *rdev = bio2->bi_private;
-	mddev_t *mddev = rdev->mddev;
-
-	if (!test_bit(BIO_UPTODATE, &bio->bi_flags) &&
-	    error == -EOPNOTSUPP) {
-		unsigned long flags;
-		/* barriers don't appear to be supported :-( */
-		set_bit(BarriersNotsupp, &rdev->flags);
-		mddev->barriers_work = 0;
-		spin_lock_irqsave(&mddev->write_lock, flags);
-		bio2->bi_next = mddev->biolist;
-		mddev->biolist = bio2;
-		spin_unlock_irqrestore(&mddev->write_lock, flags);
-		wake_up(&mddev->sb_wait);
-		bio_put(bio);
-	} else {
-		bio_put(bio2);
-		bio->bi_private = rdev;
-		super_written(bio, error);
-	}
-}
-
 void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
 		   sector_t sector, int size, struct page *page)
 {
@@ -729,51 +690,28 @@
 	 * and decrement it on completion, waking up sb_wait
 	 * if zero is reached.
 	 * If an error occurred, call md_error
-	 *
-	 * As we might need to resubmit the request if REQ_HARDBARRIER
-	 * causes ENOTSUPP, we allocate a spare bio...
 	 */
 	struct bio *bio = bio_alloc(GFP_NOIO, 1);
-	int rw = REQ_WRITE | REQ_SYNC | REQ_UNPLUG;
 
 	bio->bi_bdev = rdev->bdev;
 	bio->bi_sector = sector;
 	bio_add_page(bio, page, size, 0);
 	bio->bi_private = rdev;
 	bio->bi_end_io = super_written;
-	bio->bi_rw = rw;
 
 	atomic_inc(&mddev->pending_writes);
-	if (!test_bit(BarriersNotsupp, &rdev->flags)) {
-		struct bio *rbio;
-		rw |= REQ_HARDBARRIER;
-		rbio = bio_clone(bio, GFP_NOIO);
-		rbio->bi_private = bio;
-		rbio->bi_end_io = super_written_barrier;
-		submit_bio(rw, rbio);
-	} else
-		submit_bio(rw, bio);
+	submit_bio(REQ_WRITE | REQ_SYNC | REQ_UNPLUG | REQ_FLUSH | REQ_FUA,
+		   bio);
 }
 
 void md_super_wait(mddev_t *mddev)
 {
-	/* wait for all superblock writes that were scheduled to complete.
-	 * if any had to be retried (due to BARRIER problems), retry them
-	 */
+	/* wait for all superblock writes that were scheduled to complete */
 	DEFINE_WAIT(wq);
 	for(;;) {
 		prepare_to_wait(&mddev->sb_wait, &wq, TASK_UNINTERRUPTIBLE);
 		if (atomic_read(&mddev->pending_writes)==0)
 			break;
-		while (mddev->biolist) {
-			struct bio *bio;
-			spin_lock_irq(&mddev->write_lock);
-			bio = mddev->biolist;
-			mddev->biolist = bio->bi_next ;
-			bio->bi_next = NULL;
-			spin_unlock_irq(&mddev->write_lock);
-			submit_bio(bio->bi_rw, bio);
-		}
 		schedule();
 	}
 	finish_wait(&mddev->sb_wait, &wq);
@@ -1070,7 +1008,6 @@
 	clear_bit(Faulty, &rdev->flags);
 	clear_bit(In_sync, &rdev->flags);
 	clear_bit(WriteMostly, &rdev->flags);
-	clear_bit(BarriersNotsupp, &rdev->flags);
 
 	if (mddev->raid_disks == 0) {
 		mddev->major_version = 0;
@@ -1485,7 +1422,6 @@
 	clear_bit(Faulty, &rdev->flags);
 	clear_bit(In_sync, &rdev->flags);
 	clear_bit(WriteMostly, &rdev->flags);
-	clear_bit(BarriersNotsupp, &rdev->flags);
 
 	if (mddev->raid_disks == 0) {
 		mddev->major_version = 1;
@@ -4504,7 +4440,6 @@
 	/* may be over-ridden by personality */
 	mddev->resync_max_sectors = mddev->dev_sectors;
 
-	mddev->barriers_work = 1;
 	mddev->ok_start_degraded = start_dirty_degraded;
 
 	if (start_readonly && mddev->ro == 0)
@@ -4683,7 +4618,6 @@
 	mddev->recovery = 0;
 	mddev->in_sync = 0;
 	mddev->degraded = 0;
-	mddev->barriers_work = 0;
 	mddev->safemode = 0;
 	mddev->bitmap_info.offset = 0;
 	mddev->bitmap_info.default_offset = 0;
@@ -5951,7 +5885,7 @@
 	mddev_t *mddev = mddev_find(bdev->bd_dev);
 	int err;
 
-	lock_kernel();
+	mutex_lock(&md_mutex);
 	if (mddev->gendisk != bdev->bd_disk) {
 		/* we are racing with mddev_put which is discarding this
 		 * bd_disk.
@@ -5960,7 +5894,7 @@
 		/* Wait until bdev->bd_disk is definitely gone */
 		flush_scheduled_work();
 		/* Then retry the open from the top */
-		unlock_kernel();
+		mutex_unlock(&md_mutex);
 		return -ERESTARTSYS;
 	}
 	BUG_ON(mddev != bdev->bd_disk->private_data);
@@ -5974,7 +5908,7 @@
 
 	check_disk_size_change(mddev->gendisk, bdev);
  out:
-	unlock_kernel();
+	mutex_unlock(&md_mutex);
 	return err;
 }
 
@@ -5983,10 +5917,10 @@
  	mddev_t *mddev = disk->private_data;
 
 	BUG_ON(!mddev);
-	lock_kernel();
+	mutex_lock(&md_mutex);
 	atomic_dec(&mddev->openers);
 	mddev_put(mddev);
-	unlock_kernel();
+	mutex_unlock(&md_mutex);
 
 	return 0;
 }
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 3931299..112a2c3 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -87,7 +87,6 @@
 #define	Faulty		1		/* device is known to have a fault */
 #define	In_sync		2		/* device is in_sync with rest of array */
 #define	WriteMostly	4		/* Avoid reading if at all possible */
-#define	BarriersNotsupp	5		/* REQ_HARDBARRIER is not supported */
 #define	AllReserved	6		/* If whole device is reserved for
 					 * one array */
 #define	AutoDetected	7		/* added by auto-detect */
@@ -273,13 +272,6 @@
 	int				degraded;	/* whether md should consider
 							 * adding a spare
 							 */
-	int				barriers_work;	/* initialised to true, cleared as soon
-							 * as a barrier request to slave
-							 * fails.  Only supported
-							 */
-	struct bio			*biolist; 	/* bios that need to be retried
-							 * because REQ_HARDBARRIER is not supported
-							 */
 
 	atomic_t			recovery_active; /* blocks scheduled, but not written */
 	wait_queue_head_t		recovery_wait;
@@ -339,16 +331,13 @@
 	struct attribute_group		*to_remove;
 	struct plug_handle		*plug; /* if used by personality */
 
-	/* Generic barrier handling.
-	 * If there is a pending barrier request, all other
-	 * writes are blocked while the devices are flushed.
-	 * The last to finish a flush schedules a worker to
-	 * submit the barrier request (without the barrier flag),
-	 * then submit more flush requests.
+	/* Generic flush handling.
+	 * The last to finish preflush schedules a worker to submit
+	 * the rest of the request (without the REQ_FLUSH flag).
 	 */
-	struct bio *barrier;
+	struct bio *flush_bio;
 	atomic_t flush_pending;
-	struct work_struct barrier_work;
+	struct work_struct flush_work;
 	struct work_struct event_work;	/* used by dm to report failure event */
 };
 
@@ -502,7 +491,7 @@
 extern void md_error(mddev_t *mddev, mdk_rdev_t *rdev);
 
 extern int mddev_congested(mddev_t *mddev, int bits);
-extern void md_barrier_request(mddev_t *mddev, struct bio *bio);
+extern void md_flush_request(mddev_t *mddev, struct bio *bio);
 extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
 			   sector_t sector, int size, struct page *page);
 extern void md_super_wait(mddev_t *mddev);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 0307d21..6d7ddf3 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -142,8 +142,8 @@
 	struct multipath_bh * mp_bh;
 	struct multipath_info *multipath;
 
-	if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
-		md_barrier_request(mddev, bio);
+	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bio);
 		return 0;
 	}
 
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 6f7af46..a39f4c3 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -483,8 +483,8 @@
 	struct strip_zone *zone;
 	mdk_rdev_t *tmp_dev;
 
-	if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
-		md_barrier_request(mddev, bio);
+	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bio);
 		return 0;
 	}
 
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 0b830bb..378a258 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -319,83 +319,74 @@
 		if (r1_bio->bios[mirror] == bio)
 			break;
 
-	if (error == -EOPNOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) {
-		set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags);
-		set_bit(R1BIO_BarrierRetry, &r1_bio->state);
-		r1_bio->mddev->barriers_work = 0;
-		/* Don't rdev_dec_pending in this branch - keep it for the retry */
-	} else {
+	/*
+	 * 'one mirror IO has finished' event handler:
+	 */
+	r1_bio->bios[mirror] = NULL;
+	to_put = bio;
+	if (!uptodate) {
+		md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
+		/* an I/O failed, we can't clear the bitmap */
+		set_bit(R1BIO_Degraded, &r1_bio->state);
+	} else
 		/*
-		 * this branch is our 'one mirror IO has finished' event handler:
+		 * Set R1BIO_Uptodate in our master bio, so that we
+		 * will return a good error code for to the higher
+		 * levels even if IO on some other mirrored buffer
+		 * fails.
+		 *
+		 * The 'master' represents the composite IO operation
+		 * to user-side. So if something waits for IO, then it
+		 * will wait for the 'master' bio.
 		 */
-		r1_bio->bios[mirror] = NULL;
-		to_put = bio;
-		if (!uptodate) {
-			md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
-			/* an I/O failed, we can't clear the bitmap */
-			set_bit(R1BIO_Degraded, &r1_bio->state);
-		} else
-			/*
-			 * Set R1BIO_Uptodate in our master bio, so that
-			 * we will return a good error code for to the higher
-			 * levels even if IO on some other mirrored buffer fails.
-			 *
-			 * The 'master' represents the composite IO operation to
-			 * user-side. So if something waits for IO, then it will
-			 * wait for the 'master' bio.
-			 */
-			set_bit(R1BIO_Uptodate, &r1_bio->state);
+		set_bit(R1BIO_Uptodate, &r1_bio->state);
 
-		update_head_pos(mirror, r1_bio);
+	update_head_pos(mirror, r1_bio);
 
-		if (behind) {
-			if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
-				atomic_dec(&r1_bio->behind_remaining);
+	if (behind) {
+		if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
+			atomic_dec(&r1_bio->behind_remaining);
 
-			/* In behind mode, we ACK the master bio once the I/O has safely
-			 * reached all non-writemostly disks. Setting the Returned bit
-			 * ensures that this gets done only once -- we don't ever want to
-			 * return -EIO here, instead we'll wait */
-
-			if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
-			    test_bit(R1BIO_Uptodate, &r1_bio->state)) {
-				/* Maybe we can return now */
-				if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
-					struct bio *mbio = r1_bio->master_bio;
-					PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
-					       (unsigned long long) mbio->bi_sector,
-					       (unsigned long long) mbio->bi_sector +
-					       (mbio->bi_size >> 9) - 1);
-					bio_endio(mbio, 0);
-				}
+		/*
+		 * In behind mode, we ACK the master bio once the I/O
+		 * has safely reached all non-writemostly
+		 * disks. Setting the Returned bit ensures that this
+		 * gets done only once -- we don't ever want to return
+		 * -EIO here, instead we'll wait
+		 */
+		if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
+		    test_bit(R1BIO_Uptodate, &r1_bio->state)) {
+			/* Maybe we can return now */
+			if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+				struct bio *mbio = r1_bio->master_bio;
+				PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
+				       (unsigned long long) mbio->bi_sector,
+				       (unsigned long long) mbio->bi_sector +
+				       (mbio->bi_size >> 9) - 1);
+				bio_endio(mbio, 0);
 			}
 		}
-		rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
 	}
+	rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
+
 	/*
-	 *
 	 * Let's see if all mirrored write operations have finished
 	 * already.
 	 */
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
-		if (test_bit(R1BIO_BarrierRetry, &r1_bio->state))
-			reschedule_retry(r1_bio);
-		else {
-			/* it really is the end of this request */
-			if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
-				/* free extra copy of the data pages */
-				int i = bio->bi_vcnt;
-				while (i--)
-					safe_put_page(bio->bi_io_vec[i].bv_page);
-			}
-			/* clear the bitmap if all writes complete successfully */
-			bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
-					r1_bio->sectors,
-					!test_bit(R1BIO_Degraded, &r1_bio->state),
-					behind);
-			md_write_end(r1_bio->mddev);
-			raid_end_bio_io(r1_bio);
+		if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+			/* free extra copy of the data pages */
+			int i = bio->bi_vcnt;
+			while (i--)
+				safe_put_page(bio->bi_io_vec[i].bv_page);
 		}
+		/* clear the bitmap if all writes complete successfully */
+		bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
+				r1_bio->sectors,
+				!test_bit(R1BIO_Degraded, &r1_bio->state),
+				behind);
+		md_write_end(r1_bio->mddev);
+		raid_end_bio_io(r1_bio);
 	}
 
 	if (to_put)
@@ -788,16 +779,13 @@
 	struct page **behind_pages = NULL;
 	const int rw = bio_data_dir(bio);
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
-	unsigned long do_barriers;
+	const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
 	mdk_rdev_t *blocked_rdev;
 
 	/*
 	 * Register the new request and wait if the reconstruction
 	 * thread has put up a bar for new requests.
 	 * Continue immediately if no resync is active currently.
-	 * We test barriers_work *after* md_write_start as md_write_start
-	 * may cause the first superblock write, and that will check out
-	 * if barriers work.
 	 */
 
 	md_write_start(mddev, bio); /* wait on superblock update early */
@@ -821,13 +809,6 @@
 		}
 		finish_wait(&conf->wait_barrier, &w);
 	}
-	if (unlikely(!mddev->barriers_work &&
-		     (bio->bi_rw & REQ_HARDBARRIER))) {
-		if (rw == WRITE)
-			md_write_end(mddev);
-		bio_endio(bio, -EOPNOTSUPP);
-		return 0;
-	}
 
 	wait_barrier(conf);
 
@@ -959,10 +940,6 @@
 	atomic_set(&r1_bio->remaining, 0);
 	atomic_set(&r1_bio->behind_remaining, 0);
 
-	do_barriers = bio->bi_rw & REQ_HARDBARRIER;
-	if (do_barriers)
-		set_bit(R1BIO_Barrier, &r1_bio->state);
-
 	bio_list_init(&bl);
 	for (i = 0; i < disks; i++) {
 		struct bio *mbio;
@@ -975,7 +952,7 @@
 		mbio->bi_sector	= r1_bio->sector + conf->mirrors[i].rdev->data_offset;
 		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
 		mbio->bi_end_io	= raid1_end_write_request;
-		mbio->bi_rw = WRITE | do_barriers | do_sync;
+		mbio->bi_rw = WRITE | do_flush_fua | do_sync;
 		mbio->bi_private = r1_bio;
 
 		if (behind_pages) {
@@ -1634,41 +1611,6 @@
 		if (test_bit(R1BIO_IsSync, &r1_bio->state)) {
 			sync_request_write(mddev, r1_bio);
 			unplug = 1;
-		} else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
-			/* some requests in the r1bio were REQ_HARDBARRIER
-			 * requests which failed with -EOPNOTSUPP.  Hohumm..
-			 * Better resubmit without the barrier.
-			 * We know which devices to resubmit for, because
-			 * all others have had their bios[] entry cleared.
-			 * We already have a nr_pending reference on these rdevs.
-			 */
-			int i;
-			const unsigned long do_sync = (r1_bio->master_bio->bi_rw & REQ_SYNC);
-			clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
-			clear_bit(R1BIO_Barrier, &r1_bio->state);
-			for (i=0; i < conf->raid_disks; i++)
-				if (r1_bio->bios[i])
-					atomic_inc(&r1_bio->remaining);
-			for (i=0; i < conf->raid_disks; i++)
-				if (r1_bio->bios[i]) {
-					struct bio_vec *bvec;
-					int j;
-
-					bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
-					/* copy pages from the failed bio, as
-					 * this might be a write-behind device */
-					__bio_for_each_segment(bvec, bio, j, 0)
-						bvec->bv_page = bio_iovec_idx(r1_bio->bios[i], j)->bv_page;
-					bio_put(r1_bio->bios[i]);
-					bio->bi_sector = r1_bio->sector +
-						conf->mirrors[i].rdev->data_offset;
-					bio->bi_bdev = conf->mirrors[i].rdev->bdev;
-					bio->bi_end_io = raid1_end_write_request;
-					bio->bi_rw = WRITE | do_sync;
-					bio->bi_private = r1_bio;
-					r1_bio->bios[i] = bio;
-					generic_make_request(bio);
-				}
 		} else {
 			int disk;
 
diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
index 5f2d443..adf8cfd 100644
--- a/drivers/md/raid1.h
+++ b/drivers/md/raid1.h
@@ -117,8 +117,6 @@
 #define	R1BIO_IsSync	1
 #define	R1BIO_Degraded	2
 #define	R1BIO_BehindIO	3
-#define	R1BIO_Barrier	4
-#define R1BIO_BarrierRetry 5
 /* For write-behind requests, we call bi_end_io when
  * the last non-write-behind device completes, providing
  * any write was successful.  Otherwise we call when
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 8471838..f0d082f 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -800,12 +800,13 @@
 	int chunk_sects = conf->chunk_mask + 1;
 	const int rw = bio_data_dir(bio);
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
+	const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
 	struct bio_list bl;
 	unsigned long flags;
 	mdk_rdev_t *blocked_rdev;
 
-	if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) {
-		md_barrier_request(mddev, bio);
+	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bio);
 		return 0;
 	}
 
@@ -965,7 +966,7 @@
 			conf->mirrors[d].rdev->data_offset;
 		mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
 		mbio->bi_end_io	= raid10_end_write_request;
-		mbio->bi_rw = WRITE | do_sync;
+		mbio->bi_rw = WRITE | do_sync | do_fua;
 		mbio->bi_private = r10_bio;
 
 		atomic_inc(&r10_bio->remaining);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 69b0a16..31140d1 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -506,9 +506,12 @@
 		int rw;
 		struct bio *bi;
 		mdk_rdev_t *rdev;
-		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
-			rw = WRITE;
-		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
+		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
+			if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags))
+				rw = WRITE_FUA;
+			else
+				rw = WRITE;
+		} else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
 			rw = READ;
 		else
 			continue;
@@ -1031,6 +1034,8 @@
 
 			while (wbi && wbi->bi_sector <
 				dev->sector + STRIPE_SECTORS) {
+				if (wbi->bi_rw & REQ_FUA)
+					set_bit(R5_WantFUA, &dev->flags);
 				tx = async_copy_data(1, wbi, dev->page,
 					dev->sector, tx);
 				wbi = r5_next_bio(wbi, dev->sector);
@@ -1048,15 +1053,22 @@
 	int pd_idx = sh->pd_idx;
 	int qd_idx = sh->qd_idx;
 	int i;
+	bool fua = false;
 
 	pr_debug("%s: stripe %llu\n", __func__,
 		(unsigned long long)sh->sector);
 
+	for (i = disks; i--; )
+		fua |= test_bit(R5_WantFUA, &sh->dev[i].flags);
+
 	for (i = disks; i--; ) {
 		struct r5dev *dev = &sh->dev[i];
 
-		if (dev->written || i == pd_idx || i == qd_idx)
+		if (dev->written || i == pd_idx || i == qd_idx) {
 			set_bit(R5_UPTODATE, &dev->flags);
+			if (fua)
+				set_bit(R5_WantFUA, &dev->flags);
+		}
 	}
 
 	if (sh->reconstruct_state == reconstruct_state_drain_run)
@@ -3281,7 +3293,7 @@
 
 	if (dec_preread_active) {
 		/* We delay this until after ops_run_io so that if make_request
-		 * is waiting on a barrier, it won't continue until the writes
+		 * is waiting on a flush, it won't continue until the writes
 		 * have actually been submitted.
 		 */
 		atomic_dec(&conf->preread_active_stripes);
@@ -3583,7 +3595,7 @@
 
 	if (dec_preread_active) {
 		/* We delay this until after ops_run_io so that if make_request
-		 * is waiting on a barrier, it won't continue until the writes
+		 * is waiting on a flush, it won't continue until the writes
 		 * have actually been submitted.
 		 */
 		atomic_dec(&conf->preread_active_stripes);
@@ -3978,14 +3990,8 @@
 	const int rw = bio_data_dir(bi);
 	int remaining;
 
-	if (unlikely(bi->bi_rw & REQ_HARDBARRIER)) {
-		/* Drain all pending writes.  We only really need
-		 * to ensure they have been submitted, but this is
-		 * easier.
-		 */
-		mddev->pers->quiesce(mddev, 1);
-		mddev->pers->quiesce(mddev, 0);
-		md_barrier_request(mddev, bi);
+	if (unlikely(bi->bi_rw & REQ_FLUSH)) {
+		md_flush_request(mddev, bi);
 		return 0;
 	}
 
@@ -4103,7 +4109,7 @@
 			finish_wait(&conf->wait_for_overlap, &w);
 			set_bit(STRIPE_HANDLE, &sh->state);
 			clear_bit(STRIPE_DELAYED, &sh->state);
-			if (mddev->barrier && 
+			if ((bi->bi_rw & REQ_SYNC) &&
 			    !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
 				atomic_inc(&conf->preread_active_stripes);
 			release_stripe(sh);
@@ -4126,13 +4132,6 @@
 		bio_endio(bi, 0);
 	}
 
-	if (mddev->barrier) {
-		/* We need to wait for the stripes to all be handled.
-		 * So: wait for preread_active_stripes to drop to 0.
-		 */
-		wait_event(mddev->thread->wqueue,
-			   atomic_read(&conf->preread_active_stripes) == 0);
-	}
 	return 0;
 }
 
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 36eaed5..2ace058 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -275,6 +275,7 @@
 				    * filling
 				    */
 #define R5_Wantdrain	13 /* dev->towrite needs to be drained */
+#define R5_WantFUA	14	/* Write should be FUA */
 /*
  * Write method
  */
diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
index c185422..faed5a3 100644
--- a/drivers/media/IR/imon.c
+++ b/drivers/media/IR/imon.c
@@ -151,7 +151,8 @@
 	.owner		= THIS_MODULE,
 	.open		= &display_open,
 	.write		= &vfd_write,
-	.release	= &display_close
+	.release	= &display_close,
+	.llseek		= noop_llseek,
 };
 
 /* lcd character device file operations */
@@ -159,7 +160,8 @@
 	.owner		= THIS_MODULE,
 	.open		= &display_open,
 	.write		= &lcd_write,
-	.release	= &display_close
+	.release	= &display_close,
+	.llseek		= noop_llseek,
 };
 
 enum {
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c
index e63f757..1983cd3 100644
--- a/drivers/media/IR/ir-lirc-codec.c
+++ b/drivers/media/IR/ir-lirc-codec.c
@@ -235,6 +235,7 @@
 	.poll		= lirc_dev_fop_poll,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
+	.llseek		= no_llseek,
 };
 
 static int ir_lirc_register(struct input_dev *input_dev)
diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c
index 899891b..0acf639 100644
--- a/drivers/media/IR/lirc_dev.c
+++ b/drivers/media/IR/lirc_dev.c
@@ -163,6 +163,7 @@
 	.unlocked_ioctl	= lirc_dev_fop_ioctl,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
+	.llseek		= noop_llseek,
 };
 
 static int lirc_cdev_add(struct irctl *ir)
@@ -460,6 +461,8 @@
 
 	mutex_unlock(&lirc_dev_lock);
 
+	nonseekable_open(inode, file);
+
 	return retval;
 }
 EXPORT_SYMBOL(lirc_dev_fop_open);
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index a28541b..bad2ced 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -19,6 +19,7 @@
 
 config VIDEO_DEV
 	tristate "Video For Linux"
+	depends on BKL # used in many drivers for ioctl handling, need to kill
 	---help---
 	  V4L core support for video capture and overlay devices, webcams and
 	  AM/FM radio cards.
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index cf87051..48e48e8 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -22,7 +22,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/dvb/ca.h>
 #include "dvbdev.h"
@@ -52,6 +52,7 @@
 } while(0)
 
 
+static DEFINE_MUTEX(dst_ca_mutex);
 static unsigned int verbose = 5;
 module_param(verbose, int, 0644);
 MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
@@ -564,7 +565,7 @@
 	void __user *arg = (void __user *)ioctl_arg;
 	int result = 0;
 
-	lock_kernel();
+	mutex_lock(&dst_ca_mutex);
 	dvbdev = file->private_data;
 	state = (struct dst_state *)dvbdev->priv;
 	p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
@@ -652,7 +653,7 @@
 	kfree (p_ca_slot_info);
 	kfree (p_ca_caps);
 
-	unlock_kernel();
+	mutex_unlock(&dst_ca_mutex);
 	return result;
 }
 
@@ -694,7 +695,8 @@
 	.open = dst_ca_open,
 	.release = dst_ca_release,
 	.read = dst_ca_read,
-	.write = dst_ca_write
+	.write = dst_ca_write,
+	.llseek = noop_llseek,
 };
 
 static struct dvb_device dvbdev_ca = {
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 0042306..ad1f61d 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -25,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <linux/ioctl.h>
 #include <linux/wait.h>
@@ -1088,13 +1087,7 @@
 static long dvb_demux_ioctl(struct file *file, unsigned int cmd,
 			    unsigned long arg)
 {
-	int ret;
-
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
 }
 
 static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
@@ -1150,6 +1143,7 @@
 	.open = dvb_demux_open,
 	.release = dvb_demux_release,
 	.poll = dvb_demux_poll,
+	.llseek = default_llseek,
 };
 
 static struct dvb_device dvbdev_demux = {
@@ -1186,13 +1180,7 @@
 static long dvb_dvr_ioctl(struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
-	int ret;
-
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
 }
 
 static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
@@ -1225,6 +1213,7 @@
 	.open = dvb_dvr_open,
 	.release = dvb_dvr_release,
 	.poll = dvb_dvr_poll,
+	.llseek = default_llseek,
 };
 
 static struct dvb_device dvbdev_dvr = {
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index cb97e6b..4d0646d 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1259,13 +1259,7 @@
 static long dvb_ca_en50221_io_ioctl(struct file *file,
 				    unsigned int cmd, unsigned long arg)
 {
-	int ret;
-
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
 }
 
 
@@ -1628,6 +1622,7 @@
 	.open = dvb_ca_en50221_io_open,
 	.release = dvb_ca_en50221_io_release,
 	.poll = dvb_ca_en50221_io_poll,
+	.llseek = noop_llseek,
 };
 
 static struct dvb_device dvbdev_ca = {
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 4d45b7d..970c9b8 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -2034,7 +2034,8 @@
 	.unlocked_ioctl	= dvb_generic_ioctl,
 	.poll		= dvb_frontend_poll,
 	.open		= dvb_frontend_open,
-	.release	= dvb_frontend_release
+	.release	= dvb_frontend_release,
+	.llseek		= noop_llseek,
 };
 
 int dvb_register_frontend(struct dvb_adapter* dvb,
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 6c3a8a0..4df42aa 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -59,7 +59,6 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/dvb/net.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <asm/uaccess.h>
 #include <linux/crc32.h>
@@ -1445,13 +1444,7 @@
 static long dvb_net_ioctl(struct file *file,
 	      unsigned int cmd, unsigned long arg)
 {
-	int ret;
-
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
 }
 
 static int dvb_net_close(struct inode *inode, struct file *file)
@@ -1475,6 +1468,7 @@
 	.unlocked_ioctl = dvb_net_ioctl,
 	.open =	dvb_generic_open,
 	.release = dvb_net_close,
+	.llseek = noop_llseek,
 };
 
 static struct dvb_device dvbdev_net = {
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index b915c39..f732877 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -32,9 +32,9 @@
 #include <linux/fs.h>
 #include <linux/cdev.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include "dvbdev.h"
 
+static DEFINE_MUTEX(dvbdev_mutex);
 static int dvbdev_debug;
 
 module_param(dvbdev_debug, int, 0644);
@@ -68,7 +68,7 @@
 {
 	struct dvb_device *dvbdev;
 
-	lock_kernel();
+	mutex_lock(&dvbdev_mutex);
 	down_read(&minor_rwsem);
 	dvbdev = dvb_minors[iminor(inode)];
 
@@ -91,12 +91,12 @@
 		}
 		fops_put(old_fops);
 		up_read(&minor_rwsem);
-		unlock_kernel();
+		mutex_unlock(&dvbdev_mutex);
 		return err;
 	}
 fail:
 	up_read(&minor_rwsem);
-	unlock_kernel();
+	mutex_unlock(&dvbdev_mutex);
 	return -ENODEV;
 }
 
@@ -105,6 +105,7 @@
 {
 	.owner =	THIS_MODULE,
 	.open =		dvb_device_open,
+	.llseek =	noop_llseek,
 };
 
 static struct cdev dvb_device_cdev;
@@ -158,7 +159,6 @@
 		       unsigned int cmd, unsigned long arg)
 {
 	struct dvb_device *dvbdev = file->private_data;
-	int ret;
 
 	if (!dvbdev)
 		return -ENODEV;
@@ -166,11 +166,7 @@
 	if (!dvbdev->kernel_ioctl)
 		return -EINVAL;
 
-	lock_kernel();
-	ret = dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
-	unlock_kernel();
-
-	return ret;
+	return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
 }
 EXPORT_SYMBOL(dvb_generic_ioctl);
 
@@ -421,8 +417,10 @@
 	}
 
 	/* call driver */
+	mutex_lock(&dvbdev_mutex);
 	if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
 		err = -EINVAL;
+	mutex_unlock(&dvbdev_mutex);
 
 	if (err < 0)
 		goto out;
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c
index d3c2cf6..8ffb565 100644
--- a/drivers/media/dvb/firewire/firedtv-ci.c
+++ b/drivers/media/dvb/firewire/firedtv-ci.c
@@ -220,6 +220,7 @@
 	.open		= dvb_generic_open,
 	.release	= dvb_generic_release,
 	.poll		= fdtv_ca_io_poll,
+	.llseek		= noop_llseek,
 };
 
 static struct dvb_device fdtv_ca = {
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index a6be529..893fbc5 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -730,6 +730,7 @@
 	.unlocked_ioctl	= dvb_generic_ioctl,
 	.open		= dvb_generic_open,
 	.release	= dvb_generic_release,
+	.llseek		= noop_llseek,
 };
 
 static struct dvb_device dvbdev_osd = {
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 13efba9..6ef3996 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -1521,6 +1521,7 @@
 	.open		= dvb_video_open,
 	.release	= dvb_video_release,
 	.poll		= dvb_video_poll,
+	.llseek		= noop_llseek,
 };
 
 static struct dvb_device dvbdev_video = {
@@ -1539,6 +1540,7 @@
 	.open		= dvb_audio_open,
 	.release	= dvb_audio_release,
 	.poll		= dvb_audio_poll,
+	.llseek		= noop_llseek,
 };
 
 static struct dvb_device dvbdev_audio = {
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index 4eba35a..43f61f2 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -353,6 +353,7 @@
 	.open		= dvb_ca_open,
 	.release	= dvb_generic_release,
 	.poll		= dvb_ca_poll,
+	.llseek		= default_llseek,
 };
 
 static struct dvb_device dvbdev_ca = {
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index b070e88..908f272 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -312,6 +312,7 @@
 static const struct file_operations av7110_ir_proc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= av7110_ir_proc_write,
+	.llseek		= noop_llseek,
 };
 
 /* interrupt handler */
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index 5b176bd..f3e25e9 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -32,7 +32,6 @@
 #include <linux/list.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
@@ -621,7 +620,6 @@
 	if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
 		return -EIO;
 
-	lock_kernel();
 	s = &dabusb[devnum - DABUSB_MINOR];
 
 	dbg("dabusb_open");
@@ -630,21 +628,17 @@
 	while (!s->usbdev || s->opened) {
 		mutex_unlock(&s->mutex);
 
-		if (file->f_flags & O_NONBLOCK) {
+		if (file->f_flags & O_NONBLOCK)
 			return -EBUSY;
-		}
 		msleep_interruptible(500);
 
-		if (signal_pending (current)) {
-			unlock_kernel();
+		if (signal_pending (current))
 			return -EAGAIN;
-		}
 		mutex_lock(&s->mutex);
 	}
 	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
 		mutex_unlock(&s->mutex);
 		dev_err(&s->usbdev->dev, "set_interface failed\n");
-		unlock_kernel();
 		return -EINVAL;
 	}
 	s->opened = 1;
@@ -654,7 +648,6 @@
 	file->private_data = s;
 
 	r = nonseekable_open(inode, file);
-	unlock_kernel();
 	return r;
 }
 
@@ -689,17 +682,13 @@
 
 	dbg("dabusb_ioctl");
 
-	lock_kernel();
-	if (s->remove_pending) {
-		unlock_kernel();
+	if (s->remove_pending)
 		return -EIO;
-	}
 
 	mutex_lock(&s->mutex);
 
 	if (!s->usbdev) {
 		mutex_unlock(&s->mutex);
-		unlock_kernel();
 		return -EIO;
 	}
 
@@ -735,7 +724,6 @@
 		break;
 	}
 	mutex_unlock(&s->mutex);
-	unlock_kernel();
 	return ret;
 }
 
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index d3f1a08..02362ec 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -18,11 +18,12 @@
 #include <linux/kthread.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/memstick.h>
 
 #define DRIVER_NAME "mspro_block"
 
+static DEFINE_MUTEX(mspro_block_mutex);
 static int major;
 module_param(major, int, 0644);
 
@@ -180,7 +181,7 @@
 	struct mspro_block_data *msb = disk->private_data;
 	int rc = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&mspro_block_mutex);
 	mutex_lock(&mspro_block_disk_lock);
 
 	if (msb && msb->card) {
@@ -192,7 +193,7 @@
 	}
 
 	mutex_unlock(&mspro_block_disk_lock);
-	unlock_kernel();
+	mutex_unlock(&mspro_block_mutex);
 
 	return rc;
 }
@@ -225,9 +226,9 @@
 static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode)
 {
 	int ret;
-	lock_kernel();
+	mutex_lock(&mspro_block_mutex);
 	ret = mspro_block_disk_release(disk);
-	unlock_kernel();
+	mutex_unlock(&mspro_block_mutex);
 	return ret;
 }
 
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 6837a8e..3e57b61 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -5945,8 +5945,10 @@
 		goto out;
 
 	mem = kmalloc(iocpage2sz, GFP_KERNEL);
-	if (!mem)
+	if (!mem) {
+		rc = -ENOMEM;
 		goto out;
+	}
 
 	memcpy(mem, (u8 *)pIoc2, iocpage2sz);
 	ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index d8ddfdf..a3856ed 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -54,7 +54,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>	/* for mdelay */
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 
 #include <asm/io.h>
@@ -83,6 +83,7 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
+static DEFINE_MUTEX(mpctl_mutex);
 static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS;
 static u8 mptctl_taskmgmt_id = MPT_MAX_PROTOCOL_DRIVERS;
 
@@ -601,12 +602,12 @@
 	MPT_ADAPTER	*ioc;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&mpctl_mutex);
 	list_for_each_entry(ioc, &ioc_list, list)
 		ioc->aen_event_read_flag=0;
 
 	ret = fasync_helper(fd, filep, mode, &async_queue);
-	unlock_kernel();
+	mutex_unlock(&mpctl_mutex);
 	return ret;
 }
 
@@ -698,9 +699,9 @@
 mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&mpctl_mutex);
 	ret = __mptctl_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&mpctl_mutex);
 	return ret;
 }
 
@@ -2926,7 +2927,7 @@
 static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&mpctl_mutex);
 	switch (cmd) {
 	case MPTIOCINFO:
 	case MPTIOCINFO1:
@@ -2951,7 +2952,7 @@
 		ret = -ENOIOCTLCMD;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&mpctl_mutex);
 	return ret;
 }
 
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index f0f1e66..f87a9d4 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -53,7 +53,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2o.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <linux/mempool.h>
 
@@ -69,6 +69,7 @@
 #define OSM_VERSION	"1.325"
 #define OSM_DESCRIPTION	"I2O Block Device OSM"
 
+static DEFINE_MUTEX(i2o_block_mutex);
 static struct i2o_driver i2o_block_driver;
 
 /* global Block OSM request mempool */
@@ -578,7 +579,7 @@
 	if (!dev->i2o_dev)
 		return -ENODEV;
 
-	lock_kernel();
+	mutex_lock(&i2o_block_mutex);
 	if (dev->power > 0x1f)
 		i2o_block_device_power(dev, 0x02);
 
@@ -587,7 +588,7 @@
 	i2o_block_device_lock(dev->i2o_dev, -1);
 
 	osm_debug("Ready.\n");
-	unlock_kernel();
+	mutex_unlock(&i2o_block_mutex);
 
 	return 0;
 };
@@ -618,7 +619,7 @@
 	if (!dev->i2o_dev)
 		return 0;
 
-	lock_kernel();
+	mutex_lock(&i2o_block_mutex);
 	i2o_block_device_flush(dev->i2o_dev);
 
 	i2o_block_device_unlock(dev->i2o_dev, -1);
@@ -629,7 +630,7 @@
 		operation = 0x24;
 
 	i2o_block_device_power(dev, operation);
-	unlock_kernel();
+	mutex_unlock(&i2o_block_mutex);
 
 	return 0;
 }
@@ -664,7 +665,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	lock_kernel();
+	mutex_lock(&i2o_block_mutex);
 	switch (cmd) {
 	case BLKI2OGRSTRAT:
 		ret = put_user(dev->rcache, (int __user *)arg);
@@ -688,7 +689,7 @@
 		ret = 0;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&i2o_block_mutex);
 
 	return ret;
 };
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 068ba07..7d3cc57 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -31,7 +31,7 @@
  */
 
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 #include <linux/slab.h>
 
@@ -41,6 +41,7 @@
 
 #define SG_TABLESIZE		30
 
+static DEFINE_MUTEX(i2o_cfg_mutex);
 static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long);
 
 static spinlock_t i2o_config_lock;
@@ -741,7 +742,7 @@
 				 unsigned long arg)
 {
 	int ret;
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	switch (cmd) {
 	case I2OGETIOPS:
 		ret = i2o_cfg_ioctl(file, cmd, arg);
@@ -753,7 +754,7 @@
 		ret = -ENOIOCTLCMD;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 	return ret;
 }
 
@@ -981,7 +982,7 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	switch (cmd) {
 	case I2OGETIOPS:
 		ret = i2o_cfg_getiops(arg);
@@ -1037,7 +1038,7 @@
 		osm_debug("unknown ioctl called!\n");
 		ret = -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 	return ret;
 }
 
@@ -1051,7 +1052,7 @@
 	if (!tmp)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	file->private_data = (void *)(i2o_cfg_info_id++);
 	tmp->fp = file;
 	tmp->fasync = NULL;
@@ -1065,7 +1066,7 @@
 	spin_lock_irqsave(&i2o_config_lock, flags);
 	open_files = tmp;
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 
 	return 0;
 }
@@ -1076,14 +1077,14 @@
 	struct i2o_cfg_info *p;
 	int ret = -EBADF;
 
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	for (p = open_files; p; p = p->next)
 		if (p->q_id == id)
 			break;
 
 	if (p)
 		ret = fasync_helper(fd, fp, on, &p->fasync);
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 	return ret;
 }
 
@@ -1093,7 +1094,7 @@
 	struct i2o_cfg_info *p, **q;
 	unsigned long flags;
 
-	lock_kernel();
+	mutex_lock(&i2o_cfg_mutex);
 	spin_lock_irqsave(&i2o_config_lock, flags);
 	for (q = &open_files; (p = *q) != NULL; q = &p->next) {
 		if (p->q_id == id) {
@@ -1103,7 +1104,7 @@
 		}
 	}
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
-	unlock_kernel();
+	mutex_unlock(&i2o_cfg_mutex);
 
 	return 0;
 }
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 66379b4..b048ecc 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -583,6 +583,7 @@
 static const struct file_operations ab3100_get_set_reg_fops = {
 	.open = ab3100_get_set_reg_open_file,
 	.write = ab3100_get_set_reg,
+	.llseek = noop_llseek,
 };
 
 static struct dentry *ab3100_dir;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b743312..db2fbe2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -248,15 +248,15 @@
 	  generic PIT, and are suitable for use as high-res timers.
 
 config HP_ILO
-	tristate "Channel interface driver for HP iLO/iLO2 processor"
+	tristate "Channel interface driver for the HP iLO processor"
 	depends on PCI
 	default n
 	help
 	  The channel interface driver allows applications to communicate
-	  with iLO/iLO2 management processors present on HP ProLiant
-	  servers.  Upon loading, the driver creates /dev/hpilo/dXccbN files,
-	  which can be used to gather data from the management processor,
-	  via read and write system calls.
+	  with iLO management processors present on HP ProLiant servers.
+	  Upon loading, the driver creates /dev/hpilo/dXccbN files, which
+	  can be used to gather data from the management processor, via
+	  read and write system calls.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called hpilo.
@@ -390,6 +390,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called bmp085.
 
+config PCH_PHUB
+	tristate "PCH Packet Hub of Intel Topcliff"
+	depends on PCI
+	help
+	  This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
+	  Intel Topcliff which is an IOH(Input/Output Hub) for x86 embedded
+	  processor. The Topcliff has MAC address and Option ROM data in SROM.
+	  This driver can access MAC address and Option ROM data in SROM.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called pch_phub.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 42eab95..9f2986b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -35,3 +35,4 @@
 obj-y				+= cb710/
 obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
 obj-$(CONFIG_ARM_CHARLCD)	+= arm-charlcd.o
+obj-$(CONFIG_PCH_PHUB)		+= pch_phub.o
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index 557a8c2..fffc227 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -1,5 +1,5 @@
 /*
- * Driver for HP iLO/iLO2 management processor.
+ * Driver for the HP iLO management processor.
  *
  * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
  *	David Altobelli <david.altobelli@hp.com>
@@ -640,6 +640,7 @@
 	.poll		= ilo_poll,
 	.open 		= ilo_open,
 	.release 	= ilo_close,
+	.llseek		= noop_llseek,
 };
 
 static irqreturn_t ilo_isr(int irq, void *data)
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 8844a3f..af2497a 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -584,6 +584,7 @@
 	.release =	command_file_close,
 	.read =		command_file_read,
 	.write =	command_file_write,
+	.llseek =	generic_file_llseek,
 };
 
 static const struct file_operations event_fops = {
@@ -591,6 +592,7 @@
 	.release =	event_file_close,
 	.read =		event_file_read,
 	.write =	event_file_write,
+	.llseek =	generic_file_llseek,
 };
 
 static const struct file_operations r_heartbeat_fops = {
@@ -598,6 +600,7 @@
 	.release =	r_heartbeat_file_close,
 	.read =		r_heartbeat_file_read,
 	.write =	r_heartbeat_file_write,
+	.llseek =	generic_file_llseek,
 };
 
 static const struct file_operations remote_settings_fops = {
@@ -605,6 +608,7 @@
 	.release =	remote_settings_file_close,
 	.read =		remote_settings_file_read,
 	.write =	remote_settings_file_write,
+	.llseek =	generic_file_llseek,
 };
 
 
diff --git a/drivers/misc/iwmc3200top/debugfs.c b/drivers/misc/iwmc3200top/debugfs.c
index e9eda47..62fbaec 100644
--- a/drivers/misc/iwmc3200top/debugfs.c
+++ b/drivers/misc/iwmc3200top/debugfs.c
@@ -71,6 +71,7 @@
 	static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
 		.read = iwmct_dbgfs_##name##_read,			\
 		.open = iwmct_dbgfs_open_file_generic,			\
+		.llseek = generic_file_llseek,				\
 	};
 
 #define DEBUGFS_WRITE_FILE_OPS(name)					\
@@ -78,6 +79,7 @@
 	static const struct file_operations iwmct_dbgfs_##name##_ops = {  \
 		.write = iwmct_dbgfs_##name##_write,			\
 		.open = iwmct_dbgfs_open_file_generic,			\
+		.llseek = generic_file_llseek,				\
 	};
 
 #define DEBUGFS_READ_WRITE_FILE_OPS(name)				\
@@ -87,6 +89,7 @@
 		.write = iwmct_dbgfs_##name##_write,			\
 		.read = iwmct_dbgfs_##name##_read,			\
 		.open = iwmct_dbgfs_open_file_generic,			\
+		.llseek = generic_file_llseek,				\
 	};
 
 
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index ef34de7..343b5d8 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -575,30 +575,39 @@
 
 static const struct crash_entry crash_entries[] = {
 	{"DIRECT", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = direct_entry} },
 	{"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = int_hardware_entry} },
 	{"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = int_hw_irq_en} },
 	{"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = int_tasklet_entry} },
 	{"FS_DEVRW", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = fs_devrw_entry} },
 	{"MEM_SWAPOUT", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = mem_swapout_entry} },
 	{"TIMERADD", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = timeradd_entry} },
 	{"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = scsi_dispatch_cmd_entry} },
 	{"IDE_CORE_CP",	{.read = lkdtm_debugfs_read,
+			.llseek = generic_file_llseek,
 			.open = lkdtm_debugfs_open,
 			.write = ide_core_cp_entry} },
 };
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
new file mode 100644
index 0000000..744b804
--- /dev/null
+++ b/drivers/misc/pch_phub.c
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., 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; 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/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/if_ether.h>
+#include <linux/ctype.h>
+
+#define PHUB_STATUS 0x00		/* Status Register offset */
+#define PHUB_CONTROL 0x04		/* Control Register offset */
+#define PHUB_TIMEOUT 0x05		/* Time out value for Status Register */
+#define PCH_PHUB_ROM_WRITE_ENABLE 0x01	/* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE 0x00	/* Disabling for writing ROM */
+#define PCH_PHUB_ROM_START_ADDR 0x14	/* ROM data area start address offset */
+
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
+#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
+#define PCH_MINOR_NOS 1
+#define CLKCFG_CAN_50MHZ 0x12000000
+#define CLKCFG_CANCLK_MASK 0xFF000000
+
+/* SROM ACCESS Macro */
+#define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
+
+/* Registers address offset */
+#define PCH_PHUB_ID_REG				0x0000
+#define PCH_PHUB_QUEUE_PRI_VAL_REG		0x0004
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG		0x0008
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG		0x000C
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG		0x0010
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG		0x0014
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG	0x0018
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0	0x0020
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1	0x0024
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2	0x0028
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3	0x002C
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	0x0040
+#define CLKCFG_REG_OFFSET			0x500
+
+#define PCH_PHUB_OROM_SIZE 15360
+
+/**
+ * struct pch_phub_reg - PHUB register structure
+ * @phub_id_reg:			PHUB_ID register val
+ * @q_pri_val_reg:			QUEUE_PRI_VAL register val
+ * @rc_q_maxsize_reg:			RC_QUEUE_MAXSIZE register val
+ * @bri_q_maxsize_reg:			BRI_QUEUE_MAXSIZE register val
+ * @comp_resp_timeout_reg:		COMP_RESP_TIMEOUT register val
+ * @bus_slave_control_reg:		BUS_SLAVE_CONTROL_REG register val
+ * @deadlock_avoid_type_reg:		DEADLOCK_AVOID_TYPE register val
+ * @intpin_reg_wpermit_reg0:		INTPIN_REG_WPERMIT register 0 val
+ * @intpin_reg_wpermit_reg1:		INTPIN_REG_WPERMIT register 1 val
+ * @intpin_reg_wpermit_reg2:		INTPIN_REG_WPERMIT register 2 val
+ * @intpin_reg_wpermit_reg3:		INTPIN_REG_WPERMIT register 3 val
+ * @int_reduce_control_reg:		INT_REDUCE_CONTROL registers val
+ * @clkcfg_reg:				CLK CFG register val
+ * @pch_phub_base_address:		Register base address
+ * @pch_phub_extrom_base_address:	external rom base address
+ */
+struct pch_phub_reg {
+	u32 phub_id_reg;
+	u32 q_pri_val_reg;
+	u32 rc_q_maxsize_reg;
+	u32 bri_q_maxsize_reg;
+	u32 comp_resp_timeout_reg;
+	u32 bus_slave_control_reg;
+	u32 deadlock_avoid_type_reg;
+	u32 intpin_reg_wpermit_reg0;
+	u32 intpin_reg_wpermit_reg1;
+	u32 intpin_reg_wpermit_reg2;
+	u32 intpin_reg_wpermit_reg3;
+	u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+	u32 clkcfg_reg;
+	void __iomem *pch_phub_base_address;
+	void __iomem *pch_phub_extrom_base_address;
+};
+
+/* SROM SPEC for MAC address assignment offset */
+static const int pch_phub_mac_offset[ETH_ALEN] = {0x3, 0x2, 0x1, 0x0, 0xb, 0xa};
+
+static DEFINE_MUTEX(pch_phub_mutex);
+
+/**
+ * pch_phub_read_modify_write_reg() - Reading modifying and writing register
+ * @reg_addr_offset:	Register offset address value.
+ * @data:		Writing value.
+ * @mask:		Mask value.
+ */
+static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip,
+					   unsigned int reg_addr_offset,
+					   unsigned int data, unsigned int mask)
+{
+	void __iomem *reg_addr = chip->pch_phub_base_address + reg_addr_offset;
+	iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+}
+
+/* pch_phub_save_reg_conf - saves register configuration */
+static void pch_phub_save_reg_conf(struct pci_dev *pdev)
+{
+	unsigned int i;
+	struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+
+	void __iomem *p = chip->pch_phub_base_address;
+
+	chip->phub_id_reg = ioread32(p + PCH_PHUB_ID_REG);
+	chip->q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+	chip->rc_q_maxsize_reg = ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	chip->bri_q_maxsize_reg = ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	chip->comp_resp_timeout_reg =
+				ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	chip->bus_slave_control_reg =
+				ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	chip->deadlock_avoid_type_reg =
+				ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	chip->intpin_reg_wpermit_reg0 =
+				ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	chip->intpin_reg_wpermit_reg1 =
+				ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	chip->intpin_reg_wpermit_reg2 =
+				ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	chip->intpin_reg_wpermit_reg3 =
+				ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "%s : "
+		"chip->phub_id_reg=%x, "
+		"chip->q_pri_val_reg=%x, "
+		"chip->rc_q_maxsize_reg=%x, "
+		"chip->bri_q_maxsize_reg=%x, "
+		"chip->comp_resp_timeout_reg=%x, "
+		"chip->bus_slave_control_reg=%x, "
+		"chip->deadlock_avoid_type_reg=%x, "
+		"chip->intpin_reg_wpermit_reg0=%x, "
+		"chip->intpin_reg_wpermit_reg1=%x, "
+		"chip->intpin_reg_wpermit_reg2=%x, "
+		"chip->intpin_reg_wpermit_reg3=%x\n", __func__,
+		chip->phub_id_reg,
+		chip->q_pri_val_reg,
+		chip->rc_q_maxsize_reg,
+		chip->bri_q_maxsize_reg,
+		chip->comp_resp_timeout_reg,
+		chip->bus_slave_control_reg,
+		chip->deadlock_avoid_type_reg,
+		chip->intpin_reg_wpermit_reg0,
+		chip->intpin_reg_wpermit_reg1,
+		chip->intpin_reg_wpermit_reg2,
+		chip->intpin_reg_wpermit_reg3);
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		chip->int_reduce_control_reg[i] =
+		    ioread32(p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "%s : "
+			"chip->int_reduce_control_reg[%d]=%x\n",
+			__func__, i, chip->int_reduce_control_reg[i]);
+	}
+	chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
+}
+
+/* pch_phub_restore_reg_conf - restore register configuration */
+static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
+{
+	unsigned int i;
+	struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+	void __iomem *p;
+	p = chip->pch_phub_base_address;
+
+	iowrite32(chip->phub_id_reg, p + PCH_PHUB_ID_REG);
+	iowrite32(chip->q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+	iowrite32(chip->rc_q_maxsize_reg, p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	iowrite32(chip->bri_q_maxsize_reg, p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	iowrite32(chip->comp_resp_timeout_reg,
+					p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	iowrite32(chip->bus_slave_control_reg,
+					p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	iowrite32(chip->deadlock_avoid_type_reg,
+					p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	iowrite32(chip->intpin_reg_wpermit_reg0,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	iowrite32(chip->intpin_reg_wpermit_reg1,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	iowrite32(chip->intpin_reg_wpermit_reg2,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	iowrite32(chip->intpin_reg_wpermit_reg3,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "%s : "
+		"chip->phub_id_reg=%x, "
+		"chip->q_pri_val_reg=%x, "
+		"chip->rc_q_maxsize_reg=%x, "
+		"chip->bri_q_maxsize_reg=%x, "
+		"chip->comp_resp_timeout_reg=%x, "
+		"chip->bus_slave_control_reg=%x, "
+		"chip->deadlock_avoid_type_reg=%x, "
+		"chip->intpin_reg_wpermit_reg0=%x, "
+		"chip->intpin_reg_wpermit_reg1=%x, "
+		"chip->intpin_reg_wpermit_reg2=%x, "
+		"chip->intpin_reg_wpermit_reg3=%x\n", __func__,
+		chip->phub_id_reg,
+		chip->q_pri_val_reg,
+		chip->rc_q_maxsize_reg,
+		chip->bri_q_maxsize_reg,
+		chip->comp_resp_timeout_reg,
+		chip->bus_slave_control_reg,
+		chip->deadlock_avoid_type_reg,
+		chip->intpin_reg_wpermit_reg0,
+		chip->intpin_reg_wpermit_reg1,
+		chip->intpin_reg_wpermit_reg2,
+		chip->intpin_reg_wpermit_reg3);
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		iowrite32(chip->int_reduce_control_reg[i],
+			p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "%s : "
+			"chip->int_reduce_control_reg[%d]=%x\n",
+			__func__, i, chip->int_reduce_control_reg[i]);
+	}
+
+	iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET);
+}
+
+/**
+ * pch_phub_read_serial_rom() - Reading Serial ROM
+ * @offset_address:	Serial ROM offset address to read.
+ * @data:		Read buffer for specified Serial ROM value.
+ */
+static void pch_phub_read_serial_rom(struct pch_phub_reg *chip,
+				     unsigned int offset_address, u8 *data)
+{
+	void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
+								offset_address;
+
+	*data = ioread8(mem_addr);
+}
+
+/**
+ * pch_phub_write_serial_rom() - Writing Serial ROM
+ * @offset_address:	Serial ROM offset address.
+ * @data:		Serial ROM value to write.
+ */
+static int pch_phub_write_serial_rom(struct pch_phub_reg *chip,
+				     unsigned int offset_address, u8 data)
+{
+	void __iomem *mem_addr = chip->pch_phub_extrom_base_address +
+					(offset_address & PCH_WORD_ADDR_MASK);
+	int i;
+	unsigned int word_data;
+	unsigned int pos;
+	unsigned int mask;
+	pos = (offset_address % 4) * 8;
+	mask = ~(0xFF << pos);
+
+	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+			chip->pch_phub_extrom_base_address + PHUB_CONTROL);
+
+	word_data = ioread32(mem_addr);
+	iowrite32((word_data & mask) | (u32)data << pos, mem_addr);
+
+	i = 0;
+	while (ioread8(chip->pch_phub_extrom_base_address +
+						PHUB_STATUS) != 0x00) {
+		msleep(1);
+		if (i == PHUB_TIMEOUT)
+			return -ETIMEDOUT;
+		i++;
+	}
+
+	iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+			chip->pch_phub_extrom_base_address + PHUB_CONTROL);
+
+	return 0;
+}
+
+/**
+ * pch_phub_read_serial_rom_val() - Read Serial ROM value
+ * @offset_address:	Serial ROM address offset value.
+ * @data:		Serial ROM value to read.
+ */
+static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip,
+					 unsigned int offset_address, u8 *data)
+{
+	unsigned int mem_addr;
+
+	mem_addr = PCH_PHUB_ROM_START_ADDR +
+			pch_phub_mac_offset[offset_address];
+
+	pch_phub_read_serial_rom(chip, mem_addr, data);
+}
+
+/**
+ * pch_phub_write_serial_rom_val() - writing Serial ROM value
+ * @offset_address:	Serial ROM address offset value.
+ * @data:		Serial ROM value.
+ */
+static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip,
+					 unsigned int offset_address, u8 data)
+{
+	int retval;
+	unsigned int mem_addr;
+
+	mem_addr = PCH_PHUB_ROM_START_ADDR +
+			pch_phub_mac_offset[offset_address];
+
+	retval = pch_phub_write_serial_rom(chip, mem_addr, data);
+
+	return retval;
+}
+
+/* pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ * for Gigabit Ethernet MAC address
+ */
+static int pch_phub_gbe_serial_rom_conf(struct pch_phub_reg *chip)
+{
+	int retval;
+
+	retval = pch_phub_write_serial_rom(chip, 0x0b, 0xbc);
+	retval |= pch_phub_write_serial_rom(chip, 0x0a, 0x10);
+	retval |= pch_phub_write_serial_rom(chip, 0x09, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x08, 0x02);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x0f, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x0e, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x0d, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x0c, 0x80);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x13, 0xbc);
+	retval |= pch_phub_write_serial_rom(chip, 0x12, 0x10);
+	retval |= pch_phub_write_serial_rom(chip, 0x11, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x10, 0x18);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x1b, 0xbc);
+	retval |= pch_phub_write_serial_rom(chip, 0x1a, 0x10);
+	retval |= pch_phub_write_serial_rom(chip, 0x19, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x18, 0x19);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x23, 0xbc);
+	retval |= pch_phub_write_serial_rom(chip, 0x22, 0x10);
+	retval |= pch_phub_write_serial_rom(chip, 0x21, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x20, 0x3a);
+
+	retval |= pch_phub_write_serial_rom(chip, 0x27, 0x01);
+	retval |= pch_phub_write_serial_rom(chip, 0x26, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x25, 0x00);
+	retval |= pch_phub_write_serial_rom(chip, 0x24, 0x00);
+
+	return retval;
+}
+
+/**
+ * pch_phub_read_gbe_mac_addr() - Read Gigabit Ethernet MAC address
+ * @offset_address:	Gigabit Ethernet MAC address offset value.
+ * @data:		Buffer of the Gigabit Ethernet MAC address value.
+ */
+static void pch_phub_read_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
+{
+	int i;
+	for (i = 0; i < ETH_ALEN; i++)
+		pch_phub_read_serial_rom_val(chip, i, &data[i]);
+}
+
+/**
+ * pch_phub_write_gbe_mac_addr() - Write MAC address
+ * @offset_address:	Gigabit Ethernet MAC address offset value.
+ * @data:		Gigabit Ethernet MAC address value.
+ */
+static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
+{
+	int retval;
+	int i;
+
+	retval = pch_phub_gbe_serial_rom_conf(chip);
+	if (retval)
+		return retval;
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		retval = pch_phub_write_serial_rom_val(chip, i, data[i]);
+		if (retval)
+			return retval;
+	}
+
+	return retval;
+}
+
+static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
+				 struct bin_attribute *attr, char *buf,
+				 loff_t off, size_t count)
+{
+	unsigned int rom_signature;
+	unsigned char rom_length;
+	unsigned int tmp;
+	unsigned int addr_offset;
+	unsigned int orom_size;
+	int ret;
+	int err;
+
+	struct pch_phub_reg *chip =
+		dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+	ret = mutex_lock_interruptible(&pch_phub_mutex);
+	if (ret) {
+		err = -ERESTARTSYS;
+		goto return_err_nomutex;
+	}
+
+	/* Get Rom signature */
+	pch_phub_read_serial_rom(chip, 0x80, (unsigned char *)&rom_signature);
+	rom_signature &= 0xff;
+	pch_phub_read_serial_rom(chip, 0x81, (unsigned char *)&tmp);
+	rom_signature |= (tmp & 0xff) << 8;
+	if (rom_signature == 0xAA55) {
+		pch_phub_read_serial_rom(chip, 0x82, &rom_length);
+		orom_size = rom_length * 512;
+		if (orom_size < off) {
+			addr_offset = 0;
+			goto return_ok;
+		}
+		if (orom_size < count) {
+			addr_offset = 0;
+			goto return_ok;
+		}
+
+		for (addr_offset = 0; addr_offset < count; addr_offset++) {
+			pch_phub_read_serial_rom(chip, 0x80 + addr_offset + off,
+							 &buf[addr_offset]);
+		}
+	} else {
+		err = -ENODATA;
+		goto return_err;
+	}
+return_ok:
+	mutex_unlock(&pch_phub_mutex);
+	return addr_offset;
+
+return_err:
+	mutex_unlock(&pch_phub_mutex);
+return_err_nomutex:
+	return err;
+}
+
+static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
+				  struct bin_attribute *attr,
+				  char *buf, loff_t off, size_t count)
+{
+	int err;
+	unsigned int addr_offset;
+	int ret;
+	struct pch_phub_reg *chip =
+		dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+	ret = mutex_lock_interruptible(&pch_phub_mutex);
+	if (ret)
+		return -ERESTARTSYS;
+
+	if (off > PCH_PHUB_OROM_SIZE) {
+		addr_offset = 0;
+		goto return_ok;
+	}
+	if (count > PCH_PHUB_OROM_SIZE) {
+		addr_offset = 0;
+		goto return_ok;
+	}
+
+	for (addr_offset = 0; addr_offset < count; addr_offset++) {
+		if (PCH_PHUB_OROM_SIZE < off + addr_offset)
+			goto return_ok;
+
+		ret = pch_phub_write_serial_rom(chip, 0x80 + addr_offset + off,
+						       buf[addr_offset]);
+		if (ret) {
+			err = ret;
+			goto return_err;
+		}
+	}
+
+return_ok:
+	mutex_unlock(&pch_phub_mutex);
+	return addr_offset;
+
+return_err:
+	mutex_unlock(&pch_phub_mutex);
+	return err;
+}
+
+static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	u8 mac[8];
+	struct pch_phub_reg *chip = dev_get_drvdata(dev);
+
+	pch_phub_read_gbe_mac_addr(chip, mac);
+
+	return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+				mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	u8 mac[6];
+	struct pch_phub_reg *chip = dev_get_drvdata(dev);
+
+	if (count != 18)
+		return -EINVAL;
+
+	sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+		(u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
+		(u32 *)&mac[4], (u32 *)&mac[5]);
+
+	pch_phub_write_gbe_mac_addr(chip, mac);
+
+	return count;
+}
+
+static DEVICE_ATTR(pch_mac, S_IRUGO | S_IWUSR, show_pch_mac, store_pch_mac);
+
+static struct bin_attribute pch_bin_attr = {
+	.attr = {
+		.name = "pch_firmware",
+		.mode = S_IRUGO | S_IWUSR,
+	},
+	.size = PCH_PHUB_OROM_SIZE + 1,
+	.read = pch_phub_bin_read,
+	.write = pch_phub_bin_write,
+};
+
+static int __devinit pch_phub_probe(struct pci_dev *pdev,
+				    const struct pci_device_id *id)
+{
+	int retval;
+
+	int ret;
+	ssize_t rom_size;
+	struct pch_phub_reg *chip;
+
+	chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+		"%s : pci_enable_device FAILED(ret=%d)", __func__, ret);
+		goto err_pci_enable_dev;
+	}
+	dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n", __func__,
+		ret);
+
+	ret = pci_request_regions(pdev, KBUILD_MODNAME);
+	if (ret) {
+		dev_err(&pdev->dev,
+		"%s : pci_request_regions FAILED(ret=%d)", __func__, ret);
+		goto err_req_regions;
+	}
+	dev_dbg(&pdev->dev, "%s : "
+		"pci_request_regions returns %d\n", __func__, ret);
+
+	chip->pch_phub_base_address = pci_iomap(pdev, 1, 0);
+
+
+	if (chip->pch_phub_base_address == 0) {
+		dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
+		ret = -ENOMEM;
+		goto err_pci_iomap;
+	}
+	dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value "
+		"in pch_phub_base_address variable is %p\n", __func__,
+		chip->pch_phub_base_address);
+	chip->pch_phub_extrom_base_address = pci_map_rom(pdev, &rom_size);
+
+	if (chip->pch_phub_extrom_base_address == 0) {
+		dev_err(&pdev->dev, "%s : pci_map_rom FAILED", __func__);
+		ret = -ENOMEM;
+		goto err_pci_map;
+	}
+	dev_dbg(&pdev->dev, "%s : "
+		"pci_map_rom SUCCESS and value in "
+		"pch_phub_extrom_base_address variable is %p\n", __func__,
+		chip->pch_phub_extrom_base_address);
+
+	pci_set_drvdata(pdev, chip);
+
+	retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+	if (retval)
+		goto err_sysfs_create;
+
+	retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+	if (retval)
+		goto exit_bin_attr;
+
+	pch_phub_read_modify_write_reg(chip, (unsigned int)CLKCFG_REG_OFFSET,
+					CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+
+	/* set the prefech value */
+	iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
+	/* set the interrupt delay value */
+	iowrite32(0x25, chip->pch_phub_base_address + 0x44);
+
+	return 0;
+exit_bin_attr:
+	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+
+err_sysfs_create:
+	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
+err_pci_map:
+	pci_iounmap(pdev, chip->pch_phub_base_address);
+err_pci_iomap:
+	pci_release_regions(pdev);
+err_req_regions:
+	pci_disable_device(pdev);
+err_pci_enable_dev:
+	kfree(chip);
+	dev_err(&pdev->dev, "%s returns %d\n", __func__, ret);
+	return ret;
+}
+
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+	struct pch_phub_reg *chip = pci_get_drvdata(pdev);
+
+	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
+	sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+	pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
+	pci_iounmap(pdev, chip->pch_phub_base_address);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	kfree(chip);
+}
+
+#ifdef CONFIG_PM
+
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int ret;
+
+	pch_phub_save_reg_conf(pdev);
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			" %s -pci_save_state returns %d\n", __func__, ret);
+		return ret;
+	}
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+static int pch_phub_resume(struct pci_dev *pdev)
+{
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+		"%s-pci_enable_device failed(ret=%d) ", __func__, ret);
+		return ret;
+	}
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pch_phub_restore_reg_conf(pdev);
+
+	return 0;
+}
+#else
+#define pch_phub_suspend NULL
+#define pch_phub_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_device_id pch_phub_pcidev_id[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+	{0,}
+};
+
+static struct pci_driver pch_phub_driver = {
+	.name = "pch_phub",
+	.id_table = pch_phub_pcidev_id,
+	.probe = pch_phub_probe,
+	.remove = __devexit_p(pch_phub_remove),
+	.suspend = pch_phub_suspend,
+	.resume = pch_phub_resume
+};
+
+static int __init pch_phub_pci_init(void)
+{
+	return pci_register_driver(&pch_phub_driver);
+}
+
+static void __exit pch_phub_pci_exit(void)
+{
+	pci_unregister_driver(&pch_phub_driver);
+}
+
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+
+MODULE_DESCRIPTION("PCH Packet Hub PCI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 75ee0d3..4197a3c 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/phantom.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -38,6 +38,7 @@
 #define PHB_RUNNING		1
 #define PHB_NOT_OH		2
 
+static DEFINE_MUTEX(phantom_mutex);
 static struct class *phantom_class;
 static int phantom_major;
 
@@ -215,17 +216,17 @@
 	struct phantom_device *dev = container_of(inode->i_cdev,
 			struct phantom_device, cdev);
 
-	lock_kernel();
+	mutex_lock(&phantom_mutex);
 	nonseekable_open(inode, file);
 
 	if (mutex_lock_interruptible(&dev->open_lock)) {
-		unlock_kernel();
+		mutex_unlock(&phantom_mutex);
 		return -ERESTARTSYS;
 	}
 
 	if (dev->opened) {
 		mutex_unlock(&dev->open_lock);
-		unlock_kernel();
+		mutex_unlock(&phantom_mutex);
 		return -EINVAL;
 	}
 
@@ -236,7 +237,7 @@
 	atomic_set(&dev->counter, 0);
 	dev->opened++;
 	mutex_unlock(&dev->open_lock);
-	unlock_kernel();
+	mutex_unlock(&phantom_mutex);
 	return 0;
 }
 
@@ -279,6 +280,7 @@
 	.unlocked_ioctl = phantom_ioctl,
 	.compat_ioctl = phantom_compat_ioctl,
 	.poll = phantom_poll,
+	.llseek = no_llseek,
 };
 
 static irqreturn_t phantom_isr(int irq, void *data)
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index cb3b4d2..28852df 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -587,6 +587,7 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= gru_file_unlocked_ioctl,
 	.mmap		= gru_file_mmap,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice gru_miscdev = {
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index d545f79..00073b7 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -29,7 +29,6 @@
 #include <linux/kdev_t.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/scatterlist.h>
 #include <linux/string_helpers.h>
 
@@ -51,6 +50,7 @@
 #define MMC_SHIFT	3
 #define MMC_NUM_MINORS	(256 >> MMC_SHIFT)
 
+static DEFINE_MUTEX(block_mutex);
 static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS);
 
 /*
@@ -108,7 +108,7 @@
 	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
 	int ret = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&block_mutex);
 	if (md) {
 		if (md->usage == 2)
 			check_disk_change(bdev);
@@ -119,7 +119,7 @@
 			ret = -EROFS;
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&block_mutex);
 
 	return ret;
 }
@@ -128,9 +128,9 @@
 {
 	struct mmc_blk_data *md = disk->private_data;
 
-	lock_kernel();
+	mutex_lock(&block_mutex);
 	mmc_blk_put(md);
-	unlock_kernel();
+	mutex_unlock(&block_mutex);
 	return 0;
 }
 
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index e876678..9c0b42b 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -128,7 +128,6 @@
 	mq->req = NULL;
 
 	blk_queue_prep_rq(mq->queue, mmc_prep_request);
-	blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN);
 	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
 	if (mmc_can_erase(card)) {
 		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mq->queue);
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 53cb380c..46bc6d7 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -245,6 +245,7 @@
 	.open		= mmc_ext_csd_open,
 	.read		= mmc_ext_csd_read,
 	.release	= mmc_ext_csd_release,
+	.llseek		= default_llseek,
 };
 
 void mmc_add_card_debugfs(struct mmc_card *card)
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 62e6870..50ab431 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -29,7 +29,6 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/hdreg.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -38,6 +37,7 @@
 
 #include "mtdcore.h"
 
+static DEFINE_MUTEX(mtd_blkdevs_mutex);
 static LIST_HEAD(blktrans_majors);
 static DEFINE_MUTEX(blktrans_ref_mutex);
 
@@ -181,7 +181,7 @@
 	if (!dev)
 		return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
 
-	lock_kernel();
+	mutex_lock(&mtd_blkdevs_mutex);
 	mutex_lock(&dev->lock);
 
 	if (!dev->mtd) {
@@ -198,7 +198,7 @@
 unlock:
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
-	unlock_kernel();
+	mutex_unlock(&mtd_blkdevs_mutex);
 	return ret;
 }
 
@@ -210,7 +210,7 @@
 	if (!dev)
 		return ret;
 
-	lock_kernel();
+	mutex_lock(&mtd_blkdevs_mutex);
 	mutex_lock(&dev->lock);
 
 	/* Release one reference, we sure its not the last one here*/
@@ -223,7 +223,7 @@
 unlock:
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
-	unlock_kernel();
+	mutex_unlock(&mtd_blkdevs_mutex);
 	return ret;
 }
 
@@ -256,7 +256,7 @@
 	if (!dev)
 		return ret;
 
-	lock_kernel();
+	mutex_lock(&mtd_blkdevs_mutex);
 	mutex_lock(&dev->lock);
 
 	if (!dev->mtd)
@@ -271,7 +271,7 @@
 	}
 unlock:
 	mutex_unlock(&dev->lock);
-	unlock_kernel();
+	mutex_unlock(&mtd_blkdevs_mutex);
 	blktrans_dev_put(dev);
 	return ret;
 }
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index a825002..5ef4548 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -26,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/backing-dev.h>
 #include <linux/compat.h>
 #include <linux/mount.h>
@@ -37,6 +37,7 @@
 #include <asm/uaccess.h>
 
 #define MTD_INODE_FS_MAGIC 0x11307854
+static DEFINE_MUTEX(mtd_mutex);
 static struct vfsmount *mtd_inode_mnt __read_mostly;
 
 /*
@@ -90,7 +91,7 @@
 	if ((file->f_mode & FMODE_WRITE) && (minor & 1))
 		return -EACCES;
 
-	lock_kernel();
+	mutex_lock(&mtd_mutex);
 	mtd = get_mtd_device(NULL, devnum);
 
 	if (IS_ERR(mtd)) {
@@ -138,7 +139,7 @@
 	file->private_data = mfi;
 
 out:
-	unlock_kernel();
+	mutex_unlock(&mtd_mutex);
 	return ret;
 } /* mtd_open */
 
@@ -866,9 +867,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&mtd_mutex);
 	ret = mtd_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&mtd_mutex);
 
 	return ret;
 }
@@ -892,7 +893,7 @@
 	void __user *argp = compat_ptr(arg);
 	int ret = 0;
 
-	lock_kernel();
+	mutex_lock(&mtd_mutex);
 
 	switch (cmd) {
 	case MEMWRITEOOB32:
@@ -927,7 +928,7 @@
 		ret = mtd_ioctl(file, cmd, (unsigned long)argp);
 	}
 
-	unlock_kernel();
+	mutex_unlock(&mtd_mutex);
 
 	return ret;
 }
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index f702a16..3cf193f 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -1,9 +1,5 @@
-menu "UBI - Unsorted block images"
-	depends on MTD
-
-config MTD_UBI
-	tristate "Enable UBI"
-	depends on MTD
+menuconfig MTD_UBI
+	tristate "Enable UBI - Unsorted block images"
 	select CRC32
 	help
 	  UBI is a software layer above MTD layer which admits of LVM-like
@@ -12,11 +8,12 @@
 	  capabilities. Please, consult the MTD web site for more details
 	  (www.linux-mtd.infradead.org).
 
+if MTD_UBI
+
 config MTD_UBI_WL_THRESHOLD
 	int "UBI wear-leveling threshold"
 	default 4096
 	range 2 65536
-	depends on MTD_UBI
 	help
 	  This parameter defines the maximum difference between the highest
 	  erase counter value and the lowest erase counter value of eraseblocks
@@ -34,7 +31,6 @@
 	int "Percentage of reserved eraseblocks for bad eraseblocks handling"
 	default 1
 	range 0 25
-	depends on MTD_UBI
 	help
 	  If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
 	  reserves some amount of physical eraseblocks to handle new bad
@@ -48,8 +44,6 @@
 
 config MTD_UBI_GLUEBI
 	tristate "MTD devices emulation driver (gluebi)"
-	default n
-	depends on MTD_UBI
 	help
 	   This option enables gluebi - an additional driver which emulates MTD
 	   devices on top of UBI volumes: for each UBI volumes an MTD device is
@@ -59,4 +53,5 @@
 	   software.
 
 source "drivers/mtd/ubi/Kconfig.debug"
-endmenu
+
+endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug
index 61f6e5e..fad4adc 100644
--- a/drivers/mtd/ubi/Kconfig.debug
+++ b/drivers/mtd/ubi/Kconfig.debug
@@ -1,94 +1,73 @@
 comment "UBI debugging options"
-	depends on MTD_UBI
 
 config MTD_UBI_DEBUG
 	bool "UBI debugging"
 	depends on SYSFS
-	depends on MTD_UBI
 	select DEBUG_FS
 	select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL
 	help
 	  This option enables UBI debugging.
 
+if MTD_UBI_DEBUG
+
 config MTD_UBI_DEBUG_MSG
 	bool "UBI debugging messages"
-	depends on MTD_UBI_DEBUG
-	default n
 	help
 	  This option enables UBI debugging messages.
 
 config MTD_UBI_DEBUG_PARANOID
 	bool "Extra self-checks"
-	default n
-	depends on MTD_UBI_DEBUG
 	help
 	  This option enables extra checks in UBI code. Note this slows UBI down
 	  significantly.
 
 config MTD_UBI_DEBUG_DISABLE_BGT
 	bool "Do not enable the UBI background thread"
-	depends on MTD_UBI_DEBUG
-	default n
 	help
 	  This option switches the background thread off by default. The thread
 	  may be also be enabled/disabled via UBI sysfs.
 
 config MTD_UBI_DEBUG_EMULATE_BITFLIPS
 	bool "Emulate flash bit-flips"
-	depends on MTD_UBI_DEBUG
-	default n
 	help
 	  This option emulates bit-flips with probability 1/50, which in turn
 	  causes scrubbing. Useful for debugging and stressing UBI.
 
 config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES
 	bool "Emulate flash write failures"
-	depends on MTD_UBI_DEBUG
-	default n
 	help
 	  This option emulates write failures with probability 1/100. Useful for
 	  debugging and testing how UBI handlines errors.
 
 config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES
 	bool "Emulate flash erase failures"
-	depends on MTD_UBI_DEBUG
-	default n
 	help
 	  This option emulates erase failures with probability 1/100. Useful for
 	  debugging and testing how UBI handlines errors.
 
-menu "Additional UBI debugging messages"
-	depends on MTD_UBI_DEBUG
+comment "Additional UBI debugging messages"
 
 config MTD_UBI_DEBUG_MSG_BLD
 	bool "Additional UBI initialization and build messages"
-	default n
-	depends on MTD_UBI_DEBUG
 	help
 	  This option enables detailed UBI initialization and device build
 	  debugging messages.
 
 config MTD_UBI_DEBUG_MSG_EBA
 	bool "Eraseblock association unit messages"
-	default n
-	depends on MTD_UBI_DEBUG
 	help
 	  This option enables debugging messages from the UBI eraseblock
 	  association unit.
 
 config MTD_UBI_DEBUG_MSG_WL
 	bool "Wear-leveling unit messages"
-	default n
-	depends on MTD_UBI_DEBUG
 	help
 	  This option enables debugging messages from the UBI wear-leveling
 	  unit.
 
 config MTD_UBI_DEBUG_MSG_IO
 	bool "Input/output unit messages"
-	default n
-	depends on MTD_UBI_DEBUG
 	help
 	  This option enables debugging messages from the UBI input/output unit.
 
-endmenu # UBI debugging messages
+endif # MTD_UBI_DEBUG
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 78ae894..5ebe280 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -95,8 +95,8 @@
 static DEFINE_SPINLOCK(ubi_devices_lock);
 
 /* "Show" method for files in '/<sysfs>/class/ubi/' */
-static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr,
-				char *buf)
+static ssize_t ubi_version_show(struct class *class,
+				struct class_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", UBI_VERSION);
 }
@@ -591,6 +591,7 @@
 
 	ubi->bad_peb_count = si->bad_peb_count;
 	ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
+	ubi->corr_peb_count = si->corr_peb_count;
 	ubi->max_ec = si->max_ec;
 	ubi->mean_ec = si->mean_ec;
 	ubi_msg("max. sequence number:       %llu", si->max_sqnum);
@@ -972,6 +973,7 @@
 	ubi_msg("MTD device size:            %llu MiB", ubi->flash_size >> 20);
 	ubi_msg("number of good PEBs:        %d", ubi->good_peb_count);
 	ubi_msg("number of bad PEBs:         %d", ubi->bad_peb_count);
+	ubi_msg("number of corrupted PEBs:   %d", ubi->corr_peb_count);
 	ubi_msg("max. allowed volumes:       %d", ubi->vtbl_slots);
 	ubi_msg("wear-leveling threshold:    %d", CONFIG_MTD_UBI_WL_THRESHOLD);
 	ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 3d2d1a6..af9fb0f 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -1100,4 +1100,5 @@
 	.owner          = THIS_MODULE,
 	.unlocked_ioctl = ctrl_cdev_ioctl,
 	.compat_ioctl   = ctrl_cdev_compat_ioctl,
+	.llseek		= noop_llseek,
 };
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 17a1071..9eca950 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -57,6 +57,9 @@
 void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
 
+#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a)  \
+		print_hex_dump(l, ps, pt, r, g, b, len, a)
+
 #ifdef CONFIG_MTD_UBI_DEBUG_MSG
 /* General debugging messages */
 #define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
@@ -172,6 +175,7 @@
 #define ubi_dbg_dump_seb(seb, type)      ({})
 #define ubi_dbg_dump_mkvol_req(req)      ({})
 #define ubi_dbg_dump_flash(ubi, pnum, offset, len) ({})
+#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a)  ({})
 
 #define UBI_IO_DEBUG               0
 #define DBG_DISABLE_BGT            0
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index fe74749..4be67181 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -418,7 +418,7 @@
 				 * may try to recover data. FIXME: but this is
 				 * not implemented.
 				 */
-				if (err == UBI_IO_BAD_HDR_READ ||
+				if (err == UBI_IO_BAD_HDR_EBADMSG ||
 				    err == UBI_IO_BAD_HDR) {
 					ubi_warn("corrupted VID header at PEB "
 						 "%d, LEB %d:%d", pnum, vol_id,
@@ -963,7 +963,7 @@
 static int is_error_sane(int err)
 {
 	if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR ||
-	    err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT)
+	    err == UBI_IO_BAD_HDR_EBADMSG || err == -ETIMEDOUT)
 		return 0;
 	return 1;
 }
@@ -1201,6 +1201,9 @@
 
 	ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d,"
 		 " need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
+	if (ubi->corr_peb_count)
+		ubi_warn("%d PEBs are corrupted and not used",
+			ubi->corr_peb_count);
 }
 
 /**
@@ -1263,6 +1266,9 @@
 	if (ubi->avail_pebs < EBA_RESERVED_PEBS) {
 		ubi_err("no enough physical eraseblocks (%d, need %d)",
 			ubi->avail_pebs, EBA_RESERVED_PEBS);
+		if (ubi->corr_peb_count)
+			ubi_err("%d PEBs are corrupted and not used",
+				ubi->corr_peb_count);
 		err = -ENOSPC;
 		goto out_free;
 	}
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 332f992..c2960ac 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -376,25 +376,6 @@
 	return 0;
 }
 
-/**
- * check_pattern - check if buffer contains only a certain byte pattern.
- * @buf: buffer to check
- * @patt: the pattern to check
- * @size: buffer size in bytes
- *
- * This function returns %1 in there are only @patt bytes in @buf, and %0 if
- * something else was also found.
- */
-static int check_pattern(const void *buf, uint8_t patt, int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++)
-		if (((const uint8_t *)buf)[i] != patt)
-			return 0;
-	return 1;
-}
-
 /* Patterns to write to a physical eraseblock when torturing it */
 static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
 
@@ -426,7 +407,7 @@
 		if (err)
 			goto out;
 
-		err = check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
+		err = ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
 		if (err == 0) {
 			ubi_err("erased PEB %d, but a non-0xFF byte found",
 				pnum);
@@ -445,7 +426,8 @@
 		if (err)
 			goto out;
 
-		err = check_pattern(ubi->peb_buf1, patterns[i], ubi->peb_size);
+		err = ubi_check_pattern(ubi->peb_buf1, patterns[i],
+					ubi->peb_size);
 		if (err == 0) {
 			ubi_err("pattern %x checking failed for PEB %d",
 				patterns[i], pnum);
@@ -517,7 +499,7 @@
 	 * In this case we probably anyway have garbage in this PEB.
 	 */
 	err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
-	if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR)
+	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
 		/*
 		 * The VID header is corrupted, so we can safely erase this
 		 * PEB and not afraid that it will be treated as a valid PEB in
@@ -712,47 +694,47 @@
  *   and corrected by the flash driver; this is harmless but may indicate that
  *   this eraseblock may become bad soon (but may be not);
  * o %UBI_IO_BAD_HDR if the erase counter header is corrupted (a CRC error);
- * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty;
+ * o %UBI_IO_BAD_HDR_EBADMSG is the same as %UBI_IO_BAD_HDR, but there also was
+ *   a data integrity error (uncorrectable ECC error in case of NAND);
+ * o %UBI_IO_FF if only 0xFF bytes were read (the PEB is supposedly empty)
  * o a negative error code in case of failure.
  */
 int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 		       struct ubi_ec_hdr *ec_hdr, int verbose)
 {
-	int err, read_err = 0;
+	int err, read_err;
 	uint32_t crc, magic, hdr_crc;
 
 	dbg_io("read EC header from PEB %d", pnum);
 	ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
 
-	err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
-	if (err) {
-		if (err != UBI_IO_BITFLIPS && err != -EBADMSG)
-			return err;
+	read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
+	if (read_err) {
+		if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+			return read_err;
 
 		/*
 		 * We read all the data, but either a correctable bit-flip
-		 * occurred, or MTD reported about some data integrity error,
-		 * like an ECC error in case of NAND. The former is harmless,
-		 * the later may mean that the read data is corrupted. But we
-		 * have a CRC check-sum and we will detect this. If the EC
-		 * header is still OK, we just report this as there was a
-		 * bit-flip.
+		 * occurred, or MTD reported a data integrity error
+		 * (uncorrectable ECC error in case of NAND). The former is
+		 * harmless, the later may mean that the read data is
+		 * corrupted. But we have a CRC check-sum and we will detect
+		 * this. If the EC header is still OK, we just report this as
+		 * there was a bit-flip, to force scrubbing.
 		 */
-		if (err == -EBADMSG)
-			read_err = UBI_IO_BAD_HDR_READ;
 	}
 
 	magic = be32_to_cpu(ec_hdr->magic);
 	if (magic != UBI_EC_HDR_MAGIC) {
-		if (read_err)
-			return read_err;
+		if (read_err == -EBADMSG)
+			return UBI_IO_BAD_HDR_EBADMSG;
 
 		/*
 		 * The magic field is wrong. Let's check if we have read all
 		 * 0xFF. If yes, this physical eraseblock is assumed to be
 		 * empty.
 		 */
-		if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
+		if (ubi_check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
 			/* The physical eraseblock is supposedly empty */
 			if (verbose)
 				ubi_warn("no EC header found at PEB %d, "
@@ -760,7 +742,10 @@
 			else if (UBI_IO_DEBUG)
 				dbg_msg("no EC header found at PEB %d, "
 					"only 0xFF bytes", pnum);
-			return UBI_IO_PEB_EMPTY;
+			if (!read_err)
+				return UBI_IO_FF;
+			else
+				return UBI_IO_FF_BITFLIPS;
 		}
 
 		/*
@@ -788,7 +773,11 @@
 		} else if (UBI_IO_DEBUG)
 			dbg_msg("bad EC header CRC at PEB %d, calculated "
 				"%#08x, read %#08x", pnum, crc, hdr_crc);
-		return read_err ?: UBI_IO_BAD_HDR;
+
+		if (!read_err)
+			return UBI_IO_BAD_HDR;
+		else
+			return UBI_IO_BAD_HDR_EBADMSG;
 	}
 
 	/* And of course validate what has just been read from the media */
@@ -975,22 +964,16 @@
  *
  * This function reads the volume identifier header from physical eraseblock
  * @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read
- * volume identifier header. The following codes may be returned:
+ * volume identifier header. The error codes are the same as in
+ * 'ubi_io_read_ec_hdr()'.
  *
- * o %0 if the CRC checksum is correct and the header was successfully read;
- * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected
- *   and corrected by the flash driver; this is harmless but may indicate that
- *   this eraseblock may become bad soon;
- * o %UBI_IO_BAD_HDR if the volume identifier header is corrupted (a CRC
- *   error detected);
- * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID
- *   header there);
- * o a negative error code in case of failure.
+ * Note, the implementation of this function is also very similar to
+ * 'ubi_io_read_ec_hdr()', so refer commentaries in 'ubi_io_read_ec_hdr()'.
  */
 int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
 			struct ubi_vid_hdr *vid_hdr, int verbose)
 {
-	int err, read_err = 0;
+	int err, read_err;
 	uint32_t crc, magic, hdr_crc;
 	void *p;
 
@@ -998,48 +981,29 @@
 	ubi_assert(pnum >= 0 &&  pnum < ubi->peb_count);
 
 	p = (char *)vid_hdr - ubi->vid_hdr_shift;
-	err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
+	read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
 			  ubi->vid_hdr_alsize);
-	if (err) {
-		if (err != UBI_IO_BITFLIPS && err != -EBADMSG)
-			return err;
-
-		/*
-		 * We read all the data, but either a correctable bit-flip
-		 * occurred, or MTD reported about some data integrity error,
-		 * like an ECC error in case of NAND. The former is harmless,
-		 * the later may mean the read data is corrupted. But we have a
-		 * CRC check-sum and we will identify this. If the VID header is
-		 * still OK, we just report this as there was a bit-flip.
-		 */
-		if (err == -EBADMSG)
-			read_err = UBI_IO_BAD_HDR_READ;
-	}
+	if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
+		return read_err;
 
 	magic = be32_to_cpu(vid_hdr->magic);
 	if (magic != UBI_VID_HDR_MAGIC) {
-		if (read_err)
-			return read_err;
+		if (read_err == -EBADMSG)
+			return UBI_IO_BAD_HDR_EBADMSG;
 
-		/*
-		 * If we have read all 0xFF bytes, the VID header probably does
-		 * not exist and the physical eraseblock is assumed to be free.
-		 */
-		if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
-			/* The physical eraseblock is supposedly free */
+		if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
 			if (verbose)
 				ubi_warn("no VID header found at PEB %d, "
 					 "only 0xFF bytes", pnum);
 			else if (UBI_IO_DEBUG)
 				dbg_msg("no VID header found at PEB %d, "
 					"only 0xFF bytes", pnum);
-			return UBI_IO_PEB_FREE;
+			if (!read_err)
+				return UBI_IO_FF;
+			else
+				return UBI_IO_FF_BITFLIPS;
 		}
 
-		/*
-		 * This is not a valid VID header, and these are not 0xFF
-		 * bytes. Report that the header is corrupted.
-		 */
 		if (verbose) {
 			ubi_warn("bad magic number at PEB %d: %08x instead of "
 				 "%08x", pnum, magic, UBI_VID_HDR_MAGIC);
@@ -1061,20 +1025,18 @@
 		} else if (UBI_IO_DEBUG)
 			dbg_msg("bad CRC at PEB %d, calculated %#08x, "
 				"read %#08x", pnum, crc, hdr_crc);
-		return read_err ?: UBI_IO_BAD_HDR;
+		if (!read_err)
+			return UBI_IO_BAD_HDR;
+		else
+			return UBI_IO_BAD_HDR_EBADMSG;
 	}
 
-	/* Validate the VID header that we have just read */
 	err = validate_vid_hdr(ubi, vid_hdr);
 	if (err) {
 		ubi_err("validation failed for PEB %d", pnum);
 		return -EINVAL;
 	}
 
-	/*
-	 * If there was a read error (%-EBADMSG), but the header CRC is still
-	 * OK, report about a bit-flip to force scrubbing on this PEB.
-	 */
 	return read_err ? UBI_IO_BITFLIPS : 0;
 }
 
@@ -1383,7 +1345,7 @@
 		goto error;
 	}
 
-	err = check_pattern(ubi->dbg_peb_buf, 0xFF, len);
+	err = ubi_check_pattern(ubi->dbg_peb_buf, 0xFF, len);
 	if (err == 0) {
 		ubi_err("flash region at PEB %d:%d, length %d does not "
 			"contain all 0xFF bytes", pnum, offset, len);
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index 22ad314..ff2a65c 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -103,3 +103,22 @@
 	if (ubi->beb_rsvd_level < MIN_RESEVED_PEBS)
 		ubi->beb_rsvd_level = MIN_RESEVED_PEBS;
 }
+
+/**
+ * ubi_check_pattern - check if buffer contains only a certain byte pattern.
+ * @buf: buffer to check
+ * @patt: the pattern to check
+ * @size: buffer size in bytes
+ *
+ * This function returns %1 in there are only @patt bytes in @buf, and %0 if
+ * something else was also found.
+ */
+int ubi_check_pattern(const void *buf, uint8_t patt, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		if (((const uint8_t *)buf)[i] != patt)
+			return 0;
+	return 1;
+}
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 69b52e9..3c63186 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -29,7 +29,7 @@
  * objects which are kept in volume RB-tree with root at the @volumes field.
  * The RB-tree is indexed by the volume ID.
  *
- * Found logical eraseblocks are represented by &struct ubi_scan_leb objects.
+ * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects.
  * These objects are kept in per-volume RB-trees with the root at the
  * corresponding &struct ubi_scan_volume object. To put it differently, we keep
  * an RB-tree of per-volume objects and each of these objects is the root of
@@ -38,6 +38,33 @@
  * Corrupted physical eraseblocks are put to the @corr list, free physical
  * eraseblocks are put to the @free list and the physical eraseblock to be
  * erased are put to the @erase list.
+ *
+ * UBI tries to distinguish between 2 types of corruptions.
+ * 1. Corruptions caused by power cuts. These are harmless and expected
+ *    corruptions and UBI tries to handle them gracefully, without printing too
+ *    many warnings and error messages. The idea is that we do not lose
+ *    important data in these case - we may lose only the data which was being
+ *    written to the media just before the power cut happened, and the upper
+ *    layers (e.g., UBIFS) are supposed to handle these situations. UBI puts
+ *    these PEBs to the head of the @erase list and they are scheduled for
+ *    erasure.
+ *
+ * 2. Unexpected corruptions which are not caused by power cuts. During
+ *    scanning, such PEBs are put to the @corr list and UBI preserves them.
+ *    Obviously, this lessens the amount of available PEBs, and if at some
+ *    point UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly
+ *    informs about such PEBs every time the MTD device is attached.
+ *
+ * However, it is difficult to reliably distinguish between these types of
+ * corruptions and UBI's strategy is as follows. UBI assumes (2.) if the VID
+ * header is corrupted and the data area does not contain all 0xFFs, and there
+ * were not bit-flips or integrity errors while reading the data area. Otherwise
+ * UBI assumes (1.). The assumptions are:
+ *   o if the data area contains only 0xFFs, there is no data, and it is safe
+ *     to just erase this PEB.
+ *   o if the data area has bit-flips and data integrity errors (ECC errors on
+ *     NAND), it is probably a PEB which was being erased when power cut
+ *     happened.
  */
 
 #include <linux/err.h>
@@ -62,26 +89,26 @@
  * @si: scanning information
  * @pnum: physical eraseblock number to add
  * @ec: erase counter of the physical eraseblock
+ * @to_head: if not zero, add to the head of the list
  * @list: the list to add to
  *
- * This function adds physical eraseblock @pnum to free, erase, corrupted or
- * alien lists. Returns zero in case of success and a negative error code in
- * case of failure.
+ * This function adds physical eraseblock @pnum to free, erase, or alien lists.
+ * If @to_head is not zero, PEB will be added to the head of the list, which
+ * basically means it will be processed first later. E.g., we add corrupted
+ * PEBs (corrupted due to power cuts) to the head of the erase list to make
+ * sure we erase them first and get rid of corruptions ASAP. This function
+ * returns zero in case of success and a negative error code in case of
+ * failure.
  */
-static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
+static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
 		       struct list_head *list)
 {
 	struct ubi_scan_leb *seb;
 
 	if (list == &si->free) {
 		dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
-		si->free_peb_count += 1;
 	} else if (list == &si->erase) {
 		dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
-		si->erase_peb_count += 1;
-	} else if (list == &si->corr) {
-		dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
-		si->corr_peb_count += 1;
 	} else if (list == &si->alien) {
 		dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
 		si->alien_peb_count += 1;
@@ -94,7 +121,37 @@
 
 	seb->pnum = pnum;
 	seb->ec = ec;
-	list_add_tail(&seb->u.list, list);
+	if (to_head)
+		list_add(&seb->u.list, list);
+	else
+		list_add_tail(&seb->u.list, list);
+	return 0;
+}
+
+/**
+ * add_corrupted - add a corrupted physical eraseblock.
+ * @si: scanning information
+ * @pnum: physical eraseblock number to add
+ * @ec: erase counter of the physical eraseblock
+ *
+ * This function adds corrupted physical eraseblock @pnum to the 'corr' list.
+ * The corruption was presumably not caused by a power cut. Returns zero in
+ * case of success and a negative error code in case of failure.
+ */
+static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
+{
+	struct ubi_scan_leb *seb;
+
+	dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
+
+	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+	if (!seb)
+		return -ENOMEM;
+
+	si->corr_peb_count += 1;
+	seb->pnum = pnum;
+	seb->ec = ec;
+	list_add(&seb->u.list, &si->corr);
 	return 0;
 }
 
@@ -258,8 +315,8 @@
 		 * created before sequence numbers support has been added. At
 		 * that times we used 32-bit LEB versions stored in logical
 		 * eraseblocks. That was before UBI got into mainline. We do not
-		 * support these images anymore. Well, those images will work
-		 * still work, but only if no unclean reboots happened.
+		 * support these images anymore. Well, those images still work,
+		 * but only if no unclean reboots happened.
 		 */
 		ubi_err("unsupported on-flash UBI format\n");
 		return -EINVAL;
@@ -285,19 +342,25 @@
 			return 1;
 		}
 	} else {
-		pnum = seb->pnum;
+		if (!seb->copy_flag) {
+			/* It is not a copy, so it is newer */
+			dbg_bld("first PEB %d is newer, copy_flag is unset",
+				pnum);
+			return bitflips << 1;
+		}
 
 		vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 		if (!vh)
 			return -ENOMEM;
 
+		pnum = seb->pnum;
 		err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
 		if (err) {
 			if (err == UBI_IO_BITFLIPS)
 				bitflips = 1;
 			else {
 				dbg_err("VID of PEB %d header is bad, but it "
-					"was OK earlier", pnum);
+					"was OK earlier, err %d", pnum, err);
 				if (err > 0)
 					err = -EIO;
 
@@ -305,14 +368,6 @@
 			}
 		}
 
-		if (!vh->copy_flag) {
-			/* It is not a copy, so it is newer */
-			dbg_bld("first PEB %d is newer, copy_flag is unset",
-				pnum);
-			err = bitflips << 1;
-			goto out_free_vidh;
-		}
-
 		vid_hdr = vh;
 	}
 
@@ -463,18 +518,15 @@
 			if (err)
 				return err;
 
-			if (cmp_res & 4)
-				err = add_to_list(si, seb->pnum, seb->ec,
-						  &si->corr);
-			else
-				err = add_to_list(si, seb->pnum, seb->ec,
-						  &si->erase);
+			err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4,
+					  &si->erase);
 			if (err)
 				return err;
 
 			seb->ec = ec;
 			seb->pnum = pnum;
 			seb->scrub = ((cmp_res & 2) || bitflips);
+			seb->copy_flag = vid_hdr->copy_flag;
 			seb->sqnum = sqnum;
 
 			if (sv->highest_lnum == lnum)
@@ -487,10 +539,8 @@
 			 * This logical eraseblock is older than the one found
 			 * previously.
 			 */
-			if (cmp_res & 4)
-				return add_to_list(si, pnum, ec, &si->corr);
-			else
-				return add_to_list(si, pnum, ec, &si->erase);
+			return add_to_list(si, pnum, ec, cmp_res & 4,
+					   &si->erase);
 		}
 	}
 
@@ -510,8 +560,9 @@
 	seb->ec = ec;
 	seb->pnum = pnum;
 	seb->lnum = lnum;
-	seb->sqnum = sqnum;
 	seb->scrub = bitflips;
+	seb->copy_flag = vid_hdr->copy_flag;
+	seb->sqnum = sqnum;
 
 	if (sv->highest_lnum <= lnum) {
 		sv->highest_lnum = lnum;
@@ -521,7 +572,6 @@
 	sv->leb_count += 1;
 	rb_link_node(&seb->u.rb, parent, p);
 	rb_insert_color(&seb->u.rb, &sv->root);
-	si->used_peb_count += 1;
 	return 0;
 }
 
@@ -668,8 +718,8 @@
 struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
 					   struct ubi_scan_info *si)
 {
-	int err = 0, i;
-	struct ubi_scan_leb *seb;
+	int err = 0;
+	struct ubi_scan_leb *seb, *tmp_seb;
 
 	if (!list_empty(&si->free)) {
 		seb = list_entry(si->free.next, struct ubi_scan_leb, u.list);
@@ -678,41 +728,89 @@
 		return seb;
 	}
 
-	for (i = 0; i < 2; i++) {
-		struct list_head *head;
-		struct ubi_scan_leb *tmp_seb;
+	/*
+	 * We try to erase the first physical eraseblock from the erase list
+	 * and pick it if we succeed, or try to erase the next one if not. And
+	 * so forth. We don't want to take care about bad eraseblocks here -
+	 * they'll be handled later.
+	 */
+	list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) {
+		if (seb->ec == UBI_SCAN_UNKNOWN_EC)
+			seb->ec = si->mean_ec;
 
-		if (i == 0)
-			head = &si->erase;
-		else
-			head = &si->corr;
+		err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
+		if (err)
+			continue;
 
-		/*
-		 * We try to erase the first physical eraseblock from the @head
-		 * list and pick it if we succeed, or try to erase the
-		 * next one if not. And so forth. We don't want to take care
-		 * about bad eraseblocks here - they'll be handled later.
-		 */
-		list_for_each_entry_safe(seb, tmp_seb, head, u.list) {
-			if (seb->ec == UBI_SCAN_UNKNOWN_EC)
-				seb->ec = si->mean_ec;
-
-			err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
-			if (err)
-				continue;
-
-			seb->ec += 1;
-			list_del(&seb->u.list);
-			dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
-			return seb;
-		}
+		seb->ec += 1;
+		list_del(&seb->u.list);
+		dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
+		return seb;
 	}
 
-	ubi_err("no eraseblocks found");
+	ubi_err("no free eraseblocks");
 	return ERR_PTR(-ENOSPC);
 }
 
 /**
+ * check_corruption - check the data area of PEB.
+ * @ubi: UBI device description object
+ * @vid_hrd: the (corrupted) VID header of this PEB
+ * @pnum: the physical eraseblock number to check
+ *
+ * This is a helper function which is used to distinguish between VID header
+ * corruptions caused by power cuts and other reasons. If the PEB contains only
+ * 0xFF bytes in the data area, the VID header is most probably corrupted
+ * because of a power cut (%0 is returned in this case). Otherwise, it was
+ * probably corrupted for some other reasons (%1 is returned in this case). A
+ * negative error code is returned if a read error occurred.
+ *
+ * If the corruption reason was a power cut, UBI can safely erase this PEB.
+ * Otherwise, it should preserve it to avoid possibly destroying important
+ * information.
+ */
+static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
+			    int pnum)
+{
+	int err;
+
+	mutex_lock(&ubi->buf_mutex);
+	memset(ubi->peb_buf1, 0x00, ubi->leb_size);
+
+	err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
+			  ubi->leb_size);
+	if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+		/*
+		 * Bit-flips or integrity errors while reading the data area.
+		 * It is difficult to say for sure what type of corruption is
+		 * this, but presumably a power cut happened while this PEB was
+		 * erased, so it became unstable and corrupted, and should be
+		 * erased.
+		 */
+		return 0;
+	}
+
+	if (err)
+		return err;
+
+	if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) {
+		mutex_unlock(&ubi->buf_mutex);
+		return 0;
+	}
+
+	ubi_err("PEB %d contains corrupted VID header, and the data does not "
+		"contain all 0xFF, this may be a non-UBI PEB or a severe VID "
+		"header corruption which requires manual inspection", pnum);
+	ubi_dbg_dump_vid_hdr(vid_hdr);
+	dbg_msg("hexdump of PEB %d offset %d, length %d",
+		pnum, ubi->leb_start, ubi->leb_size);
+	ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+			       ubi->peb_buf1, ubi->leb_size, 1);
+	mutex_unlock(&ubi->buf_mutex);
+	return 1;
+}
+
+/**
  * process_eb - read, check UBI headers, and add them to scanning information.
  * @ubi: UBI device description object
  * @si: scanning information
@@ -725,7 +823,7 @@
 		      int pnum)
 {
 	long long uninitialized_var(ec);
-	int err, bitflips = 0, vol_id, ec_corr = 0;
+	int err, bitflips = 0, vol_id, ec_err = 0;
 
 	dbg_bld("scan PEB %d", pnum);
 
@@ -746,22 +844,37 @@
 	err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
 	if (err < 0)
 		return err;
-	else if (err == UBI_IO_BITFLIPS)
+	switch (err) {
+	case 0:
+		break;
+	case UBI_IO_BITFLIPS:
 		bitflips = 1;
-	else if (err == UBI_IO_PEB_EMPTY)
-		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase);
-	else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) {
+		break;
+	case UBI_IO_FF:
+		si->empty_peb_count += 1;
+		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0,
+				   &si->erase);
+	case UBI_IO_FF_BITFLIPS:
+		si->empty_peb_count += 1;
+		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1,
+				   &si->erase);
+	case UBI_IO_BAD_HDR_EBADMSG:
+	case UBI_IO_BAD_HDR:
 		/*
 		 * We have to also look at the VID header, possibly it is not
 		 * corrupted. Set %bitflips flag in order to make this PEB be
 		 * moved and EC be re-created.
 		 */
-		ec_corr = err;
+		ec_err = err;
 		ec = UBI_SCAN_UNKNOWN_EC;
 		bitflips = 1;
+		break;
+	default:
+		ubi_err("'ubi_io_read_ec_hdr()' returned unknown code %d", err);
+		return -EINVAL;
 	}
 
-	if (!ec_corr) {
+	if (!ec_err) {
 		int image_seq;
 
 		/* Make sure UBI version is OK */
@@ -814,24 +927,67 @@
 	err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
 	if (err < 0)
 		return err;
-	else if (err == UBI_IO_BITFLIPS)
+	switch (err) {
+	case 0:
+		break;
+	case UBI_IO_BITFLIPS:
 		bitflips = 1;
-	else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR ||
-		 (err == UBI_IO_PEB_FREE && ec_corr)) {
-		/* VID header is corrupted */
-		if (err == UBI_IO_BAD_HDR_READ ||
-		    ec_corr == UBI_IO_BAD_HDR_READ)
-			si->read_err_count += 1;
-		err = add_to_list(si, pnum, ec, &si->corr);
+		break;
+	case UBI_IO_BAD_HDR_EBADMSG:
+		if (ec_err == UBI_IO_BAD_HDR_EBADMSG)
+			/*
+			 * Both EC and VID headers are corrupted and were read
+			 * with data integrity error, probably this is a bad
+			 * PEB, bit it is not marked as bad yet. This may also
+			 * be a result of power cut during erasure.
+			 */
+			si->maybe_bad_peb_count += 1;
+	case UBI_IO_BAD_HDR:
+		if (ec_err)
+			/*
+			 * Both headers are corrupted. There is a possibility
+			 * that this a valid UBI PEB which has corresponding
+			 * LEB, but the headers are corrupted. However, it is
+			 * impossible to distinguish it from a PEB which just
+			 * contains garbage because of a power cut during erase
+			 * operation. So we just schedule this PEB for erasure.
+			 */
+			err = 0;
+		else
+			/*
+			 * The EC was OK, but the VID header is corrupted. We
+			 * have to check what is in the data area.
+			 */
+			err = check_corruption(ubi, vidh, pnum);
+
+		if (err < 0)
+			return err;
+		else if (!err)
+			/* This corruption is caused by a power cut */
+			err = add_to_list(si, pnum, ec, 1, &si->erase);
+		else
+			/* This is an unexpected corruption */
+			err = add_corrupted(si, pnum, ec);
 		if (err)
 			return err;
 		goto adjust_mean_ec;
-	} else if (err == UBI_IO_PEB_FREE) {
-		/* No VID header - the physical eraseblock is free */
-		err = add_to_list(si, pnum, ec, &si->free);
+	case UBI_IO_FF_BITFLIPS:
+		err = add_to_list(si, pnum, ec, 1, &si->erase);
 		if (err)
 			return err;
 		goto adjust_mean_ec;
+	case UBI_IO_FF:
+		if (ec_err)
+			err = add_to_list(si, pnum, ec, 1, &si->erase);
+		else
+			err = add_to_list(si, pnum, ec, 0, &si->free);
+		if (err)
+			return err;
+		goto adjust_mean_ec;
+	default:
+		ubi_err("'ubi_io_read_vid_hdr()' returned unknown code %d",
+			err);
+		return -EINVAL;
 	}
 
 	vol_id = be32_to_cpu(vidh->vol_id);
@@ -843,7 +999,7 @@
 		case UBI_COMPAT_DELETE:
 			ubi_msg("\"delete\" compatible internal volume %d:%d"
 				" found, will remove it", vol_id, lnum);
-			err = add_to_list(si, pnum, ec, &si->erase);
+			err = add_to_list(si, pnum, ec, 1, &si->erase);
 			if (err)
 				return err;
 			return 0;
@@ -858,7 +1014,7 @@
 		case UBI_COMPAT_PRESERVE:
 			ubi_msg("\"preserve\" compatible internal volume %d:%d"
 				" found", vol_id, lnum);
-			err = add_to_list(si, pnum, ec, &si->alien);
+			err = add_to_list(si, pnum, ec, 0, &si->alien);
 			if (err)
 				return err;
 			return 0;
@@ -870,7 +1026,7 @@
 		}
 	}
 
-	if (ec_corr)
+	if (ec_err)
 		ubi_warn("valid VID header but corrupted EC header at PEB %d",
 			 pnum);
 	err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips);
@@ -878,7 +1034,7 @@
 		return err;
 
 adjust_mean_ec:
-	if (!ec_corr) {
+	if (!ec_err) {
 		si->ec_sum += ec;
 		si->ec_count += 1;
 		if (ec > si->max_ec)
@@ -904,19 +1060,20 @@
 static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
 {
 	struct ubi_scan_leb *seb;
-	int max_corr;
+	int max_corr, peb_count;
 
-	max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
-	max_corr = max_corr / 20 ?: 8;
+	peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
+	max_corr = peb_count / 20 ?: 8;
 
 	/*
-	 * Few corrupted PEBs are not a problem and may be just a result of
+	 * Few corrupted PEBs is not a problem and may be just a result of
 	 * unclean reboots. However, many of them may indicate some problems
 	 * with the flash HW or driver.
 	 */
-	if (si->corr_peb_count >= 8) {
-		ubi_warn("%d PEBs are corrupted", si->corr_peb_count);
-		printk(KERN_WARNING "corrupted PEBs are:");
+	if (si->corr_peb_count) {
+		ubi_err("%d PEBs are corrupted and preserved",
+			si->corr_peb_count);
+		printk(KERN_ERR "Corrupted PEBs are:");
 		list_for_each_entry(seb, &si->corr, u.list)
 			printk(KERN_CONT " %d", seb->pnum);
 		printk(KERN_CONT "\n");
@@ -931,41 +1088,35 @@
 		}
 	}
 
-	if (si->free_peb_count + si->used_peb_count +
-	    si->alien_peb_count == 0) {
-		/* No UBI-formatted eraseblocks were found */
-		if (si->corr_peb_count == si->read_err_count &&
-		    si->corr_peb_count < 8) {
-			/* No or just few corrupted PEBs, and all of them had a
-			 * read error. We assume that those are bad PEBs, which
-			 * were just not marked as bad so far.
-			 *
-			 * This piece of code basically tries to distinguish
-			 * between the following 2 situations:
-			 *
-			 * 1. Flash is empty, but there are few bad PEBs, which
-			 *    are not marked as bad so far, and which were read
-			 *    with error. We want to go ahead and format this
-			 *    flash. While formating, the faulty PEBs will
-			 *    probably be marked as bad.
-			 *
-			 * 2. Flash probably contains non-UBI data and we do
-			 * not want to format it and destroy possibly needed
-			 * data (e.g., consider the case when the bootloader
-			 * MTD partition was accidentally fed to UBI).
-			 */
+	if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) {
+		/*
+		 * All PEBs are empty, or almost all - a couple PEBs look like
+		 * they may be bad PEBs which were not marked as bad yet.
+		 *
+		 * This piece of code basically tries to distinguish between
+		 * the following situations:
+		 *
+		 * 1. Flash is empty, but there are few bad PEBs, which are not
+		 *    marked as bad so far, and which were read with error. We
+		 *    want to go ahead and format this flash. While formatting,
+		 *    the faulty PEBs will probably be marked as bad.
+		 *
+		 * 2. Flash contains non-UBI data and we do not want to format
+		 *    it and destroy possibly important information.
+		 */
+		if (si->maybe_bad_peb_count <= 2) {
 			si->is_empty = 1;
 			ubi_msg("empty MTD device detected");
-			get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq));
+			get_random_bytes(&ubi->image_seq,
+					 sizeof(ubi->image_seq));
 		} else {
-			ubi_err("MTD device possibly contains non-UBI data, "
-				"refusing it");
+			ubi_err("MTD device is not UBI-formatted and possibly "
+				"contains non-UBI data - refusing it");
 			return -EINVAL;
 		}
+
 	}
 
-	if (si->corr_peb_count > 0)
-		ubi_msg("corrupted PEBs will be formatted");
 	return 0;
 }
 
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index 2576a8d..a3264f0 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -30,6 +30,7 @@
  * @pnum: physical eraseblock number
  * @lnum: logical eraseblock number
  * @scrub: if this physical eraseblock needs scrubbing
+ * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
  * @sqnum: sequence number
  * @u: unions RB-tree or @list links
  * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
@@ -42,7 +43,8 @@
 	int ec;
 	int pnum;
 	int lnum;
-	int scrub;
+	unsigned int scrub:1;
+	unsigned int copy_flag:1;
 	unsigned long long sqnum;
 	union {
 		struct rb_node rb;
@@ -91,14 +93,13 @@
  * @erase: list of physical eraseblocks which have to be erased
  * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
  *         those belonging to "preserve"-compatible internal volumes)
- * @used_peb_count: count of used PEBs
  * @corr_peb_count: count of PEBs in the @corr list
- * @read_err_count: count of PEBs read with error (%UBI_IO_BAD_HDR_READ was
- *                  returned)
- * @free_peb_count: count of PEBs in the @free list
- * @erase_peb_count: count of PEBs in the @erase list
+ * @empty_peb_count: count of PEBs which are presumably empty (contain only
+ *                   0xFF bytes)
  * @alien_peb_count: count of PEBs in the @alien list
  * @bad_peb_count: count of bad physical eraseblocks
+ * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
+ *                       as bad yet, but which look like bad
  * @vols_found: number of volumes found during scanning
  * @highest_vol_id: highest volume ID
  * @is_empty: flag indicating whether the MTD device is empty or not
@@ -119,13 +120,11 @@
 	struct list_head free;
 	struct list_head erase;
 	struct list_head alien;
-	int used_peb_count;
 	int corr_peb_count;
-	int read_err_count;
-	int free_peb_count;
-	int erase_peb_count;
+	int empty_peb_count;
 	int alien_peb_count;
 	int bad_peb_count;
+	int maybe_bad_peb_count;
 	int vols_found;
 	int highest_vol_id;
 	int is_empty;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 0359e0c..0b0149c 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -85,21 +85,26 @@
 /*
  * Error codes returned by the I/O sub-system.
  *
- * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only
- *                   %0xFF bytes
- * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a
- *                  valid erase counter header, and the rest are %0xFF bytes
+ * UBI_IO_FF: the read region of flash contains only 0xFFs
+ * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also also there was a data
+ *                     integrity error reported by the MTD driver
+ *                     (uncorrectable ECC error in case of NAND)
  * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC)
- * UBI_IO_BAD_HDR_READ: the same as %UBI_IO_BAD_HDR, but also there was a read
- * 			error reported by the flash driver
+ * UBI_IO_BAD_HDR_EBADMSG: the same as %UBI_IO_BAD_HDR, but also there was a
+ *                         data integrity error reported by the MTD driver
+ *                         (uncorrectable ECC error in case of NAND)
  * UBI_IO_BITFLIPS: bit-flips were detected and corrected
+ *
+ * Note, it is probably better to have bit-flip and ebadmsg as flags which can
+ * be or'ed with other error code. But this is a big change because there are
+ * may callers, so it does not worth the risk of introducing a bug
  */
 enum {
-	UBI_IO_PEB_EMPTY = 1,
-	UBI_IO_PEB_FREE,
+	UBI_IO_FF = 1,
+	UBI_IO_FF_BITFLIPS,
 	UBI_IO_BAD_HDR,
-	UBI_IO_BAD_HDR_READ,
-	UBI_IO_BITFLIPS
+	UBI_IO_BAD_HDR_EBADMSG,
+	UBI_IO_BITFLIPS,
 };
 
 /*
@@ -356,6 +361,8 @@
  * @peb_size: physical eraseblock size
  * @bad_peb_count: count of bad physical eraseblocks
  * @good_peb_count: count of good physical eraseblocks
+ * @corr_peb_count: count of corrupted physical eraseblocks (preserved and not
+ *                  used by UBI)
  * @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous
  * @max_erroneous: maximum allowed amount of erroneous physical eraseblocks
  * @min_io_size: minimal input/output unit size of the underlying MTD device
@@ -442,6 +449,7 @@
 	int peb_size;
 	int bad_peb_count;
 	int good_peb_count;
+	int corr_peb_count;
 	int erroneous_peb_count;
 	int max_erroneous;
 	int min_io_size;
@@ -506,6 +514,7 @@
 		      int length);
 int ubi_check_volume(struct ubi_device *ubi, int vol_id);
 void ubi_calculate_reserved(struct ubi_device *ubi);
+int ubi_check_pattern(const void *buf, uint8_t patt, int size);
 
 /* eba.c */
 int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index e42afab..c47620d 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -261,6 +261,9 @@
 	/* Reserve physical eraseblocks */
 	if (vol->reserved_pebs > ubi->avail_pebs) {
 		dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
+		if (ubi->corr_peb_count)
+			dbg_err("%d PEBs are corrupted and not used",
+				ubi->corr_peb_count);
 		err = -ENOSPC;
 		goto out_unlock;
 	}
@@ -527,6 +530,9 @@
 		if (pebs > ubi->avail_pebs) {
 			dbg_err("not enough PEBs: requested %d, available %d",
 				pebs, ubi->avail_pebs);
+			if (ubi->corr_peb_count)
+				dbg_err("%d PEBs are corrupted and not used",
+					ubi->corr_peb_count);
 			spin_unlock(&ubi->volumes_lock);
 			err = -ENOSPC;
 			goto out_free;
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 14c10be..fcdb7f6 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -366,7 +366,7 @@
 		 * Probably this physical eraseblock went bad, try to pick
 		 * another one.
 		 */
-		list_add_tail(&new_seb->u.list, &si->corr);
+		list_add(&new_seb->u.list, &si->erase);
 		goto retry;
 	}
 	kfree(new_seb);
@@ -662,9 +662,13 @@
 	ubi->vol_count += 1;
 	vol->ubi = ubi;
 
-	if (reserved_pebs > ubi->avail_pebs)
+	if (reserved_pebs > ubi->avail_pebs) {
 		ubi_err("not enough PEBs, required %d, available %d",
 			reserved_pebs, ubi->avail_pebs);
+		if (ubi->corr_peb_count)
+			ubi_err("%d PEBs are corrupted and not used",
+				ubi->corr_peb_count);
+	}
 	ubi->rsvd_pebs += reserved_pebs;
 	ubi->avail_pebs -= reserved_pebs;
 
@@ -837,7 +841,7 @@
 			return PTR_ERR(ubi->vtbl);
 	}
 
-	ubi->avail_pebs = ubi->good_peb_count;
+	ubi->avail_pebs = ubi->good_peb_count - ubi->corr_peb_count;
 
 	/*
 	 * The layout volume is OK, initialize the corresponding in-RAM data
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 97a4356..655bbbe 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -745,7 +745,7 @@
 
 	err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0);
 	if (err && err != UBI_IO_BITFLIPS) {
-		if (err == UBI_IO_PEB_FREE) {
+		if (err == UBI_IO_FF) {
 			/*
 			 * We are trying to move PEB without a VID header. UBI
 			 * always write VID headers shortly after the PEB was
@@ -759,6 +759,16 @@
 			dbg_wl("PEB %d has no VID header", e1->pnum);
 			protect = 1;
 			goto out_not_moved;
+		} else if (err == UBI_IO_FF_BITFLIPS) {
+			/*
+			 * The same situation as %UBI_IO_FF, but bit-flips were
+			 * detected. It is better to schedule this PEB for
+			 * scrubbing.
+			 */
+			dbg_wl("PEB %d has no VID header but has bit-flips",
+			       e1->pnum);
+			scrubbing = 1;
+			goto out_not_moved;
 		}
 
 		ubi_err("error %d while reading VID header from PEB %d",
@@ -1468,22 +1478,6 @@
 		ubi->lookuptbl[e->pnum] = e;
 	}
 
-	list_for_each_entry(seb, &si->corr, u.list) {
-		cond_resched();
-
-		e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
-		if (!e)
-			goto out_free;
-
-		e->pnum = seb->pnum;
-		e->ec = seb->ec;
-		ubi->lookuptbl[e->pnum] = e;
-		if (schedule_erase(ubi, e, 0)) {
-			kmem_cache_free(ubi_wl_entry_slab, e);
-			goto out_free;
-		}
-	}
-
 	ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
 		ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
 			cond_resched();
@@ -1510,6 +1504,9 @@
 	if (ubi->avail_pebs < WL_RESERVED_PEBS) {
 		ubi_err("no enough physical eraseblocks (%d, need %d)",
 			ubi->avail_pebs, WL_RESERVED_PEBS);
+		if (ubi->corr_peb_count)
+			ubi_err("%d PEBs are corrupted and not used",
+				ubi->corr_peb_count);
 		goto out_free;
 	}
 	ubi->avail_pebs -= WL_RESERVED_PEBS;
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index 0a0e0cd..20f97e7 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -3,6 +3,7 @@
 #
 config ATALK
 	tristate "Appletalk protocol support"
+	depends on BKL # waiting to be removed from net/appletalk/ddp.c
 	select LLC
 	---help---
 	  AppleTalk is the protocol that Apple computers can use to communicate
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index f5058ff..8427533 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -240,13 +240,15 @@
 static const struct file_operations dbgfs_state_fops = {
 	.open = dbgfs_open,
 	.read = dbgfs_state,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations dbgfs_frame_fops = {
 	.open = dbgfs_open,
 	.read = dbgfs_frame,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static inline void dev_debugfs_add(struct cfspi *cfspi)
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index c327527..e2bf10d 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -2026,6 +2026,7 @@
 	.owner   = THIS_MODULE,
 	.open    = mem_open,
 	.read    = mem_read,
+	.llseek  = default_llseek,
 };
 
 static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 736b917..4bddb2a 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -856,7 +856,8 @@
 	.poll		= ppp_poll,
 	.unlocked_ioctl	= ppp_ioctl,
 	.open		= ppp_open,
-	.release	= ppp_release
+	.release	= ppp_release,
+	.llseek		= noop_llseek,
 };
 
 static __net_init int ppp_init_net(struct net *net)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 1cd752f..b8e9572 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1645,11 +1645,11 @@
  * NB: both 1->0 and 0->1 transitions are counted except for
  *     RI where only 0->1 is counted.
  */
-static int hso_get_count(struct hso_serial *serial,
-			  struct serial_icounter_struct __user *icnt)
+static int hso_get_count(struct tty_struct *tty,
+		  struct serial_icounter_struct *icount)
 {
-	struct serial_icounter_struct icount;
 	struct uart_icount cnow;
+	struct hso_serial *serial = get_serial_by_tty(tty);
 	struct hso_tiocmget  *tiocmget = serial->tiocmget;
 
 	memset(&icount, 0, sizeof(struct serial_icounter_struct));
@@ -1660,19 +1660,19 @@
 	memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
 	spin_unlock_irq(&serial->serial_lock);
 
-	icount.cts         = cnow.cts;
-	icount.dsr         = cnow.dsr;
-	icount.rng         = cnow.rng;
-	icount.dcd         = cnow.dcd;
-	icount.rx          = cnow.rx;
-	icount.tx          = cnow.tx;
-	icount.frame       = cnow.frame;
-	icount.overrun     = cnow.overrun;
-	icount.parity      = cnow.parity;
-	icount.brk         = cnow.brk;
-	icount.buf_overrun = cnow.buf_overrun;
+	icount->cts         = cnow.cts;
+	icount->dsr         = cnow.dsr;
+	icount->rng         = cnow.rng;
+	icount->dcd         = cnow.dcd;
+	icount->rx          = cnow.rx;
+	icount->tx          = cnow.tx;
+	icount->frame       = cnow.frame;
+	icount->overrun     = cnow.overrun;
+	icount->parity      = cnow.parity;
+	icount->brk         = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
 
-	return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+	return 0;
 }
 
 
@@ -1764,10 +1764,6 @@
 	case TIOCMIWAIT:
 		ret = hso_wait_modem_status(serial, arg);
 		break;
-
-	case TIOCGICOUNT:
-		ret = hso_get_count(serial, uarg);
-		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
@@ -3300,6 +3296,7 @@
 	.chars_in_buffer = hso_serial_chars_in_buffer,
 	.tiocmget = hso_serial_tiocmget,
 	.tiocmset = hso_serial_tiocmset,
+	.get_icount = hso_get_count,
 	.unthrottle = hso_unthrottle
 };
 
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
index b1aec3e..9c70b5f 100644
--- a/drivers/net/wimax/i2400m/debugfs.c
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -119,6 +119,7 @@
 	.open =		i2400m_stats_open,
 	.read =		i2400m_rx_stats_read,
 	.write =	i2400m_rx_stats_write,
+	.llseek =	default_llseek,
 };
 
 
@@ -171,6 +172,7 @@
 	.open =		i2400m_stats_open,
 	.read =		i2400m_tx_stats_read,
 	.write =	i2400m_tx_stats_write,
+	.llseek =	default_llseek,
 };
 
 
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 1d05445..ce77575 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4430,21 +4430,24 @@
 	.owner		= THIS_MODULE,
 	.read		= proc_read,
 	.open		= proc_statsdelta_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_stats_ops = {
 	.owner		= THIS_MODULE,
 	.read		= proc_read,
 	.open		= proc_stats_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_status_ops = {
 	.owner		= THIS_MODULE,
 	.read		= proc_read,
 	.open		= proc_status_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_SSID_ops = {
@@ -4452,7 +4455,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_SSID_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_BSSList_ops = {
@@ -4460,7 +4464,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_BSSList_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_APList_ops = {
@@ -4468,7 +4473,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_APList_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_config_ops = {
@@ -4476,7 +4482,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_config_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_wepkey_ops = {
@@ -4484,7 +4491,8 @@
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_wepkey_open,
-	.release	= proc_close
+	.release	= proc_close,
+	.llseek		= default_llseek,
 };
 
 static struct proc_dir_entry *airo_entry;
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 4cccc29..fb339c3 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -271,6 +271,7 @@
 	.write = write_file_beacon,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -290,6 +291,7 @@
 	.write = write_file_reset,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 
@@ -369,6 +371,7 @@
 	.write = write_file_debug,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -480,6 +483,7 @@
 	.write = write_file_antenna,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -591,6 +595,7 @@
 	.write = write_file_frameerrors,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -748,6 +753,7 @@
 	.write = write_file_ani,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -811,6 +817,7 @@
 	.write = write_file_queue,
 	.open = ath5k_debugfs_open,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 54aae93..cf500bf 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -71,7 +71,8 @@
 	.read = read_file_debug,
 	.write = write_file_debug,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 #endif
@@ -116,7 +117,8 @@
 	.read = read_file_tx_chainmask,
 	.write = write_file_tx_chainmask,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -158,7 +160,8 @@
 	.read = read_file_rx_chainmask,
 	.write = write_file_rx_chainmask,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -259,7 +262,8 @@
 static const struct file_operations fops_dma = {
 	.read = read_file_dma,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 
@@ -375,7 +379,8 @@
 static const struct file_operations fops_interrupt = {
 	.read = read_file_interrupt,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 void ath_debug_stat_rc(struct ath_softc *sc, int final_rate)
@@ -464,7 +469,8 @@
 static const struct file_operations fops_rcstat = {
 	.read = read_file_rcstat,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
@@ -623,7 +629,8 @@
 	.read = read_file_wiphy,
 	.write = write_file_wiphy,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 #define PR(str, elem)							\
@@ -702,7 +709,8 @@
 static const struct file_operations fops_xmit = {
 	.read = read_file_xmit,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_recv(struct file *file, char __user *user_buf,
@@ -814,7 +822,8 @@
 static const struct file_operations fops_recv = {
 	.read = read_file_recv,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
@@ -852,7 +861,8 @@
 	.read = read_file_regidx,
 	.write = write_file_regidx,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_regval(struct file *file, char __user *user_buf,
@@ -894,7 +904,8 @@
 	.read = read_file_regval,
 	.write = write_file_regval,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 int ath9k_init_debug(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 7d09b4b..bc2ca7d 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -536,7 +536,8 @@
 static const struct file_operations fops_tgt_stats = {
 	.read = read_file_tgt_stats,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
@@ -584,7 +585,8 @@
 static const struct file_operations fops_xmit = {
 	.read = read_file_xmit,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 static ssize_t read_file_recv(struct file *file, char __user *user_buf,
@@ -613,7 +615,8 @@
 static const struct file_operations fops_recv = {
 	.read = read_file_recv,
 	.open = ath9k_debugfs_open,
-	.owner = THIS_MODULE
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 int ath9k_htc_init_debug(struct ath_hw *ah)
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 80b19a4..59f59fa 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -627,6 +627,7 @@
 			.open	= b43_debugfs_open,		\
 			.read	= b43_debugfs_read,		\
 			.write	= b43_debugfs_write,		\
+			.llseek = generic_file_llseek,		\
 		},						\
 		.file_struct_offset = offsetof(struct b43_dfsentry, \
 					       file_##name),	\
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index 1f85ac5..f232618 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -334,6 +334,7 @@
 			.open	= b43legacy_debugfs_open,		\
 			.read	= b43legacy_debugfs_read,		\
 			.write	= b43legacy_debugfs_write,		\
+			.llseek = generic_file_llseek,			\
 		},						\
 		.file_struct_offset = offsetof(struct b43legacy_dfsentry, \
 					       file_##name),	\
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 8e84a08..293e1db 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -873,6 +873,7 @@
 static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
 	.read = iwl3945_sta_dbgfs_stats_table_read,
 	.open = iwl3945_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static void iwl3945_add_debugfs(void *priv, void *priv_sta,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 23e5c42..a4378ba 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -2873,6 +2873,7 @@
 	.write = rs_sta_dbgfs_scale_table_write,
 	.read = rs_sta_dbgfs_scale_table_read,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
 			char __user *user_buf, size_t count, loff_t *ppos)
@@ -2915,6 +2916,7 @@
 static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
 	.read = rs_sta_dbgfs_stats_table_read,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
@@ -2946,6 +2948,7 @@
 static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
 	.read = rs_sta_dbgfs_rate_scale_data_read,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static void rs_add_debugfs(void *priv, void *priv_sta,
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index e96a1bb..a32d5d3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -87,6 +87,7 @@
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 	.read = iwl_dbgfs_##name##_read,                       		\
 	.open = iwl_dbgfs_open_file_generic,                    	\
+	.llseek = generic_file_llseek,					\
 };
 
 #define DEBUGFS_WRITE_FILE_OPS(name)                                    \
@@ -94,6 +95,7 @@
 static const struct file_operations iwl_dbgfs_##name##_ops = {          \
 	.write = iwl_dbgfs_##name##_write,                              \
 	.open = iwl_dbgfs_open_file_generic,                    	\
+	.llseek = generic_file_llseek,					\
 };
 
 
@@ -104,6 +106,7 @@
 	.write = iwl_dbgfs_##name##_write,                              \
 	.read = iwl_dbgfs_##name##_read,                                \
 	.open = iwl_dbgfs_open_file_generic,                            \
+	.llseek = generic_file_llseek,					\
 };
 
 static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
index 53b0b77..0a0cc96 100644
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -402,24 +402,28 @@
 	.owner =	THIS_MODULE,
 	.open =		iwm_generic_open,
 	.read =		iwm_debugfs_txq_read,
+	.llseek =	default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_tx_credit_fops = {
 	.owner =	THIS_MODULE,
 	.open =		iwm_generic_open,
 	.read =		iwm_debugfs_tx_credit_read,
+	.llseek =	default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_rx_ticket_fops = {
 	.owner =	THIS_MODULE,
 	.open =		iwm_generic_open,
 	.read =		iwm_debugfs_rx_ticket_read,
+	.llseek =	default_llseek,
 };
 
 static const struct file_operations iwm_debugfs_fw_err_fops = {
 	.owner =	THIS_MODULE,
 	.open =		iwm_generic_open,
 	.read =		iwm_debugfs_fw_err_read,
+	.llseek =	default_llseek,
 };
 
 void iwm_debugfs_init(struct iwm_priv *iwm)
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
index edcb523..56383e7 100644
--- a/drivers/net/wireless/iwmc3200wifi/sdio.c
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.c
@@ -364,6 +364,7 @@
 	.owner =	THIS_MODULE,
 	.open =		iwm_debugfs_sdio_open,
 	.read =		iwm_debugfs_sdio_read,
+	.llseek =	default_llseek,
 };
 
 static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 651a79c..fbf3b033 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -696,6 +696,7 @@
 	.open = open_file_generic, \
 	.read = (fread), \
 	.write = (fwrite), \
+	.llseek = generic_file_llseek, \
 }
 
 struct lbs_debugfs_files {
@@ -961,6 +962,7 @@
 	.open = open_file_generic,
 	.write = lbs_debugfs_write,
 	.read = lbs_debugfs_read,
+	.llseek = default_llseek,
 };
 
 /**
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index af5b17c..46da037 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -2765,6 +2765,7 @@
 static const struct file_operations ray_cs_essid_proc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= ray_cs_essid_proc_write,
+	.llseek		= noop_llseek,
 };
 
 static ssize_t int_proc_write(struct file *file, const char __user *buffer,
@@ -2798,6 +2799,7 @@
 static const struct file_operations int_proc_fops = {
 	.owner		= THIS_MODULE,
 	.write		= int_proc_write,
+	.llseek		= noop_llseek,
 };
 #endif
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index b0498e7..cea81e4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -315,6 +315,7 @@
 	.poll		= rt2x00debug_poll_queue_dump,
 	.open		= rt2x00debug_open_queue_dump,
 	.release	= rt2x00debug_release_queue_dump,
+	.llseek		= default_llseek,
 };
 
 static ssize_t rt2x00debug_read_queue_stats(struct file *file,
@@ -371,6 +372,7 @@
 	.read		= rt2x00debug_read_queue_stats,
 	.open		= rt2x00debug_file_open,
 	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
 };
 
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
@@ -423,6 +425,7 @@
 	.read		= rt2x00debug_read_crypto_stats,
 	.open		= rt2x00debug_file_open,
 	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
 };
 #endif
 
@@ -509,6 +512,7 @@
 	.write		= rt2x00debug_write_##__name,		\
 	.open		= rt2x00debug_file_open,		\
 	.release	= rt2x00debug_file_release,		\
+	.llseek		= generic_file_llseek,			\
 };
 
 RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
@@ -542,6 +546,7 @@
 	.read		= rt2x00debug_read_dev_flags,
 	.open		= rt2x00debug_file_open,
 	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
 };
 
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c
index 5e4465a..fa620a5 100644
--- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c
+++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.c
@@ -50,6 +50,7 @@
 static const struct file_operations name## _ops = {			\
 	.read = name## _read,						\
 	.open = wl1251_open_file_generic,				\
+	.llseek	= generic_file_llseek,					\
 };
 
 #define DEBUGFS_ADD(name, parent)					\
@@ -86,6 +87,7 @@
 static const struct file_operations sub## _ ##name## _ops = {		\
 	.read = sub## _ ##name## _read,					\
 	.open = wl1251_open_file_generic,				\
+	.llseek	= generic_file_llseek,					\
 };
 
 #define DEBUGFS_FWSTATS_ADD(sub, name)				\
@@ -236,6 +238,7 @@
 static const struct file_operations tx_queue_len_ops = {
 	.read = tx_queue_len_read,
 	.open = wl1251_open_file_generic,
+	.llseek = generic_file_llseek,
 };
 
 static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
@@ -257,6 +260,7 @@
 static const struct file_operations tx_queue_status_ops = {
 	.read = tx_queue_status_read,
 	.open = wl1251_open_file_generic,
+	.llseek = generic_file_llseek,
 };
 
 static void wl1251_debugfs_delete_files(struct wl1251 *wl)
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
index c239ef4..66c2b90 100644
--- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c
+++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
@@ -51,6 +51,7 @@
 static const struct file_operations name## _ops = {			\
 	.read = name## _read,						\
 	.open = wl1271_open_file_generic,				\
+	.llseek	= generic_file_llseek,					\
 };
 
 #define DEBUGFS_ADD(name, parent)					\
@@ -87,6 +88,7 @@
 static const struct file_operations sub## _ ##name## _ops = {		\
 	.read = sub## _ ##name## _read,					\
 	.open = wl1271_open_file_generic,				\
+	.llseek	= generic_file_llseek,					\
 };
 
 #define DEBUGFS_FWSTATS_ADD(sub, name)				\
@@ -237,6 +239,7 @@
 static const struct file_operations tx_queue_len_ops = {
 	.read = tx_queue_len_read,
 	.open = wl1271_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t gpio_power_read(struct file *file, char __user *user_buf,
@@ -291,7 +294,8 @@
 static const struct file_operations gpio_power_ops = {
 	.read = gpio_power_read,
 	.write = gpio_power_write,
-	.open = wl1271_open_file_generic
+	.open = wl1271_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static void wl1271_debugfs_delete_files(struct wl1271 *wl)
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index ccf099e..89f6345 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -59,6 +59,7 @@
 static const struct file_operations timeout_fops = {
 	.read		= timeout_read,
 	.write		= timeout_write,
+	.llseek		= default_llseek,
 };
 
 #endif
@@ -96,7 +97,8 @@
 
 static const struct file_operations depth_fops = {
 	.read		= depth_read,
-	.write		= depth_write
+	.write		= depth_write,
+	.llseek		= default_llseek,
 };
 
 
@@ -108,6 +110,7 @@
 
 static const struct file_operations pointer_size_fops = {
 	.read		= pointer_size_read,
+	.llseek		= default_llseek,
 };
 
 
@@ -119,6 +122,7 @@
 
 static const struct file_operations cpu_type_fops = {
 	.read		= cpu_type_read,
+	.llseek		= default_llseek,
 };
 
 
@@ -154,6 +158,7 @@
 static const struct file_operations enable_fops = {
 	.read		= enable_read,
 	.write		= enable_write,
+	.llseek		= default_llseek,
 };
 
 
@@ -166,6 +171,7 @@
 
 static const struct file_operations dump_fops = {
 	.write		= dump_write,
+	.llseek		= noop_llseek,
 };
 
 void oprofile_create_files(struct super_block *sb, struct dentry *root)
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index 1944621..95f711b 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -121,12 +121,14 @@
 	.read		= ulong_read_file,
 	.write		= ulong_write_file,
 	.open		= default_open,
+	.llseek		= default_llseek,
 };
 
 
 static const struct file_operations ulong_ro_fops = {
 	.read		= ulong_read_file,
 	.open		= default_open,
+	.llseek		= default_llseek,
 };
 
 
@@ -178,6 +180,7 @@
 static const struct file_operations atomic_ro_fops = {
 	.read		= atomic_read_file,
 	.open		= default_open,
+	.llseek		= default_llseek,
 };
 
 
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 5621532..4cb3044 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -34,10 +34,11 @@
 #include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/debugfs.h>
 #include "cpqphp.h"
 
+static DEFINE_MUTEX(cpqphp_mutex);
 static int show_ctrl (struct controller *ctrl, char *buf)
 {
 	char *out = buf;
@@ -147,7 +148,7 @@
 	struct ctrl_dbg *dbg;
 	int retval = -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&cpqphp_mutex);
 	dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
 	if (!dbg)
 		goto exit;
@@ -160,7 +161,7 @@
 	file->private_data = dbg;
 	retval = 0;
 exit:
-	unlock_kernel();
+	mutex_unlock(&cpqphp_mutex);
 	return retval;
 }
 
@@ -169,7 +170,7 @@
 	struct ctrl_dbg *dbg;
 	loff_t new = -1;
 
-	lock_kernel();
+	mutex_lock(&cpqphp_mutex);
 	dbg = file->private_data;
 
 	switch (whence) {
@@ -181,10 +182,10 @@
 		break;
 	}
 	if (new < 0 || new > dbg->size) {
-		unlock_kernel();
+		mutex_unlock(&cpqphp_mutex);
 		return -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&cpqphp_mutex);
 	return (file->f_pos = new);
 }
 
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 73d5139..838f571 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -36,6 +36,7 @@
 #include <linux/sched.h>		/* signal_pending() */
 #include <linux/pcieport_if.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #define MY_NAME	"pciehp"
 
@@ -44,6 +45,7 @@
 extern int pciehp_debug;
 extern int pciehp_force;
 extern struct workqueue_struct *pciehp_wq;
+extern struct workqueue_struct *pciehp_ordered_wq;
 
 #define dbg(format, arg...)						\
 do {									\
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index aa5f3ff..7ac8358 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -43,6 +43,7 @@
 int pciehp_poll_time;
 int pciehp_force;
 struct workqueue_struct *pciehp_wq;
+struct workqueue_struct *pciehp_ordered_wq;
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -340,18 +341,33 @@
 {
 	int retval = 0;
 
+	pciehp_wq = alloc_workqueue("pciehp", 0, 0);
+	if (!pciehp_wq)
+		return -ENOMEM;
+
+	pciehp_ordered_wq = alloc_ordered_workqueue("pciehp_ordered", 0);
+	if (!pciehp_ordered_wq) {
+		destroy_workqueue(pciehp_wq);
+		return -ENOMEM;
+	}
+
 	pciehp_firmware_init();
 	retval = pcie_port_service_register(&hpdriver_portdrv);
  	dbg("pcie_port_service_register = %d\n", retval);
   	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- 	if (retval)
+ 	if (retval) {
+		destroy_workqueue(pciehp_ordered_wq);
+		destroy_workqueue(pciehp_wq);
 		dbg("Failure to register service\n");
+	}
 	return retval;
 }
 
 static void __exit pcied_cleanup(void)
 {
 	dbg("unload_pciehpd()\n");
+	destroy_workqueue(pciehp_ordered_wq);
+	destroy_workqueue(pciehp_wq);
 	pcie_port_service_unregister(&hpdriver_portdrv);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 8f58148..085dbb5 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -32,7 +32,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/workqueue.h>
 #include "../pci.h"
 #include "pciehp.h"
 
@@ -50,7 +49,7 @@
 	info->p_slot = p_slot;
 	INIT_WORK(&info->work, interrupt_event_handler);
 
-	schedule_work(&info->work);
+	queue_work(pciehp_wq, &info->work);
 
 	return 0;
 }
@@ -345,7 +344,7 @@
 		kfree(info);
 		goto out;
 	}
-	queue_work(pciehp_wq, &info->work);
+	queue_work(pciehp_ordered_wq, &info->work);
  out:
 	mutex_unlock(&p_slot->lock);
 }
@@ -378,7 +377,7 @@
 		if (ATTN_LED(ctrl))
 			pciehp_set_attention_status(p_slot, 0);
 
-		schedule_delayed_work(&p_slot->work, 5*HZ);
+		queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
 		break;
 	case BLINKINGOFF_STATE:
 	case BLINKINGON_STATE:
@@ -440,7 +439,7 @@
 	else
 		p_slot->state = POWERON_STATE;
 
-	queue_work(pciehp_wq, &info->work);
+	queue_work(pciehp_ordered_wq, &info->work);
 }
 
 static void interrupt_event_handler(struct work_struct *work)
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 0cd4204..50a23da 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -41,8 +41,6 @@
 #include "../pci.h"
 #include "pciehp.h"
 
-static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
-
 static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
 {
 	struct pci_dev *dev = ctrl->pcie->port;
@@ -805,8 +803,8 @@
 {
 	struct slot *slot = ctrl->slot;
 	cancel_delayed_work(&slot->work);
-	flush_scheduled_work();
 	flush_workqueue(pciehp_wq);
+	flush_workqueue(pciehp_ordered_wq);
 	kfree(slot);
 }
 
@@ -912,16 +910,6 @@
 	/* Disable sotfware notification */
 	pcie_disable_notification(ctrl);
 
-	/*
-	 * If this is the first controller to be initialized,
-	 * initialize the pciehp work queue
-	 */
-	if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
-		pciehp_wq = create_singlethread_workqueue("pciehpd");
-		if (!pciehp_wq)
-			goto abort_ctrl;
-	}
-
 	ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
 		  pdev->vendor, pdev->device, pdev->subsystem_vendor,
 		  pdev->subsystem_device);
@@ -941,11 +929,5 @@
 {
 	pcie_shutdown_notification(ctrl);
 	pcie_cleanup_slot(ctrl);
-	/*
-	 * If this is the last controller to be released, destroy the
-	 * pciehp work queue
-	 */
-	if (atomic_dec_and_test(&pciehp_num_controllers))
-		destroy_workqueue(pciehp_wq);
 	kfree(ctrl);
 }
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index d2627e1..e0c90e6 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/sched.h>	/* signal_pending(), struct timer_list */
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #if !defined(MODULE)
 	#define MY_NAME	"shpchp"
@@ -46,6 +47,7 @@
 extern int shpchp_poll_time;
 extern int shpchp_debug;
 extern struct workqueue_struct *shpchp_wq;
+extern struct workqueue_struct *shpchp_ordered_wq;
 
 #define dbg(format, arg...)						\
 do {									\
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index a7bd504..aca972b 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -33,7 +33,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/workqueue.h>
 #include "shpchp.h"
 
 /* Global variables */
@@ -41,6 +40,7 @@
 int shpchp_poll_mode;
 int shpchp_poll_time;
 struct workqueue_struct *shpchp_wq;
+struct workqueue_struct *shpchp_ordered_wq;
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -174,8 +174,8 @@
 		slot = list_entry(tmp, struct slot, slot_list);
 		list_del(&slot->slot_list);
 		cancel_delayed_work(&slot->work);
-		flush_scheduled_work();
 		flush_workqueue(shpchp_wq);
+		flush_workqueue(shpchp_ordered_wq);
 		pci_hp_deregister(slot->hotplug_slot);
 	}
 }
@@ -360,9 +360,23 @@
 {
 	int retval = 0;
 
+	shpchp_wq = alloc_ordered_workqueue("shpchp", 0);
+	if (!shpchp_wq)
+		return -ENOMEM;
+
+	shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0);
+	if (!shpchp_ordered_wq) {
+		destroy_workqueue(shpchp_wq);
+		return -ENOMEM;
+	}
+
 	retval = pci_register_driver(&shpc_driver);
 	dbg("%s: pci_register_driver = %d\n", __func__, retval);
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	if (retval) {
+		destroy_workqueue(shpchp_ordered_wq);
+		destroy_workqueue(shpchp_wq);
+	}
 	return retval;
 }
 
@@ -370,6 +384,8 @@
 {
 	dbg("unload_shpchpd()\n");
 	pci_unregister_driver(&shpc_driver);
+	destroy_workqueue(shpchp_ordered_wq);
+	destroy_workqueue(shpchp_wq);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 3387fbf..b00b09b 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -32,7 +32,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/workqueue.h>
 #include "../pci.h"
 #include "shpchp.h"
 
@@ -52,7 +51,7 @@
 	info->p_slot = p_slot;
 	INIT_WORK(&info->work, interrupt_event_handler);
 
-	schedule_work(&info->work);
+	queue_work(shpchp_wq, &info->work);
 
 	return 0;
 }
@@ -457,7 +456,7 @@
 		kfree(info);
 		goto out;
 	}
-	queue_work(shpchp_wq, &info->work);
+	queue_work(shpchp_ordered_wq, &info->work);
  out:
 	mutex_unlock(&p_slot->lock);
 }
@@ -505,7 +504,7 @@
 		p_slot->hpc_ops->green_led_blink(p_slot);
 		p_slot->hpc_ops->set_attention_status(p_slot, 0);
 
-		schedule_delayed_work(&p_slot->work, 5*HZ);
+		queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ);
 		break;
 	case BLINKINGOFF_STATE:
 	case BLINKINGON_STATE:
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index d3985e7..36547f0 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -179,8 +179,6 @@
 #define SLOT_EVENT_LATCH	0x2
 #define SLOT_SERR_INT_MASK	0x3
 
-static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
-
 static irqreturn_t shpc_isr(int irq, void *dev_id);
 static void start_int_poll_timer(struct controller *ctrl, int sec);
 static int hpc_check_cmd_status(struct controller *ctrl);
@@ -614,13 +612,6 @@
 
 	iounmap(ctrl->creg);
 	release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
-
-	/*
-	 * If this is the last controller to be released, destroy the
-	 * shpchpd work queue
-	 */
-	if (atomic_dec_and_test(&shpchp_num_controllers))
-		destroy_workqueue(shpchp_wq);
 }
 
 static int hpc_power_on_slot(struct slot * slot)
@@ -1077,9 +1068,8 @@
 
 		rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
 				 MY_NAME, (void *)ctrl);
-		ctrl_dbg(ctrl, "request_irq %d for hpc%d (returns %d)\n",
-			 ctrl->pci_dev->irq,
-		    atomic_read(&shpchp_num_controllers), rc);
+		ctrl_dbg(ctrl, "request_irq %d (returns %d)\n",
+			 ctrl->pci_dev->irq, rc);
 		if (rc) {
 			ctrl_err(ctrl, "Can't get irq %d for the hotplug "
 				 "controller\n", ctrl->pci_dev->irq);
@@ -1092,18 +1082,6 @@
 	shpc_get_cur_bus_speed(ctrl);
 
 	/*
-	 * If this is the first controller to be initialized,
-	 * initialize the shpchpd work queue
-	 */
-	if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
-		shpchp_wq = create_singlethread_workqueue("shpchpd");
-		if (!shpchp_wq) {
-			rc = -ENOMEM;
-			goto abort_iounmap;
-		}
-	}
-
-	/*
 	 * Unmask all event interrupts of all slots
 	 */
 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 9099246..b3cf622 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer/aer_inject.c
@@ -472,6 +472,7 @@
 static const struct file_operations aer_inject_fops = {
 	.write = aer_inject_write,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice aer_inject_device = {
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index a9af0d7..0bdda5b3 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -514,7 +514,9 @@
 	}
 
 	/* Pick memory or I/O card, DMA mode, interrupt */
-	if (p_dev->_io)
+	if (p_dev->_io || flags & CONF_ENABLE_IRQ)
+		flags |= CONF_ENABLE_IOCARD;
+	if (flags & CONF_ENABLE_IOCARD)
 		s->socket.flags |= SS_IOCARD;
 	if (flags & CONF_ENABLE_SPKR) {
 		s->socket.flags |= SS_SPKR_ENA;
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index e3154ff..f200677 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -2360,6 +2360,7 @@
 	.release	= sonypi_misc_release,
 	.fasync		= sonypi_misc_fasync,
 	.unlocked_ioctl	= sonypi_misc_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice sonypi_misc_device = {
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index 3f94eda..e73ebef 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -31,8 +31,9 @@
 static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
 {
 	loff_t new = -1;
+	struct inode *inode = file->f_path.dentry->d_inode;
 
-	lock_kernel();
+	mutex_lock(&inode->i_mutex);
 	switch (whence) {
 	case 0:
 		new = off;
@@ -44,12 +45,12 @@
 		new = 256 + off;
 		break;
 	}
-	if (new < 0 || new > 256) {
-		unlock_kernel();
-		return -EINVAL;
-	}
-	unlock_kernel();
-	return (file->f_pos = new);
+	if (new < 0 || new > 256)
+		new = -EINVAL;
+	else
+		file->f_pos = new;
+	mutex_unlock(&inode->i_mutex);
+	return new;
 }
 
 static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index d60557c..5a8daa3 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/string.h>
 #ifdef CONFIG_RTC_DRV_M41T80_WDT
 #include <linux/fs.h>
@@ -68,6 +68,7 @@
 
 #define DRV_VERSION "0.05"
 
+static DEFINE_MUTEX(m41t80_rtc_mutex);
 static const struct i2c_device_id m41t80_id[] = {
 	{ "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
 	{ "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD },
@@ -677,9 +678,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&m41t80_rtc_mutex);
 	ret = wdt_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&m41t80_rtc_mutex);
 
 	return ret;
 }
@@ -693,16 +694,16 @@
 static int wdt_open(struct inode *inode, struct file *file)
 {
 	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
-		lock_kernel();
+		mutex_lock(&m41t80_rtc_mutex);
 		if (test_and_set_bit(0, &wdt_is_open)) {
-			unlock_kernel();
+			mutex_unlock(&m41t80_rtc_mutex);
 			return -EBUSY;
 		}
 		/*
 		 *	Activate
 		 */
 		wdt_is_open = 1;
-		unlock_kernel();
+		mutex_unlock(&m41t80_rtc_mutex);
 		return nonseekable_open(inode, file);
 	}
 	return -ENODEV;
@@ -748,6 +749,7 @@
 	.write	= wdt_write,
 	.open	= wdt_open,
 	.release = wdt_release,
+	.llseek = no_llseek,
 };
 
 static struct miscdevice wdt_dev = {
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 8373ca0..aa95f10 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -21,7 +21,6 @@
 #include <linux/hdreg.h>
 #include <linux/async.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
@@ -2197,7 +2196,6 @@
 	 */
 	blk_queue_max_segment_size(block->request_queue, PAGE_SIZE);
 	blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1);
-	blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN);
 }
 
 /*
@@ -2236,7 +2234,6 @@
 	if (!block)
 		return -ENODEV;
 
-	lock_kernel();
 	base = block->base;
 	atomic_inc(&block->open_count);
 	if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) {
@@ -2271,14 +2268,12 @@
 		goto out;
 	}
 
-	unlock_kernel();
 	return 0;
 
 out:
 	module_put(base->discipline->owner);
 unlock:
 	atomic_dec(&block->open_count);
-	unlock_kernel();
 	return rc;
 }
 
@@ -2286,10 +2281,8 @@
 {
 	struct dasd_block *block = disk->private_data;
 
-	lock_kernel();
 	atomic_dec(&block->open_count);
 	module_put(block->base->discipline->owner);
-	unlock_kernel();
 	return 0;
 }
 
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 7158f95..c71d89d 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -670,6 +670,7 @@
 	.read		= &dasd_eer_read,
 	.poll		= &dasd_eer_poll,
 	.owner		= THIS_MODULE,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice *dasd_eer_dev = NULL;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 1557214..26075e9 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -16,7 +16,6 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/blkpg.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/compat.h>
 #include <asm/ccwdev.h>
@@ -370,9 +369,8 @@
 	return ret;
 }
 
-static int
-dasd_do_ioctl(struct block_device *bdev, fmode_t mode,
-	      unsigned int cmd, unsigned long arg)
+int dasd_ioctl(struct block_device *bdev, fmode_t mode,
+	       unsigned int cmd, unsigned long arg)
 {
 	struct dasd_block *block = bdev->bd_disk->private_data;
 	void __user *argp;
@@ -430,14 +428,3 @@
 		return -EINVAL;
 	}
 }
-
-int dasd_ioctl(struct block_device *bdev, fmode_t mode,
-	       unsigned int cmd, unsigned long arg)
-{
-	int rc;
-
-	lock_kernel();
-	rc = dasd_do_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
-	return rc;
-}
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 2bd72aa..9b43ae9 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -776,7 +775,6 @@
 	struct dcssblk_dev_info *dev_info;
 	int rc;
 
-	lock_kernel();
 	dev_info = bdev->bd_disk->private_data;
 	if (NULL == dev_info) {
 		rc = -ENODEV;
@@ -786,7 +784,6 @@
 	bdev->bd_block_size = 4096;
 	rc = 0;
 out:
-	unlock_kernel();
 	return rc;
 }
 
@@ -797,7 +794,6 @@
 	struct segment_info *entry;
 	int rc;
 
-	lock_kernel();
 	if (!dev_info) {
 		rc = -ENODEV;
 		goto out;
@@ -815,7 +811,6 @@
 	up_write(&dcssblk_devices_sem);
 	rc = 0;
 out:
-	unlock_kernel();
 	return rc;
 }
 
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 857dfcb..eb28fb0 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -520,6 +520,7 @@
 	.compat_ioctl	 = fs3270_ioctl,	/* ioctl */
 	.open		 = fs3270_open,		/* open */
 	.release	 = fs3270_close,	/* release */
+	.llseek		= no_llseek,
 };
 
 /*
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index e021ec6..5b8b859 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -447,6 +447,7 @@
 	.release = &mon_close,
 	.read    = &mon_read,
 	.poll    = &mon_poll,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice mon_dev = {
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 572a1e7..e0702d3 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -274,6 +274,7 @@
 	.open	 = &monwrite_open,
 	.release = &monwrite_close,
 	.write	 = &monwrite_write,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice mon_dev = {
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 85cf607..f0fa9ca 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -16,7 +16,7 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
@@ -45,6 +45,7 @@
 /*
  * file operation structure for tape block frontend
  */
+static DEFINE_MUTEX(tape_block_mutex);
 static int tapeblock_open(struct block_device *, fmode_t);
 static int tapeblock_release(struct gendisk *, fmode_t);
 static int tapeblock_medium_changed(struct gendisk *);
@@ -361,7 +362,7 @@
 	struct tape_device *	device;
 	int			rc;
 
-	lock_kernel();
+	mutex_lock(&tape_block_mutex);
 	device = tape_get_device(disk->private_data);
 
 	if (device->required_tapemarks) {
@@ -385,14 +386,14 @@
 	 *       is called.
 	 */
 	tape_state_set(device, TS_BLKUSE);
-	unlock_kernel();
+	mutex_unlock(&tape_block_mutex);
 	return 0;
 
 release:
 	tape_release(device);
  put_device:
 	tape_put_device(device);
-	unlock_kernel();
+	mutex_unlock(&tape_block_mutex);
 	return rc;
 }
 
@@ -407,11 +408,11 @@
 {
 	struct tape_device *device = disk->private_data;
  
-	lock_kernel();
+	mutex_lock(&tape_block_mutex);
 	tape_state_set(device, TS_IN_USE);
 	tape_release(device);
 	tape_put_device(device);
-	unlock_kernel();
+	mutex_unlock(&tape_block_mutex);
 
 	return 0;
 }
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 539045a..883e2db 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -53,6 +53,7 @@
 #endif
 	.open = tapechar_open,
 	.release = tapechar_release,
+	.llseek = no_llseek,
 };
 
 static int tapechar_major = TAPECHAR_MAJOR;
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 04e532e..0e7cb1a 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -177,6 +177,7 @@
 	.write		= vmcp_write,
 	.unlocked_ioctl	= vmcp_ioctl,
 	.compat_ioctl	= vmcp_ioctl,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice vmcp_dev = {
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index e40a1b8..0d6dc4b 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -97,6 +97,7 @@
 	.open    = vmlogrdr_open,
 	.release = vmlogrdr_release,
 	.read    = vmlogrdr_read,
+	.llseek  = no_llseek,
 };
 
 
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index e13508c..12ef912 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -297,6 +297,7 @@
 	.unlocked_ioctl = &vmwdt_ioctl,
 	.write   = &vmwdt_write,
 	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice vmwdt_dev = {
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index f5ea338..3b94044 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -459,6 +459,7 @@
 	.read		= zcore_memmap_read,
 	.open		= zcore_memmap_open,
 	.release	= zcore_memmap_release,
+	.llseek		= no_llseek,
 };
 
 static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf,
@@ -486,6 +487,7 @@
 	.write		= zcore_reipl_write,
 	.open		= zcore_reipl_open,
 	.release	= zcore_reipl_release,
+	.llseek		= no_llseek,
 };
 
 #ifdef CONFIG_32BIT
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index a83877c..f2b77e7 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -806,6 +806,7 @@
 	.open = nonseekable_open,
 	.unlocked_ioctl = chsc_ioctl,
 	.compat_ioctl = chsc_ioctl,
+	.llseek = no_llseek,
 };
 
 static struct miscdevice chsc_misc_device = {
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index ac94ac75..ca8e1c2 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1067,6 +1067,7 @@
 static const struct file_operations cio_settle_proc_fops = {
 	.open = nonseekable_open,
 	.write = cio_settle_write,
+	.llseek = no_llseek,
 };
 
 static int __init cio_settle_init(void)
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 41e0aae..f522174 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -897,7 +897,8 @@
 	.compat_ioctl	= zcrypt_compat_ioctl,
 #endif
 	.open		= zcrypt_open,
-	.release	= zcrypt_release
+	.release	= zcrypt_release,
+	.llseek		= no_llseek,
 };
 
 /*
diff --git a/drivers/s390/scsi/Makefile b/drivers/s390/scsi/Makefile
index cb301cc..c454ffe 100644
--- a/drivers/s390/scsi/Makefile
+++ b/drivers/s390/scsi/Makefile
@@ -2,7 +2,8 @@
 # Makefile for the S/390 specific device drivers
 #
 
-zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
-	     zfcp_fsf.o zfcp_dbf.o zfcp_sysfs.o zfcp_fc.o zfcp_cfdc.o
+zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_cfdc.o zfcp_dbf.o zfcp_erp.o \
+	     zfcp_fc.o zfcp_fsf.o zfcp_qdio.o zfcp_scsi.o zfcp_sysfs.o \
+	     zfcp_unit.o
 
 obj-$(CONFIG_ZFCP) += zfcp.o
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 96fa1f5..044fb22 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -56,7 +56,6 @@
 	struct ccw_device *cdev;
 	struct zfcp_adapter *adapter;
 	struct zfcp_port *port;
-	struct zfcp_unit *unit;
 
 	cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
 	if (!cdev)
@@ -72,17 +71,11 @@
 	port = zfcp_get_port_by_wwpn(adapter, wwpn);
 	if (!port)
 		goto out_port;
+	flush_work(&port->rport_work);
 
-	unit = zfcp_unit_enqueue(port, lun);
-	if (IS_ERR(unit))
-		goto out_unit;
-
-	zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
-	zfcp_erp_wait(adapter);
-	flush_work(&unit->scsi_work);
-
-out_unit:
+	zfcp_unit_add(port, lun);
 	put_device(&port->dev);
+
 out_port:
 	zfcp_ccw_adapter_put(adapter);
 out_ccw_device:
@@ -158,6 +151,9 @@
 		fc_attach_transport(&zfcp_transport_functions);
 	if (!zfcp_data.scsi_transport_template)
 		goto out_transport;
+	scsi_transport_reserve_device(zfcp_data.scsi_transport_template,
+				      sizeof(struct zfcp_scsi_dev));
+
 
 	retval = misc_register(&zfcp_cfdc_misc);
 	if (retval) {
@@ -211,30 +207,6 @@
 module_exit(zfcp_module_exit);
 
 /**
- * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN
- * @port: pointer to port to search for unit
- * @fcp_lun: FCP LUN to search for
- *
- * Returns: pointer to zfcp_unit or NULL
- */
-struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
-{
-	unsigned long flags;
-	struct zfcp_unit *unit;
-
-	read_lock_irqsave(&port->unit_list_lock, flags);
-	list_for_each_entry(unit, &port->unit_list, list)
-		if (unit->fcp_lun == fcp_lun) {
-			if (!get_device(&unit->dev))
-				unit = NULL;
-			read_unlock_irqrestore(&port->unit_list_lock, flags);
-			return unit;
-		}
-	read_unlock_irqrestore(&port->unit_list_lock, flags);
-	return NULL;
-}
-
-/**
  * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn
  * @adapter: pointer to adapter to search for port
  * @wwpn: wwpn to search for
@@ -259,92 +231,6 @@
 	return NULL;
 }
 
-/**
- * zfcp_unit_release - dequeue unit
- * @dev: pointer to device
- *
- * waits until all work is done on unit and removes it then from the unit->list
- * of the associated port.
- */
-static void zfcp_unit_release(struct device *dev)
-{
-	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
-
-	put_device(&unit->port->dev);
-	kfree(unit);
-}
-
-/**
- * zfcp_unit_enqueue - enqueue unit to unit list of a port.
- * @port: pointer to port where unit is added
- * @fcp_lun: FCP LUN of unit to be enqueued
- * Returns: pointer to enqueued unit on success, ERR_PTR on error
- *
- * Sets up some unit internal structures and creates sysfs entry.
- */
-struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
-{
-	struct zfcp_unit *unit;
-	int retval = -ENOMEM;
-
-	get_device(&port->dev);
-
-	unit = zfcp_get_unit_by_lun(port, fcp_lun);
-	if (unit) {
-		put_device(&unit->dev);
-		retval = -EEXIST;
-		goto err_out;
-	}
-
-	unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
-	if (!unit)
-		goto err_out;
-
-	unit->port = port;
-	unit->fcp_lun = fcp_lun;
-	unit->dev.parent = &port->dev;
-	unit->dev.release = zfcp_unit_release;
-
-	if (dev_set_name(&unit->dev, "0x%016llx",
-			 (unsigned long long) fcp_lun)) {
-		kfree(unit);
-		goto err_out;
-	}
-	retval = -EINVAL;
-
-	INIT_WORK(&unit->scsi_work, zfcp_scsi_scan_work);
-
-	spin_lock_init(&unit->latencies.lock);
-	unit->latencies.write.channel.min = 0xFFFFFFFF;
-	unit->latencies.write.fabric.min = 0xFFFFFFFF;
-	unit->latencies.read.channel.min = 0xFFFFFFFF;
-	unit->latencies.read.fabric.min = 0xFFFFFFFF;
-	unit->latencies.cmd.channel.min = 0xFFFFFFFF;
-	unit->latencies.cmd.fabric.min = 0xFFFFFFFF;
-
-	if (device_register(&unit->dev)) {
-		put_device(&unit->dev);
-		goto err_out;
-	}
-
-	if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs))
-		goto err_out_put;
-
-	write_lock_irq(&port->unit_list_lock);
-	list_add_tail(&unit->list, &port->unit_list);
-	write_unlock_irq(&port->unit_list_lock);
-
-	atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
-
-	return unit;
-
-err_out_put:
-	device_unregister(&unit->dev);
-err_out:
-	put_device(&port->dev);
-	return ERR_PTR(retval);
-}
-
 static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
 {
 	adapter->pool.erp_req =
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index ce1cc7a..0833c2b 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -46,8 +46,7 @@
 	if (!adapter)
 		return 0;
 
-	zfcp_erp_modify_adapter_status(adapter, "ccresu1", NULL,
-				       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 				"ccresu2", NULL);
 	zfcp_erp_wait(adapter);
@@ -164,14 +163,7 @@
 	BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
 	adapter->req_no = 0;
 
-	zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
-				       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
-	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
-				"ccsonl2", NULL);
-	zfcp_erp_wait(adapter);
-
-	flush_work(&adapter->scan_work);
-
+	zfcp_ccw_activate(cdev);
 	zfcp_ccw_adapter_put(adapter);
 	return 0;
 }
@@ -224,9 +216,8 @@
 		break;
 	case CIO_OPER:
 		dev_info(&cdev->dev, "The FCP device is operational again\n");
-		zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL,
-					       ZFCP_STATUS_COMMON_RUNNING,
-					       ZFCP_SET);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_RUNNING);
 		zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 					"ccnoti4", NULL);
 		break;
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
index fcbd2b7..d692e229 100644
--- a/drivers/s390/scsi/zfcp_cfdc.c
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -2,9 +2,10 @@
  * zfcp device driver
  *
  * Userspace interface for accessing the
- * Access Control Lists / Control File Data Channel
+ * Access Control Lists / Control File Data Channel;
+ * handling of response code and states for ports and LUNs.
  *
- * Copyright IBM Corporation 2008, 2009
+ * Copyright IBM Corporation 2008, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -251,8 +252,9 @@
 	.open = nonseekable_open,
 	.unlocked_ioctl = zfcp_cfdc_dev_ioctl,
 #ifdef CONFIG_COMPAT
-	.compat_ioctl = zfcp_cfdc_dev_ioctl
+	.compat_ioctl = zfcp_cfdc_dev_ioctl,
 #endif
+	.llseek = no_llseek,
 };
 
 struct miscdevice zfcp_cfdc_misc = {
@@ -260,3 +262,184 @@
 	.name = "zfcp_cfdc",
 	.fops = &zfcp_cfdc_fops,
 };
+
+/**
+ * zfcp_cfdc_adapter_access_changed - Process change in adapter ACT
+ * @adapter: Adapter where the Access Control Table (ACT) changed
+ *
+ * After a change in the adapter ACT, check if access to any
+ * previously denied resources is now possible.
+ */
+void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter)
+{
+	unsigned long flags;
+	struct zfcp_port *port;
+	struct scsi_device *sdev;
+	struct zfcp_scsi_dev *zfcp_sdev;
+	int status;
+
+	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+		return;
+
+	read_lock_irqsave(&adapter->port_list_lock, flags);
+	list_for_each_entry(port, &adapter->port_list, list) {
+		status = atomic_read(&port->status);
+		if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
+		    (status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
+			zfcp_erp_port_reopen(port,
+					     ZFCP_STATUS_COMMON_ERP_FAILED,
+					     "cfaac_1", NULL);
+	}
+	read_unlock_irqrestore(&adapter->port_list_lock, flags);
+
+	shost_for_each_device(sdev, port->adapter->scsi_host) {
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		status = atomic_read(&zfcp_sdev->status);
+		if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
+		    (status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
+			zfcp_erp_lun_reopen(sdev,
+					    ZFCP_STATUS_COMMON_ERP_FAILED,
+					    "cfaac_2", NULL);
+	}
+}
+
+static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
+{
+	u16 subtable = table >> 16;
+	u16 rule = table & 0xffff;
+	const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
+
+	if (subtable && subtable < ARRAY_SIZE(act_type))
+		dev_warn(&adapter->ccw_device->dev,
+			 "Access denied according to ACT rule type %s, "
+			 "rule %d\n", act_type[subtable], rule);
+}
+
+/**
+ * zfcp_cfdc_port_denied - Process "access denied" for port
+ * @port: The port where the acces has been denied
+ * @qual: The FSF status qualifier for the access denied FSF status
+ */
+void zfcp_cfdc_port_denied(struct zfcp_port *port,
+			   union fsf_status_qual *qual)
+{
+	dev_warn(&port->adapter->ccw_device->dev,
+		 "Access denied to port 0x%016Lx\n",
+		 (unsigned long long)port->wwpn);
+
+	zfcp_act_eval_err(port->adapter, qual->halfword[0]);
+	zfcp_act_eval_err(port->adapter, qual->halfword[1]);
+	zfcp_erp_set_port_status(port,
+				 ZFCP_STATUS_COMMON_ERP_FAILED |
+				 ZFCP_STATUS_COMMON_ACCESS_DENIED);
+}
+
+/**
+ * zfcp_cfdc_lun_denied - Process "access denied" for LUN
+ * @sdev: The SCSI device / LUN where the access has been denied
+ * @qual: The FSF status qualifier for the access denied FSF status
+ */
+void zfcp_cfdc_lun_denied(struct scsi_device *sdev,
+			  union fsf_status_qual *qual)
+{
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev,
+		 "Access denied to LUN 0x%016Lx on port 0x%016Lx\n",
+		 zfcp_scsi_dev_lun(sdev),
+		 (unsigned long long)zfcp_sdev->port->wwpn);
+	zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[0]);
+	zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[1]);
+	zfcp_erp_set_lun_status(sdev,
+				ZFCP_STATUS_COMMON_ERP_FAILED |
+				ZFCP_STATUS_COMMON_ACCESS_DENIED);
+
+	atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
+	atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
+}
+
+/**
+ * zfcp_cfdc_lun_shrng_vltn - Evaluate LUN sharing violation status
+ * @sdev: The LUN / SCSI device where sharing violation occurred
+ * @qual: The FSF status qualifier from the LUN sharing violation
+ */
+void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *sdev,
+			      union fsf_status_qual *qual)
+{
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	if (qual->word[0])
+		dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev,
+			 "LUN 0x%Lx on port 0x%Lx is already in "
+			 "use by CSS%d, MIF Image ID %x\n",
+			 zfcp_scsi_dev_lun(sdev),
+			 (unsigned long long)zfcp_sdev->port->wwpn,
+			 qual->fsf_queue_designator.cssid,
+			 qual->fsf_queue_designator.hla);
+	else
+		zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->word[2]);
+
+	zfcp_erp_set_lun_status(sdev,
+				ZFCP_STATUS_COMMON_ERP_FAILED |
+				ZFCP_STATUS_COMMON_ACCESS_DENIED);
+	atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
+	atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
+}
+
+/**
+ * zfcp_cfdc_open_lun_eval - Eval access ctrl. status for successful "open lun"
+ * @sdev: The SCSI device / LUN where to evaluate the status
+ * @bottom: The qtcb bottom with the status from the "open lun"
+ *
+ * Returns: 0 if LUN is usable, -EACCES if the access control table
+ *          reports an unsupported configuration.
+ */
+int zfcp_cfdc_open_lun_eval(struct scsi_device *sdev,
+			    struct fsf_qtcb_bottom_support *bottom)
+{
+	int shared, rw;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
+
+	if ((adapter->connection_features & FSF_FEATURE_NPIV_MODE) ||
+	    !(adapter->adapter_features & FSF_FEATURE_LUN_SHARING) ||
+	    zfcp_ccw_priv_sch(adapter))
+		return 0;
+
+	shared = !(bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE);
+	rw = (bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
+
+	if (shared)
+		atomic_set_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status);
+
+	if (!rw) {
+		atomic_set_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status);
+		dev_info(&adapter->ccw_device->dev, "SCSI device at LUN "
+			 "0x%016Lx on port 0x%016Lx opened read-only\n",
+			 zfcp_scsi_dev_lun(sdev),
+			 (unsigned long long)zfcp_sdev->port->wwpn);
+	}
+
+	if (!shared && !rw) {
+		dev_err(&adapter->ccw_device->dev, "Exclusive read-only access "
+			"not supported (LUN 0x%016Lx, port 0x%016Lx)\n",
+			zfcp_scsi_dev_lun(sdev),
+			(unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
+		zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6", NULL);
+		return -EACCES;
+	}
+
+	if (shared && rw) {
+		dev_err(&adapter->ccw_device->dev,
+			"Shared read-write access not supported "
+			"(LUN 0x%016Lx, port 0x%016Lx)\n",
+			zfcp_scsi_dev_lun(sdev),
+			(unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
+		zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8", NULL);
+		return -EACCES;
+	}
+
+	return 0;
+}
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index a86117b..2cdd6b2 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -154,7 +154,6 @@
 		scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
 		if (scsi_cmnd) {
 			response->u.fcp.cmnd = (unsigned long)scsi_cmnd;
-			response->u.fcp.serial = scsi_cmnd->serial_number;
 			response->u.fcp.data_dir =
 				qtcb->bottom.io.data_direction;
 		}
@@ -330,7 +329,6 @@
 			break;
 		zfcp_dbf_out(p, "data_direction", "0x%04x", r->u.fcp.data_dir);
 		zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd);
-		zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial);
 		*p += sprintf(*p, "\n");
 		break;
 
@@ -482,7 +480,7 @@
 		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);
+		zfcp_dbf_out(&p, "lun_status", "0x%08x", r->u.trigger.ls);
 		break;
 	case ZFCP_REC_DBF_ID_ACTION:
 		zfcp_dbf_out(&p, "erp_action", "0x%016Lx", r->u.action.action);
@@ -600,19 +598,20 @@
 }
 
 /**
- * zfcp_dbf_rec_unit - trace event for unit state change
+ * zfcp_dbf_rec_lun - trace event for LUN state change
  * @id: identifier for trigger of state change
  * @ref: additional reference (e.g. request)
- * @unit: unit
+ * @sdev: SCSI device
  */
-void zfcp_dbf_rec_unit(char *id, void *ref, struct zfcp_unit *unit)
+void zfcp_dbf_rec_lun(char *id, void *ref, struct scsi_device *sdev)
 {
-	struct zfcp_port *port = unit->port;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_port *port = zfcp_sdev->port;
 	struct zfcp_dbf *dbf = port->adapter->dbf;
 
-	zfcp_dbf_rec_target(id, ref, dbf, &unit->status,
-				  &unit->erp_counter, port->wwpn, port->d_id,
-				  unit->fcp_lun);
+	zfcp_dbf_rec_target(id, ref, dbf, &zfcp_sdev->status,
+			    &zfcp_sdev->erp_counter, port->wwpn, port->d_id,
+			    zfcp_scsi_dev_lun(sdev));
 }
 
 /**
@@ -624,11 +623,11 @@
  * @action: address of error recovery action struct
  * @adapter: adapter
  * @port: port
- * @unit: unit
+ * @sdev: SCSI device
  */
 void zfcp_dbf_rec_trigger(char *id2, void *ref, u8 want, u8 need, void *action,
 			  struct zfcp_adapter *adapter, struct zfcp_port *port,
-			  struct zfcp_unit *unit)
+			  struct scsi_device *sdev)
 {
 	struct zfcp_dbf *dbf = adapter->dbf;
 	struct zfcp_dbf_rec_record *r = &dbf->rec_buf;
@@ -647,9 +646,10 @@
 		r->u.trigger.ps = atomic_read(&port->status);
 		r->u.trigger.wwpn = port->wwpn;
 	}
-	if (unit)
-		r->u.trigger.us = atomic_read(&unit->status);
-	r->u.trigger.fcp_lun = unit ? unit->fcp_lun : ZFCP_DBF_INVALID_LUN;
+	if (sdev)
+		r->u.trigger.ls = atomic_read(&sdev_to_zfcp(sdev)->status);
+	r->u.trigger.fcp_lun = sdev ? zfcp_scsi_dev_lun(sdev) :
+				      ZFCP_DBF_INVALID_LUN;
 	debug_event(dbf->rec, action ? 1 : 4, r, sizeof(*r));
 	spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
@@ -879,7 +879,6 @@
 				}
 				rec->scsi_result = scsi_cmnd->result;
 				rec->scsi_cmnd = (unsigned long)scsi_cmnd;
-				rec->scsi_serial = scsi_cmnd->serial_number;
 				memcpy(rec->scsi_opcode, scsi_cmnd->cmnd,
 					min((int)scsi_cmnd->cmd_len,
 						ZFCP_DBF_SCSI_OPCODE));
@@ -948,7 +947,6 @@
 	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);
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 2bcc340..04081b1 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -60,7 +60,7 @@
 	u8 need;
 	u32 as;
 	u32 ps;
-	u32 us;
+	u32 ls;
 	u64 ref;
 	u64 action;
 	u64 wwpn;
@@ -110,7 +110,6 @@
 	union {
 		struct {
 			u64 cmnd;
-			u64 serial;
 			u32 data_dir;
 		} fcp;
 		struct {
@@ -206,7 +205,6 @@
 	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;
@@ -350,16 +348,16 @@
 /**
  * zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset
  * @tag: tag indicating success or failure of reset operation
+ * @scmnd: SCSI command which caused this error recovery
  * @flag: indicates type of reset (Target Reset, Logical Unit Reset)
- * @unit: unit that needs reset
- * @scsi_cmnd: SCSI command which caused this error recovery
  */
 static inline
-void zfcp_dbf_scsi_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
-			    struct scsi_cmnd *scsi_cmnd)
+void zfcp_dbf_scsi_devreset(const char *tag, struct scsi_cmnd *scmnd, u8 flag)
 {
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
+
 	zfcp_dbf_scsi(flag == FCP_TMF_TGT_RESET ? "trst" : "lrst", tag, 1,
-			    unit->port->adapter->dbf, scsi_cmnd, NULL, 0);
+		      zfcp_sdev->port->adapter->dbf, scmnd, NULL, 0);
 }
 
 #endif /* ZFCP_DBF_H */
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index e1c6b6e..9ae1d0a 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -85,8 +85,8 @@
 #define ZFCP_STATUS_PORT_LINK_TEST		0x00000002
 
 /* logical unit status */
-#define ZFCP_STATUS_UNIT_SHARED			0x00000004
-#define ZFCP_STATUS_UNIT_READONLY		0x00000008
+#define ZFCP_STATUS_LUN_SHARED			0x00000004
+#define ZFCP_STATUS_LUN_READONLY		0x00000008
 
 /* FSF request status (this does not have a common part) */
 #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT	0x00000002
@@ -118,7 +118,7 @@
 	int action;	              /* requested action code */
 	struct zfcp_adapter *adapter; /* device which should be recovered */
 	struct zfcp_port *port;
-	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
 	u32		status;	      /* recovery status */
 	u32 step;	              /* active step of this erp action */
 	unsigned long		fsf_req_id;
@@ -219,21 +219,66 @@
 	unsigned int		starget_id;
 };
 
+/**
+ * struct zfcp_unit - LUN configured via zfcp sysfs
+ * @dev: struct device for sysfs representation and reference counting
+ * @list: entry in LUN/unit list per zfcp_port
+ * @port: reference to zfcp_port where this LUN is configured
+ * @fcp_lun: 64 bit LUN value
+ * @scsi_work: for running scsi_scan_target
+ *
+ * This is the representation of a LUN that has been configured for
+ * usage. The main data here is the 64 bit LUN value, data for
+ * running I/O and recovery is in struct zfcp_scsi_dev.
+ */
 struct zfcp_unit {
-	struct device          dev;
-	struct list_head       list;	       /* list of logical units */
-	struct zfcp_port       *port;	       /* remote port of unit */
-	atomic_t	       status;	       /* status of this logical unit */
-	u64		       fcp_lun;	       /* own FCP_LUN */
-	u32		       handle;	       /* handle assigned by FSF */
-        struct scsi_device     *device;        /* scsi device struct pointer */
-	struct zfcp_erp_action erp_action;     /* pending error recovery */
-        atomic_t               erp_counter;
-	struct zfcp_latencies	latencies;
+	struct device		dev;
+	struct list_head	list;
+	struct zfcp_port	*port;
+	u64			fcp_lun;
 	struct work_struct	scsi_work;
 };
 
 /**
+ * struct zfcp_scsi_dev - zfcp data per SCSI device
+ * @status: zfcp internal status flags
+ * @lun_handle: handle from "open lun" for issuing FSF requests
+ * @erp_action: zfcp erp data for opening and recovering this LUN
+ * @erp_counter: zfcp erp counter for this LUN
+ * @latencies: FSF channel and fabric latencies
+ * @port: zfcp_port where this LUN belongs to
+ */
+struct zfcp_scsi_dev {
+	atomic_t		status;
+	u32			lun_handle;
+	struct zfcp_erp_action	erp_action;
+	atomic_t		erp_counter;
+	struct zfcp_latencies	latencies;
+	struct zfcp_port	*port;
+};
+
+/**
+ * sdev_to_zfcp - Access zfcp LUN data for SCSI device
+ * @sdev: scsi_device where to get the zfcp_scsi_dev pointer
+ */
+static inline struct zfcp_scsi_dev *sdev_to_zfcp(struct scsi_device *sdev)
+{
+	return scsi_transport_device_data(sdev);
+}
+
+/**
+ * zfcp_scsi_dev_lun - Return SCSI device LUN as 64 bit FCP LUN
+ * @sdev: SCSI device where to get the LUN from
+ */
+static inline u64 zfcp_scsi_dev_lun(struct scsi_device *sdev)
+{
+	u64 fcp_lun;
+
+	int_to_scsilun(sdev->lun, (struct scsi_lun *)&fcp_lun);
+	return fcp_lun;
+}
+
+/**
  * struct zfcp_fsf_req - basic FSF request structure
  * @list: list of FSF requests
  * @req_id: unique request ID
@@ -249,7 +294,6 @@
  * @erp_action: reference to erp action if request issued on behalf of ERP
  * @pool: reference to memory pool if used for this request
  * @issued: time when request was send (STCK)
- * @unit: reference to unit if this request is a SCSI request
  * @handler: handler which should be called to process response
  */
 struct zfcp_fsf_req {
@@ -267,7 +311,6 @@
 	struct zfcp_erp_action	*erp_action;
 	mempool_t		*pool;
 	unsigned long long	issued;
-	struct zfcp_unit	*unit;
 	void			(*handler)(struct zfcp_fsf_req *);
 };
 
@@ -282,9 +325,4 @@
 	struct kmem_cache	*adisc_cache;
 };
 
-/********************** ZFCP SPECIFIC DEFINES ********************************/
-
-#define ZFCP_SET                0x00000100
-#define ZFCP_CLEAR              0x00000200
-
 #endif /* ZFCP_DEF_H */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 160b432..d37c733 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -21,6 +21,7 @@
 	ZFCP_STATUS_ERP_DISMISSING	= 0x00100000,
 	ZFCP_STATUS_ERP_DISMISSED	= 0x00200000,
 	ZFCP_STATUS_ERP_LOWMEM		= 0x00400000,
+	ZFCP_STATUS_ERP_NO_REF		= 0x00800000,
 };
 
 enum zfcp_erp_steps {
@@ -29,12 +30,12 @@
 	ZFCP_ERP_STEP_PHYS_PORT_CLOSING	= 0x0010,
 	ZFCP_ERP_STEP_PORT_CLOSING	= 0x0100,
 	ZFCP_ERP_STEP_PORT_OPENING	= 0x0800,
-	ZFCP_ERP_STEP_UNIT_CLOSING	= 0x1000,
-	ZFCP_ERP_STEP_UNIT_OPENING	= 0x2000,
+	ZFCP_ERP_STEP_LUN_CLOSING	= 0x1000,
+	ZFCP_ERP_STEP_LUN_OPENING	= 0x2000,
 };
 
 enum zfcp_erp_act_type {
-	ZFCP_ERP_ACTION_REOPEN_UNIT        = 1,
+	ZFCP_ERP_ACTION_REOPEN_LUN         = 1,
 	ZFCP_ERP_ACTION_REOPEN_PORT	   = 2,
 	ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3,
 	ZFCP_ERP_ACTION_REOPEN_ADAPTER     = 4,
@@ -56,9 +57,8 @@
 
 static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask)
 {
-	zfcp_erp_modify_adapter_status(adapter, "erablk1", NULL,
-				       ZFCP_STATUS_COMMON_UNBLOCKED | mask,
-				       ZFCP_CLEAR);
+	zfcp_erp_clear_adapter_status(adapter,
+				       ZFCP_STATUS_COMMON_UNBLOCKED | mask);
 }
 
 static int zfcp_erp_action_exists(struct zfcp_erp_action *act)
@@ -88,24 +88,24 @@
 		zfcp_erp_action_ready(act);
 }
 
-static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
+static void zfcp_erp_action_dismiss_lun(struct scsi_device *sdev)
 {
-	if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
-		zfcp_erp_action_dismiss(&unit->erp_action);
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
+		zfcp_erp_action_dismiss(&zfcp_sdev->erp_action);
 }
 
 static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 {
-	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
 
 	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
 		zfcp_erp_action_dismiss(&port->erp_action);
-	else {
-		read_lock(&port->unit_list_lock);
-		list_for_each_entry(unit, &port->unit_list, list)
-			zfcp_erp_action_dismiss_unit(unit);
-		read_unlock(&port->unit_list_lock);
-	}
+	else
+		shost_for_each_device(sdev, port->adapter->scsi_host)
+			if (sdev_to_zfcp(sdev)->port == port)
+				zfcp_erp_action_dismiss_lun(sdev);
 }
 
 static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
@@ -124,15 +124,17 @@
 
 static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
 				 struct zfcp_port *port,
-				 struct zfcp_unit *unit)
+				 struct scsi_device *sdev)
 {
 	int need = want;
-	int u_status, p_status, a_status;
+	int l_status, p_status, a_status;
+	struct zfcp_scsi_dev *zfcp_sdev;
 
 	switch (want) {
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		u_status = atomic_read(&unit->status);
-		if (u_status & ZFCP_STATUS_COMMON_ERP_INUSE)
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		l_status = atomic_read(&zfcp_sdev->status);
+		if (l_status & ZFCP_STATUS_COMMON_ERP_INUSE)
 			return 0;
 		p_status = atomic_read(&port->status);
 		if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) ||
@@ -169,22 +171,26 @@
 	return need;
 }
 
-static struct zfcp_erp_action *zfcp_erp_setup_act(int need,
+static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
 						  struct zfcp_adapter *adapter,
 						  struct zfcp_port *port,
-						  struct zfcp_unit *unit)
+						  struct scsi_device *sdev)
 {
 	struct zfcp_erp_action *erp_action;
-	u32 status = 0;
+	struct zfcp_scsi_dev *zfcp_sdev;
 
 	switch (need) {
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		if (!get_device(&unit->dev))
-			return NULL;
-		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status);
-		erp_action = &unit->erp_action;
-		if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING))
-			status = ZFCP_STATUS_ERP_CLOSE_ONLY;
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		if (!(act_status & ZFCP_STATUS_ERP_NO_REF))
+			if (scsi_device_get(sdev))
+				return NULL;
+		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
+				&zfcp_sdev->status);
+		erp_action = &zfcp_sdev->erp_action;
+		if (!(atomic_read(&zfcp_sdev->status) &
+		      ZFCP_STATUS_COMMON_RUNNING))
+			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
@@ -195,7 +201,7 @@
 		atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
 		erp_action = &port->erp_action;
 		if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
-			status = ZFCP_STATUS_ERP_CLOSE_ONLY;
+			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
@@ -205,7 +211,7 @@
 		erp_action = &adapter->erp_action;
 		if (!(atomic_read(&adapter->status) &
 		      ZFCP_STATUS_COMMON_RUNNING))
-			status = ZFCP_STATUS_ERP_CLOSE_ONLY;
+			act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
 		break;
 
 	default:
@@ -215,16 +221,17 @@
 	memset(erp_action, 0, sizeof(struct zfcp_erp_action));
 	erp_action->adapter = adapter;
 	erp_action->port = port;
-	erp_action->unit = unit;
+	erp_action->sdev = sdev;
 	erp_action->action = need;
-	erp_action->status = status;
+	erp_action->status = act_status;
 
 	return erp_action;
 }
 
 static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
 				   struct zfcp_port *port,
-				   struct zfcp_unit *unit, char *id, void *ref)
+				   struct scsi_device *sdev,
+				   char *id, void *ref, u32 act_status)
 {
 	int retval = 1, need;
 	struct zfcp_erp_action *act = NULL;
@@ -232,21 +239,21 @@
 	if (!adapter->erp_thread)
 		return -EIO;
 
-	need = zfcp_erp_required_act(want, adapter, port, unit);
+	need = zfcp_erp_required_act(want, adapter, port, sdev);
 	if (!need)
 		goto out;
 
-	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
-	act = zfcp_erp_setup_act(need, adapter, port, unit);
+	act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev);
 	if (!act)
 		goto out;
+	atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
 	++adapter->erp_total_count;
 	list_add_tail(&act->list, &adapter->erp_ready_head);
 	wake_up(&adapter->erp_ready_wq);
 	zfcp_dbf_rec_thread("eracte1", adapter->dbf);
 	retval = 0;
  out:
-	zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, unit);
+	zfcp_dbf_rec_trigger(id, ref, want, need, act, adapter, port, sdev);
 	return retval;
 }
 
@@ -258,11 +265,12 @@
 
 	/* ensure propagation of failed status to new devices */
 	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
-		zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_ERP_FAILED);
 		return -EIO;
 	}
 	return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
-				       adapter, NULL, NULL, id, ref);
+				       adapter, NULL, NULL, id, ref, 0);
 }
 
 /**
@@ -282,10 +290,11 @@
 
 	write_lock_irqsave(&adapter->erp_lock, flags);
 	if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
-		zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_ERP_FAILED);
 	else
 		zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
-					NULL, NULL, id, ref);
+					NULL, NULL, id, ref, 0);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
@@ -317,25 +326,10 @@
 	zfcp_erp_port_reopen(port, clear | flags, id, ref);
 }
 
-/**
- * zfcp_erp_unit_shutdown - Shutdown unit
- * @unit: Unit to shut down.
- * @clear: Status flags to clear.
- * @id: Id for debug trace event.
- * @ref: Reference for debug trace event.
- */
-void zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear, char *id,
-			    void *ref)
-{
-	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
-	zfcp_erp_unit_reopen(unit, clear | flags, id, ref);
-}
-
 static void zfcp_erp_port_block(struct zfcp_port *port, int clear)
 {
-	zfcp_erp_modify_port_status(port, "erpblk1", NULL,
-				    ZFCP_STATUS_COMMON_UNBLOCKED | clear,
-				    ZFCP_CLEAR);
+	zfcp_erp_clear_port_status(port,
+				    ZFCP_STATUS_COMMON_UNBLOCKED | clear);
 }
 
 static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port,
@@ -348,7 +342,7 @@
 		return;
 
 	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
-				port->adapter, port, NULL, id, ref);
+				port->adapter, port, NULL, id, ref, 0);
 }
 
 /**
@@ -376,12 +370,12 @@
 
 	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
 		/* ensure propagation of failed status to new devices */
-		zfcp_erp_port_failed(port, "erpreo1", NULL);
+		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
 		return -EIO;
 	}
 
 	return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
-				       port->adapter, port, NULL, id, ref);
+				       port->adapter, port, NULL, id, ref, 0);
 }
 
 /**
@@ -404,55 +398,90 @@
 	return retval;
 }
 
-static void zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask)
+static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask)
 {
-	zfcp_erp_modify_unit_status(unit, "erublk1", NULL,
-				    ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask,
-				    ZFCP_CLEAR);
+	zfcp_erp_clear_lun_status(sdev,
+				  ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask);
 }
 
-static void _zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
-				  void *ref)
+static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
+				 void *ref, u32 act_status)
 {
-	struct zfcp_adapter *adapter = unit->port->adapter;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 
-	zfcp_erp_unit_block(unit, clear);
+	zfcp_erp_lun_block(sdev, clear);
 
-	if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
 		return;
 
-	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_UNIT,
-				adapter, unit->port, unit, id, ref);
+	zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter,
+				zfcp_sdev->port, sdev, id, ref, act_status);
 }
 
 /**
- * zfcp_erp_unit_reopen - initiate reopen of a unit
- * @unit: unit to be reopened
- * @clear_mask: specifies flags in unit status to be cleared
+ * zfcp_erp_lun_reopen - initiate reopen of a LUN
+ * @sdev: SCSI device / LUN to be reopened
+ * @clear_mask: specifies flags in LUN status to be cleared
  * Return: 0 on success, < 0 on error
  */
-void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
-			  void *ref)
+void zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
+			 void *ref)
 {
 	unsigned long flags;
-	struct zfcp_port *port = unit->port;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_port *port = zfcp_sdev->port;
 	struct zfcp_adapter *adapter = port->adapter;
 
 	write_lock_irqsave(&adapter->erp_lock, flags);
-	_zfcp_erp_unit_reopen(unit, clear, id, ref);
+	_zfcp_erp_lun_reopen(sdev, clear, id, ref, 0);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
 }
 
+/**
+ * zfcp_erp_lun_shutdown - Shutdown LUN
+ * @sdev: SCSI device / LUN to shut down.
+ * @clear: Status flags to clear.
+ * @id: Id for debug trace event.
+ * @ref: Reference for debug trace event.
+ */
+void zfcp_erp_lun_shutdown(struct scsi_device *sdev, int clear, char *id,
+			   void *ref)
+{
+	int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
+	zfcp_erp_lun_reopen(sdev, clear | flags, id, ref);
+}
+
+/**
+ * zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion
+ * @sdev: SCSI device / LUN to shut down.
+ * @id: Id for debug trace event.
+ *
+ * Do not acquire a reference for the LUN when creating the ERP
+ * action. It is safe, because this function waits for the ERP to
+ * complete first. This allows to shutdown the LUN, even when the SCSI
+ * device is in the state SDEV_DEL when scsi_device_get will fail.
+ */
+void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id)
+{
+	unsigned long flags;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_port *port = zfcp_sdev->port;
+	struct zfcp_adapter *adapter = port->adapter;
+	int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED;
+
+	write_lock_irqsave(&adapter->erp_lock, flags);
+	_zfcp_erp_lun_reopen(sdev, clear, id, NULL, ZFCP_STATUS_ERP_NO_REF);
+	write_unlock_irqrestore(&adapter->erp_lock, flags);
+
+	zfcp_erp_wait(adapter);
+}
+
 static int status_change_set(unsigned long mask, atomic_t *status)
 {
 	return (atomic_read(status) ^ mask) & mask;
 }
 
-static int status_change_clear(unsigned long mask, atomic_t *status)
-{
-	return atomic_read(status) & mask;
-}
-
 static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
 {
 	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
@@ -467,11 +496,13 @@
 	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
 }
 
-static void zfcp_erp_unit_unblock(struct zfcp_unit *unit)
+static void zfcp_erp_lun_unblock(struct scsi_device *sdev)
 {
-	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))
-		zfcp_dbf_rec_unit("eruubl1", NULL, unit);
-	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status))
+		zfcp_dbf_rec_lun("erlubl1", NULL, sdev);
+	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
 }
 
 static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
@@ -559,15 +590,14 @@
 	read_unlock(&adapter->port_list_lock);
 }
 
-static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
-				      char *id, void *ref)
+static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear,
+				     char *id, void *ref)
 {
-	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
 
-	read_lock(&port->unit_list_lock);
-	list_for_each_entry(unit, &port->unit_list, list)
-		_zfcp_erp_unit_reopen(unit, clear, id, ref);
-	read_unlock(&port->unit_list_lock);
+	shost_for_each_device(sdev, port->adapter->scsi_host)
+		if (sdev_to_zfcp(sdev)->port == port)
+			_zfcp_erp_lun_reopen(sdev, clear, id, ref, 0);
 }
 
 static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
@@ -582,8 +612,8 @@
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
 		_zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL);
 		break;
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		_zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		_zfcp_erp_lun_reopen(act->sdev, 0, "ersff_4", NULL, 0);
 		break;
 	}
 }
@@ -598,7 +628,7 @@
 		_zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL);
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
-		_zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL);
+		_zfcp_erp_lun_reopen_all(act->port, 0, "ersfs_3", NULL);
 		break;
 	}
 }
@@ -742,9 +772,8 @@
 	zfcp_fsf_req_dismiss_all(adapter);
 	adapter->fsf_req_seq_no = 0;
 	zfcp_fc_wka_ports_force_offline(adapter->gs);
-	/* all ports and units are closed */
-	zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
-				       ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
+	/* all ports and LUNs are closed */
+	zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN);
 
 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
 			  ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
@@ -861,7 +890,7 @@
 	struct zfcp_port *port = act->port;
 
 	if (port->wwpn != adapter->peer_wwpn) {
-		zfcp_erp_port_failed(port, "eroptp1", NULL);
+		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
 		return ZFCP_ERP_FAILED;
 	}
 	port->d_id = adapter->peer_d_id;
@@ -933,82 +962,87 @@
 	return zfcp_erp_port_strategy_open_common(erp_action);
 }
 
-static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
+static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev)
 {
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
 	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
-			  ZFCP_STATUS_UNIT_SHARED |
-			  ZFCP_STATUS_UNIT_READONLY,
-			  &unit->status);
+			  ZFCP_STATUS_LUN_SHARED | ZFCP_STATUS_LUN_READONLY,
+			  &zfcp_sdev->status);
 }
 
-static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
+static int zfcp_erp_lun_strategy_close(struct zfcp_erp_action *erp_action)
 {
-	int retval = zfcp_fsf_close_unit(erp_action);
+	int retval = zfcp_fsf_close_lun(erp_action);
 	if (retval == -ENOMEM)
 		return ZFCP_ERP_NOMEM;
-	erp_action->step = ZFCP_ERP_STEP_UNIT_CLOSING;
+	erp_action->step = ZFCP_ERP_STEP_LUN_CLOSING;
 	if (retval)
 		return ZFCP_ERP_FAILED;
 	return ZFCP_ERP_CONTINUES;
 }
 
-static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
+static int zfcp_erp_lun_strategy_open(struct zfcp_erp_action *erp_action)
 {
-	int retval = zfcp_fsf_open_unit(erp_action);
+	int retval = zfcp_fsf_open_lun(erp_action);
 	if (retval == -ENOMEM)
 		return ZFCP_ERP_NOMEM;
-	erp_action->step = ZFCP_ERP_STEP_UNIT_OPENING;
+	erp_action->step = ZFCP_ERP_STEP_LUN_OPENING;
 	if (retval)
 		return  ZFCP_ERP_FAILED;
 	return ZFCP_ERP_CONTINUES;
 }
 
-static int zfcp_erp_unit_strategy(struct zfcp_erp_action *erp_action)
+static int zfcp_erp_lun_strategy(struct zfcp_erp_action *erp_action)
 {
-	struct zfcp_unit *unit = erp_action->unit;
+	struct scsi_device *sdev = erp_action->sdev;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 
 	switch (erp_action->step) {
 	case ZFCP_ERP_STEP_UNINITIALIZED:
-		zfcp_erp_unit_strategy_clearstati(unit);
-		if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
-			return zfcp_erp_unit_strategy_close(erp_action);
+		zfcp_erp_lun_strategy_clearstati(sdev);
+		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
+			return zfcp_erp_lun_strategy_close(erp_action);
 		/* already closed, fall through */
-	case ZFCP_ERP_STEP_UNIT_CLOSING:
-		if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
+	case ZFCP_ERP_STEP_LUN_CLOSING:
+		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
 			return ZFCP_ERP_FAILED;
 		if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
 			return ZFCP_ERP_EXIT;
-		return zfcp_erp_unit_strategy_open(erp_action);
+		return zfcp_erp_lun_strategy_open(erp_action);
 
-	case ZFCP_ERP_STEP_UNIT_OPENING:
-		if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_OPEN)
+	case ZFCP_ERP_STEP_LUN_OPENING:
+		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
 			return ZFCP_ERP_SUCCEEDED;
 	}
 	return ZFCP_ERP_FAILED;
 }
 
-static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
+static int zfcp_erp_strategy_check_lun(struct scsi_device *sdev, int result)
 {
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
 	switch (result) {
 	case ZFCP_ERP_SUCCEEDED :
-		atomic_set(&unit->erp_counter, 0);
-		zfcp_erp_unit_unblock(unit);
+		atomic_set(&zfcp_sdev->erp_counter, 0);
+		zfcp_erp_lun_unblock(sdev);
 		break;
 	case ZFCP_ERP_FAILED :
-		atomic_inc(&unit->erp_counter);
-		if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) {
-			dev_err(&unit->port->adapter->ccw_device->dev,
-				"ERP failed for unit 0x%016Lx on "
+		atomic_inc(&zfcp_sdev->erp_counter);
+		if (atomic_read(&zfcp_sdev->erp_counter) > ZFCP_MAX_ERPS) {
+			dev_err(&zfcp_sdev->port->adapter->ccw_device->dev,
+				"ERP failed for LUN 0x%016Lx on "
 				"port 0x%016Lx\n",
-				(unsigned long long)unit->fcp_lun,
-				(unsigned long long)unit->port->wwpn);
-			zfcp_erp_unit_failed(unit, "erusck1", NULL);
+				(unsigned long long)zfcp_scsi_dev_lun(sdev),
+				(unsigned long long)zfcp_sdev->port->wwpn);
+			zfcp_erp_set_lun_status(sdev,
+						ZFCP_STATUS_COMMON_ERP_FAILED);
 		}
 		break;
 	}
 
-	if (atomic_read(&unit->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
-		zfcp_erp_unit_block(unit, 0);
+	if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
+		zfcp_erp_lun_block(sdev, 0);
 		result = ZFCP_ERP_EXIT;
 	}
 	return result;
@@ -1032,7 +1066,8 @@
 			dev_err(&port->adapter->ccw_device->dev,
 				"ERP failed for remote port 0x%016Lx\n",
 				(unsigned long long)port->wwpn);
-			zfcp_erp_port_failed(port, "erpsck1", NULL);
+			zfcp_erp_set_port_status(port,
+					 ZFCP_STATUS_COMMON_ERP_FAILED);
 		}
 		break;
 	}
@@ -1059,7 +1094,8 @@
 			dev_err(&adapter->ccw_device->dev,
 				"ERP cannot recover an error "
 				"on the FCP device\n");
-			zfcp_erp_adapter_failed(adapter, "erasck1", NULL);
+			zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_ERP_FAILED);
 		}
 		break;
 	}
@@ -1076,12 +1112,12 @@
 {
 	struct zfcp_adapter *adapter = erp_action->adapter;
 	struct zfcp_port *port = erp_action->port;
-	struct zfcp_unit *unit = erp_action->unit;
+	struct scsi_device *sdev = erp_action->sdev;
 
 	switch (erp_action->action) {
 
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		result = zfcp_erp_strategy_check_unit(unit, result);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		result = zfcp_erp_strategy_check_lun(sdev, result);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
@@ -1116,7 +1152,8 @@
 	int action = act->action;
 	struct zfcp_adapter *adapter = act->adapter;
 	struct zfcp_port *port = act->port;
-	struct zfcp_unit *unit = act->unit;
+	struct scsi_device *sdev = act->sdev;
+	struct zfcp_scsi_dev *zfcp_sdev;
 	u32 erp_status = act->status;
 
 	switch (action) {
@@ -1139,11 +1176,12 @@
 		}
 		break;
 
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		if (zfcp_erp_strat_change_det(&unit->status, erp_status)) {
-			_zfcp_erp_unit_reopen(unit,
-					      ZFCP_STATUS_COMMON_ERP_FAILED,
-					      "ersscg3", NULL);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		if (zfcp_erp_strat_change_det(&zfcp_sdev->status, erp_status)) {
+			_zfcp_erp_lun_reopen(sdev,
+					     ZFCP_STATUS_COMMON_ERP_FAILED,
+					     "ersscg3", NULL, 0);
 			return ZFCP_ERP_EXIT;
 		}
 		break;
@@ -1154,6 +1192,7 @@
 static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
 {
 	struct zfcp_adapter *adapter = erp_action->adapter;
+	struct zfcp_scsi_dev *zfcp_sdev;
 
 	adapter->erp_total_count--;
 	if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) {
@@ -1165,9 +1204,10 @@
 	zfcp_dbf_rec_action("eractd1", erp_action);
 
 	switch (erp_action->action) {
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
 		atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
-				  &erp_action->unit->status);
+				  &zfcp_sdev->status);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
@@ -1187,11 +1227,12 @@
 {
 	struct zfcp_adapter *adapter = act->adapter;
 	struct zfcp_port *port = act->port;
-	struct zfcp_unit *unit = act->unit;
+	struct scsi_device *sdev = act->sdev;
 
 	switch (act->action) {
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		put_device(&unit->dev);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
+			scsi_device_put(sdev);
 		break;
 
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
@@ -1222,8 +1263,8 @@
 		return zfcp_erp_port_forced_strategy(erp_action);
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
 		return zfcp_erp_port_strategy(erp_action);
-	case ZFCP_ERP_ACTION_REOPEN_UNIT:
-		return zfcp_erp_unit_strategy(erp_action);
+	case ZFCP_ERP_ACTION_REOPEN_LUN:
+		return zfcp_erp_lun_strategy(erp_action);
 	}
 	return ZFCP_ERP_FAILED;
 }
@@ -1376,42 +1417,6 @@
 }
 
 /**
- * zfcp_erp_adapter_failed - Set adapter status to failed.
- * @adapter: Failed adapter.
- * @id: Event id for debug trace.
- * @ref: Reference for debug trace.
- */
-void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, char *id, void *ref)
-{
-	zfcp_erp_modify_adapter_status(adapter, id, ref,
-				       ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-}
-
-/**
- * zfcp_erp_port_failed - Set port status to failed.
- * @port: Failed port.
- * @id: Event id for debug trace.
- * @ref: Reference for debug trace.
- */
-void zfcp_erp_port_failed(struct zfcp_port *port, char *id, void *ref)
-{
-	zfcp_erp_modify_port_status(port, id, ref,
-				    ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-}
-
-/**
- * zfcp_erp_unit_failed - Set unit status to failed.
- * @unit: Failed unit.
- * @id: Event id for debug trace.
- * @ref: Reference for debug trace.
- */
-void zfcp_erp_unit_failed(struct zfcp_unit *unit, char *id, void *ref)
-{
-	zfcp_erp_modify_unit_status(unit, id, ref,
-				    ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-}
-
-/**
  * zfcp_erp_wait - wait for completion of error recovery on an adapter
  * @adapter: adapter for which to wait for completion of its error recovery
  */
@@ -1423,210 +1428,148 @@
 }
 
 /**
- * zfcp_erp_modify_adapter_status - change adapter status bits
+ * zfcp_erp_set_adapter_status - set adapter status bits
  * @adapter: adapter to change the status
- * @id: id for the debug trace
- * @ref: reference for the debug trace
  * @mask: status bits to change
- * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
  *
- * Changes in common status bits are propagated to attached ports and units.
+ * Changes in common status bits are propagated to attached ports and LUNs.
  */
-void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
-				    void *ref, u32 mask, int set_or_clear)
+void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask)
 {
 	struct zfcp_port *port;
+	struct scsi_device *sdev;
 	unsigned long flags;
 	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
 
-	if (set_or_clear == ZFCP_SET) {
-		if (status_change_set(mask, &adapter->status))
-			zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
-		atomic_set_mask(mask, &adapter->status);
-	} else {
-		if (status_change_clear(mask, &adapter->status))
-			zfcp_dbf_rec_adapter(id, ref, adapter->dbf);
-		atomic_clear_mask(mask, &adapter->status);
-		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
-			atomic_set(&adapter->erp_counter, 0);
-	}
+	atomic_set_mask(mask, &adapter->status);
 
-	if (common_mask) {
-		read_lock_irqsave(&adapter->port_list_lock, flags);
-		list_for_each_entry(port, &adapter->port_list, list)
-			zfcp_erp_modify_port_status(port, id, ref, common_mask,
-						    set_or_clear);
-		read_unlock_irqrestore(&adapter->port_list_lock, flags);
-	}
-}
-
-/**
- * zfcp_erp_modify_port_status - change port status bits
- * @port: port to change the status bits
- * @id: id for the debug trace
- * @ref: reference for the debug trace
- * @mask: status bits to change
- * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
- *
- * Changes in common status bits are propagated to attached units.
- */
-void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
-				 u32 mask, int set_or_clear)
-{
-	struct zfcp_unit *unit;
-	unsigned long flags;
-	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
-
-	if (set_or_clear == ZFCP_SET) {
-		if (status_change_set(mask, &port->status))
-			zfcp_dbf_rec_port(id, ref, port);
-		atomic_set_mask(mask, &port->status);
-	} else {
-		if (status_change_clear(mask, &port->status))
-			zfcp_dbf_rec_port(id, ref, port);
-		atomic_clear_mask(mask, &port->status);
-		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
-			atomic_set(&port->erp_counter, 0);
-	}
-
-	if (common_mask) {
-		read_lock_irqsave(&port->unit_list_lock, flags);
-		list_for_each_entry(unit, &port->unit_list, list)
-			zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
-						    set_or_clear);
-		read_unlock_irqrestore(&port->unit_list_lock, flags);
-	}
-}
-
-/**
- * zfcp_erp_modify_unit_status - change unit status bits
- * @unit: unit to change the status bits
- * @id: id for the debug trace
- * @ref: reference for the debug trace
- * @mask: status bits to change
- * @set_or_clear: ZFCP_SET or ZFCP_CLEAR
- */
-void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref,
-				 u32 mask, int set_or_clear)
-{
-	if (set_or_clear == ZFCP_SET) {
-		if (status_change_set(mask, &unit->status))
-			zfcp_dbf_rec_unit(id, ref, unit);
-		atomic_set_mask(mask, &unit->status);
-	} else {
-		if (status_change_clear(mask, &unit->status))
-			zfcp_dbf_rec_unit(id, ref, unit);
-		atomic_clear_mask(mask, &unit->status);
-		if (mask & ZFCP_STATUS_COMMON_ERP_FAILED) {
-			atomic_set(&unit->erp_counter, 0);
-		}
-	}
-}
-
-/**
- * zfcp_erp_port_boxed - Mark port as "boxed" and start ERP
- * @port: The "boxed" port.
- * @id: The debug trace id.
- * @id: Reference for the debug trace.
- */
-void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref)
-{
-	zfcp_erp_modify_port_status(port, id, ref,
-				    ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
-	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
-}
-
-/**
- * zfcp_erp_unit_boxed - Mark unit as "boxed" and start ERP
- * @port: The "boxed" unit.
- * @id: The debug trace id.
- * @id: Reference for the debug trace.
- */
-void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref)
-{
-	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);
-}
-
-/**
- * zfcp_erp_port_access_denied - Adapter denied access to port.
- * @port: port where access has been denied
- * @id: id for debug trace
- * @ref: reference for debug trace
- *
- * Since the adapter has denied access, stop using the port and the
- * attached units.
- */
-void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref)
-{
-	zfcp_erp_modify_port_status(port, id, ref,
-				    ZFCP_STATUS_COMMON_ERP_FAILED |
-				    ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
-}
-
-/**
- * zfcp_erp_unit_access_denied - Adapter denied access to unit.
- * @unit: unit where access has been denied
- * @id: id for debug trace
- * @ref: reference for debug trace
- *
- * Since the adapter has denied access, stop using the unit.
- */
-void zfcp_erp_unit_access_denied(struct zfcp_unit *unit, char *id, void *ref)
-{
-	zfcp_erp_modify_unit_status(unit, id, ref,
-				    ZFCP_STATUS_COMMON_ERP_FAILED |
-				    ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
-}
-
-static void zfcp_erp_unit_access_changed(struct zfcp_unit *unit, char *id,
-					 void *ref)
-{
-	int status = atomic_read(&unit->status);
-	if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
-			ZFCP_STATUS_COMMON_ACCESS_BOXED)))
-		return;
-
-	zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
-}
-
-static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id,
-					 void *ref)
-{
-	struct zfcp_unit *unit;
-	unsigned long flags;
-	int status = atomic_read(&port->status);
-
-	if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
-			ZFCP_STATUS_COMMON_ACCESS_BOXED))) {
-		read_lock_irqsave(&port->unit_list_lock, flags);
-		list_for_each_entry(unit, &port->unit_list, list)
-				    zfcp_erp_unit_access_changed(unit, id, ref);
-		read_unlock_irqrestore(&port->unit_list_lock, flags);
-		return;
-	}
-
-	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
-}
-
-/**
- * zfcp_erp_adapter_access_changed - Process change in adapter ACT
- * @adapter: Adapter where the Access Control Table (ACT) changed
- * @id: Id for debug trace
- * @ref: Reference for debug trace
- */
-void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id,
-				     void *ref)
-{
-	unsigned long flags;
-	struct zfcp_port *port;
-
-	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+	if (!common_mask)
 		return;
 
 	read_lock_irqsave(&adapter->port_list_lock, flags);
 	list_for_each_entry(port, &adapter->port_list, list)
-		zfcp_erp_port_access_changed(port, id, ref);
+		atomic_set_mask(common_mask, &port->status);
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
+
+	shost_for_each_device(sdev, adapter->scsi_host)
+		atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
 }
+
+/**
+ * zfcp_erp_clear_adapter_status - clear adapter status bits
+ * @adapter: adapter to change the status
+ * @mask: status bits to change
+ *
+ * Changes in common status bits are propagated to attached ports and LUNs.
+ */
+void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask)
+{
+	struct zfcp_port *port;
+	struct scsi_device *sdev;
+	unsigned long flags;
+	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+	u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
+
+	atomic_clear_mask(mask, &adapter->status);
+
+	if (!common_mask)
+		return;
+
+	if (clear_counter)
+		atomic_set(&adapter->erp_counter, 0);
+
+	read_lock_irqsave(&adapter->port_list_lock, flags);
+	list_for_each_entry(port, &adapter->port_list, list) {
+		atomic_clear_mask(common_mask, &port->status);
+		if (clear_counter)
+			atomic_set(&port->erp_counter, 0);
+	}
+	read_unlock_irqrestore(&adapter->port_list_lock, flags);
+
+	shost_for_each_device(sdev, adapter->scsi_host) {
+		atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status);
+		if (clear_counter)
+			atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
+	}
+}
+
+/**
+ * zfcp_erp_set_port_status - set port status bits
+ * @port: port to change the status
+ * @mask: status bits to change
+ *
+ * Changes in common status bits are propagated to attached LUNs.
+ */
+void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask)
+{
+	struct scsi_device *sdev;
+	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+
+	atomic_set_mask(mask, &port->status);
+
+	if (!common_mask)
+		return;
+
+	shost_for_each_device(sdev, port->adapter->scsi_host)
+		if (sdev_to_zfcp(sdev)->port == port)
+			atomic_set_mask(common_mask,
+					&sdev_to_zfcp(sdev)->status);
+}
+
+/**
+ * zfcp_erp_clear_port_status - clear port status bits
+ * @port: adapter to change the status
+ * @mask: status bits to change
+ *
+ * Changes in common status bits are propagated to attached LUNs.
+ */
+void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask)
+{
+	struct scsi_device *sdev;
+	u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+	u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
+
+	atomic_clear_mask(mask, &port->status);
+
+	if (!common_mask)
+		return;
+
+	if (clear_counter)
+		atomic_set(&port->erp_counter, 0);
+
+	shost_for_each_device(sdev, port->adapter->scsi_host)
+		if (sdev_to_zfcp(sdev)->port == port) {
+			atomic_clear_mask(common_mask,
+					  &sdev_to_zfcp(sdev)->status);
+			if (clear_counter)
+				atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
+		}
+}
+
+/**
+ * zfcp_erp_set_lun_status - set lun status bits
+ * @sdev: SCSI device / lun to set the status bits
+ * @mask: status bits to change
+ */
+void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask)
+{
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	atomic_set_mask(mask, &zfcp_sdev->status);
+}
+
+/**
+ * zfcp_erp_clear_lun_status - clear lun status bits
+ * @sdev: SCSi device / lun to clear the status bits
+ * @mask: status bits to change
+ */
+void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask)
+{
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	atomic_clear_mask(mask, &zfcp_sdev->status);
+
+	if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
+		atomic_set(&zfcp_sdev->erp_counter, 0);
+}
+
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 3b93239..bf8f3e5 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -15,12 +15,10 @@
 #include "zfcp_fc.h"
 
 /* zfcp_aux.c */
-extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64);
 extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64);
 extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
 extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
 					   u32);
-extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
 extern void zfcp_sg_free_table(struct scatterlist *, int);
 extern int zfcp_sg_setup_table(struct scatterlist *, int);
 extern void zfcp_device_unregister(struct device *,
@@ -36,6 +34,14 @@
 
 /* zfcp_cfdc.c */
 extern struct miscdevice zfcp_cfdc_misc;
+extern void zfcp_cfdc_port_denied(struct zfcp_port *, union fsf_status_qual *);
+extern void zfcp_cfdc_lun_denied(struct scsi_device *, union fsf_status_qual *);
+extern void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *,
+				     union fsf_status_qual *);
+extern int zfcp_cfdc_open_lun_eval(struct scsi_device *,
+				   struct fsf_qtcb_bottom_support *);
+extern void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *);
+
 
 /* zfcp_dbf.c */
 extern int zfcp_dbf_adapter_register(struct zfcp_adapter *);
@@ -44,10 +50,10 @@
 extern void zfcp_dbf_rec_thread_lock(char *, struct zfcp_dbf *);
 extern void zfcp_dbf_rec_adapter(char *, void *, struct zfcp_dbf *);
 extern void zfcp_dbf_rec_port(char *, void *, struct zfcp_port *);
-extern void zfcp_dbf_rec_unit(char *, void *, struct zfcp_unit *);
+extern void zfcp_dbf_rec_lun(char *, void *, struct scsi_device *);
 extern void zfcp_dbf_rec_trigger(char *, void *, u8, u8, void *,
 				 struct zfcp_adapter *, struct zfcp_port *,
-				 struct zfcp_unit *);
+				 struct scsi_device *);
 extern void zfcp_dbf_rec_action(char *, struct zfcp_erp_action *);
 extern void _zfcp_dbf_hba_fsf_response(const char *, int, struct zfcp_fsf_req *,
 				       struct zfcp_dbf *);
@@ -65,34 +71,26 @@
 			   unsigned long);
 
 /* zfcp_erp.c */
-extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, char *,
-					   void *, u32, int);
+extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32);
+extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32);
 extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *, void *);
 extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *,
 				      void *);
-extern void zfcp_erp_adapter_failed(struct zfcp_adapter *, char *, void *);
-extern void zfcp_erp_modify_port_status(struct zfcp_port *, char *, void *, u32,
-					int);
+extern void zfcp_erp_set_port_status(struct zfcp_port *, u32);
+extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32);
 extern int  zfcp_erp_port_reopen(struct zfcp_port *, int, char *, void *);
 extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *, void *);
 extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *,
 					void *);
-extern void zfcp_erp_port_failed(struct zfcp_port *, char *, void *);
-extern void zfcp_erp_modify_unit_status(struct zfcp_unit *, char *, void *, u32,
-					int);
-extern void zfcp_erp_unit_reopen(struct zfcp_unit *, int, char *, void *);
-extern void zfcp_erp_unit_shutdown(struct zfcp_unit *, int, char *, void *);
-extern void zfcp_erp_unit_failed(struct zfcp_unit *, char *, void *);
+extern void zfcp_erp_set_lun_status(struct scsi_device *, u32);
+extern void zfcp_erp_clear_lun_status(struct scsi_device *, u32);
+extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *, void *);
+extern void zfcp_erp_lun_shutdown(struct scsi_device *, int, char *, void *);
+extern void zfcp_erp_lun_shutdown_wait(struct scsi_device *, char *);
 extern int  zfcp_erp_thread_setup(struct zfcp_adapter *);
 extern void zfcp_erp_thread_kill(struct zfcp_adapter *);
 extern void zfcp_erp_wait(struct zfcp_adapter *);
 extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long);
-extern void zfcp_erp_port_boxed(struct zfcp_port *, char *, void *);
-extern void zfcp_erp_unit_boxed(struct zfcp_unit *, char *, void *);
-extern void zfcp_erp_port_access_denied(struct zfcp_port *, char *, void *);
-extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, char *, void *);
-extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *,
-					    void *);
 extern void zfcp_erp_timeout_handler(unsigned long);
 
 /* zfcp_fc.c */
@@ -118,8 +116,8 @@
 extern int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *);
 extern int zfcp_fsf_close_port(struct zfcp_erp_action *);
 extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *);
-extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
-extern int zfcp_fsf_close_unit(struct zfcp_erp_action *);
+extern int zfcp_fsf_open_lun(struct zfcp_erp_action *);
+extern int zfcp_fsf_close_lun(struct zfcp_erp_action *);
 extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
 extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *,
 					      struct fsf_qtcb_bottom_config *);
@@ -135,12 +133,10 @@
 			    mempool_t *, unsigned int);
 extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32,
 			     struct zfcp_fsf_ct_els *, unsigned int);
-extern int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *,
-					  struct scsi_cmnd *);
+extern int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *);
 extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
-extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *, u8);
-extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
-						       struct zfcp_unit *);
+extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *, u8);
+extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *);
 extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
 
 /* zfcp_qdio.c */
@@ -163,8 +159,6 @@
 extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
 extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
 extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
-extern void zfcp_scsi_scan(struct zfcp_unit *);
-extern void zfcp_scsi_scan_work(struct work_struct *);
 extern void zfcp_scsi_set_prot(struct zfcp_adapter *);
 extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int);
 
@@ -175,4 +169,13 @@
 extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
 extern struct device_attribute *zfcp_sysfs_shost_attrs[];
 
+/* zfcp_unit.c */
+extern int zfcp_unit_add(struct zfcp_port *, u64);
+extern int zfcp_unit_remove(struct zfcp_port *, u64);
+extern struct zfcp_unit *zfcp_unit_find(struct zfcp_port *, u64);
+extern struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit);
+extern void zfcp_unit_scsi_scan(struct zfcp_unit *);
+extern void zfcp_unit_queue_scsi_scan(struct zfcp_port *);
+extern unsigned int zfcp_unit_sdev_status(struct zfcp_unit *);
+
 #endif	/* ZFCP_EXT_H */
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 6f3ed2b..86fd905 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -365,7 +365,7 @@
 	}
 
 	if (!port->d_id) {
-		zfcp_erp_port_failed(port, "fcgpn_2", NULL);
+		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
 		goto out;
 	}
 
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 9d1d7d1..beaf091 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -61,45 +61,6 @@
 	[FSF_QTCB_UPLOAD_CONTROL_FILE] =  FSF_SUPPORT_COMMAND
 };
 
-static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
-{
-	u16 subtable = table >> 16;
-	u16 rule = table & 0xffff;
-	const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
-
-	if (subtable && subtable < ARRAY_SIZE(act_type))
-		dev_warn(&adapter->ccw_device->dev,
-			 "Access denied according to ACT rule type %s, "
-			 "rule %d\n", act_type[subtable], rule);
-}
-
-static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
-					struct zfcp_port *port)
-{
-	struct fsf_qtcb_header *header = &req->qtcb->header;
-	dev_warn(&req->adapter->ccw_device->dev,
-		 "Access denied to port 0x%016Lx\n",
-		 (unsigned long long)port->wwpn);
-	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
-	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
-	zfcp_erp_port_access_denied(port, "fspad_1", req);
-	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-}
-
-static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
-					struct zfcp_unit *unit)
-{
-	struct fsf_qtcb_header *header = &req->qtcb->header;
-	dev_warn(&req->adapter->ccw_device->dev,
-		 "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
-		 (unsigned long long)unit->fcp_lun,
-		 (unsigned long long)unit->port->wwpn);
-	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
-	zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
-	zfcp_erp_unit_access_denied(unit, "fsuad_1", req);
-	req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-}
-
 static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
 {
 	dev_err(&req->adapter->ccw_device->dev, "FCP device not "
@@ -143,7 +104,7 @@
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 }
 
-static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
+static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req,
 					 struct fsf_link_down_info *link_down)
 {
 	struct zfcp_adapter *adapter = req->adapter;
@@ -223,7 +184,7 @@
 			 "the FC fabric is down\n");
 	}
 out:
-	zfcp_erp_adapter_failed(adapter, id, req);
+	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
 }
 
 static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
@@ -234,13 +195,13 @@
 
 	switch (sr_buf->status_subtype) {
 	case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
-		zfcp_fsf_link_down_info_eval(req, "fssrld1", ldi);
+		zfcp_fsf_link_down_info_eval(req, ldi);
 		break;
 	case FSF_STATUS_READ_SUB_FDISC_FAILED:
-		zfcp_fsf_link_down_info_eval(req, "fssrld2", ldi);
+		zfcp_fsf_link_down_info_eval(req, ldi);
 		break;
 	case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
-		zfcp_fsf_link_down_info_eval(req, "fssrld3", NULL);
+		zfcp_fsf_link_down_info_eval(req, NULL);
 	};
 }
 
@@ -281,9 +242,8 @@
 		dev_info(&adapter->ccw_device->dev,
 			 "The local link has been restored\n");
 		/* All ports should be marked as ready to run again */
-		zfcp_erp_modify_adapter_status(adapter, "fssrh_1", NULL,
-					       ZFCP_STATUS_COMMON_RUNNING,
-					       ZFCP_SET);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_RUNNING);
 		zfcp_erp_adapter_reopen(adapter,
 					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
 					ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -293,13 +253,12 @@
 		break;
 	case FSF_STATUS_READ_NOTIFICATION_LOST:
 		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
-			zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
-							req);
+			zfcp_cfdc_adapter_access_changed(adapter);
 		if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
 			queue_work(adapter->work_queue, &adapter->scan_work);
 		break;
 	case FSF_STATUS_READ_CFDC_UPDATED:
-		zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
+		zfcp_cfdc_adapter_access_changed(adapter);
 		break;
 	case FSF_STATUS_READ_FEATURE_UPDATE_ALERT:
 		adapter->adapter_features = sr_buf->payload.word[0];
@@ -399,16 +358,14 @@
 		zfcp_erp_adapter_shutdown(adapter, 0, "fspse_4", req);
 		break;
 	case FSF_PROT_LINK_DOWN:
-		zfcp_fsf_link_down_info_eval(req, "fspse_5",
-					     &psq->link_down_info);
+		zfcp_fsf_link_down_info_eval(req, &psq->link_down_info);
 		/* go through reopen to flush pending requests */
 		zfcp_erp_adapter_reopen(adapter, 0, "fspse_6", req);
 		break;
 	case FSF_PROT_REEST_QUEUE:
 		/* All ports should be marked as ready to run again */
-		zfcp_erp_modify_adapter_status(adapter, "fspse_7", NULL,
-					       ZFCP_STATUS_COMMON_RUNNING,
-					       ZFCP_SET);
+		zfcp_erp_set_adapter_status(adapter,
+					    ZFCP_STATUS_COMMON_RUNNING);
 		zfcp_erp_adapter_reopen(adapter,
 					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
 					ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -578,7 +535,7 @@
 		atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
 				&adapter->status);
 
-		zfcp_fsf_link_down_info_eval(req, "fsecdh2",
+		zfcp_fsf_link_down_info_eval(req,
 			&qtcb->header.fsf_status_qual.link_down_info);
 		break;
 	default:
@@ -644,7 +601,7 @@
 		break;
 	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
 		zfcp_fsf_exchange_port_evaluate(req);
-		zfcp_fsf_link_down_info_eval(req, "fsepdh1",
+		zfcp_fsf_link_down_info_eval(req,
 			&qtcb->header.fsf_status_qual.link_down_info);
 		break;
 	}
@@ -771,7 +728,7 @@
 	struct fsf_status_read_buffer *sr_buf;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -805,13 +762,14 @@
 	zfcp_fsf_req_free(req);
 	zfcp_dbf_hba_fsf_unsol("fail", adapter->dbf, NULL);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
 static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
 {
-	struct zfcp_unit *unit = req->data;
+	struct scsi_device *sdev = req->data;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 	union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
@@ -820,14 +778,15 @@
 	switch (req->qtcb->header.fsf_status) {
 	case FSF_PORT_HANDLE_NOT_VALID:
 		if (fsq->word[0] == fsq->word[1]) {
-			zfcp_erp_adapter_reopen(unit->port->adapter, 0,
+			zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0,
 						"fsafch1", req);
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		}
 		break;
 	case FSF_LUN_HANDLE_NOT_VALID:
 		if (fsq->word[0] == fsq->word[1]) {
-			zfcp_erp_port_reopen(unit->port, 0, "fsafch2", req);
+			zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fsafch2",
+					     req);
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		}
 		break;
@@ -835,17 +794,23 @@
 		req->status |= ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED;
 		break;
 	case FSF_PORT_BOXED:
-		zfcp_erp_port_boxed(unit->port, "fsafch3", req);
+		zfcp_erp_set_port_status(zfcp_sdev->port,
+					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(zfcp_sdev->port,
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsafch3",
+				     req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_BOXED:
-		zfcp_erp_unit_boxed(unit, "fsafch4", req);
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+				    "fsafch4", req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
                 break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (fsq->word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			zfcp_fc_test_link(unit->port);
+			zfcp_fc_test_link(zfcp_sdev->port);
 			/* fall through */
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -859,19 +824,20 @@
 }
 
 /**
- * zfcp_fsf_abort_fcp_command - abort running SCSI command
- * @old_req_id: unsigned long
- * @unit: pointer to struct zfcp_unit
+ * zfcp_fsf_abort_fcp_cmnd - abort running SCSI command
+ * @scmnd: The SCSI command to abort
  * Returns: pointer to struct zfcp_fsf_req
  */
 
-struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
-						struct zfcp_unit *unit)
+struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd)
 {
 	struct zfcp_fsf_req *req = NULL;
-	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
+	struct scsi_device *sdev = scmnd->device;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
+	unsigned long old_req_id = (unsigned long) scmnd->host_scribble;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 	req = zfcp_fsf_req_create(qdio, FSF_QTCB_ABORT_FCP_CMND,
@@ -882,16 +848,16 @@
 		goto out;
 	}
 
-	if (unlikely(!(atomic_read(&unit->status) &
+	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
 		       ZFCP_STATUS_COMMON_UNBLOCKED)))
 		goto out_error_free;
 
 	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
-	req->data = unit;
+	req->data = zfcp_sdev;
 	req->handler = zfcp_fsf_abort_fcp_command_handler;
-	req->qtcb->header.lun_handle = unit->handle;
-	req->qtcb->header.port_handle = unit->port->handle;
+	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
 	req->qtcb->bottom.support.req_handle = (u64) old_req_id;
 
 	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
@@ -902,7 +868,7 @@
 	zfcp_fsf_req_free(req);
 	req = NULL;
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return req;
 }
 
@@ -1041,7 +1007,7 @@
 	struct zfcp_fsf_req *req;
 	int ret = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1073,7 +1039,7 @@
 failed_send:
 	zfcp_fsf_req_free(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return ret;
 }
 
@@ -1111,8 +1077,10 @@
 	case FSF_RESPONSE_SIZE_TOO_LARGE:
 		break;
 	case FSF_ACCESS_DENIED:
-		if (port)
-			zfcp_fsf_access_denied_port(req, port);
+		if (port) {
+			zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
+			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		}
 		break;
 	case FSF_SBAL_MISMATCH:
 		/* should never occure, avoided in zfcp_fsf_send_els */
@@ -1137,7 +1105,7 @@
 	struct zfcp_qdio *qdio = adapter->qdio;
 	int ret = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1173,7 +1141,7 @@
 failed_send:
 	zfcp_fsf_req_free(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return ret;
 }
 
@@ -1183,7 +1151,7 @@
 	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1215,7 +1183,7 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1225,7 +1193,7 @@
 	struct zfcp_fsf_req *req = NULL;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out_unlock;
 
@@ -1251,7 +1219,7 @@
 
 	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
 	retval = zfcp_fsf_req_send(req);
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	if (!retval)
 		wait_for_completion(&req->completion);
 
@@ -1259,7 +1227,7 @@
 	return retval;
 
 out_unlock:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1277,7 +1245,7 @@
 	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
 		return -EOPNOTSUPP;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1304,7 +1272,7 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1323,7 +1291,7 @@
 	if (!(qdio->adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
 		return -EOPNOTSUPP;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out_unlock;
 
@@ -1343,7 +1311,7 @@
 	req->handler = zfcp_fsf_exchange_port_data_handler;
 	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
 	retval = zfcp_fsf_req_send(req);
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 
 	if (!retval)
 		wait_for_completion(&req->completion);
@@ -1353,7 +1321,7 @@
 	return retval;
 
 out_unlock:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1370,14 +1338,16 @@
 	case FSF_PORT_ALREADY_OPEN:
 		break;
 	case FSF_ACCESS_DENIED:
-		zfcp_fsf_access_denied_port(req, port);
+		zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
 		dev_warn(&req->adapter->ccw_device->dev,
 			 "Not enough FCP adapter resources to open "
 			 "remote port 0x%016Lx\n",
 			 (unsigned long long)port->wwpn);
-		zfcp_erp_port_failed(port, "fsoph_1", req);
+		zfcp_erp_set_port_status(port,
+					 ZFCP_STATUS_COMMON_ERP_FAILED);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1437,7 +1407,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1468,7 +1438,7 @@
 		put_device(&port->dev);
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1487,9 +1457,7 @@
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		break;
 	case FSF_GOOD:
-		zfcp_erp_modify_port_status(port, "fscph_2", req,
-					    ZFCP_STATUS_COMMON_OPEN,
-					    ZFCP_CLEAR);
+		zfcp_erp_clear_port_status(port, ZFCP_STATUS_COMMON_OPEN);
 		break;
 	}
 }
@@ -1505,7 +1473,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1534,7 +1502,7 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1580,7 +1548,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1605,7 +1573,7 @@
 	if (retval)
 		zfcp_fsf_req_free(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1633,7 +1601,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1658,7 +1626,7 @@
 	if (retval)
 		zfcp_fsf_req_free(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -1666,7 +1634,7 @@
 {
 	struct zfcp_port *port = req->data;
 	struct fsf_qtcb_header *header = &req->qtcb->header;
-	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
@@ -1677,18 +1645,19 @@
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ACCESS_DENIED:
-		zfcp_fsf_access_denied_port(req, port);
+		zfcp_cfdc_port_denied(port, &header->fsf_status_qual);
 		break;
 	case FSF_PORT_BOXED:
 		/* 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);
-		read_lock(&port->unit_list_lock);
-		list_for_each_entry(unit, &port->unit_list, list)
-			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
-					  &unit->status);
-		read_unlock(&port->unit_list_lock);
-		zfcp_erp_port_boxed(port, "fscpph2", req);
+		shost_for_each_device(sdev, port->adapter->scsi_host)
+			if (sdev_to_zfcp(sdev)->port == port)
+				atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
+						  &sdev_to_zfcp(sdev)->status);
+		zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
+				     "fscpph2", req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
@@ -1705,11 +1674,10 @@
 		 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
 		 */
 		atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
-		read_lock(&port->unit_list_lock);
-		list_for_each_entry(unit, &port->unit_list, list)
-			atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
-					  &unit->status);
-		read_unlock(&port->unit_list_lock);
+		shost_for_each_device(sdev, port->adapter->scsi_host)
+			if (sdev_to_zfcp(sdev)->port == port)
+				atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
+						  &sdev_to_zfcp(sdev)->status);
 		break;
 	}
 }
@@ -1725,7 +1693,7 @@
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1754,69 +1722,57 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
-static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
 {
 	struct zfcp_adapter *adapter = req->adapter;
-	struct zfcp_unit *unit = req->data;
+	struct scsi_device *sdev = req->data;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 	struct fsf_qtcb_header *header = &req->qtcb->header;
 	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
-	struct fsf_queue_designator *queue_designator =
-				&header->fsf_status_qual.fsf_queue_designator;
-	int exclusive, readwrite;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
 
 	atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
 			  ZFCP_STATUS_COMMON_ACCESS_BOXED |
-			  ZFCP_STATUS_UNIT_SHARED |
-			  ZFCP_STATUS_UNIT_READONLY,
-			  &unit->status);
+			  ZFCP_STATUS_LUN_SHARED |
+			  ZFCP_STATUS_LUN_READONLY,
+			  &zfcp_sdev->status);
 
 	switch (header->fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fsouh_1", req);
+		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1", req);
 		/* fall through */
 	case FSF_LUN_ALREADY_OPEN:
 		break;
 	case FSF_ACCESS_DENIED:
-		zfcp_fsf_access_denied_unit(req, unit);
-		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
-		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PORT_BOXED:
-		zfcp_erp_port_boxed(unit->port, "fsouh_2", req);
+		zfcp_erp_set_port_status(zfcp_sdev->port,
+					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(zfcp_sdev->port,
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fsouh_2",
+				     req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_SHARING_VIOLATION:
-		if (header->fsf_status_qual.word[0])
-			dev_warn(&adapter->ccw_device->dev,
-				 "LUN 0x%Lx on port 0x%Lx is already in "
-				 "use by CSS%d, MIF Image ID %x\n",
-				 (unsigned long long)unit->fcp_lun,
-				 (unsigned long long)unit->port->wwpn,
-				 queue_designator->cssid,
-				 queue_designator->hla);
-		else
-			zfcp_act_eval_err(adapter,
-					  header->fsf_status_qual.word[2]);
-		zfcp_erp_unit_access_denied(unit, "fsouh_3", req);
-		atomic_clear_mask(ZFCP_STATUS_UNIT_SHARED, &unit->status);
-		atomic_clear_mask(ZFCP_STATUS_UNIT_READONLY, &unit->status);
+		zfcp_cfdc_lun_shrng_vltn(sdev, &header->fsf_status_qual);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
 		dev_warn(&adapter->ccw_device->dev,
 			 "No handle is available for LUN "
 			 "0x%016Lx on port 0x%016Lx\n",
-			 (unsigned long long)unit->fcp_lun,
-			 (unsigned long long)unit->port->wwpn);
-		zfcp_erp_unit_failed(unit, "fsouh_4", req);
+			 (unsigned long long)zfcp_scsi_dev_lun(sdev),
+			 (unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
 		/* fall through */
 	case FSF_INVALID_COMMAND_OPTION:
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1824,7 +1780,7 @@
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			zfcp_fc_test_link(unit->port);
+			zfcp_fc_test_link(zfcp_sdev->port);
 			/* fall through */
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1833,70 +1789,26 @@
 		break;
 
 	case FSF_GOOD:
-		unit->handle = header->lun_handle;
-		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
-
-		if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) &&
-		    (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) &&
-		    !zfcp_ccw_priv_sch(adapter)) {
-			exclusive = (bottom->lun_access_info &
-					FSF_UNIT_ACCESS_EXCLUSIVE);
-			readwrite = (bottom->lun_access_info &
-					FSF_UNIT_ACCESS_OUTBOUND_TRANSFER);
-
-			if (!exclusive)
-		                atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
-						&unit->status);
-
-			if (!readwrite) {
-                		atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
-						&unit->status);
-				dev_info(&adapter->ccw_device->dev,
-					 "SCSI device at LUN 0x%016Lx on port "
-					 "0x%016Lx opened read-only\n",
-					 (unsigned long long)unit->fcp_lun,
-					 (unsigned long long)unit->port->wwpn);
-        		}
-
-        		if (exclusive && !readwrite) {
-				dev_err(&adapter->ccw_device->dev,
-					"Exclusive read-only access not "
-					"supported (unit 0x%016Lx, "
-					"port 0x%016Lx)\n",
-					(unsigned long long)unit->fcp_lun,
-					(unsigned long long)unit->port->wwpn);
-				zfcp_erp_unit_failed(unit, "fsouh_5", req);
-				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-				zfcp_erp_unit_shutdown(unit, 0, "fsouh_6", req);
-        		} else if (!exclusive && readwrite) {
-				dev_err(&adapter->ccw_device->dev,
-					"Shared read-write access not "
-					"supported (unit 0x%016Lx, port "
-					"0x%016Lx)\n",
-					(unsigned long long)unit->fcp_lun,
-					(unsigned long long)unit->port->wwpn);
-				zfcp_erp_unit_failed(unit, "fsouh_7", req);
-				req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-				zfcp_erp_unit_shutdown(unit, 0, "fsouh_8", req);
-        		}
-		}
+		zfcp_sdev->lun_handle = header->lun_handle;
+		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
+		zfcp_cfdc_open_lun_eval(sdev, bottom);
 		break;
 	}
 }
 
 /**
- * zfcp_fsf_open_unit - open unit
+ * zfcp_fsf_open_lun - open LUN
  * @erp_action: pointer to struct zfcp_erp_action
  * Returns: 0 on success, error otherwise
  */
-int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
+int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action)
 {
 	struct zfcp_adapter *adapter = erp_action->adapter;
 	struct zfcp_qdio *qdio = adapter->qdio;
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1913,9 +1825,9 @@
 	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
 	req->qtcb->header.port_handle = erp_action->port->handle;
-	req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
-	req->handler = zfcp_fsf_open_unit_handler;
-	req->data = erp_action->unit;
+	req->qtcb->bottom.support.fcp_lun = zfcp_scsi_dev_lun(erp_action->sdev);
+	req->handler = zfcp_fsf_open_lun_handler;
+	req->data = erp_action->sdev;
 	req->erp_action = erp_action;
 	erp_action->fsf_req_id = req->req_id;
 
@@ -1929,34 +1841,40 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
-static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
 {
-	struct zfcp_unit *unit = req->data;
+	struct scsi_device *sdev = req->data;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
 
 	switch (req->qtcb->header.fsf_status) {
 	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fscuh_1", req);
+		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1",
+					req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_LUN_HANDLE_NOT_VALID:
-		zfcp_erp_port_reopen(unit->port, 0, "fscuh_2", req);
+		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fscuh_2", req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_PORT_BOXED:
-		zfcp_erp_port_boxed(unit->port, "fscuh_3", req);
+		zfcp_erp_set_port_status(zfcp_sdev->port,
+					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(zfcp_sdev->port,
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fscuh_3",
+				     req);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (req->qtcb->header.fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			zfcp_fc_test_link(unit->port);
+			zfcp_fc_test_link(zfcp_sdev->port);
 			/* fall through */
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1964,23 +1882,24 @@
 		}
 		break;
 	case FSF_GOOD:
-		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
+		atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
 		break;
 	}
 }
 
 /**
- * zfcp_fsf_close_unit - close zfcp unit
- * @erp_action: pointer to struct zfcp_unit
+ * zfcp_fsf_close_LUN - close LUN
+ * @erp_action: pointer to erp_action triggering the "close LUN"
  * Returns: 0 on success, error otherwise
  */
-int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
+int zfcp_fsf_close_lun(struct zfcp_erp_action *erp_action)
 {
 	struct zfcp_qdio *qdio = erp_action->adapter->qdio;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
 	struct zfcp_fsf_req *req;
 	int retval = -EIO;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -1997,9 +1916,9 @@
 	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
 	req->qtcb->header.port_handle = erp_action->port->handle;
-	req->qtcb->header.lun_handle = erp_action->unit->handle;
-	req->handler = zfcp_fsf_close_unit_handler;
-	req->data = erp_action->unit;
+	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+	req->handler = zfcp_fsf_close_lun_handler;
+	req->data = erp_action->sdev;
 	req->erp_action = erp_action;
 	erp_action->fsf_req_id = req->req_id;
 
@@ -2010,7 +1929,7 @@
 		erp_action->fsf_req_id = 0;
 	}
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return retval;
 }
 
@@ -2025,7 +1944,7 @@
 {
 	struct fsf_qual_latency_info *lat_in;
 	struct latency_cont *lat = NULL;
-	struct zfcp_unit *unit = req->unit;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
 	struct zfcp_blk_drv_data blktrc;
 	int ticks = req->adapter->timer_ticks;
 
@@ -2048,24 +1967,24 @@
 		case FSF_DATADIR_DIF_READ_STRIP:
 		case FSF_DATADIR_DIF_READ_CONVERT:
 		case FSF_DATADIR_READ:
-			lat = &unit->latencies.read;
+			lat = &zfcp_sdev->latencies.read;
 			break;
 		case FSF_DATADIR_DIF_WRITE_INSERT:
 		case FSF_DATADIR_DIF_WRITE_CONVERT:
 		case FSF_DATADIR_WRITE:
-			lat = &unit->latencies.write;
+			lat = &zfcp_sdev->latencies.write;
 			break;
 		case FSF_DATADIR_CMND:
-			lat = &unit->latencies.cmd;
+			lat = &zfcp_sdev->latencies.cmd;
 			break;
 		}
 
 		if (lat) {
-			spin_lock(&unit->latencies.lock);
+			spin_lock(&zfcp_sdev->latencies.lock);
 			zfcp_fsf_update_lat(&lat->channel, lat_in->channel_lat);
 			zfcp_fsf_update_lat(&lat->fabric, lat_in->fabric_lat);
 			lat->counter++;
-			spin_unlock(&unit->latencies.lock);
+			spin_unlock(&zfcp_sdev->latencies.lock);
 		}
 	}
 
@@ -2073,12 +1992,88 @@
 			    sizeof(blktrc));
 }
 
-static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
+static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
+{
+	struct scsi_cmnd *scmnd = req->data;
+	struct scsi_device *sdev = scmnd->device;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct fsf_qtcb_header *header = &req->qtcb->header;
+
+	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
+		return;
+
+	switch (header->fsf_status) {
+	case FSF_HANDLE_MISMATCH:
+	case FSF_PORT_HANDLE_NOT_VALID:
+		zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1",
+					req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_FCPLUN_NOT_VALID:
+	case FSF_LUN_HANDLE_NOT_VALID:
+		zfcp_erp_port_reopen(zfcp_sdev->port, 0, "fssfch2", req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
+		zfcp_fsf_class_not_supp(req);
+		break;
+	case FSF_ACCESS_DENIED:
+		zfcp_cfdc_lun_denied(sdev, &header->fsf_status_qual);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_DIRECTION_INDICATOR_NOT_VALID:
+		dev_err(&req->adapter->ccw_device->dev,
+			"Incorrect direction %d, LUN 0x%016Lx on port "
+			"0x%016Lx closed\n",
+			req->qtcb->bottom.io.data_direction,
+			(unsigned long long)zfcp_scsi_dev_lun(sdev),
+			(unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
+					  "fssfch3", req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_CMND_LENGTH_NOT_VALID:
+		dev_err(&req->adapter->ccw_device->dev,
+			"Incorrect CDB length %d, LUN 0x%016Lx on "
+			"port 0x%016Lx closed\n",
+			req->qtcb->bottom.io.fcp_cmnd_length,
+			(unsigned long long)zfcp_scsi_dev_lun(sdev),
+			(unsigned long long)zfcp_sdev->port->wwpn);
+		zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
+					  "fssfch4", req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_PORT_BOXED:
+		zfcp_erp_set_port_status(zfcp_sdev->port,
+					 ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_port_reopen(zfcp_sdev->port,
+				     ZFCP_STATUS_COMMON_ERP_FAILED, "fssfch5",
+				     req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_LUN_BOXED:
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ACCESS_BOXED);
+		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+				    "fssfch6", req);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	case FSF_ADAPTER_STATUS_AVAILABLE:
+		if (header->fsf_status_qual.word[0] ==
+		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
+			zfcp_fc_test_link(zfcp_sdev->port);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
+	}
+}
+
+static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
 {
 	struct scsi_cmnd *scpnt;
 	struct fcp_resp_with_ext *fcp_rsp;
 	unsigned long flags;
 
+	zfcp_fsf_fcp_handler_common(req);
+
 	read_lock_irqsave(&req->adapter->abort_lock, flags);
 
 	scpnt = req->data;
@@ -2125,97 +2120,6 @@
 	read_unlock_irqrestore(&req->adapter->abort_lock, flags);
 }
 
-static void zfcp_fsf_send_fcp_ctm_handler(struct zfcp_fsf_req *req)
-{
-	struct fcp_resp_with_ext *fcp_rsp;
-	struct fcp_resp_rsp_info *rsp_info;
-
-	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
-	rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
-
-	if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
-	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
-		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
-}
-
-
-static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
-{
-	struct zfcp_unit *unit;
-	struct fsf_qtcb_header *header = &req->qtcb->header;
-
-	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT))
-		unit = req->data;
-	else
-		unit = req->unit;
-
-	if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
-		goto skip_fsfstatus;
-
-	switch (header->fsf_status) {
-	case FSF_HANDLE_MISMATCH:
-	case FSF_PORT_HANDLE_NOT_VALID:
-		zfcp_erp_adapter_reopen(unit->port->adapter, 0, "fssfch1", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_FCPLUN_NOT_VALID:
-	case FSF_LUN_HANDLE_NOT_VALID:
-		zfcp_erp_port_reopen(unit->port, 0, "fssfch2", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-		zfcp_fsf_class_not_supp(req);
-		break;
-	case FSF_ACCESS_DENIED:
-		zfcp_fsf_access_denied_unit(req, unit);
-		break;
-	case FSF_DIRECTION_INDICATOR_NOT_VALID:
-		dev_err(&req->adapter->ccw_device->dev,
-			"Incorrect direction %d, unit 0x%016Lx on port "
-			"0x%016Lx closed\n",
-			req->qtcb->bottom.io.data_direction,
-			(unsigned long long)unit->fcp_lun,
-			(unsigned long long)unit->port->wwpn);
-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch3",
-					  req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_CMND_LENGTH_NOT_VALID:
-		dev_err(&req->adapter->ccw_device->dev,
-			"Incorrect CDB length %d, unit 0x%016Lx on "
-			"port 0x%016Lx closed\n",
-			req->qtcb->bottom.io.fcp_cmnd_length,
-			(unsigned long long)unit->fcp_lun,
-			(unsigned long long)unit->port->wwpn);
-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0, "fssfch4",
-					  req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_PORT_BOXED:
-		zfcp_erp_port_boxed(unit->port, "fssfch5", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_LUN_BOXED:
-		zfcp_erp_unit_boxed(unit, "fssfch6", req);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	case FSF_ADAPTER_STATUS_AVAILABLE:
-		if (header->fsf_status_qual.word[0] ==
-		    FSF_SQ_INVOKE_LINK_TEST_PROCEDURE)
-			zfcp_fc_test_link(unit->port);
-		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-	}
-skip_fsfstatus:
-	if (req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)
-		zfcp_fsf_send_fcp_ctm_handler(req);
-	else {
-		zfcp_fsf_send_fcp_command_task_handler(req);
-		req->unit = NULL;
-		put_device(&unit->dev);
-	}
-}
-
 static int zfcp_fsf_set_data_dir(struct scsi_cmnd *scsi_cmnd, u32 *data_dir)
 {
 	switch (scsi_get_prot_op(scsi_cmnd)) {
@@ -2255,22 +2159,22 @@
 }
 
 /**
- * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
- * @unit: unit where command is sent to
+ * zfcp_fsf_fcp_cmnd - initiate an FCP command (for a SCSI command)
  * @scsi_cmnd: scsi command to be sent
  */
-int zfcp_fsf_send_fcp_command_task(struct zfcp_unit *unit,
-				   struct scsi_cmnd *scsi_cmnd)
+int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
 {
 	struct zfcp_fsf_req *req;
 	struct fcp_cmnd *fcp_cmnd;
 	unsigned int sbtype = SBAL_FLAGS0_TYPE_READ;
 	int real_bytes, retval = -EIO, dix_bytes = 0;
-	struct zfcp_adapter *adapter = unit->port->adapter;
+	struct scsi_device *sdev = scsi_cmnd->device;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct zfcp_qdio *qdio = adapter->qdio;
 	struct fsf_qtcb_bottom_io *io;
 
-	if (unlikely(!(atomic_read(&unit->status) &
+	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
 		       ZFCP_STATUS_COMMON_UNBLOCKED)))
 		return -EBUSY;
 
@@ -2295,11 +2199,10 @@
 
 	io = &req->qtcb->bottom.io;
 	req->status |= ZFCP_STATUS_FSFREQ_CLEANUP;
-	req->unit = unit;
 	req->data = scsi_cmnd;
-	req->handler = zfcp_fsf_send_fcp_command_handler;
-	req->qtcb->header.lun_handle = unit->handle;
-	req->qtcb->header.port_handle = unit->port->handle;
+	req->handler = zfcp_fsf_fcp_cmnd_handler;
+	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
 	io->service_class = FSF_CLASS_3;
 	io->fcp_cmnd_length = FCP_CMND_LEN;
 
@@ -2310,8 +2213,6 @@
 
 	zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);
 
-	get_device(&unit->dev);
-
 	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
 	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
 
@@ -2338,7 +2239,6 @@
 	goto out;
 
 failed_scsi_cmnd:
-	put_device(&unit->dev);
 	zfcp_fsf_req_free(req);
 	scsi_cmnd->host_scribble = NULL;
 out:
@@ -2346,23 +2246,40 @@
 	return retval;
 }
 
+static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req)
+{
+	struct fcp_resp_with_ext *fcp_rsp;
+	struct fcp_resp_rsp_info *rsp_info;
+
+	zfcp_fsf_fcp_handler_common(req);
+
+	fcp_rsp = (struct fcp_resp_with_ext *) &req->qtcb->bottom.io.fcp_rsp;
+	rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
+
+	if ((rsp_info->rsp_code != FCP_TMF_CMPL) ||
+	     (req->status & ZFCP_STATUS_FSFREQ_ERROR))
+		req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
+}
+
 /**
- * zfcp_fsf_send_fcp_ctm - send SCSI task management command
- * @unit: pointer to struct zfcp_unit
+ * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
+ * @scmnd: SCSI command to send the task management command for
  * @tm_flags: unsigned byte for task management flags
  * Returns: on success pointer to struct fsf_req, NULL otherwise
  */
-struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_unit *unit, u8 tm_flags)
+struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
+					    u8 tm_flags)
 {
 	struct zfcp_fsf_req *req = NULL;
 	struct fcp_cmnd *fcp_cmnd;
-	struct zfcp_qdio *qdio = unit->port->adapter->qdio;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
+	struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
 
-	if (unlikely(!(atomic_read(&unit->status) &
+	if (unlikely(!(atomic_read(&zfcp_sdev->status) &
 		       ZFCP_STATUS_COMMON_UNBLOCKED)))
 		return NULL;
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -2376,10 +2293,10 @@
 	}
 
 	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
-	req->data = unit;
-	req->handler = zfcp_fsf_send_fcp_command_handler;
-	req->qtcb->header.lun_handle = unit->handle;
-	req->qtcb->header.port_handle = unit->port->handle;
+	req->data = scmnd;
+	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
+	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
+	req->qtcb->header.port_handle = zfcp_sdev->port->handle;
 	req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
 	req->qtcb->bottom.io.service_class = FSF_CLASS_3;
 	req->qtcb->bottom.io.fcp_cmnd_length = FCP_CMND_LEN;
@@ -2387,7 +2304,7 @@
 	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
 	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
-	zfcp_fc_fcp_tm(fcp_cmnd, unit->device, tm_flags);
+	zfcp_fc_fcp_tm(fcp_cmnd, scmnd->device, tm_flags);
 
 	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
 	if (!zfcp_fsf_req_send(req))
@@ -2396,7 +2313,7 @@
 	zfcp_fsf_req_free(req);
 	req = NULL;
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return req;
 }
 
@@ -2432,7 +2349,7 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (zfcp_qdio_sbal_get(qdio))
 		goto out;
 
@@ -2459,7 +2376,7 @@
 	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
 	retval = zfcp_fsf_req_send(req);
 out:
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 
 	if (!retval) {
 		wait_for_completion(&req->completion);
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index b263575..60e6e57 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -60,13 +60,11 @@
 	unsigned long long now, span;
 	int used;
 
-	spin_lock(&qdio->stat_lock);
 	now = get_clock_monotonic();
 	span = (now - qdio->req_q_time) >> 12;
 	used = QDIO_MAX_BUFFERS_PER_Q - atomic_read(&qdio->req_q_free);
 	qdio->req_q_util += used * span;
 	qdio->req_q_time = now;
-	spin_unlock(&qdio->stat_lock);
 }
 
 static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int qdio_err,
@@ -84,7 +82,9 @@
 	/* cleanup all SBALs being program-owned now */
 	zfcp_qdio_zero_sbals(qdio->req_q, idx, count);
 
+	spin_lock_irq(&qdio->stat_lock);
 	zfcp_qdio_account(qdio);
+	spin_unlock_irq(&qdio->stat_lock);
 	atomic_add(count, &qdio->req_q_free);
 	wake_up(&qdio->req_q_wq);
 }
@@ -201,11 +201,11 @@
 
 static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
 {
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	if (atomic_read(&qdio->req_q_free) ||
 	    !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
 		return 1;
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	return 0;
 }
 
@@ -223,7 +223,7 @@
 {
 	long ret;
 
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 	ret = wait_event_interruptible_timeout(qdio->req_q_wq,
 			       zfcp_qdio_sbal_check(qdio), 5 * HZ);
 
@@ -239,7 +239,7 @@
 		zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1", NULL);
 	}
 
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	return -EIO;
 }
 
@@ -254,7 +254,9 @@
 	int retval;
 	u8 sbal_number = q_req->sbal_number;
 
+	spin_lock(&qdio->stat_lock);
 	zfcp_qdio_account(qdio);
+	spin_unlock(&qdio->stat_lock);
 
 	retval = do_QDIO(qdio->adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0,
 			 q_req->sbal_first, sbal_number);
@@ -328,9 +330,9 @@
 		return;
 
 	/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
-	spin_lock_bh(&qdio->req_q_lock);
+	spin_lock_irq(&qdio->req_q_lock);
 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
-	spin_unlock_bh(&qdio->req_q_lock);
+	spin_unlock_irq(&qdio->req_q_lock);
 
 	wake_up(&qdio->req_q_wq);
 
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index cb000c9..50286d8 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -49,11 +49,12 @@
 	return sdev->queue_depth;
 }
 
-static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
+static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
 {
-	struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
-	unit->device = NULL;
-	put_device(&unit->dev);
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+
+	zfcp_erp_lun_shutdown_wait(sdev, "scssd_1");
+	put_device(&zfcp_sdev->port->dev);
 }
 
 static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
@@ -78,23 +79,16 @@
 static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 				  void (*done) (struct scsi_cmnd *))
 {
-	struct zfcp_unit *unit;
-	struct zfcp_adapter *adapter;
-	int    status, scsi_result, ret;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
+	int    status, scsi_result, ret;
 
 	/* reset the status for this request */
 	scpnt->result = 0;
 	scpnt->host_scribble = NULL;
 	scpnt->scsi_done = done;
 
-	/*
-	 * figure out adapter and target device
-	 * (stored there by zfcp_scsi_slave_alloc)
-	 */
-	adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
-	unit = scpnt->device->hostdata;
-
 	scsi_result = fc_remote_port_chkready(rport);
 	if (unlikely(scsi_result)) {
 		scpnt->result = scsi_result;
@@ -103,11 +97,11 @@
 		return 0;
 	}
 
-	status = atomic_read(&unit->status);
+	status = atomic_read(&zfcp_sdev->status);
 	if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) &&
-		     !(atomic_read(&unit->port->status) &
+		     !(atomic_read(&zfcp_sdev->port->status) &
 		       ZFCP_STATUS_COMMON_ERP_FAILED)) {
-		/* only unit access denied, but port is good
+		/* only LUN access denied, but port is good
 		 * not covered by FC transport, have to fail here */
 		zfcp_scsi_command_fail(scpnt, DID_ERROR);
 		return 0;
@@ -115,8 +109,8 @@
 
 	if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
 		/* This could be either
-		 * open unit pending: this is temporary, will result in
-		 * 	open unit or ERP_FAILED, so retry command
+		 * open LUN pending: this is temporary, will result in
+		 *	open LUN or ERP_FAILED, so retry command
 		 * call to rport_delete pending: mimic retry from
 		 * 	fc_remote_port_chkready until rport is BLOCKED
 		 */
@@ -124,7 +118,7 @@
 		return 0;
 	}
 
-	ret = zfcp_fsf_send_fcp_command_task(unit, scpnt);
+	ret = zfcp_fsf_fcp_cmnd(scpnt);
 	if (unlikely(ret == -EBUSY))
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 	else if (unlikely(ret < 0))
@@ -133,45 +127,42 @@
 	return ret;
 }
 
-static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter,
-					  unsigned int id, u64 lun)
+static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
 {
-	unsigned long flags;
+	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+	struct zfcp_adapter *adapter =
+		(struct zfcp_adapter *) sdev->host->hostdata[0];
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
 	struct zfcp_port *port;
-	struct zfcp_unit *unit = NULL;
-
-	read_lock_irqsave(&adapter->port_list_lock, flags);
-	list_for_each_entry(port, &adapter->port_list, list) {
-		if (!port->rport || (id != port->rport->scsi_target_id))
-			continue;
-		unit = zfcp_get_unit_by_lun(port, lun);
-		if (unit)
-			break;
-	}
-	read_unlock_irqrestore(&adapter->port_list_lock, flags);
-
-	return unit;
-}
-
-static int zfcp_scsi_slave_alloc(struct scsi_device *sdp)
-{
-	struct zfcp_adapter *adapter;
 	struct zfcp_unit *unit;
-	u64 lun;
 
-	adapter = (struct zfcp_adapter *) sdp->host->hostdata[0];
-	if (!adapter)
-		goto out;
+	port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
+	if (!port)
+		return -ENXIO;
 
-	int_to_scsilun(sdp->lun, (struct scsi_lun *)&lun);
-	unit = zfcp_unit_lookup(adapter, sdp->id, lun);
-	if (unit) {
-		sdp->hostdata = unit;
-		unit->device = sdp;
-		return 0;
+	unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
+	if (unit)
+		put_device(&unit->dev);
+
+	if (!unit && !(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) {
+		put_device(&port->dev);
+		return -ENXIO;
 	}
-out:
-	return -ENXIO;
+
+	zfcp_sdev->port = port;
+	zfcp_sdev->latencies.write.channel.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.write.fabric.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.read.channel.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.read.fabric.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.cmd.channel.min = 0xFFFFFFFF;
+	zfcp_sdev->latencies.cmd.fabric.min = 0xFFFFFFFF;
+	spin_lock_init(&zfcp_sdev->latencies.lock);
+
+	zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+	zfcp_erp_lun_reopen(sdev, 0, "scsla_1", NULL);
+	zfcp_erp_wait(port->adapter);
+
+	return 0;
 }
 
 static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
@@ -179,7 +170,6 @@
 	struct Scsi_Host *scsi_host = scpnt->device->host;
 	struct zfcp_adapter *adapter =
 		(struct zfcp_adapter *) scsi_host->hostdata[0];
-	struct zfcp_unit *unit = scpnt->device->hostdata;
 	struct zfcp_fsf_req *old_req, *abrt_req;
 	unsigned long flags;
 	unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
@@ -203,7 +193,7 @@
 	write_unlock_irqrestore(&adapter->abort_lock, flags);
 
 	while (retry--) {
-		abrt_req = zfcp_fsf_abort_fcp_command(old_reqid, unit);
+		abrt_req = zfcp_fsf_abort_fcp_cmnd(scpnt);
 		if (abrt_req)
 			break;
 
@@ -238,14 +228,14 @@
 
 static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 {
-	struct zfcp_unit *unit = scpnt->device->hostdata;
-	struct zfcp_adapter *adapter = unit->port->adapter;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	struct zfcp_fsf_req *fsf_req = NULL;
 	int retval = SUCCESS, ret;
 	int retry = 3;
 
 	while (retry--) {
-		fsf_req = zfcp_fsf_send_fcp_ctm(unit, tm_flags);
+		fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags);
 		if (fsf_req)
 			break;
 
@@ -256,7 +246,7 @@
 
 		if (!(atomic_read(&adapter->status) &
 		      ZFCP_STATUS_COMMON_RUNNING)) {
-			zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt);
+			zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags);
 			return SUCCESS;
 		}
 	}
@@ -266,10 +256,10 @@
 	wait_for_completion(&fsf_req->completion);
 
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
-		zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt);
+		zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
 		retval = FAILED;
 	} else
-		zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt);
+		zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
 
 	zfcp_fsf_req_free(fsf_req);
 	return retval;
@@ -287,8 +277,8 @@
 
 static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
-	struct zfcp_unit *unit = scpnt->device->hostdata;
-	struct zfcp_adapter *adapter = unit->port->adapter;
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
 	int ret;
 
 	zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt);
@@ -319,8 +309,8 @@
 	}
 
 	/* tell the SCSI stack some characteristics of this adapter */
-	adapter->scsi_host->max_id = 1;
-	adapter->scsi_host->max_lun = 1;
+	adapter->scsi_host->max_id = 511;
+	adapter->scsi_host->max_lun = 0xFFFFFFFF;
 	adapter->scsi_host->max_channel = 0;
 	adapter->scsi_host->unique_id = dev_id.devno;
 	adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
@@ -534,20 +524,6 @@
 	}
 }
 
-static void zfcp_scsi_queue_unit_register(struct zfcp_port *port)
-{
-	struct zfcp_unit *unit;
-
-	read_lock_irq(&port->unit_list_lock);
-	list_for_each_entry(unit, &port->unit_list, list) {
-		get_device(&unit->dev);
-		if (scsi_queue_work(port->adapter->scsi_host,
-				    &unit->scsi_work) <= 0)
-			put_device(&unit->dev);
-	}
-	read_unlock_irq(&port->unit_list_lock);
-}
-
 static void zfcp_scsi_rport_register(struct zfcp_port *port)
 {
 	struct fc_rport_identifiers ids;
@@ -574,7 +550,7 @@
 	port->rport = rport;
 	port->starget_id = rport->scsi_target_id;
 
-	zfcp_scsi_queue_unit_register(port);
+	zfcp_unit_queue_scsi_scan(port);
 }
 
 static void zfcp_scsi_rport_block(struct zfcp_port *port)
@@ -638,29 +614,6 @@
 }
 
 /**
- * zfcp_scsi_scan - Register LUN with SCSI midlayer
- * @unit: The LUN/unit to register
- */
-void zfcp_scsi_scan(struct zfcp_unit *unit)
-{
-	struct fc_rport *rport = unit->port->rport;
-
-	if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
-		scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
-				 scsilun_to_int((struct scsi_lun *)
-						&unit->fcp_lun), 0);
-}
-
-void zfcp_scsi_scan_work(struct work_struct *work)
-{
-	struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
-					      scsi_work);
-
-	zfcp_scsi_scan(unit);
-	put_device(&unit->dev);
-}
-
-/**
  * zfcp_scsi_set_prot - Configure DIF/DIX support in scsi_host
  * @adapter: The adapter where to configure DIF/DIX for the SCSI host
  */
@@ -681,6 +634,7 @@
 	    adapter->adapter_features & FSF_FEATURE_DIX_PROT_TCPIP) {
 		mask |= SHOST_DIX_TYPE1_PROTECTION;
 		scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP);
+		shost->sg_prot_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
 		shost->sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ / 2;
 		shost->max_sectors = ZFCP_QDIO_MAX_SBALES_PER_REQ * 8 / 2;
 	}
@@ -734,7 +688,6 @@
 	.show_host_port_type = 1,
 	.show_host_speed = 1,
 	.show_host_port_id = 1,
-	.disable_target_scan = 1,
 	.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
 };
 
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index b4561c86..2f2c54f 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -68,63 +68,96 @@
 		  ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
 
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
-		 atomic_read(&unit->status));
+		 zfcp_unit_sdev_status(unit));
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, in_recovery, "%d\n",
-		 (atomic_read(&unit->status) &
+		 (zfcp_unit_sdev_status(unit) &
 		  ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_denied, "%d\n",
-		 (atomic_read(&unit->status) &
+		 (zfcp_unit_sdev_status(unit) &
 		  ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_shared, "%d\n",
-		 (atomic_read(&unit->status) &
-		  ZFCP_STATUS_UNIT_SHARED) != 0);
+		 (zfcp_unit_sdev_status(unit) &
+		  ZFCP_STATUS_LUN_SHARED) != 0);
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, access_readonly, "%d\n",
-		 (atomic_read(&unit->status) &
-		  ZFCP_STATUS_UNIT_READONLY) != 0);
+		 (zfcp_unit_sdev_status(unit) &
+		  ZFCP_STATUS_LUN_READONLY) != 0);
 
-#define ZFCP_SYSFS_FAILED(_feat_def, _feat, _adapter, _mod_id, _reopen_id)     \
-static ssize_t zfcp_sysfs_##_feat##_failed_show(struct device *dev,	       \
-						struct device_attribute *attr, \
-						char *buf)		       \
-{									       \
-	struct _feat_def *_feat = container_of(dev, struct _feat_def, dev);    \
-									       \
-	if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_ERP_FAILED)       \
-		return sprintf(buf, "1\n");				       \
-	else								       \
-		return sprintf(buf, "0\n");				       \
-}									       \
-static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev,	       \
-						 struct device_attribute *attr,\
-						 const char *buf, size_t count)\
-{									       \
-	struct _feat_def *_feat = container_of(dev, struct _feat_def, dev);    \
-	unsigned long val;						       \
-	int retval = 0;							       \
-									       \
-	if (!(_feat && get_device(&_feat->dev)))			       \
-		return -EBUSY;						       \
-									       \
-	if (strict_strtoul(buf, 0, &val) || val != 0) {			       \
-		retval = -EINVAL;					       \
-		goto out;						       \
-	}								       \
-									       \
-	zfcp_erp_modify_##_feat##_status(_feat, _mod_id, NULL,		       \
-					 ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);\
-	zfcp_erp_##_feat##_reopen(_feat, ZFCP_STATUS_COMMON_ERP_FAILED,	       \
-				  _reopen_id, NULL);			       \
-	zfcp_erp_wait(_adapter);					       \
-out:									       \
-	put_device(&_feat->dev);					       \
-	return retval ? retval : (ssize_t) count;			       \
-}									       \
-static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO,			       \
-		     zfcp_sysfs_##_feat##_failed_show,			       \
-		     zfcp_sysfs_##_feat##_failed_store);
+static ssize_t zfcp_sysfs_port_failed_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
 
-ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
-ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
+	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+		return sprintf(buf, "1\n");
+
+	return sprintf(buf, "0\n");
+}
+
+static ssize_t zfcp_sysfs_port_failed_store(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t count)
+{
+	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
+	unsigned long val;
+
+	if (strict_strtoul(buf, 0, &val) || val != 0)
+		return -EINVAL;
+
+	zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_RUNNING);
+	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, "sypfai2",
+			     NULL);
+	zfcp_erp_wait(port->adapter);
+
+	return count;
+}
+static ZFCP_DEV_ATTR(port, failed, S_IWUSR | S_IRUGO,
+		     zfcp_sysfs_port_failed_show,
+		     zfcp_sysfs_port_failed_store);
+
+static ssize_t zfcp_sysfs_unit_failed_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
+	struct scsi_device *sdev;
+	unsigned int status, failed = 1;
+
+	sdev = zfcp_unit_sdev(unit);
+	if (sdev) {
+		status = atomic_read(&sdev_to_zfcp(sdev)->status);
+		failed = status & ZFCP_STATUS_COMMON_ERP_FAILED ? 1 : 0;
+		scsi_device_put(sdev);
+	}
+
+	return sprintf(buf, "%d\n", failed);
+}
+
+static ssize_t zfcp_sysfs_unit_failed_store(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t count)
+{
+	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
+	unsigned long val;
+	struct scsi_device *sdev;
+
+	if (strict_strtoul(buf, 0, &val) || val != 0)
+		return -EINVAL;
+
+	sdev = zfcp_unit_sdev(unit);
+	if (sdev) {
+		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+		zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+				    "syufai2", NULL);
+		zfcp_erp_wait(unit->port->adapter);
+	} else
+		zfcp_unit_scsi_scan(unit);
+
+	return count;
+}
+static ZFCP_DEV_ATTR(unit, failed, S_IWUSR | S_IRUGO,
+		     zfcp_sysfs_unit_failed_show,
+		     zfcp_sysfs_unit_failed_store);
 
 static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev,
 					      struct device_attribute *attr,
@@ -163,8 +196,7 @@
 		goto out;
 	}
 
-	zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL,
-				       ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
+	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
 				"syafai2", NULL);
 	zfcp_erp_wait(adapter);
@@ -257,28 +289,15 @@
 					 const char *buf, size_t count)
 {
 	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
-	struct zfcp_unit *unit;
 	u64 fcp_lun;
-	int retval = -EINVAL;
-
-	if (!(port && get_device(&port->dev)))
-		return -EBUSY;
 
 	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
-		goto out;
+		return -EINVAL;
 
-	unit = zfcp_unit_enqueue(port, fcp_lun);
-	if (IS_ERR(unit))
-		goto out;
-	else
-		retval = 0;
+	if (zfcp_unit_add(port, fcp_lun))
+		return -EINVAL;
 
-	zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
-	zfcp_erp_wait(unit->port->adapter);
-	zfcp_scsi_scan(unit);
-out:
-	put_device(&port->dev);
-	return retval ? retval : (ssize_t) count;
+	return count;
 }
 static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
 
@@ -287,42 +306,15 @@
 					    const char *buf, size_t count)
 {
 	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
-	struct zfcp_unit *unit;
 	u64 fcp_lun;
-	int retval = -EINVAL;
-	struct scsi_device *sdev;
-
-	if (!(port && get_device(&port->dev)))
-		return -EBUSY;
 
 	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
-		goto out;
+		return -EINVAL;
 
-	unit = zfcp_get_unit_by_lun(port, fcp_lun);
-	if (!unit)
-		goto out;
-	else
-		retval = 0;
+	if (zfcp_unit_remove(port, fcp_lun))
+		return -EINVAL;
 
-	sdev = scsi_device_lookup(port->adapter->scsi_host, 0,
-				  port->starget_id,
-				  scsilun_to_int((struct scsi_lun *)&fcp_lun));
-	if (sdev) {
-		scsi_remove_device(sdev);
-		scsi_device_put(sdev);
-	}
-
-	write_lock_irq(&port->unit_list_lock);
-	list_del(&unit->list);
-	write_unlock_irq(&port->unit_list_lock);
-
-	put_device(&unit->dev);
-
-	zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
-	zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
-out:
-	put_device(&port->dev);
-	return retval ? retval : (ssize_t) count;
+	return count;
 }
 static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
 
@@ -363,9 +355,9 @@
 				       struct device_attribute *attr,	\
 				       char *buf) {			\
 	struct scsi_device *sdev = to_scsi_device(dev);			\
-	struct zfcp_unit *unit = sdev->hostdata;			\
-	struct zfcp_latencies *lat = &unit->latencies;			\
-	struct zfcp_adapter *adapter = unit->port->adapter;		\
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);		\
+	struct zfcp_latencies *lat = &zfcp_sdev->latencies;		\
+	struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;	\
 	unsigned long long fsum, fmin, fmax, csum, cmin, cmax, cc;	\
 									\
 	spin_lock_bh(&lat->lock);					\
@@ -394,8 +386,8 @@
 					const char *buf, size_t count)	\
 {									\
 	struct scsi_device *sdev = to_scsi_device(dev);			\
-	struct zfcp_unit *unit = sdev->hostdata;			\
-	struct zfcp_latencies *lat = &unit->latencies;			\
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);		\
+	struct zfcp_latencies *lat = &zfcp_sdev->latencies;		\
 	unsigned long flags;						\
 									\
 	spin_lock_irqsave(&lat->lock, flags);				\
@@ -423,19 +415,28 @@
 					      struct device_attribute *attr,\
 					      char *buf)                 \
 {                                                                        \
-	struct scsi_device *sdev  = to_scsi_device(dev);		 \
-	struct zfcp_unit *unit = sdev->hostdata;			 \
+	struct scsi_device *sdev = to_scsi_device(dev);			 \
+	struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);		 \
+	struct zfcp_port *port = zfcp_sdev->port;			 \
 									 \
 	return sprintf(buf, _format, _value);                            \
 }                                                                        \
 static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
 
 ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
-		      dev_name(&unit->port->adapter->ccw_device->dev));
+		      dev_name(&port->adapter->ccw_device->dev));
 ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
-		      (unsigned long long) unit->port->wwpn);
-ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n",
-		      (unsigned long long) unit->fcp_lun);
+		      (unsigned long long) port->wwpn);
+
+static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+
+	return sprintf(buf, "0x%016llx\n", zfcp_scsi_dev_lun(sdev));
+}
+static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_scsi_fcp_lun_show, NULL);
 
 struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
 	&dev_attr_fcp_lun,
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c
new file mode 100644
index 0000000..1119c53
--- /dev/null
+++ b/drivers/s390/scsi/zfcp_unit.c
@@ -0,0 +1,244 @@
+/*
+ * zfcp device driver
+ *
+ * Tracking of manually configured LUNs and helper functions to
+ * register the LUNs with the SCSI midlayer.
+ *
+ * Copyright IBM Corporation 2010
+ */
+
+#include "zfcp_def.h"
+#include "zfcp_ext.h"
+
+/**
+ * zfcp_unit_scsi_scan - Register LUN with SCSI midlayer
+ * @unit: The zfcp LUN/unit to register
+ *
+ * When the SCSI midlayer is not allowed to automatically scan and
+ * attach SCSI devices, zfcp has to register the single devices with
+ * the SCSI midlayer.
+ */
+void zfcp_unit_scsi_scan(struct zfcp_unit *unit)
+{
+	struct fc_rport *rport = unit->port->rport;
+	unsigned int lun;
+
+	lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
+
+	if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
+		scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, lun, 1);
+}
+
+static void zfcp_unit_scsi_scan_work(struct work_struct *work)
+{
+	struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
+					      scsi_work);
+
+	zfcp_unit_scsi_scan(unit);
+	put_device(&unit->dev);
+}
+
+/**
+ * zfcp_unit_queue_scsi_scan - Register configured units on port
+ * @port: The zfcp_port where to register units
+ *
+ * After opening a port, all units configured on this port have to be
+ * registered with the SCSI midlayer. This function should be called
+ * after calling fc_remote_port_add, so that the fc_rport is already
+ * ONLINE and the call to scsi_scan_target runs the same way as the
+ * call in the FC transport class.
+ */
+void zfcp_unit_queue_scsi_scan(struct zfcp_port *port)
+{
+	struct zfcp_unit *unit;
+
+	read_lock_irq(&port->unit_list_lock);
+	list_for_each_entry(unit, &port->unit_list, list) {
+		get_device(&unit->dev);
+		if (scsi_queue_work(port->adapter->scsi_host,
+				    &unit->scsi_work) <= 0)
+			put_device(&unit->dev);
+	}
+	read_unlock_irq(&port->unit_list_lock);
+}
+
+static struct zfcp_unit *_zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
+{
+	struct zfcp_unit *unit;
+
+	list_for_each_entry(unit, &port->unit_list, list)
+		if (unit->fcp_lun == fcp_lun) {
+			get_device(&unit->dev);
+			return unit;
+		}
+
+	return NULL;
+}
+
+/**
+ * zfcp_unit_find - Find and return zfcp_unit with specified FCP LUN
+ * @port: zfcp_port where to look for the unit
+ * @fcp_lun: 64 Bit FCP LUN used to identify the zfcp_unit
+ *
+ * If zfcp_unit is found, a reference is acquired that has to be
+ * released later.
+ *
+ * Returns: Pointer to the zfcp_unit, or NULL if there is no zfcp_unit
+ *          with the specified FCP LUN.
+ */
+struct zfcp_unit *zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
+{
+	struct zfcp_unit *unit;
+
+	read_lock_irq(&port->unit_list_lock);
+	unit = _zfcp_unit_find(port, fcp_lun);
+	read_unlock_irq(&port->unit_list_lock);
+	return unit;
+}
+
+/**
+ * zfcp_unit_release - Drop reference to zfcp_port and free memory of zfcp_unit.
+ * @dev: pointer to device in zfcp_unit
+ */
+static void zfcp_unit_release(struct device *dev)
+{
+	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
+
+	put_device(&unit->port->dev);
+	kfree(unit);
+}
+
+/**
+ * zfcp_unit_enqueue - enqueue unit to unit list of a port.
+ * @port: pointer to port where unit is added
+ * @fcp_lun: FCP LUN of unit to be enqueued
+ * Returns: 0 success
+ *
+ * Sets up some unit internal structures and creates sysfs entry.
+ */
+int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
+{
+	struct zfcp_unit *unit;
+
+	unit = zfcp_unit_find(port, fcp_lun);
+	if (unit) {
+		put_device(&unit->dev);
+		return -EEXIST;
+	}
+
+	unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
+	if (!unit)
+		return -ENOMEM;
+
+	unit->port = port;
+	unit->fcp_lun = fcp_lun;
+	unit->dev.parent = &port->dev;
+	unit->dev.release = zfcp_unit_release;
+	INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work);
+
+	if (dev_set_name(&unit->dev, "0x%016llx",
+			 (unsigned long long) fcp_lun)) {
+		kfree(unit);
+		return -ENOMEM;
+	}
+
+	if (device_register(&unit->dev)) {
+		put_device(&unit->dev);
+		return -ENOMEM;
+	}
+
+	if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
+		device_unregister(&unit->dev);
+		return -EINVAL;
+	}
+
+	get_device(&port->dev);
+
+	write_lock_irq(&port->unit_list_lock);
+	list_add_tail(&unit->list, &port->unit_list);
+	write_unlock_irq(&port->unit_list_lock);
+
+	zfcp_unit_scsi_scan(unit);
+
+	return 0;
+}
+
+/**
+ * zfcp_unit_sdev - Return SCSI device for zfcp_unit
+ * @unit: The zfcp_unit where to get the SCSI device for
+ *
+ * Returns: scsi_device pointer on success, NULL if there is no SCSI
+ *          device for this zfcp_unit
+ *
+ * On success, the caller also holds a reference to the SCSI device
+ * that must be released with scsi_device_put.
+ */
+struct scsi_device *zfcp_unit_sdev(struct zfcp_unit *unit)
+{
+	struct Scsi_Host *shost;
+	struct zfcp_port *port;
+	unsigned int lun;
+
+	lun = scsilun_to_int((struct scsi_lun *) &unit->fcp_lun);
+	port = unit->port;
+	shost = port->adapter->scsi_host;
+	return scsi_device_lookup(shost, 0, port->starget_id, lun);
+}
+
+/**
+ * zfcp_unit_sdev_status - Return zfcp LUN status for SCSI device
+ * @unit: The unit to lookup the SCSI device for
+ *
+ * Returns the zfcp LUN status field of the SCSI device if the SCSI device
+ * for the zfcp_unit exists, 0 otherwise.
+ */
+unsigned int zfcp_unit_sdev_status(struct zfcp_unit *unit)
+{
+	unsigned int status = 0;
+	struct scsi_device *sdev;
+	struct zfcp_scsi_dev *zfcp_sdev;
+
+	sdev = zfcp_unit_sdev(unit);
+	if (sdev) {
+		zfcp_sdev = sdev_to_zfcp(sdev);
+		status = atomic_read(&zfcp_sdev->status);
+		scsi_device_put(sdev);
+	}
+
+	return status;
+}
+
+/**
+ * zfcp_unit_remove - Remove entry from list of configured units
+ * @port: The port where to remove the unit from the configuration
+ * @fcp_lun: The 64 bit LUN of the unit to remove
+ *
+ * Returns: -EINVAL if a unit with the specified LUN does not exist,
+ *          0 on success.
+ */
+int zfcp_unit_remove(struct zfcp_port *port, u64 fcp_lun)
+{
+	struct zfcp_unit *unit;
+	struct scsi_device *sdev;
+
+	write_lock_irq(&port->unit_list_lock);
+	unit = _zfcp_unit_find(port, fcp_lun);
+	if (unit)
+		list_del(&unit->list);
+	write_unlock_irq(&port->unit_list_lock);
+
+	if (!unit)
+		return -EINVAL;
+
+	sdev = zfcp_unit_sdev(unit);
+	if (sdev) {
+		scsi_remove_device(sdev);
+		scsi_device_put(sdev);
+	}
+
+	put_device(&unit->dev);
+
+	zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
+
+	return 0;
+}
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 1690e53..55f71ea 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -162,6 +162,7 @@
 	.compat_ioctl =		d7s_ioctl,
 	.open =			d7s_open,
 	.release =		d7s_release,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice d7s_miscdev = {
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 078e5f4..8ce414e 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -720,6 +720,7 @@
 #endif
 	.open =			envctrl_open,
 	.release =		envctrl_release,
+	.llseek =		noop_llseek,
 };	
 
 static struct miscdevice envctrl_dev = {
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 4942050..13f48e2 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -27,7 +27,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
@@ -68,6 +68,8 @@
 #define JSF_PART_BITS	 2	/* 2 bits of minors to cover JSF_NPART */
 #define JSF_PART_MASK	 0x3	/* 2 bits mask */
 
+static DEFINE_MUTEX(jsf_mutex);
+
 /*
  * Access functions.
  * We could ioremap(), but it's easier this way.
@@ -225,7 +227,7 @@
 {
 	loff_t ret;
 
-	lock_kernel();
+	mutex_lock(&jsf_mutex);
 	switch (orig) {
 		case 0:
 			file->f_pos = offset;
@@ -238,7 +240,7 @@
 		default:
 			ret = -EINVAL;
 	}
-	unlock_kernel();
+	mutex_unlock(&jsf_mutex);
 	return ret;
 }
 
@@ -384,18 +386,18 @@
 
 static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
-	lock_kernel();
+	mutex_lock(&jsf_mutex);
 	int error = -ENOTTY;
 	void __user *argp = (void __user *)arg;
 
 	if (!capable(CAP_SYS_ADMIN)) {
-		unlock_kernel();
+		mutex_unlock(&jsf_mutex);
 		return -EPERM;
 	}
 	switch (cmd) {
 	case JSFLASH_IDENT:
 		if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) {
-			unlock_kernel();
+			mutex_unlock(&jsf_mutex);
 			return -EFAULT;
 		}
 		break;
@@ -407,7 +409,7 @@
 		break;
 	}
 
-	unlock_kernel();
+	mutex_unlock(&jsf_mutex);
 	return error;
 }
 
@@ -418,17 +420,17 @@
 
 static int jsf_open(struct inode * inode, struct file * filp)
 {
-	lock_kernel();
+	mutex_lock(&jsf_mutex);
 	if (jsf0.base == 0) {
-		unlock_kernel();
+		mutex_unlock(&jsf_mutex);
 		return -ENXIO;
 	}
 	if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) {
-		unlock_kernel();
+		mutex_unlock(&jsf_mutex);
 		return -EBUSY;
 	}
 
-	unlock_kernel();
+	mutex_unlock(&jsf_mutex);
 	return 0;	/* XXX What security? */
 }
 
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index e20b7bd..fcf08b3 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -92,7 +92,6 @@
 #include <linux/pci.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -105,6 +104,7 @@
 
 /* Globals */
 #define TW_DRIVER_VERSION "2.26.02.014"
+static DEFINE_MUTEX(twa_chrdev_mutex);
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -222,7 +222,8 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= twa_chrdev_ioctl,
 	.open		= twa_chrdev_open,
-	.release	= NULL
+	.release	= NULL,
+	.llseek		= noop_llseek,
 };
 
 /* This function will complete an aen request from the isr */
@@ -658,7 +659,7 @@
 	int retval = TW_IOCTL_ERROR_OS_EFAULT;
 	void __user *argp = (void __user *)arg;
 
-	lock_kernel();
+	mutex_lock(&twa_chrdev_mutex);
 
 	/* Only let one of these through at a time */
 	if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
@@ -879,7 +880,7 @@
 out2:
 	mutex_unlock(&tw_dev->ioctl_lock);
 out:
-	unlock_kernel();
+	mutex_unlock(&twa_chrdev_mutex);
 	return retval;
 } /* End twa_chrdev_ioctl() */
 
@@ -890,7 +891,6 @@
 	unsigned int minor_number;
 	int retval = TW_IOCTL_ERROR_OS_ENODEV;
 
-	cycle_kernel_lock();
 	minor_number = iminor(inode);
 	if (minor_number >= twa_device_extension_count)
 		goto out;
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index f481e73..6a95d11 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -64,7 +64,6 @@
 #include <linux/pci.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -77,6 +76,7 @@
 
 /* Globals */
 #define TW_DRIVER_VERSION "3.26.02.000"
+static DEFINE_MUTEX(twl_chrdev_mutex);
 static TW_Device_Extension *twl_device_extension_list[TW_MAX_SLOT];
 static unsigned int twl_device_extension_count;
 static int twl_major = -1;
@@ -764,7 +764,7 @@
 	int retval = -EFAULT;
 	void __user *argp = (void __user *)arg;
 
-	lock_kernel();
+	mutex_lock(&twl_chrdev_mutex);
 
 	/* Only let one of these through at a time */
 	if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
@@ -861,7 +861,7 @@
 out2:
 	mutex_unlock(&tw_dev->ioctl_lock);
 out:
-	unlock_kernel();
+	mutex_unlock(&twl_chrdev_mutex);
 	return retval;
 } /* End twl_chrdev_ioctl() */
 
@@ -876,7 +876,6 @@
 		goto out;
 	}
 
-	cycle_kernel_lock();
 	minor_number = iminor(inode);
 	if (minor_number >= twl_device_extension_count)
 		goto out;
@@ -890,7 +889,8 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= twl_chrdev_ioctl,
 	.open		= twl_chrdev_open,
-	.release	= NULL
+	.release	= NULL,
+	.llseek		= noop_llseek,
 };
 
 /* This function passes sense data from firmware to scsi layer */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 30d735a..b112534 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -199,7 +199,6 @@
 
 #include <linux/module.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/moduleparam.h>
@@ -221,6 +220,7 @@
 
 /* Globals */
 #define TW_DRIVER_VERSION "1.26.02.003"
+static DEFINE_MUTEX(tw_mutex);
 static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 static int tw_device_extension_count = 0;
 static int twe_major = -1;
@@ -900,10 +900,10 @@
 
 	dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
 
-	lock_kernel();
+	mutex_lock(&tw_mutex);
 	/* Only let one of these through at a time */
 	if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
-		unlock_kernel();
+		mutex_unlock(&tw_mutex);
 		return -EINTR;
 	}
 
@@ -1034,7 +1034,7 @@
 	dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
 out:
 	mutex_unlock(&tw_dev->ioctl_lock);
-	unlock_kernel();
+	mutex_unlock(&tw_mutex);
 	return retval;
 } /* End tw_chrdev_ioctl() */
 
@@ -1044,7 +1044,6 @@
 {
 	unsigned int minor_number;
 
-	cycle_kernel_lock();
 	dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
 
 	minor_number = iminor(inode);
@@ -1059,7 +1058,8 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= tw_chrdev_ioctl,
 	.open		= tw_chrdev_open,
-	.release	= NULL
+	.release	= NULL,
+	.llseek		= noop_llseek,
 };
 
 /* This function will free up device extension resources */
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index bbf91ae..2e9632e 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -316,7 +316,8 @@
 
 config SCSI_SAS_ATTRS
 	tristate "SAS Transport Attributes"
-	depends on SCSI && BLK_DEV_BSG
+	depends on SCSI
+	select BLK_DEV_BSG
 	help
 	  If you wish to export transport-specific information about
 	  each attached SAS device to sysfs, say Y.
@@ -378,7 +379,7 @@
 	  via sysfs to userspace. If you wish to export this information,
 	  say Y. Otherwise, say N.
 
-source "drivers/scsi/cxgb3i/Kconfig"
+source "drivers/scsi/cxgbi/Kconfig"
 source "drivers/scsi/bnx2i/Kconfig"
 source "drivers/scsi/be2iscsi/Kconfig"
 
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 2703c6e..2e9a87e 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -133,7 +133,8 @@
 obj-$(CONFIG_SCSI_STEX)		+= stex.o
 obj-$(CONFIG_SCSI_MVSAS)	+= mvsas/
 obj-$(CONFIG_PS3_ROM)		+= ps3rom.o
-obj-$(CONFIG_SCSI_CXGB3_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB3_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgbi/
+obj-$(CONFIG_SCSI_CXGB4_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgbi/
 obj-$(CONFIG_SCSI_BNX2_ISCSI)	+= libiscsi.o bnx2i/
 obj-$(CONFIG_BE2ISCSI)		+= libiscsi.o be2iscsi/
 obj-$(CONFIG_SCSI_PMCRAID)	+= pmcraid.o
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 1a5bf57..645ddd9 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -190,7 +190,7 @@
 		/*
 		 *	Initialize the mutex used to wait for the next AIF.
 		 */
-		init_MUTEX_LOCKED(&fibctx->wait_sem);
+		sema_init(&fibctx->wait_sem, 0);
 		fibctx->wait = 0;
 		/*
 		 *	Initialize the fibs and set the count of fibs on
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 7007914..afc9aeb 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -124,7 +124,7 @@
 		fibptr->hw_fib_va = hw_fib;
 		fibptr->data = (void *) fibptr->hw_fib_va->data;
 		fibptr->next = fibptr+1;	/* Forward chain the fibs */
-		init_MUTEX_LOCKED(&fibptr->event_wait);
+		sema_init(&fibptr->event_wait, 0);
 		spin_lock_init(&fibptr->event_lock);
 		hw_fib->header.XferState = cpu_to_le32(0xffffffff);
 		hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index cad6f9a..dae46d7 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -38,7 +38,7 @@
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
 #include <linux/delay.h>
@@ -76,6 +76,7 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
 
+static DEFINE_MUTEX(aac_mutex);
 static LIST_HEAD(aac_devices);
 static int aac_cfg_major = -1;
 char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
@@ -678,7 +679,7 @@
 	unsigned minor_number = iminor(inode);
 	int err = -ENODEV;
 
-	lock_kernel();  /* BKL pushdown: nothing else protects this list */
+	mutex_lock(&aac_mutex);  /* BKL pushdown: nothing else protects this list */
 	list_for_each_entry(aac, &aac_devices, entry) {
 		if (aac->id == minor_number) {
 			file->private_data = aac;
@@ -686,7 +687,7 @@
 			break;
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&aac_mutex);
 
 	return err;
 }
@@ -711,9 +712,9 @@
 	int ret;
 	if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
-	lock_kernel();
+	mutex_lock(&aac_mutex);
 	ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg);
-	unlock_kernel();
+	mutex_unlock(&aac_mutex);
 
 	return ret;
 }
@@ -722,7 +723,7 @@
 static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&aac_mutex);
 	switch (cmd) {
 	case FSACTL_MINIPORT_REV_CHECK:
 	case FSACTL_SENDFIB:
@@ -756,7 +757,7 @@
 		ret = -ENOIOCTLCMD;
 		break;
 	}
-	unlock_kernel();
+	mutex_unlock(&aac_mutex);
 	return ret;
 }
 
@@ -1039,6 +1040,7 @@
 	.compat_ioctl   = aac_compat_cfg_ioctl,
 #endif
 	.open		= aac_cfg_open,
+	.llseek		= noop_llseek,
 };
 
 static struct scsi_host_template aac_driver_template = {
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 93984c9..aee73fa 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -2850,12 +2850,6 @@
       aic_dev->r_total++;
       ptr = aic_dev->r_bins;
     }
-    if(cmd->device->simple_tags && cmd->request->cmd_flags & REQ_HARDBARRIER)
-    {
-      aic_dev->barrier_total++;
-      if(scb->tag_action == MSG_ORDERED_Q_TAG)
-        aic_dev->ordered_total++;
-    }
     x = scb->sg_length;
     x >>= 10;
     for(i=0; i<6; i++)
@@ -10125,7 +10119,6 @@
   struct aic_dev_data *aic_dev = cmd->device->hostdata;
   struct scsi_device *sdptr = cmd->device;
   unsigned char tindex = TARGET_INDEX(cmd);
-  struct request *req = cmd->request;
   int use_sg;
 
   mask = (0x01 << tindex);
@@ -10144,19 +10137,8 @@
     /* We always force TEST_UNIT_READY to untagged */
     if (cmd->cmnd[0] != TEST_UNIT_READY && sdptr->simple_tags)
     {
-      if (req->cmd_flags & REQ_HARDBARRIER)
-      {
-	if(sdptr->ordered_tags)
-	{
-          hscb->control |= MSG_ORDERED_Q_TAG;
-          scb->tag_action = MSG_ORDERED_Q_TAG;
-	}
-      }
-      else
-      {
-        hscb->control |= MSG_SIMPLE_Q_TAG;
-        scb->tag_action = MSG_SIMPLE_Q_TAG;
-      }
+      hscb->control |= MSG_SIMPLE_Q_TAG;
+      scb->tag_action = MSG_SIMPLE_Q_TAG;
     }
   }
   if ( !(aic_dev->dtr_pending) &&
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index c8dc392..05a78e5 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -878,8 +878,8 @@
 	if (!error) {
 		if (acb->devstate[id][lun] == ARECA_RAID_GONE)
 			acb->devstate[id][lun] = ARECA_RAID_GOOD;
-			ccb->pcmd->result = DID_OK << 16;
-			arcmsr_ccb_complete(ccb);
+		ccb->pcmd->result = DID_OK << 16;
+		arcmsr_ccb_complete(ccb);
 	}else{
 		switch (ccb->arcmsr_cdb.DeviceStatus) {
 		case ARCMSR_DEV_SELECT_TIMEOUT: {
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 7c75373..ad24636 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -335,7 +335,7 @@
 		if (ready)
 			break;
 
-		if (cnt > 6000000) {
+		if (cnt > 12000000) {
 			dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n");
 			return -EBUSY;
 		}
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 7f11f3e..eaaa881 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -522,7 +522,6 @@
 	if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
 				  phba->params.cxns_per_ctrl * 2)) {
 		SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
-		beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
 		goto free_ep;
 	}
 
@@ -559,7 +558,6 @@
 		SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed"
 				    " status = %d extd_status = %d\n",
 				    status, extd_status);
-		beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
 		free_mcc_tag(&phba->ctrl, tag);
 		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 			    nonemb_cmd.va, nonemb_cmd.dma);
@@ -574,7 +572,6 @@
 		beiscsi_ep->cid_vld = 1;
 		SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
 	}
-	beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
 	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
 			    nonemb_cmd.va, nonemb_cmd.dma);
 	return 0;
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 8220bde..75a85aa 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -2040,7 +2040,7 @@
 	      unsigned int num_sg, struct beiscsi_io_task *io_task)
 {
 	struct iscsi_sge *psgl;
-	unsigned short sg_len, index;
+	unsigned int sg_len, index;
 	unsigned int sge_len = 0;
 	unsigned long long addr;
 	struct scatterlist *l_sg;
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile
index ac3fdf0..d2eefd3 100644
--- a/drivers/scsi/bfa/Makefile
+++ b/drivers/scsi/bfa/Makefile
@@ -1,15 +1,8 @@
 obj-$(CONFIG_SCSI_BFA_FC) := bfa.o
 
-bfa-y := bfad.o bfad_intr.o bfad_os.o bfad_im.o bfad_attr.o bfad_fwimg.o
-bfa-y += bfad_debugfs.o
-bfa-y += bfa_core.o bfa_ioc.o bfa_ioc_ct.o bfa_ioc_cb.o bfa_iocfc.o bfa_fcxp.o
-bfa-y += bfa_lps.o bfa_hw_cb.o bfa_hw_ct.o bfa_intr.o bfa_timer.o bfa_rport.o
-bfa-y += bfa_fcport.o bfa_port.o bfa_uf.o bfa_sgpg.o bfa_module.o bfa_ioim.o
-bfa-y += bfa_itnim.o bfa_fcpim.o bfa_tskim.o bfa_log.o bfa_log_module.o
-bfa-y += bfa_csdebug.o bfa_sm.o plog.o
+bfa-y := bfad.o bfad_im.o bfad_attr.o bfad_debugfs.o
+bfa-y += bfa_ioc.o bfa_ioc_cb.o bfa_ioc_ct.o bfa_hw_cb.o bfa_hw_ct.o
+bfa-y += bfa_fcs.o bfa_fcs_lport.o bfa_fcs_rport.o bfa_fcs_fcpim.o bfa_fcbuild.o
+bfa-y += bfa_port.o bfa_fcpim.o bfa_core.o bfa_drv.o bfa_svc.o
 
-bfa-y += fcbuild.o fabric.o fcpim.o vfapi.o fcptm.o bfa_fcs.o bfa_fcs_port.o
-bfa-y += bfa_fcs_uf.o bfa_fcs_lport.o fab.o fdmi.o ms.o ns.o scn.o loop.o
-bfa-y += lport_api.o n2n.o rport.o rport_api.o rport_ftrs.o vport.o
-
-ccflags-y := -I$(obj) -I$(obj)/include -I$(obj)/include/cna -DBFA_PERF_BUILD
+ccflags-y := -DBFA_PERF_BUILD
diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h
new file mode 100644
index 0000000..ceaac65
--- /dev/null
+++ b/drivers/scsi/bfa/bfa.h
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+#ifndef __BFA_H__
+#define __BFA_H__
+
+#include "bfa_os_inc.h"
+#include "bfa_cs.h"
+#include "bfa_plog.h"
+#include "bfa_defs_svc.h"
+#include "bfi.h"
+#include "bfa_ioc.h"
+
+struct bfa_s;
+
+typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
+typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
+
+/**
+ * Interrupt message handlers
+ */
+void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
+void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
+
+/**
+ * Request and response queue related defines
+ */
+#define BFA_REQQ_NELEMS_MIN	(4)
+#define BFA_RSPQ_NELEMS_MIN	(4)
+
+#define bfa_reqq_pi(__bfa, __reqq)	((__bfa)->iocfc.req_cq_pi[__reqq])
+#define bfa_reqq_ci(__bfa, __reqq)					\
+	(*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva))
+
+#define bfa_reqq_full(__bfa, __reqq)				\
+	(((bfa_reqq_pi(__bfa, __reqq) + 1) &			\
+	  ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) ==	\
+	 bfa_reqq_ci(__bfa, __reqq))
+
+#define bfa_reqq_next(__bfa, __reqq)					\
+	(bfa_reqq_full(__bfa, __reqq) ? NULL :				\
+	 ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
+		   + bfa_reqq_pi((__bfa), (__reqq)))))
+
+#define bfa_reqq_produce(__bfa, __reqq)	do {				\
+		(__bfa)->iocfc.req_cq_pi[__reqq]++;			\
+		(__bfa)->iocfc.req_cq_pi[__reqq] &=			\
+			((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1);      \
+		bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq],	\
+			      (__bfa)->iocfc.req_cq_pi[__reqq]);      \
+		mmiowb();      \
+	} while (0)
+
+#define bfa_rspq_pi(__bfa, __rspq)					\
+	(*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva))
+
+#define bfa_rspq_ci(__bfa, __rspq)	((__bfa)->iocfc.rsp_cq_ci[__rspq])
+#define bfa_rspq_elem(__bfa, __rspq, __ci)				\
+	(&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci])
+
+#define CQ_INCR(__index, __size) do {			\
+	(__index)++;					\
+	(__index) &= ((__size) - 1);			\
+} while (0)
+
+/**
+ * Queue element to wait for room in request queue. FIFO order is
+ * maintained when fullfilling requests.
+ */
+struct bfa_reqq_wait_s {
+	struct list_head	qe;
+	void		(*qresume) (void *cbarg);
+	void		*cbarg;
+};
+
+/**
+ * Circular queue usage assignments
+ */
+enum {
+	BFA_REQQ_IOC	= 0,	/*  all low-priority IOC msgs	*/
+	BFA_REQQ_FCXP	= 0,	/*  all FCXP messages		*/
+	BFA_REQQ_LPS	= 0,	/*  all lport service msgs	*/
+	BFA_REQQ_PORT	= 0,	/*  all port messages		*/
+	BFA_REQQ_FLASH	= 0,	/*  for flash module		*/
+	BFA_REQQ_DIAG	= 0,	/*  for diag module		*/
+	BFA_REQQ_RPORT	= 0,	/*  all port messages		*/
+	BFA_REQQ_SBOOT	= 0,	/*  all san boot messages	*/
+	BFA_REQQ_QOS_LO	= 1,	/*  all low priority IO	*/
+	BFA_REQQ_QOS_MD	= 2,	/*  all medium priority IO	*/
+	BFA_REQQ_QOS_HI	= 3,	/*  all high priority IO	*/
+};
+
+static inline void
+bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
+	       void *cbarg)
+{
+	wqe->qresume = qresume;
+	wqe->cbarg = cbarg;
+}
+
+#define bfa_reqq(__bfa, __reqq)	(&(__bfa)->reqq_waitq[__reqq])
+
+/**
+ * static inline void
+ * bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
+ */
+#define bfa_reqq_wait(__bfa, __reqq, __wqe) do {			\
+									\
+		struct list_head *waitq = bfa_reqq(__bfa, __reqq);      \
+									\
+		bfa_assert(((__reqq) < BFI_IOC_MAX_CQS));      \
+		bfa_assert((__wqe)->qresume && (__wqe)->cbarg);      \
+									\
+		list_add_tail(&(__wqe)->qe, waitq);      \
+	} while (0)
+
+#define bfa_reqq_wcancel(__wqe)	list_del(&(__wqe)->qe)
+
+
+/**
+ * Generic BFA callback element.
+ */
+struct bfa_cb_qe_s {
+	struct list_head         qe;
+	bfa_cb_cbfn_t  cbfn;
+	bfa_boolean_t   once;
+	u32		rsvd;
+	void           *cbarg;
+};
+
+#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\
+		(__hcb_qe)->cbfn  = (__cbfn);      \
+		(__hcb_qe)->cbarg = (__cbarg);      \
+		list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \
+	} while (0)
+
+#define bfa_cb_dequeue(__hcb_qe)	list_del(&(__hcb_qe)->qe)
+
+#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\
+		(__hcb_qe)->cbfn  = (__cbfn);      \
+		(__hcb_qe)->cbarg = (__cbarg);      \
+		if (!(__hcb_qe)->once) {      \
+			list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \
+			(__hcb_qe)->once = BFA_TRUE;			\
+		}							\
+	} while (0)
+
+#define bfa_cb_queue_done(__hcb_qe) do {	\
+		(__hcb_qe)->once = BFA_FALSE;	\
+	} while (0)
+
+
+/**
+ * PCI devices supported by the current BFA
+ */
+struct bfa_pciid_s {
+	u16	device_id;
+	u16	vendor_id;
+};
+
+extern char     bfa_version[];
+
+/**
+ * BFA memory resources
+ */
+enum bfa_mem_type {
+	BFA_MEM_TYPE_KVA = 1,	/*  Kernel Virtual Memory *(non-dma-able) */
+	BFA_MEM_TYPE_DMA = 2,	/*  DMA-able memory */
+	BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
+};
+
+struct bfa_mem_elem_s {
+	enum bfa_mem_type mem_type;	/* see enum bfa_mem_type */
+	u32	mem_len;	/*  Total Length in Bytes	*/
+	u8		*kva;		/*  kernel virtual address	*/
+	u64	dma;		/*  dma address if DMA memory	*/
+	u8		*kva_curp;	/*  kva allocation cursor	*/
+	u64	dma_curp;	/*  dma allocation cursor	*/
+};
+
+struct bfa_meminfo_s {
+	struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
+};
+#define bfa_meminfo_kva(_m)				\
+	((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
+#define bfa_meminfo_dma_virt(_m)			\
+	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
+#define bfa_meminfo_dma_phys(_m)			\
+	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
+
+struct bfa_iocfc_regs_s {
+	bfa_os_addr_t   intr_status;
+	bfa_os_addr_t   intr_mask;
+	bfa_os_addr_t   cpe_q_pi[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   cpe_q_ci[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   cpe_q_depth[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   cpe_q_ctrl[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   rme_q_ci[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   rme_q_pi[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   rme_q_depth[BFI_IOC_MAX_CQS];
+	bfa_os_addr_t   rme_q_ctrl[BFI_IOC_MAX_CQS];
+};
+
+/**
+ * MSIX vector handlers
+ */
+#define BFA_MSIX_MAX_VECTORS	22
+typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
+struct bfa_msix_s {
+	int	nvecs;
+	bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
+};
+
+/**
+ * Chip specific interfaces
+ */
+struct bfa_hwif_s {
+	void (*hw_reginit)(struct bfa_s *bfa);
+	void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
+	void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
+	void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
+	void (*hw_msix_install)(struct bfa_s *bfa);
+	void (*hw_msix_uninstall)(struct bfa_s *bfa);
+	void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
+	void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
+				u32 *nvecs, u32 *maxvec);
+	void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
+				       u32 *end);
+};
+typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
+
+struct bfa_iocfc_s {
+	struct bfa_s		*bfa;
+	struct bfa_iocfc_cfg_s	cfg;
+	int			action;
+	u32		req_cq_pi[BFI_IOC_MAX_CQS];
+	u32		rsp_cq_ci[BFI_IOC_MAX_CQS];
+	struct bfa_cb_qe_s	init_hcb_qe;
+	struct bfa_cb_qe_s	stop_hcb_qe;
+	struct bfa_cb_qe_s	dis_hcb_qe;
+	struct bfa_cb_qe_s	stats_hcb_qe;
+	bfa_boolean_t		cfgdone;
+
+	struct bfa_dma_s	cfg_info;
+	struct bfi_iocfc_cfg_s *cfginfo;
+	struct bfa_dma_s	cfgrsp_dma;
+	struct bfi_iocfc_cfgrsp_s *cfgrsp;
+	struct bfi_iocfc_cfg_reply_s *cfg_reply;
+	struct bfa_dma_s	req_cq_ba[BFI_IOC_MAX_CQS];
+	struct bfa_dma_s	req_cq_shadow_ci[BFI_IOC_MAX_CQS];
+	struct bfa_dma_s	rsp_cq_ba[BFI_IOC_MAX_CQS];
+	struct bfa_dma_s	rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
+	struct bfa_iocfc_regs_s	bfa_regs;	/*  BFA device registers */
+	struct bfa_hwif_s	hwif;
+	bfa_cb_iocfc_t		updateq_cbfn; /*  bios callback function */
+	void			*updateq_cbarg;	/*  bios callback arg */
+	u32	intr_mask;
+};
+
+#define bfa_lpuid(__bfa)						\
+	bfa_ioc_portid(&(__bfa)->ioc)
+#define bfa_msix_init(__bfa, __nvecs)					\
+	((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
+#define bfa_msix_install(__bfa)						\
+	((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
+#define bfa_msix_uninstall(__bfa)					\
+	((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
+#define bfa_isr_mode_set(__bfa, __msix)					\
+	((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
+#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)		\
+	((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap,		\
+					__nvecs, __maxvec))
+#define bfa_msix_get_rme_range(__bfa, __start, __end)			\
+	((__bfa)->iocfc.hwif.hw_msix_get_rme_range(__bfa, __start, __end))
+#define bfa_msix(__bfa, __vec)						\
+	((__bfa)->msix.handler[__vec](__bfa, __vec))
+
+/*
+ * FC specific IOC functions.
+ */
+void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		       u32 *dm_len);
+void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
+		      struct bfa_iocfc_cfg_s *cfg,
+		      struct bfa_meminfo_s *meminfo,
+		      struct bfa_pcidev_s *pcidev);
+void bfa_iocfc_detach(struct bfa_s *bfa);
+void bfa_iocfc_init(struct bfa_s *bfa);
+void bfa_iocfc_start(struct bfa_s *bfa);
+void bfa_iocfc_stop(struct bfa_s *bfa);
+void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
+void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
+bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
+void bfa_iocfc_reset_queues(struct bfa_s *bfa);
+
+void bfa_msix_all(struct bfa_s *bfa, int vec);
+void bfa_msix_reqq(struct bfa_s *bfa, int vec);
+void bfa_msix_rspq(struct bfa_s *bfa, int vec);
+void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
+
+void bfa_hwcb_reginit(struct bfa_s *bfa);
+void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
+void bfa_hwcb_msix_install(struct bfa_s *bfa);
+void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
+void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
+void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
+			   u32 *maxvec);
+void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
+				 u32 *end);
+void bfa_hwct_reginit(struct bfa_s *bfa);
+void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
+void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
+void bfa_hwct_msix_install(struct bfa_s *bfa);
+void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
+void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
+void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, u32 *nvecs,
+			   u32 *maxvec);
+void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start,
+				 u32 *end);
+void bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi);
+void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
+wwn_t bfa_iocfc_get_pwwn(struct bfa_s *bfa);
+wwn_t bfa_iocfc_get_nwwn(struct bfa_s *bfa);
+void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa,
+				struct bfa_boot_pbc_s *pbcfg);
+int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
+				struct bfi_pbc_vport_s *pbc_vport);
+
+
+/**
+ *----------------------------------------------------------------------
+ *		BFA public interfaces
+ *----------------------------------------------------------------------
+ */
+#define bfa_stats(_mod, _stats)	((_mod)->stats._stats++)
+#define bfa_ioc_get_stats(__bfa, __ioc_stats)		\
+	bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
+#define bfa_ioc_clear_stats(__bfa)		\
+	bfa_ioc_clr_stats(&(__bfa)->ioc)
+#define bfa_get_nports(__bfa)			\
+	bfa_ioc_get_nports(&(__bfa)->ioc)
+#define bfa_get_adapter_manufacturer(__bfa, __manufacturer)		\
+	bfa_ioc_get_adapter_manufacturer(&(__bfa)->ioc, __manufacturer)
+#define bfa_get_adapter_model(__bfa, __model)			\
+	bfa_ioc_get_adapter_model(&(__bfa)->ioc, __model)
+#define bfa_get_adapter_serial_num(__bfa, __serial_num)			\
+	bfa_ioc_get_adapter_serial_num(&(__bfa)->ioc, __serial_num)
+#define bfa_get_adapter_fw_ver(__bfa, __fw_ver)			\
+	bfa_ioc_get_adapter_fw_ver(&(__bfa)->ioc, __fw_ver)
+#define bfa_get_adapter_optrom_ver(__bfa, __optrom_ver)			\
+	bfa_ioc_get_adapter_optrom_ver(&(__bfa)->ioc, __optrom_ver)
+#define bfa_get_pci_chip_rev(__bfa, __chip_rev)			\
+	bfa_ioc_get_pci_chip_rev(&(__bfa)->ioc, __chip_rev)
+#define bfa_get_ioc_state(__bfa)		\
+	bfa_ioc_get_state(&(__bfa)->ioc)
+#define bfa_get_type(__bfa)			\
+	bfa_ioc_get_type(&(__bfa)->ioc)
+#define bfa_get_mac(__bfa)			\
+	bfa_ioc_get_mac(&(__bfa)->ioc)
+#define bfa_get_mfg_mac(__bfa)			\
+	bfa_ioc_get_mfg_mac(&(__bfa)->ioc)
+#define bfa_get_fw_clock_res(__bfa)		\
+	((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res)
+
+void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
+void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
+void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
+void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
+			 struct bfa_meminfo_s *meminfo);
+void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		struct bfa_meminfo_s *meminfo,
+		struct bfa_pcidev_s *pcidev);
+void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
+void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
+void bfa_detach(struct bfa_s *bfa);
+void bfa_init(struct bfa_s *bfa);
+void bfa_start(struct bfa_s *bfa);
+void bfa_stop(struct bfa_s *bfa);
+void bfa_attach_fcs(struct bfa_s *bfa);
+void bfa_cb_init(void *bfad, bfa_status_t status);
+void bfa_cb_updateq(void *bfad, bfa_status_t status);
+
+bfa_boolean_t bfa_intx(struct bfa_s *bfa);
+void bfa_intx_disable(struct bfa_s *bfa);
+void bfa_intx_enable(struct bfa_s *bfa);
+void bfa_isr_enable(struct bfa_s *bfa);
+void bfa_isr_disable(struct bfa_s *bfa);
+
+void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
+void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);
+void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);
+
+typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
+void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
+void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
+
+void bfa_adapter_get_attr(struct bfa_s *bfa,
+			  struct bfa_adapter_attr_s *ad_attr);
+u64 bfa_adapter_get_id(struct bfa_s *bfa);
+
+bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
+				   struct bfa_iocfc_intr_attr_s *attr);
+
+void bfa_iocfc_enable(struct bfa_s *bfa);
+void bfa_iocfc_disable(struct bfa_s *bfa);
+void bfa_chip_reset(struct bfa_s *bfa);
+void bfa_timer_tick(struct bfa_s *bfa);
+#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout)		\
+	bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
+
+/*
+ * BFA debug API functions
+ */
+bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
+bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
+bfa_status_t bfa_debug_fwcore(struct bfa_s *bfa, void *buf,
+			      u32 *offset, int *buflen);
+void bfa_debug_fwsave_clear(struct bfa_s *bfa);
+bfa_status_t bfa_fw_stats_get(struct bfa_s *bfa, void *data);
+bfa_status_t bfa_fw_stats_clear(struct bfa_s *bfa);
+
+#endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/bfa_callback_priv.h b/drivers/scsi/bfa/bfa_callback_priv.h
deleted file mode 100644
index 1e3265c..0000000
--- a/drivers/scsi/bfa/bfa_callback_priv.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_CALLBACK_PRIV_H__
-#define __BFA_CALLBACK_PRIV_H__
-
-#include <cs/bfa_q.h>
-
-typedef void    (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
-
-/**
- * Generic BFA callback element.
- */
-struct bfa_cb_qe_s {
-	struct list_head         qe;
-	bfa_cb_cbfn_t  cbfn;
-	bfa_boolean_t   once;
-	u32		rsvd;
-	void           *cbarg;
-};
-
-#define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do {		\
-	(__hcb_qe)->cbfn  = (__cbfn);      \
-	(__hcb_qe)->cbarg = (__cbarg);      \
-	list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q);      \
-} while (0)
-
-#define bfa_cb_dequeue(__hcb_qe)	list_del(&(__hcb_qe)->qe)
-
-#define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do {	\
-	(__hcb_qe)->cbfn  = (__cbfn);      \
-	(__hcb_qe)->cbarg = (__cbarg);      \
-	if (!(__hcb_qe)->once) {      \
-		list_add_tail((__hcb_qe), &(__bfa)->comp_q);      \
-		(__hcb_qe)->once = BFA_TRUE;				\
-	}								\
-} while (0)
-
-#define bfa_cb_queue_done(__hcb_qe) do {				\
-	(__hcb_qe)->once = BFA_FALSE;					\
-} while (0)
-
-#endif /* __BFA_CALLBACK_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_cb_ioim_macros.h b/drivers/scsi/bfa/bfa_cb_ioim.h
similarity index 85%
rename from drivers/scsi/bfa/bfa_cb_ioim_macros.h
rename to drivers/scsi/bfa/bfa_cb_ioim.h
index 3906ed9..a989a94 100644
--- a/drivers/scsi/bfa/bfa_cb_ioim_macros.h
+++ b/drivers/scsi/bfa/bfa_cb_ioim.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,37 +15,25 @@
  * General Public License for more details.
  */
 
-/**
- *  bfa_cb_ioim_macros.h BFA IOIM driver interface macros.
- */
+#ifndef __BFA_HCB_IOIM_H__
+#define __BFA_HCB_IOIM_H__
 
-#ifndef __BFA_HCB_IOIM_MACROS_H__
-#define __BFA_HCB_IOIM_MACROS_H__
-
-#include <bfa_os_inc.h>
-/*
- * #include <linux/dma-mapping.h>
- *
- * #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include
- * <scsi/scsi_device.h> #include <scsi/scsi_host.h>
- */
-#include "bfad_im_compat.h"
-
+#include "bfa_os_inc.h"
 /*
  * task attribute values in FCP-2 FCP_CMND IU
  */
 #define SIMPLE_Q    0
 #define HEAD_OF_Q   1
 #define ORDERED_Q   2
-#define ACA_Q       4
+#define ACA_Q	    4
 #define UNTAGGED    5
 
 static inline lun_t
 bfad_int_to_lun(u32 luno)
 {
 	union {
-		u16        scsi_lun[4];
-		lun_t           bfa_lun;
+		u16	scsi_lun[4];
+		lun_t		bfa_lun;
 	} lun;
 
 	lun.bfa_lun     = 0;
@@ -141,7 +129,7 @@
 bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio)
 {
 	struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio;
-	u8         task_attr = UNTAGGED;
+	u8	task_attr = UNTAGGED;
 
 	if (cmnd->device->tagged_supported) {
 		switch (cmnd->tag) {
@@ -178,4 +166,4 @@
  */
 #define bfa_cb_ioim_get_reqq(__dio) BFA_FALSE
 
-#endif /* __BFA_HCB_IOIM_MACROS_H__ */
+#endif /* __BFA_HCB_IOIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_cee.c b/drivers/scsi/bfa/bfa_cee.c
deleted file mode 100644
index 2b91779..0000000
--- a/drivers/scsi/bfa/bfa_cee.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <defs/bfa_defs_cee.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-#include <cs/bfa_debug.h>
-#include <cee/bfa_cee.h>
-#include <bfi/bfi_cee.h>
-#include <bfi/bfi.h>
-#include <bfa_ioc.h>
-#include <cna/bfa_cna_trcmod.h>
-
-BFA_TRC_FILE(CNA, CEE);
-
-#define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
-
-static void     bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg);
-static void     bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s
-					   *dcbcx_stats);
-static void     bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s
-					  *lldp_stats);
-static void     bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats);
-static void     bfa_cee_format_cee_cfg(void *buffer);
-static void     bfa_cee_format_cee_stats(void *buffer);
-
-static void
-bfa_cee_format_cee_stats(void *buffer)
-{
-	struct bfa_cee_stats_s *cee_stats = buffer;
-	bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats);
-	bfa_cee_format_lldp_stats(&cee_stats->lldp_stats);
-	bfa_cee_format_cfg_stats(&cee_stats->cfg_stats);
-}
-
-static void
-bfa_cee_format_cee_cfg(void *buffer)
-{
-	struct bfa_cee_attr_s *cee_cfg = buffer;
-	bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote);
-}
-
-static void
-bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats)
-{
-	dcbcx_stats->subtlvs_unrecognized =
-		bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized);
-	dcbcx_stats->negotiation_failed =
-		bfa_os_ntohl(dcbcx_stats->negotiation_failed);
-	dcbcx_stats->remote_cfg_changed =
-		bfa_os_ntohl(dcbcx_stats->remote_cfg_changed);
-	dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received);
-	dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid);
-	dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno);
-	dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno);
-	dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno);
-	dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno);
-}
-
-static void
-bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats)
-{
-	lldp_stats->frames_transmitted =
-		bfa_os_ntohl(lldp_stats->frames_transmitted);
-	lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out);
-	lldp_stats->frames_discarded =
-		bfa_os_ntohl(lldp_stats->frames_discarded);
-	lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error);
-	lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd);
-	lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded);
-	lldp_stats->tlvs_unrecognized =
-		bfa_os_ntohl(lldp_stats->tlvs_unrecognized);
-}
-
-static void
-bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats)
-{
-	cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down);
-	cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up);
-	cfg_stats->cee_hw_cfg_changed =
-		bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed);
-	cfg_stats->recvd_invalid_cfg =
-		bfa_os_ntohl(cfg_stats->recvd_invalid_cfg);
-}
-
-static void
-bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg)
-{
-	lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval);
-	lldp_cfg->enabled_system_cap =
-		bfa_os_ntohs(lldp_cfg->enabled_system_cap);
-}
-
-/**
- * bfa_cee_attr_meminfo()
- *
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-static          u32
-bfa_cee_attr_meminfo(void)
-{
-	return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ);
-}
-
-/**
- * bfa_cee_stats_meminfo()
- *
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-static          u32
-bfa_cee_stats_meminfo(void)
-{
-	return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- *
- * @param[in] cee - Pointer to the CEE module
- *            status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status)
-{
-	cee->get_attr_status = status;
-	bfa_trc(cee, 0);
-	if (status == BFA_STATUS_OK) {
-		bfa_trc(cee, 0);
-		/*
-		 * The requested data has been copied to the DMA area, *process
-		 * it.
-		 */
-		memcpy(cee->attr, cee->attr_dma.kva,
-		       sizeof(struct bfa_cee_attr_s));
-		bfa_cee_format_cee_cfg(cee->attr);
-	}
-	cee->get_attr_pending = BFA_FALSE;
-	if (cee->cbfn.get_attr_cbfn) {
-		bfa_trc(cee, 0);
-		cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status);
-	}
-	bfa_trc(cee, 0);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- *
- * @param[in] cee - Pointer to the CEE module
- *            status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
-{
-	cee->get_stats_status = status;
-	bfa_trc(cee, 0);
-	if (status == BFA_STATUS_OK) {
-		bfa_trc(cee, 0);
-		/*
-		 * The requested data has been copied to the DMA area, process
-		 * it.
-		 */
-		memcpy(cee->stats, cee->stats_dma.kva,
-		       sizeof(struct bfa_cee_stats_s));
-		bfa_cee_format_cee_stats(cee->stats);
-	}
-	cee->get_stats_pending = BFA_FALSE;
-	bfa_trc(cee, 0);
-	if (cee->cbfn.get_stats_cbfn) {
-		bfa_trc(cee, 0);
-		cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status);
-	}
-	bfa_trc(cee, 0);
-}
-
-/**
- * bfa_cee_get_attr_isr()
- *
- *
- * @param[in] cee - Pointer to the CEE module
- *            status - Return status from the f/w
- *
- * @return void
- */
-static void
-bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status)
-{
-	cee->reset_stats_status = status;
-	cee->reset_stats_pending = BFA_FALSE;
-	if (cee->cbfn.reset_stats_cbfn)
-		cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status);
-}
-
-/**
- * bfa_cee_meminfo()
- *
- *
- * @param[in] void
- *
- * @return Size of DMA region
- */
-u32
-bfa_cee_meminfo(void)
-{
-	return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo();
-}
-
-/**
- * bfa_cee_mem_claim()
- *
- *
- * @param[in] cee CEE module pointer
- * 	      dma_kva Kernel Virtual Address of CEE DMA Memory
- * 	      dma_pa  Physical Address of CEE DMA Memory
- *
- * @return void
- */
-void
-bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa)
-{
-	cee->attr_dma.kva = dma_kva;
-	cee->attr_dma.pa = dma_pa;
-	cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo();
-	cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo();
-	cee->attr = (struct bfa_cee_attr_s *)dma_kva;
-	cee->stats =
-		(struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo());
-}
-
-/**
- * bfa_cee_get_attr()
- *
- *   Send the request to the f/w to fetch CEE attributes.
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return Status
- */
-
-bfa_status_t
-bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr,
-		 bfa_cee_get_attr_cbfn_t cbfn, void *cbarg)
-{
-	struct bfi_cee_get_req_s *cmd;
-
-	bfa_assert((cee != NULL) && (cee->ioc != NULL));
-	bfa_trc(cee, 0);
-	if (!bfa_ioc_is_operational(cee->ioc)) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_IOC_FAILURE;
-	}
-	if (cee->get_attr_pending == BFA_TRUE) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_DEVBUSY;
-	}
-	cee->get_attr_pending = BFA_TRUE;
-	cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg;
-	cee->attr = attr;
-	cee->cbfn.get_attr_cbfn = cbfn;
-	cee->cbfn.get_attr_cbarg = cbarg;
-	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ,
-		    bfa_ioc_portid(cee->ioc));
-	bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa);
-	bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb);
-	bfa_trc(cee, 0);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * bfa_cee_get_stats()
- *
- *   Send the request to the f/w to fetch CEE statistics.
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return Status
- */
-
-bfa_status_t
-bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats,
-		  bfa_cee_get_stats_cbfn_t cbfn, void *cbarg)
-{
-	struct bfi_cee_get_req_s *cmd;
-
-	bfa_assert((cee != NULL) && (cee->ioc != NULL));
-
-	if (!bfa_ioc_is_operational(cee->ioc)) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_IOC_FAILURE;
-	}
-	if (cee->get_stats_pending == BFA_TRUE) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_DEVBUSY;
-	}
-	cee->get_stats_pending = BFA_TRUE;
-	cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg;
-	cee->stats = stats;
-	cee->cbfn.get_stats_cbfn = cbfn;
-	cee->cbfn.get_stats_cbarg = cbarg;
-	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ,
-		    bfa_ioc_portid(cee->ioc));
-	bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa);
-	bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb);
-	bfa_trc(cee, 0);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * bfa_cee_reset_stats()
- *
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return Status
- */
-
-bfa_status_t
-bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn,
-		    void *cbarg)
-{
-	struct bfi_cee_reset_stats_s *cmd;
-
-	bfa_assert((cee != NULL) && (cee->ioc != NULL));
-	if (!bfa_ioc_is_operational(cee->ioc)) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_IOC_FAILURE;
-	}
-	if (cee->reset_stats_pending == BFA_TRUE) {
-		bfa_trc(cee, 0);
-		return BFA_STATUS_DEVBUSY;
-	}
-	cee->reset_stats_pending = BFA_TRUE;
-	cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg;
-	cee->cbfn.reset_stats_cbfn = cbfn;
-	cee->cbfn.reset_stats_cbarg = cbarg;
-	bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS,
-		    bfa_ioc_portid(cee->ioc));
-	bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb);
-	bfa_trc(cee, 0);
-	return BFA_STATUS_OK;
-}
-
-/**
- * bfa_cee_isrs()
- *
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return void
- */
-
-void
-bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
-{
-	union bfi_cee_i2h_msg_u *msg;
-	struct bfi_cee_get_rsp_s *get_rsp;
-	struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg;
-	msg = (union bfi_cee_i2h_msg_u *)m;
-	get_rsp = (struct bfi_cee_get_rsp_s *)m;
-	bfa_trc(cee, msg->mh.msg_id);
-	switch (msg->mh.msg_id) {
-	case BFI_CEE_I2H_GET_CFG_RSP:
-		bfa_trc(cee, get_rsp->cmd_status);
-		bfa_cee_get_attr_isr(cee, get_rsp->cmd_status);
-		break;
-	case BFI_CEE_I2H_GET_STATS_RSP:
-		bfa_cee_get_stats_isr(cee, get_rsp->cmd_status);
-		break;
-	case BFI_CEE_I2H_RESET_STATS_RSP:
-		bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status);
-		break;
-	default:
-		bfa_assert(0);
-	}
-}
-
-/**
- * bfa_cee_hbfail()
- *
- *
- * @param[in] Pointer to the CEE module data structure.
- *
- * @return void
- */
-
-void
-bfa_cee_hbfail(void *arg)
-{
-	struct bfa_cee_s *cee;
-	cee = (struct bfa_cee_s *)arg;
-
-	if (cee->get_attr_pending == BFA_TRUE) {
-		cee->get_attr_status = BFA_STATUS_FAILED;
-		cee->get_attr_pending = BFA_FALSE;
-		if (cee->cbfn.get_attr_cbfn) {
-			cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg,
-						BFA_STATUS_FAILED);
-		}
-	}
-	if (cee->get_stats_pending == BFA_TRUE) {
-		cee->get_stats_status = BFA_STATUS_FAILED;
-		cee->get_stats_pending = BFA_FALSE;
-		if (cee->cbfn.get_stats_cbfn) {
-			cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg,
-						 BFA_STATUS_FAILED);
-		}
-	}
-	if (cee->reset_stats_pending == BFA_TRUE) {
-		cee->reset_stats_status = BFA_STATUS_FAILED;
-		cee->reset_stats_pending = BFA_FALSE;
-		if (cee->cbfn.reset_stats_cbfn) {
-			cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg,
-						   BFA_STATUS_FAILED);
-		}
-	}
-}
-
-/**
- * bfa_cee_attach()
- *
- *
- * @param[in] cee - Pointer to the CEE module data structure
- *            ioc - Pointer to the ioc module data structure
- *            dev - Pointer to the device driver module data structure
- *                  The device driver specific mbox ISR functions have
- *                  this pointer as one of the parameters.
- *            trcmod -
- *            logmod -
- *
- * @return void
- */
-void
-bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
-	       struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
-{
-	bfa_assert(cee != NULL);
-	cee->dev = dev;
-	cee->trcmod = trcmod;
-	cee->logmod = logmod;
-	cee->ioc = ioc;
-
-	bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee);
-	bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee);
-	bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail);
-	bfa_trc(cee, 0);
-}
-
-/**
- * bfa_cee_detach()
- *
- *
- * @param[in] cee - Pointer to the CEE module data structure
- *
- * @return void
- */
-void
-bfa_cee_detach(struct bfa_cee_s *cee)
-{
-	/*
-	 * For now, just check if there is some ioctl pending and mark that as
-	 * failed?
-	 */
-	/* bfa_cee_hbfail(cee); */
-}
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 76fa5c5..c2fa07f 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,27 +15,992 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <defs/bfa_defs_pci.h>
-#include <cs/bfa_debug.h>
-#include <bfa_iocfc.h>
+#include "bfa_modules.h"
+#include "bfi_ctreg.h"
+#include "bfad_drv.h"
 
-#define DEF_CFG_NUM_FABRICS         1
-#define DEF_CFG_NUM_LPORTS          256
-#define DEF_CFG_NUM_CQS             4
-#define DEF_CFG_NUM_IOIM_REQS       (BFA_IOIM_MAX)
-#define DEF_CFG_NUM_TSKIM_REQS      128
-#define DEF_CFG_NUM_FCXP_REQS       64
-#define DEF_CFG_NUM_UF_BUFS         64
-#define DEF_CFG_NUM_RPORTS          1024
-#define DEF_CFG_NUM_ITNIMS          (DEF_CFG_NUM_RPORTS)
-#define DEF_CFG_NUM_TINS            256
+BFA_TRC_FILE(HAL, CORE);
 
-#define DEF_CFG_NUM_SGPGS           2048
-#define DEF_CFG_NUM_REQQ_ELEMS      256
-#define DEF_CFG_NUM_RSPQ_ELEMS      64
-#define DEF_CFG_NUM_SBOOT_TGTS      16
-#define DEF_CFG_NUM_SBOOT_LUNS      16
+/**
+ * BFA IOC FC related definitions
+ */
+
+/**
+ * IOC local definitions
+ */
+#define BFA_IOCFC_TOV		5000	/* msecs */
+
+enum {
+	BFA_IOCFC_ACT_NONE	= 0,
+	BFA_IOCFC_ACT_INIT	= 1,
+	BFA_IOCFC_ACT_STOP	= 2,
+	BFA_IOCFC_ACT_DISABLE	= 3,
+};
+
+#define DEF_CFG_NUM_FABRICS		1
+#define DEF_CFG_NUM_LPORTS		256
+#define DEF_CFG_NUM_CQS			4
+#define DEF_CFG_NUM_IOIM_REQS		(BFA_IOIM_MAX)
+#define DEF_CFG_NUM_TSKIM_REQS		128
+#define DEF_CFG_NUM_FCXP_REQS		64
+#define DEF_CFG_NUM_UF_BUFS		64
+#define DEF_CFG_NUM_RPORTS		1024
+#define DEF_CFG_NUM_ITNIMS		(DEF_CFG_NUM_RPORTS)
+#define DEF_CFG_NUM_TINS		256
+
+#define DEF_CFG_NUM_SGPGS		2048
+#define DEF_CFG_NUM_REQQ_ELEMS		256
+#define DEF_CFG_NUM_RSPQ_ELEMS		64
+#define DEF_CFG_NUM_SBOOT_TGTS		16
+#define DEF_CFG_NUM_SBOOT_LUNS		16
+
+/**
+ * forward declaration for IOC FC functions
+ */
+static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status);
+static void bfa_iocfc_disable_cbfn(void *bfa_arg);
+static void bfa_iocfc_hbfail_cbfn(void *bfa_arg);
+static void bfa_iocfc_reset_cbfn(void *bfa_arg);
+static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn;
+
+/**
+ * BFA Interrupt handling functions
+ */
+static void
+bfa_msix_errint(struct bfa_s *bfa, u32 intr)
+{
+	bfa_ioc_error_isr(&bfa->ioc);
+}
+
+static void
+bfa_msix_lpu(struct bfa_s *bfa)
+{
+	bfa_ioc_mbox_isr(&bfa->ioc);
+}
+
+static void
+bfa_reqq_resume(struct bfa_s *bfa, int qid)
+{
+	struct list_head *waitq, *qe, *qen;
+	struct bfa_reqq_wait_s *wqe;
+
+	waitq = bfa_reqq(bfa, qid);
+	list_for_each_safe(qe, qen, waitq) {
+		/**
+		 * Callback only as long as there is room in request queue
+		 */
+		if (bfa_reqq_full(bfa, qid))
+			break;
+
+		list_del(qe);
+		wqe = (struct bfa_reqq_wait_s *) qe;
+		wqe->qresume(wqe->cbarg);
+	}
+}
+
+void
+bfa_msix_all(struct bfa_s *bfa, int vec)
+{
+	bfa_intx(bfa);
+}
+
+/**
+ *  hal_intr_api
+ */
+bfa_boolean_t
+bfa_intx(struct bfa_s *bfa)
+{
+	u32 intr, qintr;
+	int queue;
+
+	intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
+	if (!intr)
+		return BFA_FALSE;
+
+	/**
+	 * RME completion queue interrupt
+	 */
+	qintr = intr & __HFN_INT_RME_MASK;
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
+
+	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
+		if (intr & (__HFN_INT_RME_Q0 << queue))
+			bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+	}
+	intr &= ~qintr;
+	if (!intr)
+		return BFA_TRUE;
+
+	/**
+	 * CPE completion queue interrupt
+	 */
+	qintr = intr & __HFN_INT_CPE_MASK;
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
+
+	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
+		if (intr & (__HFN_INT_CPE_Q0 << queue))
+			bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
+	}
+	intr &= ~qintr;
+	if (!intr)
+		return BFA_TRUE;
+
+	bfa_msix_lpu_err(bfa, intr);
+
+	return BFA_TRUE;
+}
+
+void
+bfa_intx_enable(struct bfa_s *bfa)
+{
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, bfa->iocfc.intr_mask);
+}
+
+void
+bfa_intx_disable(struct bfa_s *bfa)
+{
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
+}
+
+void
+bfa_isr_enable(struct bfa_s *bfa)
+{
+	u32 intr_unmask;
+	int pci_func = bfa_ioc_pcifn(&bfa->ioc);
+
+	bfa_trc(bfa, pci_func);
+
+	bfa_msix_install(bfa);
+	intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
+		       __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
+		       __HFN_INT_LL_HALT);
+
+	if (pci_func == 0)
+		intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
+				__HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
+				__HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
+				__HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
+				__HFN_INT_MBOX_LPU0);
+	else
+		intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
+				__HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
+				__HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
+				__HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
+				__HFN_INT_MBOX_LPU1);
+
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask);
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask);
+	bfa->iocfc.intr_mask = ~intr_unmask;
+	bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
+}
+
+void
+bfa_isr_disable(struct bfa_s *bfa)
+{
+	bfa_isr_mode_set(bfa, BFA_FALSE);
+	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
+	bfa_msix_uninstall(bfa);
+}
+
+void
+bfa_msix_reqq(struct bfa_s *bfa, int qid)
+{
+	struct list_head *waitq;
+
+	qid &= (BFI_IOC_MAX_CQS - 1);
+
+	bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
+
+	/**
+	 * Resume any pending requests in the corresponding reqq.
+	 */
+	waitq = bfa_reqq(bfa, qid);
+	if (!list_empty(waitq))
+		bfa_reqq_resume(bfa, qid);
+}
+
+void
+bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	bfa_trc(bfa, m->mhdr.msg_class);
+	bfa_trc(bfa, m->mhdr.msg_id);
+	bfa_trc(bfa, m->mhdr.mtag.i2htok);
+	bfa_assert(0);
+	bfa_trc_stop(bfa->trcmod);
+}
+
+void
+bfa_msix_rspq(struct bfa_s *bfa, int qid)
+{
+	struct bfi_msg_s *m;
+	u32 pi, ci;
+	struct list_head *waitq;
+
+	bfa_trc_fp(bfa, qid);
+
+	qid &= (BFI_IOC_MAX_CQS - 1);
+
+	bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
+
+	ci = bfa_rspq_ci(bfa, qid);
+	pi = bfa_rspq_pi(bfa, qid);
+
+	bfa_trc_fp(bfa, ci);
+	bfa_trc_fp(bfa, pi);
+
+	if (bfa->rme_process) {
+		while (ci != pi) {
+			m = bfa_rspq_elem(bfa, qid, ci);
+			bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
+
+			bfa_isrs[m->mhdr.msg_class] (bfa, m);
+
+			CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
+		}
+	}
+
+	/**
+	 * update CI
+	 */
+	bfa_rspq_ci(bfa, qid) = pi;
+	bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[qid], pi);
+	mmiowb();
+
+	/**
+	 * Resume any pending requests in the corresponding reqq.
+	 */
+	waitq = bfa_reqq(bfa, qid);
+	if (!list_empty(waitq))
+		bfa_reqq_resume(bfa, qid);
+}
+
+void
+bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
+{
+	u32 intr, curr_value;
+
+	intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
+
+	if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
+		bfa_msix_lpu(bfa);
+
+	intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
+		__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
+
+	if (intr) {
+		if (intr & __HFN_INT_LL_HALT) {
+			/**
+			 * If LL_HALT bit is set then FW Init Halt LL Port
+			 * Register needs to be cleared as well so Interrupt
+			 * Status Register will be cleared.
+			 */
+			curr_value = bfa_reg_read(bfa->ioc.ioc_regs.ll_halt);
+			curr_value &= ~__FW_INIT_HALT_P;
+			bfa_reg_write(bfa->ioc.ioc_regs.ll_halt, curr_value);
+		}
+
+		if (intr & __HFN_INT_ERR_PSS) {
+			/**
+			 * ERR_PSS bit needs to be cleared as well in case
+			 * interrups are shared so driver's interrupt handler is
+			 * still called eventhough it is already masked out.
+			 */
+			curr_value = bfa_reg_read(
+					bfa->ioc.ioc_regs.pss_err_status_reg);
+			curr_value &= __PSS_ERR_STATUS_SET;
+			bfa_reg_write(bfa->ioc.ioc_regs.pss_err_status_reg,
+					curr_value);
+		}
+
+		bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr);
+		bfa_msix_errint(bfa, intr);
+	}
+}
+
+void
+bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
+{
+	bfa_isrs[mc] = isr_func;
+}
+
+/**
+ * BFA IOC FC related functions
+ */
+
+/**
+ *  hal_ioc_pvt BFA IOC private functions
+ */
+
+static void
+bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
+{
+	int		i, per_reqq_sz, per_rspq_sz;
+
+	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+				  BFA_DMA_ALIGN_SZ);
+	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+				  BFA_DMA_ALIGN_SZ);
+
+	/*
+	 * Calculate CQ size
+	 */
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+		*dm_len = *dm_len + per_reqq_sz;
+		*dm_len = *dm_len + per_rspq_sz;
+	}
+
+	/*
+	 * Calculate Shadow CI/PI size
+	 */
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++)
+		*dm_len += (2 * BFA_CACHELINE_SZ);
+}
+
+static void
+bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
+{
+	*dm_len +=
+		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+	*dm_len +=
+		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+			    BFA_CACHELINE_SZ);
+}
+
+/**
+ * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
+ */
+static void
+bfa_iocfc_send_cfg(void *bfa_arg)
+{
+	struct bfa_s *bfa = bfa_arg;
+	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+	struct bfi_iocfc_cfg_req_s cfg_req;
+	struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
+	struct bfa_iocfc_cfg_s	*cfg = &iocfc->cfg;
+	int		i;
+
+	bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
+	bfa_trc(bfa, cfg->fwcfg.num_cqs);
+
+	bfa_iocfc_reset_queues(bfa);
+
+	/**
+	 * initialize IOC configuration info
+	 */
+	cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
+	cfg_info->num_cqs = cfg->fwcfg.num_cqs;
+
+	bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
+	/**
+	 * dma map REQ and RSP circular queues and shadow pointers
+	 */
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+		bfa_dma_be_addr_set(cfg_info->req_cq_ba[i],
+				    iocfc->req_cq_ba[i].pa);
+		bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i],
+				    iocfc->req_cq_shadow_ci[i].pa);
+		cfg_info->req_cq_elems[i] =
+			bfa_os_htons(cfg->drvcfg.num_reqq_elems);
+
+		bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i],
+				    iocfc->rsp_cq_ba[i].pa);
+		bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i],
+				    iocfc->rsp_cq_shadow_pi[i].pa);
+		cfg_info->rsp_cq_elems[i] =
+			bfa_os_htons(cfg->drvcfg.num_rspq_elems);
+	}
+
+	/**
+	 * Enable interrupt coalescing if it is driver init path
+	 * and not ioc disable/enable path.
+	 */
+	if (!iocfc->cfgdone)
+		cfg_info->intr_attr.coalesce = BFA_TRUE;
+
+	iocfc->cfgdone = BFA_FALSE;
+
+	/**
+	 * dma map IOC configuration itself
+	 */
+	bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
+		    bfa_lpuid(bfa));
+	bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
+
+	bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
+			  sizeof(struct bfi_iocfc_cfg_req_s));
+}
+
+static void
+bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		   struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+
+	bfa->bfad = bfad;
+	iocfc->bfa = bfa;
+	iocfc->action = BFA_IOCFC_ACT_NONE;
+
+	bfa_os_assign(iocfc->cfg, *cfg);
+
+	/**
+	 * Initialize chip specific handlers.
+	 */
+	if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
+		iocfc->hwif.hw_reginit = bfa_hwct_reginit;
+		iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
+		iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
+		iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
+		iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
+		iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
+		iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
+		iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
+		iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
+	} else {
+		iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
+		iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
+		iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
+		iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
+		iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
+		iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
+		iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
+		iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
+		iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
+	}
+
+	iocfc->hwif.hw_reginit(bfa);
+	bfa->msix.nvecs = 0;
+}
+
+static void
+bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
+		    struct bfa_meminfo_s *meminfo)
+{
+	u8	       *dm_kva;
+	u64	dm_pa;
+	int		i, per_reqq_sz, per_rspq_sz;
+	struct bfa_iocfc_s  *iocfc = &bfa->iocfc;
+	int		dbgsz;
+
+	dm_kva = bfa_meminfo_dma_virt(meminfo);
+	dm_pa = bfa_meminfo_dma_phys(meminfo);
+
+	/*
+	 * First allocate dma memory for IOC.
+	 */
+	bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
+	dm_kva += bfa_ioc_meminfo();
+	dm_pa  += bfa_ioc_meminfo();
+
+	/*
+	 * Claim DMA-able memory for the request/response queues and for shadow
+	 * ci/pi registers
+	 */
+	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
+				  BFA_DMA_ALIGN_SZ);
+	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
+				  BFA_DMA_ALIGN_SZ);
+
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+		iocfc->req_cq_ba[i].kva = dm_kva;
+		iocfc->req_cq_ba[i].pa = dm_pa;
+		bfa_os_memset(dm_kva, 0, per_reqq_sz);
+		dm_kva += per_reqq_sz;
+		dm_pa += per_reqq_sz;
+
+		iocfc->rsp_cq_ba[i].kva = dm_kva;
+		iocfc->rsp_cq_ba[i].pa = dm_pa;
+		bfa_os_memset(dm_kva, 0, per_rspq_sz);
+		dm_kva += per_rspq_sz;
+		dm_pa += per_rspq_sz;
+	}
+
+	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
+		iocfc->req_cq_shadow_ci[i].kva = dm_kva;
+		iocfc->req_cq_shadow_ci[i].pa = dm_pa;
+		dm_kva += BFA_CACHELINE_SZ;
+		dm_pa += BFA_CACHELINE_SZ;
+
+		iocfc->rsp_cq_shadow_pi[i].kva = dm_kva;
+		iocfc->rsp_cq_shadow_pi[i].pa = dm_pa;
+		dm_kva += BFA_CACHELINE_SZ;
+		dm_pa += BFA_CACHELINE_SZ;
+	}
+
+	/*
+	 * Claim DMA-able memory for the config info page
+	 */
+	bfa->iocfc.cfg_info.kva = dm_kva;
+	bfa->iocfc.cfg_info.pa = dm_pa;
+	bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
+	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
+
+	/*
+	 * Claim DMA-able memory for the config response
+	 */
+	bfa->iocfc.cfgrsp_dma.kva = dm_kva;
+	bfa->iocfc.cfgrsp_dma.pa = dm_pa;
+	bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
+
+	dm_kva +=
+		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+			    BFA_CACHELINE_SZ);
+	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
+			     BFA_CACHELINE_SZ);
+
+
+	bfa_meminfo_dma_virt(meminfo) = dm_kva;
+	bfa_meminfo_dma_phys(meminfo) = dm_pa;
+
+	dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
+	if (dbgsz > 0) {
+		bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
+		bfa_meminfo_kva(meminfo) += dbgsz;
+	}
+}
+
+/**
+ * Start BFA submodules.
+ */
+static void
+bfa_iocfc_start_submod(struct bfa_s *bfa)
+{
+	int		i;
+
+	bfa->rme_process = BFA_TRUE;
+
+	for (i = 0; hal_mods[i]; i++)
+		hal_mods[i]->start(bfa);
+}
+
+/**
+ * Disable BFA submodules.
+ */
+static void
+bfa_iocfc_disable_submod(struct bfa_s *bfa)
+{
+	int		i;
+
+	for (i = 0; hal_mods[i]; i++)
+		hal_mods[i]->iocdisable(bfa);
+}
+
+static void
+bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	if (complete) {
+		if (bfa->iocfc.cfgdone)
+			bfa_cb_init(bfa->bfad, BFA_STATUS_OK);
+		else
+			bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED);
+	} else {
+		if (bfa->iocfc.cfgdone)
+			bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
+	}
+}
+
+static void
+bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+	struct bfa_s  *bfa = bfa_arg;
+	struct bfad_s *bfad = bfa->bfad;
+
+	if (compl)
+		complete(&bfad->comp);
+	else
+		bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
+}
+
+static void
+bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
+{
+	struct bfa_s  *bfa = bfa_arg;
+	struct bfad_s *bfad = bfa->bfad;
+
+	if (compl)
+		complete(&bfad->disable_comp);
+}
+
+/**
+ * Update BFA configuration from firmware configuration.
+ */
+static void
+bfa_iocfc_cfgrsp(struct bfa_s *bfa)
+{
+	struct bfa_iocfc_s		*iocfc	 = &bfa->iocfc;
+	struct bfi_iocfc_cfgrsp_s	*cfgrsp	 = iocfc->cfgrsp;
+	struct bfa_iocfc_fwcfg_s	*fwcfg	 = &cfgrsp->fwcfg;
+
+	fwcfg->num_cqs	      = fwcfg->num_cqs;
+	fwcfg->num_ioim_reqs  = bfa_os_ntohs(fwcfg->num_ioim_reqs);
+	fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs);
+	fwcfg->num_fcxp_reqs  = bfa_os_ntohs(fwcfg->num_fcxp_reqs);
+	fwcfg->num_uf_bufs    = bfa_os_ntohs(fwcfg->num_uf_bufs);
+	fwcfg->num_rports     = bfa_os_ntohs(fwcfg->num_rports);
+
+	iocfc->cfgdone = BFA_TRUE;
+
+	/**
+	 * Configuration is complete - initialize/start submodules
+	 */
+	bfa_fcport_init(bfa);
+
+	if (iocfc->action == BFA_IOCFC_ACT_INIT)
+		bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
+	else
+		bfa_iocfc_start_submod(bfa);
+}
+void
+bfa_iocfc_reset_queues(struct bfa_s *bfa)
+{
+	int		q;
+
+	for (q = 0; q < BFI_IOC_MAX_CQS; q++) {
+		bfa_reqq_ci(bfa, q) = 0;
+		bfa_reqq_pi(bfa, q) = 0;
+		bfa_rspq_ci(bfa, q) = 0;
+		bfa_rspq_pi(bfa, q) = 0;
+	}
+}
+
+/**
+ * IOC enable request is complete
+ */
+static void
+bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	if (status != BFA_STATUS_OK) {
+		bfa_isr_disable(bfa);
+		if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
+			bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
+				     bfa_iocfc_init_cb, bfa);
+		return;
+	}
+
+	bfa_iocfc_send_cfg(bfa);
+}
+
+/**
+ * IOC disable request is complete
+ */
+static void
+bfa_iocfc_disable_cbfn(void *bfa_arg)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	bfa_isr_disable(bfa);
+	bfa_iocfc_disable_submod(bfa);
+
+	if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP)
+		bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
+			     bfa);
+	else {
+		bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
+		bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
+			     bfa);
+	}
+}
+
+/**
+ * Notify sub-modules of hardware failure.
+ */
+static void
+bfa_iocfc_hbfail_cbfn(void *bfa_arg)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	bfa->rme_process = BFA_FALSE;
+
+	bfa_isr_disable(bfa);
+	bfa_iocfc_disable_submod(bfa);
+
+	if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
+		bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb,
+			     bfa);
+}
+
+/**
+ * Actions on chip-reset completion.
+ */
+static void
+bfa_iocfc_reset_cbfn(void *bfa_arg)
+{
+	struct bfa_s	*bfa = bfa_arg;
+
+	bfa_iocfc_reset_queues(bfa);
+	bfa_isr_enable(bfa);
+}
+
+/**
+ *  hal_ioc_public
+ */
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		  u32 *dm_len)
+{
+	/* dma memory for IOC */
+	*dm_len += bfa_ioc_meminfo();
+
+	bfa_iocfc_fw_cfg_sz(cfg, dm_len);
+	bfa_iocfc_cqs_sz(cfg, dm_len);
+	*km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	int		i;
+	struct bfa_ioc_s *ioc = &bfa->ioc;
+
+	bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn;
+	bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn;
+	bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn;
+	bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn;
+
+	ioc->trcmod = bfa->trcmod;
+	bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod);
+
+	/**
+	 * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC.
+	 */
+	if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC)
+		bfa_ioc_set_fcmode(&bfa->ioc);
+
+	bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
+	bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
+
+	bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
+	bfa_iocfc_mem_claim(bfa, cfg, meminfo);
+	bfa_timer_init(&bfa->timer_mod);
+
+	INIT_LIST_HEAD(&bfa->comp_q);
+	for (i = 0; i < BFI_IOC_MAX_CQS; i++)
+		INIT_LIST_HEAD(&bfa->reqq_waitq[i]);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_detach(struct bfa_s *bfa)
+{
+	bfa_ioc_detach(&bfa->ioc);
+}
+
+/**
+ * Query IOC memory requirement information.
+ */
+void
+bfa_iocfc_init(struct bfa_s *bfa)
+{
+	bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
+	bfa_ioc_enable(&bfa->ioc);
+}
+
+/**
+ * IOC start called from bfa_start(). Called to start IOC operations
+ * at driver instantiation for this instance.
+ */
+void
+bfa_iocfc_start(struct bfa_s *bfa)
+{
+	if (bfa->iocfc.cfgdone)
+		bfa_iocfc_start_submod(bfa);
+}
+
+/**
+ * IOC stop called from bfa_stop(). Called only when driver is unloaded
+ * for this instance.
+ */
+void
+bfa_iocfc_stop(struct bfa_s *bfa)
+{
+	bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
+
+	bfa->rme_process = BFA_FALSE;
+	bfa_ioc_disable(&bfa->ioc);
+}
+
+void
+bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
+{
+	struct bfa_s		*bfa = bfaarg;
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+	union bfi_iocfc_i2h_msg_u	*msg;
+
+	msg = (union bfi_iocfc_i2h_msg_u *) m;
+	bfa_trc(bfa, msg->mh.msg_id);
+
+	switch (msg->mh.msg_id) {
+	case BFI_IOCFC_I2H_CFG_REPLY:
+		iocfc->cfg_reply = &msg->cfg_reply;
+		bfa_iocfc_cfgrsp(bfa);
+		break;
+	case BFI_IOCFC_I2H_UPDATEQ_RSP:
+		iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
+		break;
+	default:
+		bfa_assert(0);
+	}
+}
+
+void
+bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
+{
+	bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
+}
+
+u64
+bfa_adapter_get_id(struct bfa_s *bfa)
+{
+	return bfa_ioc_get_adid(&bfa->ioc);
+}
+
+void
+bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
+{
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+
+	attr->intr_attr.coalesce = iocfc->cfginfo->intr_attr.coalesce;
+
+	attr->intr_attr.delay = iocfc->cfginfo->intr_attr.delay ?
+				bfa_os_ntohs(iocfc->cfginfo->intr_attr.delay) :
+				bfa_os_ntohs(iocfc->cfgrsp->intr_attr.delay);
+
+	attr->intr_attr.latency = iocfc->cfginfo->intr_attr.latency ?
+			bfa_os_ntohs(iocfc->cfginfo->intr_attr.latency) :
+			bfa_os_ntohs(iocfc->cfgrsp->intr_attr.latency);
+
+	attr->config	= iocfc->cfg;
+}
+
+bfa_status_t
+bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
+{
+	struct bfa_iocfc_s		*iocfc = &bfa->iocfc;
+	struct bfi_iocfc_set_intr_req_s *m;
+
+	iocfc->cfginfo->intr_attr.coalesce = attr->coalesce;
+	iocfc->cfginfo->intr_attr.delay = bfa_os_htons(attr->delay);
+	iocfc->cfginfo->intr_attr.latency = bfa_os_htons(attr->latency);
+
+	if (!bfa_iocfc_is_operational(bfa))
+		return BFA_STATUS_OK;
+
+	m = bfa_reqq_next(bfa, BFA_REQQ_IOC);
+	if (!m)
+		return BFA_STATUS_DEVBUSY;
+
+	bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
+		    bfa_lpuid(bfa));
+	m->coalesce = iocfc->cfginfo->intr_attr.coalesce;
+	m->delay    = iocfc->cfginfo->intr_attr.delay;
+	m->latency  = iocfc->cfginfo->intr_attr.latency;
+
+	bfa_trc(bfa, attr->delay);
+	bfa_trc(bfa, attr->latency);
+
+	bfa_reqq_produce(bfa, BFA_REQQ_IOC);
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
+{
+	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
+
+	iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
+	bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
+}
+/**
+ * Enable IOC after it is disabled.
+ */
+void
+bfa_iocfc_enable(struct bfa_s *bfa)
+{
+	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
+		     "IOC Enable");
+	bfa_ioc_enable(&bfa->ioc);
+}
+
+void
+bfa_iocfc_disable(struct bfa_s *bfa)
+{
+	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
+		     "IOC Disable");
+	bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
+
+	bfa->rme_process = BFA_FALSE;
+	bfa_ioc_disable(&bfa->ioc);
+}
+
+
+bfa_boolean_t
+bfa_iocfc_is_operational(struct bfa_s *bfa)
+{
+	return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone;
+}
+
+/**
+ * Return boot target port wwns -- read from boot information in flash.
+ */
+void
+bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns)
+{
+	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+	int i;
+
+	if (cfgrsp->pbc_cfg.boot_enabled && cfgrsp->pbc_cfg.nbluns) {
+		bfa_trc(bfa, cfgrsp->pbc_cfg.nbluns);
+		*nwwns = cfgrsp->pbc_cfg.nbluns;
+		for (i = 0; i < cfgrsp->pbc_cfg.nbluns; i++)
+			wwns[i] = cfgrsp->pbc_cfg.blun[i].tgt_pwwn;
+
+		return;
+	}
+
+	*nwwns = cfgrsp->bootwwns.nwwns;
+	memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn));
+}
+
+void
+bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg)
+{
+	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+
+	pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled;
+	pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns;
+	pbcfg->speed = cfgrsp->pbc_cfg.port_speed;
+	memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun));
+}
+
+int
+bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
+{
+	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
+	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
+
+	memcpy(pbc_vport, cfgrsp->pbc_cfg.vport, sizeof(cfgrsp->pbc_cfg.vport));
+	return cfgrsp->pbc_cfg.nvports;
+}
+
+/**
+ *  hal_api
+ */
 
 /**
  * Use this function query the memory requirement of the BFA library.
@@ -45,16 +1010,16 @@
  * This call will fail, if the cap is out of range compared to pre-defined
  * values within the BFA library
  *
- * @param[in] cfg - 	pointer to bfa_ioc_cfg_t. Driver layer should indicate
- * 			its configuration in this structure.
+ * @param[in] cfg -	pointer to bfa_ioc_cfg_t. Driver layer should indicate
+ *			its configuration in this structure.
  *			The default values for struct bfa_iocfc_cfg_s can be
  *			fetched using bfa_cfg_get_default() API.
  *
- * 			If cap's boundary check fails, the library will use
+ *			If cap's boundary check fails, the library will use
  *			the default bfa_cap_t values (and log a warning msg).
  *
  * @param[out] meminfo - pointer to bfa_meminfo_t. This content
- * 			indicates the memory type (see bfa_mem_type_t) and
+ *			indicates the memory type (see bfa_mem_type_t) and
  *			amount of memory required.
  *
  *			Driver should allocate the memory, populate the
@@ -68,8 +1033,8 @@
 void
 bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo)
 {
-	int             i;
-	u32        km_len = 0, dm_len = 0;
+	int		i;
+	u32	km_len = 0, dm_len = 0;
 
 	bfa_assert((cfg != NULL) && (meminfo != NULL));
 
@@ -90,26 +1055,6 @@
 	meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len;
 }
 
-static void
-bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
-{
-	struct bfa_port_s       *port = &bfa->modules.port;
-	uint32_t                dm_len;
-	uint8_t                 *dm_kva;
-	uint64_t                dm_pa;
-
-	dm_len = bfa_port_meminfo();
-	dm_kva = bfa_meminfo_dma_virt(mi);
-	dm_pa  = bfa_meminfo_dma_phys(mi);
-
-	memset(port, 0, sizeof(struct bfa_port_s));
-	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod, bfa->logm);
-	bfa_port_mem_claim(port, dm_kva, dm_pa);
-
-	bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
-	bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
-}
-
 /**
  * Use this function to do attach the driver instance with the BFA
  * library. This function will not trigger any HW initialization
@@ -119,14 +1064,14 @@
  * pre-defined values within the BFA library
  *
  * @param[out]	bfa	Pointer to bfa_t.
- * @param[in]	bfad 	Opaque handle back to the driver's IOC structure
+ * @param[in]	bfad	Opaque handle back to the driver's IOC structure
  * @param[in]	cfg	Pointer to bfa_ioc_cfg_t. Should be same structure
- * 			that was used in bfa_cfg_get_meminfo().
- * @param[in] 	meminfo Pointer to bfa_meminfo_t. The driver should
- * 			use the bfa_cfg_get_meminfo() call to
- * 			find the memory blocks required, allocate the
- * 			required memory and provide the starting addresses.
- * @param[in] 	pcidev	pointer to struct bfa_pcidev_s
+ *			that was used in bfa_cfg_get_meminfo().
+ * @param[in]	meminfo	Pointer to bfa_meminfo_t. The driver should
+ *			use the bfa_cfg_get_meminfo() call to
+ *			find the memory blocks required, allocate the
+ *			required memory and provide the starting addresses.
+ * @param[in]	pcidev	pointer to struct bfa_pcidev_s
  *
  * @return
  * void
@@ -140,8 +1085,8 @@
 bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
 	       struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
 {
-	int             i;
-	struct bfa_mem_elem_s *melem;
+	int			i;
+	struct bfa_mem_elem_s	*melem;
 
 	bfa->fcs = BFA_FALSE;
 
@@ -195,20 +1140,6 @@
 	bfa->trcmod = trcmod;
 }
 
-
-void
-bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod)
-{
-	bfa->logm = logmod;
-}
-
-
-void
-bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen)
-{
-	bfa->aen = aen;
-}
-
 void
 bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog)
 {
@@ -254,14 +1185,14 @@
 
 /**
  * Use this function quiese the IOC. This function will return immediately,
- * when the IOC is actually stopped, the bfa_cb_stop() will be called.
+ * when the IOC is actually stopped, the bfad->comp will be set.
  *
- * @param[in] 	bfa - pointer to bfa_t.
+ * @param[in]bfa - pointer to bfa_t.
  *
  * @return None
  *
  * Special Considerations:
- * bfa_cb_stop() could be called before or after bfa_stop() returns.
+ * bfad->comp can be set before or after bfa_stop() returns.
  *
  * @note
  * In case of any failure, we could handle it automatically by doing a
@@ -283,9 +1214,9 @@
 void
 bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
 {
-	struct list_head        *qe;
-	struct list_head        *qen;
-	struct bfa_cb_qe_s   *hcb_qe;
+	struct list_head		*qe;
+	struct list_head		*qen;
+	struct bfa_cb_qe_s	*hcb_qe;
 
 	list_for_each_safe(qe, qen, comp_q) {
 		hcb_qe = (struct bfa_cb_qe_s *) qe;
@@ -296,8 +1227,8 @@
 void
 bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q)
 {
-	struct list_head        *qe;
-	struct bfa_cb_qe_s   *hcb_qe;
+	struct list_head		*qe;
+	struct bfa_cb_qe_s	*hcb_qe;
 
 	while (!list_empty(comp_q)) {
 		bfa_q_deq(comp_q, &qe);
@@ -321,7 +1252,6 @@
 	bfa_timer_beat(&bfa->timer_mod);
 }
 
-#ifndef BFA_BIOS_BUILD
 /**
  * Return the list of PCI vendor/device id lists supported by this
  * BFA instance.
@@ -336,7 +1266,7 @@
 		{BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT_FC},
 	};
 
-	*npciids = ARRAY_SIZE(__pciids);
+	*npciids = sizeof(__pciids) / sizeof(__pciids[0]);
 	*pciids = __pciids;
 }
 
@@ -351,7 +1281,7 @@
  *	void
  *
  * Special Considerations:
- * 	note
+ * note
  */
 void
 bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg)
@@ -389,7 +1319,7 @@
 	cfg->drvcfg.num_sgpgs      = BFA_SGPG_MIN;
 	cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN;
 	cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN;
-	cfg->drvcfg.min_cfg        = BFA_TRUE;
+	cfg->drvcfg.min_cfg	   = BFA_TRUE;
 }
 
 void
@@ -417,7 +1347,7 @@
 }
 
 /**
- * 		Fetch firmware trace data.
+ * Fetch firmware trace data.
  *
  * @param[in]		bfa			BFA instance
  * @param[out]		trcdata		Firmware trace buffer
@@ -433,6 +1363,22 @@
 }
 
 /**
+ * Dump firmware memory.
+ *
+ * @param[in]		bfa		BFA instance
+ * @param[out]		buf		buffer for dump
+ * @param[in,out]	offset		smem offset to start read
+ * @param[in,out]	buflen		length of buffer
+ *
+ * @retval BFA_STATUS_OK		Firmware memory is dumped.
+ * @retval BFA_STATUS_INPROGRESS	Firmware memory dump is in progress.
+ */
+bfa_status_t
+bfa_debug_fwcore(struct bfa_s *bfa, void *buf, u32 *offset, int *buflen)
+{
+	return bfa_ioc_debug_fwcore(&bfa->ioc, buf, offset, buflen);
+}
+/**
  * Reset hw semaphore & usage cnt regs and initialize.
  */
 void
@@ -441,4 +1387,23 @@
 	bfa_ioc_ownership_reset(&bfa->ioc);
 	bfa_ioc_pll_init(&bfa->ioc);
 }
-#endif
+
+/**
+ * Fetch firmware statistics data.
+ *
+ * @param[in]		bfa		BFA instance
+ * @param[out]		data		Firmware stats buffer
+ *
+ * @retval BFA_STATUS_OK		Firmware trace is fetched.
+ */
+bfa_status_t
+bfa_fw_stats_get(struct bfa_s *bfa, void *data)
+{
+	return bfa_ioc_fw_stats_get(&bfa->ioc, data);
+}
+
+bfa_status_t
+bfa_fw_stats_clear(struct bfa_s *bfa)
+{
+	return bfa_ioc_fw_stats_clear(&bfa->ioc);
+}
diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h
new file mode 100644
index 0000000..7260c74
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_cs.h
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  bfa_cs.h BFA common services
+ */
+
+#ifndef __BFA_CS_H__
+#define __BFA_CS_H__
+
+#include "bfa_os_inc.h"
+
+/**
+ * BFA TRC
+ */
+
+#ifndef BFA_TRC_MAX
+#define BFA_TRC_MAX	(4 * 1024)
+#endif
+
+#ifndef BFA_TRC_TS
+#define BFA_TRC_TS(_trcm)	((_trcm)->ticks++)
+#endif
+
+struct bfa_trc_s {
+#ifdef __BIGENDIAN
+	u16	fileno;
+	u16	line;
+#else
+	u16	line;
+	u16	fileno;
+#endif
+	u32	timestamp;
+	union {
+		struct {
+			u32	rsvd;
+			u32	u32;
+		} u32;
+		u64	u64;
+	} data;
+};
+
+struct bfa_trc_mod_s {
+	u32	head;
+	u32	tail;
+	u32	ntrc;
+	u32	stopped;
+	u32	ticks;
+	u32	rsvd[3];
+	struct bfa_trc_s trc[BFA_TRC_MAX];
+};
+
+enum {
+	BFA_TRC_HAL  = 1,	/*  BFA modules */
+	BFA_TRC_FCS  = 2,	/*  BFA FCS modules */
+	BFA_TRC_LDRV = 3,	/*  Linux driver modules */
+	BFA_TRC_CNA  = 4,	/*  Common modules */
+};
+#define BFA_TRC_MOD_SH	10
+#define BFA_TRC_MOD(__mod)	((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH)
+
+/**
+ * Define a new tracing file (module). Module should match one defined above.
+ */
+#define BFA_TRC_FILE(__mod, __submod)					\
+	static int __trc_fileno = ((BFA_TRC_ ## __mod ## _ ## __submod) | \
+						 BFA_TRC_MOD(__mod))
+
+
+#define bfa_trc32(_trcp, _data)	\
+	__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
+#define bfa_trc(_trcp, _data)	\
+	__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data)
+
+static inline void
+bfa_trc_init(struct bfa_trc_mod_s *trcm)
+{
+	trcm->head = trcm->tail = trcm->stopped = 0;
+	trcm->ntrc = BFA_TRC_MAX;
+}
+
+static inline void
+bfa_trc_stop(struct bfa_trc_mod_s *trcm)
+{
+	trcm->stopped = 1;
+}
+
+#ifdef FWTRC
+extern void dc_flush(void *data);
+#else
+#define dc_flush(data)
+#endif
+
+
+static inline void
+__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
+{
+	int		tail = trcm->tail;
+	struct bfa_trc_s	*trc = &trcm->trc[tail];
+
+	if (trcm->stopped)
+		return;
+
+	trc->fileno = (u16) fileno;
+	trc->line = (u16) line;
+	trc->data.u64 = data;
+	trc->timestamp = BFA_TRC_TS(trcm);
+	dc_flush(trc);
+
+	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
+	if (trcm->tail == trcm->head)
+		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
+	dc_flush(trcm);
+}
+
+
+static inline void
+__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
+{
+	int		tail = trcm->tail;
+	struct bfa_trc_s *trc = &trcm->trc[tail];
+
+	if (trcm->stopped)
+		return;
+
+	trc->fileno = (u16) fileno;
+	trc->line = (u16) line;
+	trc->data.u32.u32 = data;
+	trc->timestamp = BFA_TRC_TS(trcm);
+	dc_flush(trc);
+
+	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
+	if (trcm->tail == trcm->head)
+		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
+	dc_flush(trcm);
+}
+
+#ifndef BFA_PERF_BUILD
+#define bfa_trc_fp(_trcp, _data)	bfa_trc(_trcp, _data)
+#else
+#define bfa_trc_fp(_trcp, _data)
+#endif
+
+/**
+ * @ BFA LOG interfaces
+ */
+#define bfa_assert(__cond)	do {					\
+	if (!(__cond)) {						\
+		printk(KERN_ERR "assert(%s) failed at %s:%d\\n",         \
+		#__cond, __FILE__, __LINE__);				\
+	}								\
+} while (0)
+
+#define bfa_sm_fault(__mod, __event)	do {				\
+	bfa_trc(__mod, (((u32)0xDEAD << 16) | __event));		\
+	printk(KERN_ERR	"Assertion failure: %s:%d: %d",			\
+		__FILE__, __LINE__, (__event));				\
+} while (0)
+
+#ifndef BFA_PERF_BUILD
+#define bfa_assert_fp(__cond)	bfa_assert(__cond)
+#else
+#define bfa_assert_fp(__cond)
+#endif
+
+/* BFA queue definitions */
+#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
+#define bfa_q_next(_qe) (((struct list_head *) (_qe))->next)
+#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
+
+/*
+ * bfa_q_qe_init - to initialize a queue element
+ */
+#define bfa_q_qe_init(_qe) {				\
+	bfa_q_next(_qe) = (struct list_head *) NULL;	\
+	bfa_q_prev(_qe) = (struct list_head *) NULL;	\
+}
+
+/*
+ * bfa_q_deq - dequeue an element from head of the queue
+ */
+#define bfa_q_deq(_q, _qe) {						\
+	if (!list_empty(_q)) {						\
+		(*((struct list_head **) (_qe))) = bfa_q_next(_q);	\
+		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\
+				(struct list_head *) (_q);		\
+		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe));\
+		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\
+	} else {							\
+		*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
+	}								\
+}
+
+/*
+ * bfa_q_deq_tail - dequeue an element from tail of the queue
+ */
+#define bfa_q_deq_tail(_q, _qe) {					\
+	if (!list_empty(_q)) {						\
+		*((struct list_head **) (_qe)) = bfa_q_prev(_q);	\
+		bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) =	\
+			(struct list_head *) (_q);			\
+		bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\
+		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\
+	} else {							\
+		*((struct list_head **) (_qe)) = (struct list_head *) NULL;\
+	}								\
+}
+
+static inline int
+bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
+{
+	struct list_head        *tqe;
+
+	tqe = bfa_q_next(q);
+	while (tqe != q) {
+		if (tqe == qe)
+			return 1;
+		tqe = bfa_q_next(tqe);
+		if (tqe == NULL)
+			break;
+	}
+	return 0;
+}
+
+/*
+ * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
+ * consistent across modules)
+ */
+#ifndef BFA_PERF_BUILD
+#define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe)
+#else
+#define BFA_Q_DBG_INIT(_qe)
+#endif
+
+#define bfa_q_is_on_q(_q, _qe)      \
+	bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
+
+/**
+ * @ BFA state machine interfaces
+ */
+
+typedef void (*bfa_sm_t)(void *sm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc_s
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_sm_state_decl(oc, st, otype, etype)		\
+	static void oc ## _sm_ ## st(otype * fsm, etype event)
+
+#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
+#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
+#define bfa_sm_get_state(_sm)		((_sm)->sm)
+#define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
+
+/**
+ * For converting from state machine function to state encoding.
+ */
+struct bfa_sm_table_s {
+	bfa_sm_t	sm;	/*  state machine function	*/
+	int		state;	/*  state machine encoding	*/
+	char		*name;	/*  state name for display	*/
+};
+#define BFA_SM(_sm)	((bfa_sm_t)(_sm))
+
+/**
+ * State machine with entry actions.
+ */
+typedef void (*bfa_fsm_t)(void *fsm, int event);
+
+/**
+ * oc - object class eg. bfa_ioc
+ * st - state, eg. reset
+ * otype - object type, eg. struct bfa_ioc_s
+ * etype - object type, eg. enum ioc_event
+ */
+#define bfa_fsm_state_decl(oc, st, otype, etype)		\
+	static void oc ## _sm_ ## st(otype * fsm, etype event);      \
+	static void oc ## _sm_ ## st ## _entry(otype * fsm)
+
+#define bfa_fsm_set_state(_fsm, _state) do {	\
+	(_fsm)->fsm = (bfa_fsm_t)(_state);      \
+	_state ## _entry(_fsm);      \
+} while (0)
+
+#define bfa_fsm_send_event(_fsm, _event)	((_fsm)->fsm((_fsm), (_event)))
+#define bfa_fsm_get_state(_fsm)			((_fsm)->fsm)
+#define bfa_fsm_cmp_state(_fsm, _state)		\
+	((_fsm)->fsm == (bfa_fsm_t)(_state))
+
+static inline int
+bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
+{
+	int	i = 0;
+
+	while (smt[i].sm && smt[i].sm != sm)
+		i++;
+	return smt[i].state;
+}
+
+/**
+ * @ Generic wait counter.
+ */
+
+typedef void (*bfa_wc_resume_t) (void *cbarg);
+
+struct bfa_wc_s {
+	bfa_wc_resume_t wc_resume;
+	void		*wc_cbarg;
+	int		wc_count;
+};
+
+static inline void
+bfa_wc_up(struct bfa_wc_s *wc)
+{
+	wc->wc_count++;
+}
+
+static inline void
+bfa_wc_down(struct bfa_wc_s *wc)
+{
+	wc->wc_count--;
+	if (wc->wc_count == 0)
+		wc->wc_resume(wc->wc_cbarg);
+}
+
+/**
+ * Initialize a waiting counter.
+ */
+static inline void
+bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
+{
+	wc->wc_resume = wc_resume;
+	wc->wc_cbarg = wc_cbarg;
+	wc->wc_count = 0;
+	bfa_wc_up(wc);
+}
+
+/**
+ * Wait for counter to reach zero
+ */
+static inline void
+bfa_wc_wait(struct bfa_wc_s *wc)
+{
+	bfa_wc_down(wc);
+}
+
+#endif /* __BFA_CS_H__ */
diff --git a/drivers/scsi/bfa/bfa_csdebug.c b/drivers/scsi/bfa/bfa_csdebug.c
deleted file mode 100644
index caeb114..0000000
--- a/drivers/scsi/bfa/bfa_csdebug.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <cs/bfa_debug.h>
-#include <bfa_os_inc.h>
-#include <cs/bfa_q.h>
-#include <log/bfa_log_hal.h>
-
-/**
- *  cs_debug_api
- */
-
-
-void
-bfa_panic(int line, char *file, char *panicstr)
-{
-	bfa_log(NULL, BFA_LOG_HAL_ASSERT, file, line, panicstr);
-	bfa_os_panic();
-}
-
-void
-bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event)
-{
-	bfa_log(logm, BFA_LOG_HAL_SM_ASSERT, file, line, event);
-	bfa_os_panic();
-}
-
-int
-bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe)
-{
-	struct list_head        *tqe;
-
-	tqe = bfa_q_next(q);
-	while (tqe != q) {
-		if (tqe == qe)
-			return 1;
-		tqe = bfa_q_next(tqe);
-		if (tqe == NULL)
-			break;
-	}
-	return 0;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
new file mode 100644
index 0000000..d49877f
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFA_DEFS_H__
+#define __BFA_DEFS_H__
+
+#include "bfa_fc.h"
+#include "bfa_os_inc.h"
+
+#define BFA_MFG_SERIALNUM_SIZE                  11
+#define STRSZ(_n)                               (((_n) + 4) & ~3)
+
+/**
+ * Manufacturing card type
+ */
+enum {
+	BFA_MFG_TYPE_CB_MAX  = 825,      /*  Crossbow card type max     */
+	BFA_MFG_TYPE_FC8P2   = 825,      /*  8G 2port FC card           */
+	BFA_MFG_TYPE_FC8P1   = 815,      /*  8G 1port FC card           */
+	BFA_MFG_TYPE_FC4P2   = 425,      /*  4G 2port FC card           */
+	BFA_MFG_TYPE_FC4P1   = 415,      /*  4G 1port FC card           */
+	BFA_MFG_TYPE_CNA10P2 = 1020,     /*  10G 2port CNA card */
+	BFA_MFG_TYPE_CNA10P1 = 1010,     /*  10G 1port CNA card */
+	BFA_MFG_TYPE_JAYHAWK = 804,      /*  Jayhawk mezz card          */
+	BFA_MFG_TYPE_WANCHESE = 1007,    /*  Wanchese mezz card */
+	BFA_MFG_TYPE_ASTRA    = 807,     /*  Astra mezz card            */
+	BFA_MFG_TYPE_LIGHTNING_P0 = 902, /*  Lightning mezz card - old  */
+	BFA_MFG_TYPE_LIGHTNING = 1741,   /*  Lightning mezz card        */
+	BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type          */
+};
+
+#pragma pack(1)
+
+/**
+ * Check if Mezz card
+ */
+#define bfa_mfg_is_mezz(type) (( \
+	(type) == BFA_MFG_TYPE_JAYHAWK || \
+	(type) == BFA_MFG_TYPE_WANCHESE || \
+	(type) == BFA_MFG_TYPE_ASTRA || \
+	(type) == BFA_MFG_TYPE_LIGHTNING_P0 || \
+	(type) == BFA_MFG_TYPE_LIGHTNING))
+
+/**
+ * Check if the card having old wwn/mac handling
+ */
+#define bfa_mfg_is_old_wwn_mac_model(type) (( \
+	(type) == BFA_MFG_TYPE_FC8P2 || \
+	(type) == BFA_MFG_TYPE_FC8P1 || \
+	(type) == BFA_MFG_TYPE_FC4P2 || \
+	(type) == BFA_MFG_TYPE_FC4P1 || \
+	(type) == BFA_MFG_TYPE_CNA10P2 || \
+	(type) == BFA_MFG_TYPE_CNA10P1 || \
+	(type) == BFA_MFG_TYPE_JAYHAWK || \
+	(type) == BFA_MFG_TYPE_WANCHESE))
+
+#define bfa_mfg_increment_wwn_mac(m, i)                         \
+do {                                                            \
+	u32 t = ((u32)(m)[0] << 16) | ((u32)(m)[1] << 8) | \
+		(u32)(m)[2];  \
+	t += (i);      \
+	(m)[0] = (t >> 16) & 0xFF;                              \
+	(m)[1] = (t >> 8) & 0xFF;                               \
+	(m)[2] = t & 0xFF;                                      \
+} while (0)
+
+/**
+ * VPD data length
+ */
+#define BFA_MFG_VPD_LEN                 512
+
+/**
+ * VPD vendor tag
+ */
+enum {
+	BFA_MFG_VPD_UNKNOWN     = 0,     /*  vendor unknown             */
+	BFA_MFG_VPD_IBM         = 1,     /*  vendor IBM                 */
+	BFA_MFG_VPD_HP          = 2,     /*  vendor HP                  */
+	BFA_MFG_VPD_DELL        = 3,     /*  vendor DELL                */
+	BFA_MFG_VPD_PCI_IBM     = 0x08,  /*  PCI VPD IBM                */
+	BFA_MFG_VPD_PCI_HP      = 0x10,  /*  PCI VPD HP         */
+	BFA_MFG_VPD_PCI_DELL    = 0x20,  /*  PCI VPD DELL               */
+	BFA_MFG_VPD_PCI_BRCD    = 0xf8,  /*  PCI VPD Brocade            */
+};
+
+/**
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_vpd_s {
+	u8              version;        /*  vpd data version */
+	u8              vpd_sig[3];     /*  characters 'V', 'P', 'D' */
+	u8              chksum;         /*  u8 checksum */
+	u8              vendor;         /*  vendor */
+	u8      len;            /*  vpd data length excluding header */
+	u8      rsv;
+	u8              data[BFA_MFG_VPD_LEN];  /*  vpd data */
+};
+
+#pragma pack()
+
+/**
+ * Status return values
+ */
+enum bfa_status {
+	BFA_STATUS_OK		= 0,	/*  Success */
+	BFA_STATUS_FAILED	= 1,	/*  Operation failed */
+	BFA_STATUS_EINVAL	= 2,	/*  Invalid params Check input
+					 *  parameters */
+	BFA_STATUS_ENOMEM	= 3,	/*  Out of resources */
+	BFA_STATUS_ETIMER	= 5,	/*  Timer expired - Retry, if persists,
+					 *  contact support */
+	BFA_STATUS_EPROTOCOL	= 6,	/*  Protocol error */
+	BFA_STATUS_DEVBUSY	= 13,	/*  Device busy - Retry operation */
+	BFA_STATUS_UNKNOWN_LWWN = 18,	/*  LPORT PWWN not found */
+	BFA_STATUS_UNKNOWN_RWWN = 19,	/*  RPORT PWWN not found */
+	BFA_STATUS_VPORT_EXISTS = 21,	/*  VPORT already exists */
+	BFA_STATUS_VPORT_MAX	= 22,	/*  Reached max VPORT supported limit */
+	BFA_STATUS_UNSUPP_SPEED	= 23,	/*  Invalid Speed Check speed setting */
+	BFA_STATUS_INVLD_DFSZ	= 24,	/*  Invalid Max data field size */
+	BFA_STATUS_FABRIC_RJT	= 29,	/*  Reject from attached fabric */
+	BFA_STATUS_VPORT_WWN_BP	= 46,	/*  WWN is same as base port's WWN */
+	BFA_STATUS_NO_FCPIM_NEXUS = 52,	/* No FCP Nexus exists with the rport */
+	BFA_STATUS_IOC_FAILURE	= 56,	/* IOC failure - Retry, if persists
+					 * contact support */
+	BFA_STATUS_INVALID_WWN	= 57,	/*  Invalid WWN */
+	BFA_STATUS_DIAG_BUSY	= 71,	/*  diag busy */
+	BFA_STATUS_ENOFSAVE	= 78,	/*  No saved firmware trace */
+	BFA_STATUS_IOC_DISABLED = 82,   /* IOC is already disabled */
+	BFA_STATUS_INVALID_MAC  = 134, /*  Invalid MAC address */
+	BFA_STATUS_PBC		= 154, /*  Operation not allowed for pre-boot
+					*  configuration */
+	BFA_STATUS_TRUNK_ENABLED = 164, /* Trunk is already enabled on
+					 * this adapter */
+	BFA_STATUS_TRUNK_DISABLED  = 165, /* Trunking is disabled on
+					   * the adapter */
+	BFA_STATUS_IOPROFILE_OFF = 175, /* IO profile OFF */
+	BFA_STATUS_MAX_VAL		/* Unknown error code */
+};
+#define bfa_status_t enum bfa_status
+
+enum bfa_eproto_status {
+	BFA_EPROTO_BAD_ACCEPT = 0,
+	BFA_EPROTO_UNKNOWN_RSP = 1
+};
+#define bfa_eproto_status_t enum bfa_eproto_status
+
+enum bfa_boolean {
+	BFA_FALSE = 0,
+	BFA_TRUE  = 1
+};
+#define bfa_boolean_t enum bfa_boolean
+
+#define BFA_STRING_32	32
+#define BFA_VERSION_LEN 64
+
+/**
+ * ---------------------- adapter definitions ------------
+ */
+
+/**
+ * BFA adapter level attributes.
+ */
+enum {
+	BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
+					/*
+					 *!< adapter serial num length
+					 */
+	BFA_ADAPTER_MODEL_NAME_LEN  = 16,  /*  model name length */
+	BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*  model description length */
+	BFA_ADAPTER_MFG_NAME_LEN    = 8,   /*  manufacturer name length */
+	BFA_ADAPTER_SYM_NAME_LEN    = 64,  /*  adapter symbolic name length */
+	BFA_ADAPTER_OS_TYPE_LEN	    = 64,  /*  adapter os type length */
+};
+
+struct bfa_adapter_attr_s {
+	char		manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+	char		serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+	u32	card_type;
+	char		model[BFA_ADAPTER_MODEL_NAME_LEN];
+	char		model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
+	wwn_t		pwwn;
+	char		node_symname[FC_SYMNAME_MAX];
+	char		hw_ver[BFA_VERSION_LEN];
+	char		fw_ver[BFA_VERSION_LEN];
+	char		optrom_ver[BFA_VERSION_LEN];
+	char		os_type[BFA_ADAPTER_OS_TYPE_LEN];
+	struct bfa_mfg_vpd_s	vpd;
+	struct mac_s	mac;
+
+	u8		nports;
+	u8		max_speed;
+	u8		prototype;
+	char	        asic_rev;
+
+	u8		pcie_gen;
+	u8		pcie_lanes_orig;
+	u8		pcie_lanes;
+	u8	        cna_capable;
+
+	u8		is_mezz;
+	u8		trunk_capable;
+};
+
+/**
+ * ---------------------- IOC definitions ------------
+ */
+
+enum {
+	BFA_IOC_DRIVER_LEN	= 16,
+	BFA_IOC_CHIP_REV_LEN	= 8,
+};
+
+/**
+ * Driver and firmware versions.
+ */
+struct bfa_ioc_driver_attr_s {
+	char		driver[BFA_IOC_DRIVER_LEN];	/*  driver name */
+	char		driver_ver[BFA_VERSION_LEN];	/*  driver version */
+	char		fw_ver[BFA_VERSION_LEN];	/*  firmware version */
+	char		bios_ver[BFA_VERSION_LEN];	/*  bios version */
+	char		efi_ver[BFA_VERSION_LEN];	/*  EFI version */
+	char		ob_ver[BFA_VERSION_LEN];	/*  openboot version */
+};
+
+/**
+ * IOC PCI device attributes
+ */
+struct bfa_ioc_pci_attr_s {
+	u16	vendor_id;	/*  PCI vendor ID */
+	u16	device_id;	/*  PCI device ID */
+	u16	ssid;		/*  subsystem ID */
+	u16	ssvid;		/*  subsystem vendor ID */
+	u32	pcifn;		/*  PCI device function */
+	u32	rsvd;		/* padding */
+	char		chip_rev[BFA_IOC_CHIP_REV_LEN];	 /*  chip revision */
+};
+
+/**
+ * IOC states
+ */
+enum bfa_ioc_state {
+	BFA_IOC_UNINIT		= 1,	/*  IOC is in uninit state */
+	BFA_IOC_RESET		= 2,	/*  IOC is in reset state */
+	BFA_IOC_SEMWAIT		= 3,	/*  Waiting for IOC h/w semaphore */
+	BFA_IOC_HWINIT		= 4,	/*  IOC h/w is being initialized */
+	BFA_IOC_GETATTR		= 5,	/*  IOC is being configured */
+	BFA_IOC_OPERATIONAL	= 6,	/*  IOC is operational */
+	BFA_IOC_INITFAIL	= 7,	/*  IOC hardware failure */
+	BFA_IOC_FAIL		= 8,	/*  IOC heart-beat failure */
+	BFA_IOC_DISABLING	= 9,	/*  IOC is being disabled */
+	BFA_IOC_DISABLED	= 10,	/*  IOC is disabled */
+	BFA_IOC_FWMISMATCH	= 11,	/*  IOC f/w different from drivers */
+	BFA_IOC_ENABLING	= 12,	/*  IOC is being enabled */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_ioc_stats_s {
+	u32	enable_reqs;
+	u32	disable_reqs;
+	u32	get_attr_reqs;
+	u32	dbg_sync;
+	u32	dbg_dump;
+	u32	unknown_reqs;
+};
+
+/**
+ * IOC driver stats
+ */
+struct bfa_ioc_drv_stats_s {
+	u32	ioc_isrs;
+	u32	ioc_enables;
+	u32	ioc_disables;
+	u32	ioc_hbfails;
+	u32	ioc_boots;
+	u32	stats_tmos;
+	u32	hb_count;
+	u32	disable_reqs;
+	u32	enable_reqs;
+	u32	disable_replies;
+	u32	enable_replies;
+};
+
+/**
+ * IOC statistics
+ */
+struct bfa_ioc_stats_s {
+	struct bfa_ioc_drv_stats_s	drv_stats; /*  driver IOC stats */
+	struct bfa_fw_ioc_stats_s	fw_stats;  /*  firmware IOC stats */
+};
+
+enum bfa_ioc_type_e {
+	BFA_IOC_TYPE_FC		= 1,
+	BFA_IOC_TYPE_FCoE	= 2,
+	BFA_IOC_TYPE_LL		= 3,
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_ioc_attr_s {
+	enum bfa_ioc_type_e		ioc_type;
+	enum bfa_ioc_state		state;		/*  IOC state      */
+	struct bfa_adapter_attr_s	adapter_attr;	/*  HBA attributes */
+	struct bfa_ioc_driver_attr_s	driver_attr;	/*  driver attr    */
+	struct bfa_ioc_pci_attr_s	pci_attr;
+	u8				port_id;	/*  port number    */
+	u8				rsvd[7];	/*  64bit align    */
+};
+
+/**
+ * ---------------------- mfg definitions ------------
+ */
+
+/**
+ * Checksum size
+ */
+#define BFA_MFG_CHKSUM_SIZE			16
+
+#define BFA_MFG_PARTNUM_SIZE			14
+#define BFA_MFG_SUPPLIER_ID_SIZE		10
+#define BFA_MFG_SUPPLIER_PARTNUM_SIZE		20
+#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE		20
+#define BFA_MFG_SUPPLIER_REVISION_SIZE		4
+
+#pragma pack(1)
+
+/**
+ * All numerical fields are in big-endian format.
+ */
+struct bfa_mfg_block_s {
+	u8		version;	/*  manufacturing block version */
+	u8		mfg_sig[3];	/*  characters 'M', 'F', 'G' */
+	u16	mfgsize;	/*  mfg block size */
+	u16	u16_chksum;	/*  old u16 checksum */
+	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+	char		brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
+	u8		mfg_day;	/*  manufacturing day */
+	u8		mfg_month;	/*  manufacturing month */
+	u16	mfg_year;	/*  manufacturing year */
+	wwn_t		mfg_wwn;	/*  wwn base for this adapter */
+	u8		num_wwn;	/*  number of wwns assigned */
+	u8		mfg_speeds;	/*  speeds allowed for this adapter */
+	u8		rsv[2];
+	char		supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
+	char		supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
+	char
+		supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
+	char
+		supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
+	mac_t		mfg_mac;	/*  mac address */
+	u8		num_mac;	/*  number of mac addresses */
+	u8		rsv2;
+	u32	mfg_type;	/*  card type */
+	u8		rsv3[108];
+	u8		md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*  md5 checksum */
+};
+
+#pragma pack()
+
+/**
+ * ---------------------- pci definitions ------------
+ */
+
+/**
+ * PCI device and vendor ID information
+ */
+enum {
+	BFA_PCI_VENDOR_ID_BROCADE	= 0x1657,
+	BFA_PCI_DEVICE_ID_FC_8G2P	= 0x13,
+	BFA_PCI_DEVICE_ID_FC_8G1P	= 0x17,
+	BFA_PCI_DEVICE_ID_CT		= 0x14,
+	BFA_PCI_DEVICE_ID_CT_FC		= 0x21,
+};
+
+#define bfa_asic_id_ct(devid)			\
+	((devid) == BFA_PCI_DEVICE_ID_CT ||	\
+	 (devid) == BFA_PCI_DEVICE_ID_CT_FC)
+
+/**
+ * PCI sub-system device and vendor ID information
+ */
+enum {
+	BFA_PCI_FCOE_SSDEVICE_ID	= 0x14,
+};
+
+/**
+ * Maximum number of device address ranges mapped through different BAR(s)
+ */
+#define BFA_PCI_ACCESS_RANGES 1
+
+/*
+ *	Port speed settings. Each specific speed is a bit field. Use multiple
+ *	bits to specify speeds to be selected for auto-negotiation.
+ */
+enum bfa_port_speed {
+	BFA_PORT_SPEED_UNKNOWN = 0,
+	BFA_PORT_SPEED_1GBPS	= 1,
+	BFA_PORT_SPEED_2GBPS	= 2,
+	BFA_PORT_SPEED_4GBPS	= 4,
+	BFA_PORT_SPEED_8GBPS	= 8,
+	BFA_PORT_SPEED_10GBPS	= 10,
+	BFA_PORT_SPEED_16GBPS	= 16,
+	BFA_PORT_SPEED_AUTO =
+		(BFA_PORT_SPEED_1GBPS | BFA_PORT_SPEED_2GBPS |
+		 BFA_PORT_SPEED_4GBPS | BFA_PORT_SPEED_8GBPS),
+};
+#define bfa_port_speed_t enum bfa_port_speed
+
+enum {
+	BFA_BOOT_BOOTLUN_MAX = 4,       /*  maximum boot lun per IOC */
+	BFA_PREBOOT_BOOTLUN_MAX = 8,    /*  maximum preboot lun per IOC */
+};
+
+#define BOOT_CFG_REV1   1
+#define BOOT_CFG_VLAN   1
+
+/**
+ *      Boot options setting. Boot options setting determines from where
+ *      to get the boot lun information
+ */
+enum bfa_boot_bootopt {
+	BFA_BOOT_AUTO_DISCOVER  = 0, /*  Boot from blun provided by fabric */
+	BFA_BOOT_STORED_BLUN = 1, /*  Boot from bluns stored in flash */
+	BFA_BOOT_FIRST_LUN      = 2, /*  Boot from first discovered blun */
+	BFA_BOOT_PBC    = 3, /*  Boot from pbc configured blun  */
+};
+
+#pragma pack(1)
+/**
+ * Boot lun information.
+ */
+struct bfa_boot_bootlun_s {
+	wwn_t   pwwn;   /*  port wwn of target */
+	lun_t   lun;    /*  64-bit lun */
+};
+#pragma pack()
+
+/**
+ * BOOT boot configuraton
+ */
+struct bfa_boot_pbc_s {
+	u8              enable;         /*  enable/disable SAN boot */
+	u8              speed;          /*  boot speed settings */
+	u8              topology;       /*  boot topology setting */
+	u8              rsvd1;
+	u32     nbluns;         /*  number of boot luns */
+	struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
+};
+
+#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs_fcs.h b/drivers/scsi/bfa/bfa_defs_fcs.h
new file mode 100644
index 0000000..96905d3
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_defs_fcs.h
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFA_DEFS_FCS_H__
+#define __BFA_DEFS_FCS_H__
+
+#include "bfa_fc.h"
+#include "bfa_defs_svc.h"
+
+/**
+ * VF states
+ */
+enum bfa_vf_state {
+	BFA_VF_UNINIT    = 0,	/*  fabric is not yet initialized */
+	BFA_VF_LINK_DOWN = 1,	/*  link is down */
+	BFA_VF_FLOGI     = 2,	/*  flogi is in progress */
+	BFA_VF_AUTH      = 3,	/*  authentication in progress */
+	BFA_VF_NOFABRIC  = 4,	/*  fabric is not present */
+	BFA_VF_ONLINE    = 5,	/*  login to fabric is complete */
+	BFA_VF_EVFP      = 6,	/*  EVFP is in progress */
+	BFA_VF_ISOLATED  = 7,	/*  port isolated due to vf_id mismatch */
+};
+
+/**
+ * VF statistics
+ */
+struct bfa_vf_stats_s {
+	u32	flogi_sent;	/*  Num FLOGIs sent */
+	u32	flogi_rsp_err;	/*  FLOGI response errors */
+	u32	flogi_acc_err;	/*  FLOGI accept errors */
+	u32	flogi_accepts;	/*  FLOGI accepts received */
+	u32	flogi_rejects;	/*  FLOGI rejects received */
+	u32	flogi_unknown_rsp; /*  Unknown responses for FLOGI */
+	u32	flogi_alloc_wait; /*  Allocation waits prior to sending FLOGI */
+	u32	flogi_rcvd;	/*  FLOGIs received */
+	u32	flogi_rejected;	/*  Incoming FLOGIs rejected */
+	u32	fabric_onlines;	/*  Internal fabric online notification sent
+				 *  to other modules */
+	u32	fabric_offlines; /* Internal fabric offline notification sent
+				  * to other modules */
+	u32	resvd; /*  padding for 64 bit alignment */
+};
+
+/**
+ * VF attributes returned in queries
+ */
+struct bfa_vf_attr_s {
+	enum bfa_vf_state  state;		/*  VF state */
+	u32        rsvd;
+	wwn_t           fabric_name;	/*  fabric name */
+};
+
+#define BFA_FCS_MAX_LPORTS 256
+#define BFA_FCS_FABRIC_IPADDR_SZ  16
+
+/**
+ * symbolic names for base port/virtual port
+ */
+#define BFA_SYMNAME_MAXLEN	128	/* 128 bytes */
+struct bfa_lport_symname_s {
+	char	    symname[BFA_SYMNAME_MAXLEN];
+};
+
+/**
+* Roles of FCS port:
+ *     - FCP IM and FCP TM roles cannot be enabled together for a FCS port
+ *     - Create multiple ports if both IM and TM functions required.
+ *     - Atleast one role must be specified.
+ */
+enum bfa_lport_role {
+	BFA_LPORT_ROLE_FCP_IM	= 0x01,	/*  FCP initiator role */
+	BFA_LPORT_ROLE_FCP_MAX	= BFA_LPORT_ROLE_FCP_IM,
+};
+
+/**
+ * FCS port configuration.
+ */
+struct bfa_lport_cfg_s {
+    wwn_t	       pwwn;       /*  port wwn */
+    wwn_t	       nwwn;       /*  node wwn */
+    struct bfa_lport_symname_s  sym_name;   /*  vm port symbolic name */
+	bfa_boolean_t       preboot_vp;  /*  vport created from PBC */
+    enum bfa_lport_role     roles;      /*  FCS port roles */
+    u8	     tag[16];	/*  opaque tag from application */
+};
+
+/**
+ * FCS port states
+ */
+enum bfa_lport_state {
+	BFA_LPORT_UNINIT  = 0,	/*  PORT is not yet initialized */
+	BFA_LPORT_FDISC   = 1,	/*  FDISC is in progress */
+	BFA_LPORT_ONLINE  = 2,	/*  login to fabric is complete */
+	BFA_LPORT_OFFLINE = 3,	/*  No login to fabric */
+};
+
+/**
+ * FCS port type.
+ */
+enum bfa_lport_type {
+	BFA_LPORT_TYPE_PHYSICAL = 0,
+	BFA_LPORT_TYPE_VIRTUAL,
+};
+
+/**
+ * FCS port offline reason.
+ */
+enum bfa_lport_offline_reason {
+	BFA_LPORT_OFFLINE_UNKNOWN = 0,
+	BFA_LPORT_OFFLINE_LINKDOWN,
+	BFA_LPORT_OFFLINE_FAB_UNSUPPORTED,	/*  NPIV not supported by the
+	 *    fabric */
+	BFA_LPORT_OFFLINE_FAB_NORESOURCES,
+	BFA_LPORT_OFFLINE_FAB_LOGOUT,
+};
+
+/**
+ * FCS lport info.
+ */
+struct bfa_lport_info_s {
+	u8	 port_type;	/* bfa_lport_type_t : physical or
+	 * virtual */
+	u8	 port_state;	/* one of bfa_lport_state values */
+	u8	 offline_reason;	/* one of bfa_lport_offline_reason_t
+	 * values */
+	wwn_t	   port_wwn;
+	wwn_t	   node_wwn;
+
+	/*
+	 * following 4 feilds are valid for Physical Ports only
+	 */
+	u32	max_vports_supp;	/* Max supported vports */
+	u32	num_vports_inuse;	/* Num of in use vports */
+	u32	max_rports_supp;	/* Max supported rports */
+	u32	num_rports_inuse;	/* Num of doscovered rports */
+
+};
+
+/**
+ * FCS port statistics
+ */
+struct bfa_lport_stats_s {
+	u32	ns_plogi_sent;
+	u32	ns_plogi_rsp_err;
+	u32	ns_plogi_acc_err;
+	u32	ns_plogi_accepts;
+	u32	ns_rejects;	/* NS command rejects */
+	u32	ns_plogi_unknown_rsp;
+	u32	ns_plogi_alloc_wait;
+
+	u32	ns_retries;	/* NS command retries */
+	u32	ns_timeouts;	/* NS command timeouts */
+
+	u32	ns_rspnid_sent;
+	u32	ns_rspnid_accepts;
+	u32	ns_rspnid_rsp_err;
+	u32	ns_rspnid_rejects;
+	u32	ns_rspnid_alloc_wait;
+
+	u32	ns_rftid_sent;
+	u32	ns_rftid_accepts;
+	u32	ns_rftid_rsp_err;
+	u32	ns_rftid_rejects;
+	u32	ns_rftid_alloc_wait;
+
+	u32	ns_rffid_sent;
+	u32	ns_rffid_accepts;
+	u32	ns_rffid_rsp_err;
+	u32	ns_rffid_rejects;
+	u32	ns_rffid_alloc_wait;
+
+	u32	ns_gidft_sent;
+	u32	ns_gidft_accepts;
+	u32	ns_gidft_rsp_err;
+	u32	ns_gidft_rejects;
+	u32	ns_gidft_unknown_rsp;
+	u32	ns_gidft_alloc_wait;
+
+	/*
+	 * Mgmt Server stats
+	 */
+	u32	ms_retries;	/* MS command retries */
+	u32	ms_timeouts;	/* MS command timeouts */
+	u32	ms_plogi_sent;
+	u32	ms_plogi_rsp_err;
+	u32	ms_plogi_acc_err;
+	u32	ms_plogi_accepts;
+	u32	ms_rejects;	/* MS command rejects */
+	u32	ms_plogi_unknown_rsp;
+	u32	ms_plogi_alloc_wait;
+
+	u32	num_rscn;	/* Num of RSCN received */
+	u32	num_portid_rscn;/* Num portid format RSCN
+	* received */
+
+	u32	uf_recvs;	/* Unsolicited recv frames	*/
+	u32	uf_recv_drops;	/* Dropped received frames	*/
+
+	u32	plogi_rcvd;	/* Received plogi	*/
+	u32	prli_rcvd;	/* Received prli	*/
+	u32	adisc_rcvd;	/* Received adisc	*/
+	u32	prlo_rcvd;	/* Received prlo	*/
+	u32	logo_rcvd;	/* Received logo	*/
+	u32	rpsc_rcvd;	/* Received rpsc	*/
+	u32	un_handled_els_rcvd;	/* Received unhandled ELS	*/
+	u32	rport_plogi_timeouts; /* Rport plogi retry timeout count */
+	u32	rport_del_max_plogi_retry; /* Deleted rport
+					    * (max retry of plogi) */
+};
+
+/**
+ * BFA port attribute returned in queries
+ */
+struct bfa_lport_attr_s {
+	enum bfa_lport_state state;	/*  port state */
+	u32	 pid;	/*  port ID */
+	struct bfa_lport_cfg_s   port_cfg;	/*  port configuration */
+	enum bfa_port_type port_type;	/*  current topology */
+	u32	 loopback;	/*  cable is externally looped back */
+	wwn_t	fabric_name; /*  attached switch's nwwn */
+	u8	fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /*  attached
+	* fabric's ip addr */
+	mac_t	   fpma_mac;	/*  Lport's FPMA Mac address */
+	u16	authfail;	/*  auth failed state */
+};
+
+
+/**
+ * VPORT states
+ */
+enum bfa_vport_state {
+	BFA_FCS_VPORT_UNINIT		= 0,
+	BFA_FCS_VPORT_CREATED		= 1,
+	BFA_FCS_VPORT_OFFLINE		= 1,
+	BFA_FCS_VPORT_FDISC_SEND	= 2,
+	BFA_FCS_VPORT_FDISC		= 3,
+	BFA_FCS_VPORT_FDISC_RETRY	= 4,
+	BFA_FCS_VPORT_ONLINE		= 5,
+	BFA_FCS_VPORT_DELETING		= 6,
+	BFA_FCS_VPORT_CLEANUP		= 6,
+	BFA_FCS_VPORT_LOGO_SEND		= 7,
+	BFA_FCS_VPORT_LOGO		= 8,
+	BFA_FCS_VPORT_ERROR		= 9,
+	BFA_FCS_VPORT_MAX_STATE,
+};
+
+/**
+ * vport statistics
+ */
+struct bfa_vport_stats_s {
+	struct bfa_lport_stats_s port_stats;	/*  base class (port) stats */
+	/*
+	 * TODO - remove
+	 */
+
+	u32        fdisc_sent;	/*  num fdisc sent */
+	u32        fdisc_accepts;	/*  fdisc accepts */
+	u32        fdisc_retries;	/*  fdisc retries */
+	u32        fdisc_timeouts;	/*  fdisc timeouts */
+	u32        fdisc_rsp_err;	/*  fdisc response error */
+	u32        fdisc_acc_bad;	/*  bad fdisc accepts */
+	u32        fdisc_rejects;	/*  fdisc rejects */
+	u32        fdisc_unknown_rsp;
+	/*
+	 *!< fdisc rsp unknown error
+	 */
+	u32        fdisc_alloc_wait;/*  fdisc req (fcxp)alloc wait */
+
+	u32        logo_alloc_wait;/*  logo req (fcxp) alloc wait */
+	u32        logo_sent;	/*  logo sent */
+	u32        logo_accepts;	/*  logo accepts */
+	u32        logo_rejects;	/*  logo rejects */
+	u32        logo_rsp_err;	/*  logo rsp errors */
+	u32        logo_unknown_rsp;
+			/*  logo rsp unknown errors */
+
+	u32        fab_no_npiv;	/*  fabric does not support npiv */
+
+	u32        fab_offline;	/*  offline events from fab SM */
+	u32        fab_online;	/*  online events from fab SM */
+	u32        fab_cleanup;	/*  cleanup request from fab SM */
+	u32        rsvd;
+};
+
+/**
+ * BFA vport attribute returned in queries
+ */
+struct bfa_vport_attr_s {
+	struct bfa_lport_attr_s   port_attr; /*  base class (port) attributes */
+	enum bfa_vport_state vport_state; /*  vport state */
+	u32          rsvd;
+};
+
+/**
+ * FCS remote port states
+ */
+enum bfa_rport_state {
+	BFA_RPORT_UNINIT	= 0,	/*  PORT is not yet initialized */
+	BFA_RPORT_OFFLINE	= 1,	/*  rport is offline */
+	BFA_RPORT_PLOGI		= 2,	/*  PLOGI to rport is in progress */
+	BFA_RPORT_ONLINE	= 3,	/*  login to rport is complete */
+	BFA_RPORT_PLOGI_RETRY	= 4,	/*  retrying login to rport */
+	BFA_RPORT_NSQUERY	= 5,	/*  nameserver query */
+	BFA_RPORT_ADISC		= 6,	/*  ADISC authentication */
+	BFA_RPORT_LOGO		= 7,	/*  logging out with rport */
+	BFA_RPORT_LOGORCV	= 8,	/*  handling LOGO from rport */
+	BFA_RPORT_NSDISC	= 9,	/*  re-discover rport */
+};
+
+/**
+ *  Rport Scsi Function : Initiator/Target.
+ */
+enum bfa_rport_function {
+	BFA_RPORT_INITIATOR	= 0x01,	/*  SCSI Initiator	*/
+	BFA_RPORT_TARGET	= 0x02,	/*  SCSI Target	*/
+};
+
+/**
+ * port/node symbolic names for rport
+ */
+#define BFA_RPORT_SYMNAME_MAXLEN	255
+struct bfa_rport_symname_s {
+	char            symname[BFA_RPORT_SYMNAME_MAXLEN];
+};
+
+/**
+ * FCS remote port statistics
+ */
+struct bfa_rport_stats_s {
+	u32        offlines;           /*  remote port offline count  */
+	u32        onlines;            /*  remote port online count   */
+	u32        rscns;              /*  RSCN affecting rport       */
+	u32        plogis;		    /*  plogis sent                */
+	u32        plogi_accs;	    /*  plogi accepts              */
+	u32        plogi_timeouts;	    /*  plogi timeouts             */
+	u32        plogi_rejects;	    /*  rcvd plogi rejects         */
+	u32        plogi_failed;	    /*  local failure              */
+	u32        plogi_rcvd;	    /*  plogis rcvd                */
+	u32        prli_rcvd;          /*  inbound PRLIs              */
+	u32        adisc_rcvd;         /*  ADISCs received            */
+	u32        adisc_rejects;      /*  recvd  ADISC rejects       */
+	u32        adisc_sent;         /*  ADISC requests sent        */
+	u32        adisc_accs;         /*  ADISC accepted by rport    */
+	u32        adisc_failed;       /*  ADISC failed (no response) */
+	u32        adisc_rejected;     /*  ADISC rejected by us    */
+	u32        logos;              /*  logos sent                 */
+	u32        logo_accs;          /*  LOGO accepts from rport    */
+	u32        logo_failed;        /*  LOGO failures              */
+	u32        logo_rejected;      /*  LOGO rejects from rport    */
+	u32        logo_rcvd;          /*  LOGO from remote port      */
+
+	u32        rpsc_rcvd;         /*  RPSC received            */
+	u32        rpsc_rejects;      /*  recvd  RPSC rejects       */
+	u32        rpsc_sent;         /*  RPSC requests sent        */
+	u32        rpsc_accs;         /*  RPSC accepted by rport    */
+	u32        rpsc_failed;       /*  RPSC failed (no response) */
+	u32        rpsc_rejected;     /*  RPSC rejected by us    */
+
+	u32	rjt_insuff_res;	/*  LS RJT with insuff resources */
+	struct bfa_rport_hal_stats_s	hal_stats;  /*  BFA rport stats    */
+};
+
+/**
+ * FCS remote port attributes returned in queries
+ */
+struct bfa_rport_attr_s {
+	wwn_t		nwwn;	/*  node wwn */
+	wwn_t		pwwn;	/*  port wwn */
+	enum fc_cos cos_supported;	/*  supported class of services */
+	u32		pid;	/*  port ID */
+	u32		df_sz;	/*  Max payload size */
+	enum bfa_rport_state	state;	/*  Rport State machine state */
+	enum fc_cos	fc_cos;	/*  FC classes of services */
+	bfa_boolean_t	cisc;	/*  CISC capable device */
+	struct bfa_rport_symname_s symname; /*  Symbolic Name */
+	enum bfa_rport_function	scsi_function; /*  Initiator/Target */
+	struct bfa_rport_qos_attr_s qos_attr; /*  qos attributes  */
+	enum bfa_port_speed curr_speed;   /*  operating speed got from
+					    * RPSC ELS. UNKNOWN, if RPSC
+					    * is not supported */
+	bfa_boolean_t	trl_enforced;	/*  TRL enforced ? TRUE/FALSE */
+	enum bfa_port_speed	assigned_speed;	/* Speed assigned by the user.
+						 * will be used if RPSC is not
+						 * supported by the rport */
+};
+
+struct bfa_rport_remote_link_stats_s {
+	u32 lfc; /*  Link Failure Count */
+	u32 lsyc; /*  Loss of Synchronization Count */
+	u32 lsic; /*  Loss of Signal Count */
+	u32 pspec; /*  Primitive Sequence Protocol Error Count */
+	u32 itwc; /*  Invalid Transmission Word Count */
+	u32 icc; /*  Invalid CRC Count */
+};
+
+
+#define BFA_MAX_IO_INDEX 7
+#define BFA_NO_IO_INDEX 9
+
+/**
+ * FCS itnim states
+ */
+enum bfa_itnim_state {
+	BFA_ITNIM_OFFLINE	= 0,	/*  offline */
+	BFA_ITNIM_PRLI_SEND	= 1,	/*  prli send */
+	BFA_ITNIM_PRLI_SENT	= 2,	/*  prli sent */
+	BFA_ITNIM_PRLI_RETRY	= 3,	/*  prli retry */
+	BFA_ITNIM_HCB_ONLINE	= 4,	/*  online callback */
+	BFA_ITNIM_ONLINE	= 5,	/*  online */
+	BFA_ITNIM_HCB_OFFLINE	= 6,	/*  offline callback */
+	BFA_ITNIM_INITIATIOR	= 7,	/*  initiator */
+};
+
+/**
+ * FCS remote port statistics
+ */
+struct bfa_itnim_stats_s {
+	u32        onlines;	/*  num rport online */
+	u32        offlines;	/*  num rport offline */
+	u32        prli_sent;	/*  num prli sent out */
+	u32        fcxp_alloc_wait;/*  num fcxp alloc waits */
+	u32        prli_rsp_err;	/*  num prli rsp errors */
+	u32        prli_rsp_acc;	/*  num prli rsp accepts */
+	u32        initiator;	/*  rport is an initiator */
+	u32        prli_rsp_parse_err;	/*  prli rsp parsing errors */
+	u32        prli_rsp_rjt;	/*  num prli rsp rejects */
+	u32        timeout;	/*  num timeouts detected */
+	u32        sler;		/*  num sler notification from BFA */
+	u32	rsvd;		/* padding for 64 bit alignment */
+};
+
+/**
+ * FCS itnim attributes returned in queries
+ */
+struct bfa_itnim_attr_s {
+	enum bfa_itnim_state state; /*  FCS itnim state        */
+	u8 retry;		/*  data retransmision support */
+	u8	task_retry_id;  /*  task retry ident support   */
+	u8 rec_support;    /*  REC supported              */
+	u8 conf_comp;      /*  confirmed completion supp  */
+};
+
+#endif /* __BFA_DEFS_FCS_H__ */
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
new file mode 100644
index 0000000..56226fc
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -0,0 +1,1081 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFA_DEFS_SVC_H__
+#define __BFA_DEFS_SVC_H__
+
+#include "bfa_defs.h"
+#include "bfa_fc.h"
+#include "bfi.h"
+
+#define BFA_IOCFC_INTR_DELAY	1125
+#define BFA_IOCFC_INTR_LATENCY	225
+#define BFA_IOCFCOE_INTR_DELAY	25
+#define BFA_IOCFCOE_INTR_LATENCY 5
+
+/**
+ * Interrupt coalescing configuration.
+ */
+#pragma pack(1)
+struct bfa_iocfc_intr_attr_s {
+	u8		coalesce;	/*  enable/disable coalescing */
+	u8		rsvd[3];
+	u16	latency;	/*  latency in microseconds   */
+	u16	delay;		/*  delay in microseconds     */
+};
+
+/**
+ * IOC firmware configuraton
+ */
+struct bfa_iocfc_fwcfg_s {
+	u16        num_fabrics;	/*  number of fabrics		*/
+	u16        num_lports;	/*  number of local lports	*/
+	u16        num_rports;	/*  number of remote ports	*/
+	u16        num_ioim_reqs;	/*  number of IO reqs		*/
+	u16        num_tskim_reqs;	/*  task management requests	*/
+	u16        num_iotm_reqs;	/*  number of TM IO reqs	*/
+	u16        num_tsktm_reqs;	/*  TM task management requests*/
+	u16        num_fcxp_reqs;	/*  unassisted FC exchanges	*/
+	u16        num_uf_bufs;	/*  unsolicited recv buffers	*/
+	u8		num_cqs;
+	u8		fw_tick_res;	/*  FW clock resolution in ms */
+	u8		rsvd[4];
+};
+#pragma pack()
+
+struct bfa_iocfc_drvcfg_s {
+	u16        num_reqq_elems;	/*  number of req queue elements */
+	u16        num_rspq_elems;	/*  number of rsp queue elements */
+	u16        num_sgpgs;	/*  number of total SG pages	  */
+	u16        num_sboot_tgts;	/*  number of SAN boot targets	  */
+	u16        num_sboot_luns;	/*  number of SAN boot luns	  */
+	u16	    ioc_recover;	/*  IOC recovery mode		  */
+	u16	    min_cfg;	/*  minimum configuration	  */
+	u16        path_tov;	/*  device path timeout	  */
+	bfa_boolean_t   delay_comp; /*  delay completion of
+							failed inflight IOs */
+	u32		rsvd;
+};
+
+/**
+ * IOC configuration
+ */
+struct bfa_iocfc_cfg_s {
+	struct bfa_iocfc_fwcfg_s	fwcfg;	/*  firmware side config */
+	struct bfa_iocfc_drvcfg_s	drvcfg;	/*  driver side config	  */
+};
+
+/**
+ * IOC firmware IO stats
+ */
+struct bfa_fw_io_stats_s {
+	u32	host_abort;		/*  IO aborted by host driver*/
+	u32	host_cleanup;		/*  IO clean up by host driver */
+
+	u32	fw_io_timeout;		/*  IOs timedout */
+	u32	fw_frm_parse;		/*  frame parsed by f/w */
+	u32	fw_frm_data;		/*  fcp_data frame parsed by f/w */
+	u32	fw_frm_rsp;		/*  fcp_rsp frame parsed by f/w */
+	u32	fw_frm_xfer_rdy;	/*  xfer_rdy frame parsed by f/w */
+	u32	fw_frm_bls_acc;		/*  BLS ACC  frame parsed by f/w */
+	u32	fw_frm_tgt_abort;	/*  target ABTS parsed by f/w */
+	u32	fw_frm_unknown;		/*  unknown parsed by f/w */
+	u32	fw_data_dma;		/*  f/w DMA'ed the data frame */
+	u32	fw_frm_drop;		/*  f/w drop the frame */
+
+	u32	rec_timeout;		/*  FW rec timed out */
+	u32	error_rec;			/*  FW sending rec on
+							* an error condition*/
+	u32	wait_for_si;		/*  FW wait for SI */
+	u32	rec_rsp_inval;		/*  REC rsp invalid */
+	u32	seqr_io_abort;		/*  target does not know cmd so abort */
+	u32	seqr_io_retry;		/*  SEQR failed so retry IO */
+
+	u32	itn_cisc_upd_rsp;	/*  ITN cisc updated on fcp_rsp */
+	u32	itn_cisc_upd_data;	/*  ITN cisc updated on fcp_data */
+	u32	itn_cisc_upd_xfer_rdy;	/*  ITN cisc updated on fcp_data */
+
+	u32	fcp_data_lost;		/*  fcp data lost */
+
+	u32	ro_set_in_xfer_rdy;	/*  Target set RO in Xfer_rdy frame */
+	u32	xfer_rdy_ooo_err;	/*  Out of order Xfer_rdy received */
+	u32	xfer_rdy_unknown_err;	/*  unknown error in xfer_rdy frame */
+
+	u32	io_abort_timeout;	/*  ABTS timedout  */
+	u32	sler_initiated;		/*  SLER initiated */
+
+	u32	unexp_fcp_rsp;		/*  fcp response in wrong state */
+
+	u32	fcp_rsp_under_run;	/*  fcp rsp IO underrun */
+	u32        fcp_rsp_under_run_wr;   /*  fcp rsp IO underrun for write */
+	u32	fcp_rsp_under_run_err;	/*  fcp rsp IO underrun error */
+	u32        fcp_rsp_resid_inval;    /*  invalid residue */
+	u32	fcp_rsp_over_run;	/*  fcp rsp IO overrun */
+	u32	fcp_rsp_over_run_err;	/*  fcp rsp IO overrun error */
+	u32	fcp_rsp_proto_err;	/*  protocol error in fcp rsp */
+	u32	fcp_rsp_sense_err;	/*  error in sense info in fcp rsp */
+	u32	fcp_conf_req;		/*  FCP conf requested */
+
+	u32	tgt_aborted_io;		/*  target initiated abort */
+
+	u32	ioh_edtov_timeout_event;/*  IOH edtov timer popped */
+	u32	ioh_fcp_rsp_excp_event;	/*  IOH FCP_RSP exception */
+	u32	ioh_fcp_conf_event;	/*  IOH FCP_CONF */
+	u32	ioh_mult_frm_rsp_event;	/*  IOH multi_frame FCP_RSP */
+	u32	ioh_hit_class2_event;	/*  IOH hit class2 */
+	u32	ioh_miss_other_event;	/*  IOH miss other */
+	u32	ioh_seq_cnt_err_event;	/*  IOH seq cnt error */
+	u32	ioh_len_err_event;		/*  IOH len error - fcp_dl !=
+							* bytes xfered */
+	u32	ioh_seq_len_err_event;	/*  IOH seq len error */
+	u32	ioh_data_oor_event;	/*  Data out of range */
+	u32	ioh_ro_ooo_event;	/*  Relative offset out of range */
+	u32	ioh_cpu_owned_event;	/*  IOH hit -iost owned by f/w */
+	u32	ioh_unexp_frame_event;	/*  unexpected frame recieved
+						 *   count */
+	u32	ioh_err_int;		/*  IOH error int during data-phase
+						 *   for scsi write
+						 */
+};
+
+/**
+ * IOC port firmware stats
+ */
+
+struct bfa_fw_port_fpg_stats_s {
+    u32    intr_evt;
+    u32    intr;
+    u32    intr_excess;
+    u32    intr_cause0;
+    u32    intr_other;
+    u32    intr_other_ign;
+    u32    sig_lost;
+    u32    sig_regained;
+    u32    sync_lost;
+    u32    sync_to;
+    u32    sync_regained;
+    u32    div2_overflow;
+    u32    div2_underflow;
+    u32    efifo_overflow;
+    u32    efifo_underflow;
+    u32    idle_rx;
+    u32    lrr_rx;
+    u32    lr_rx;
+    u32    ols_rx;
+    u32    nos_rx;
+    u32    lip_rx;
+    u32    arbf0_rx;
+    u32    arb_rx;
+    u32    mrk_rx;
+    u32    const_mrk_rx;
+    u32    prim_unknown;
+};
+
+
+struct bfa_fw_port_lksm_stats_s {
+    u32    hwsm_success;       /*  hwsm state machine success          */
+    u32    hwsm_fails;         /*  hwsm fails                          */
+    u32    hwsm_wdtov;         /*  hwsm timed out                      */
+    u32    swsm_success;       /*  swsm success                        */
+    u32    swsm_fails;         /*  swsm fails                          */
+    u32    swsm_wdtov;         /*  swsm timed out                      */
+    u32    busybufs;           /*  link init failed due to busybuf     */
+    u32    buf_waits;          /*  bufwait state entries               */
+    u32    link_fails;         /*  link failures                       */
+    u32    psp_errors;         /*  primitive sequence protocol errors  */
+    u32    lr_unexp;           /*  No. of times LR rx-ed unexpectedly  */
+    u32    lrr_unexp;          /*  No. of times LRR rx-ed unexpectedly */
+    u32    lr_tx;              /*  No. of times LR tx started          */
+    u32    lrr_tx;             /*  No. of times LRR tx started         */
+    u32    ols_tx;             /*  No. of times OLS tx started         */
+    u32    nos_tx;             /*  No. of times NOS tx started         */
+    u32    hwsm_lrr_rx;        /*  No. of times LRR rx-ed by HWSM      */
+    u32    hwsm_lr_rx;         /*  No. of times LR rx-ed by HWSM      */
+};
+
+struct bfa_fw_port_snsm_stats_s {
+    u32    hwsm_success;       /*  Successful hwsm terminations        */
+    u32    hwsm_fails;         /*  hwsm fail count                     */
+    u32    hwsm_wdtov;         /*  hwsm timed out                      */
+    u32    swsm_success;       /*  swsm success                        */
+    u32    swsm_wdtov;         /*  swsm timed out                      */
+    u32    error_resets;       /*  error resets initiated by upsm      */
+    u32    sync_lost;          /*  Sync loss count                     */
+    u32    sig_lost;           /*  Signal loss count                   */
+};
+
+struct bfa_fw_port_physm_stats_s {
+    u32    module_inserts;     /*  Module insert count                 */
+    u32    module_xtracts;     /*  Module extracts count               */
+    u32    module_invalids;    /*  Invalid module inserted count       */
+    u32    module_read_ign;    /*  Module validation status ignored    */
+    u32    laser_faults;       /*  Laser fault count                   */
+    u32    rsvd;
+};
+
+struct bfa_fw_fip_stats_s {
+    u32    vlan_req;           /*  vlan discovery requests             */
+    u32    vlan_notify;        /*  vlan notifications                  */
+    u32    vlan_err;           /*  vlan response error                 */
+    u32    vlan_timeouts;      /*  vlan disvoery timeouts              */
+    u32    vlan_invalids;      /*  invalid vlan in discovery advert.   */
+    u32    disc_req;           /*  Discovery solicit requests          */
+    u32    disc_rsp;           /*  Discovery solicit response          */
+    u32    disc_err;           /*  Discovery advt. parse errors        */
+    u32    disc_unsol;         /*  Discovery unsolicited               */
+    u32    disc_timeouts;      /*  Discovery timeouts                  */
+    u32    disc_fcf_unavail;   /*  Discovery FCF Not Avail.            */
+    u32    linksvc_unsupp;     /*  Unsupported link service req        */
+    u32    linksvc_err;        /*  Parse error in link service req     */
+    u32    logo_req;           /*  FIP logos received                  */
+    u32    clrvlink_req;       /*  Clear virtual link req              */
+    u32    op_unsupp;          /*  Unsupported FIP operation           */
+    u32    untagged;           /*  Untagged frames (ignored)           */
+    u32    invalid_version;    /*  Invalid FIP version                 */
+};
+
+struct bfa_fw_lps_stats_s {
+    u32    mac_invalids;       /*  Invalid mac assigned                */
+    u32    rsvd;
+};
+
+struct bfa_fw_fcoe_stats_s {
+    u32    cee_linkups;        /*  CEE link up count                   */
+    u32    cee_linkdns;        /*  CEE link down count                 */
+    u32    fip_linkups;        /*  FIP link up count                   */
+    u32    fip_linkdns;        /*  FIP link up count                   */
+    u32    fip_fails;          /*  FIP fail count                      */
+    u32    mac_invalids;       /*  Invalid mac assigned                */
+};
+
+/**
+ * IOC firmware FCoE port stats
+ */
+struct bfa_fw_fcoe_port_stats_s {
+    struct bfa_fw_fcoe_stats_s  fcoe_stats;
+    struct bfa_fw_fip_stats_s   fip_stats;
+};
+
+/**
+ * IOC firmware FC uport stats
+ */
+struct bfa_fw_fc_uport_stats_s {
+	struct bfa_fw_port_snsm_stats_s		snsm_stats;
+	struct bfa_fw_port_lksm_stats_s		lksm_stats;
+};
+
+/**
+ * IOC firmware FC port stats
+ */
+union bfa_fw_fc_port_stats_s {
+	struct bfa_fw_fc_uport_stats_s	fc_stats;
+	struct bfa_fw_fcoe_port_stats_s	fcoe_stats;
+};
+
+/**
+ * IOC firmware port stats
+ */
+struct bfa_fw_port_stats_s {
+	struct bfa_fw_port_fpg_stats_s		fpg_stats;
+	struct bfa_fw_port_physm_stats_s	physm_stats;
+	union  bfa_fw_fc_port_stats_s		fc_port;
+};
+
+/**
+ * fcxchg module statistics
+ */
+struct bfa_fw_fcxchg_stats_s {
+	u32	ua_tag_inv;
+	u32	ua_state_inv;
+};
+
+struct bfa_fw_lpsm_stats_s {
+	u32	cls_rx;
+	u32	cls_tx;
+};
+
+/**
+ *  Trunk statistics
+ */
+struct bfa_fw_trunk_stats_s {
+	u32 emt_recvd;		/*  Trunk EMT received		*/
+	u32 emt_accepted;		/*  Trunk EMT Accepted		*/
+	u32 emt_rejected;		/*  Trunk EMT rejected		*/
+	u32 etp_recvd;		/*  Trunk ETP received		*/
+	u32 etp_accepted;		/*  Trunk ETP Accepted		*/
+	u32 etp_rejected;		/*  Trunk ETP rejected		*/
+	u32 lr_recvd;		/*  Trunk LR received		*/
+	u32 rsvd;			/*  padding for 64 bit alignment */
+};
+
+struct bfa_fw_advsm_stats_s {
+	u32 flogi_sent;		/*  Flogi sent			*/
+	u32 flogi_acc_recvd;	/*  Flogi Acc received		*/
+	u32 flogi_rjt_recvd;	/*  Flogi rejects received	*/
+	u32 flogi_retries;		/*  Flogi retries		*/
+
+	u32 elp_recvd;		/*  ELP received		*/
+	u32 elp_accepted;		/*  ELP Accepted		*/
+	u32 elp_rejected;		/*  ELP rejected		*/
+	u32 elp_dropped;		/*  ELP dropped		*/
+};
+
+/**
+ * IOCFC firmware stats
+ */
+struct bfa_fw_iocfc_stats_s {
+	u32	cfg_reqs;	/*  cfg request */
+	u32	updq_reqs;	/*  update queue request */
+	u32	ic_reqs;	/*  interrupt coalesce reqs */
+	u32	unknown_reqs;
+	u32	set_intr_reqs;	/*  set interrupt reqs */
+};
+
+/**
+ * IOC attributes returned in queries
+ */
+struct bfa_iocfc_attr_s {
+	struct bfa_iocfc_cfg_s		config;		/*  IOCFC config   */
+	struct bfa_iocfc_intr_attr_s	intr_attr;	/*  interrupt attr */
+};
+
+/**
+ * Eth_sndrcv mod stats
+ */
+struct bfa_fw_eth_sndrcv_stats_s {
+	u32	crc_err;
+	u32	rsvd;		/*  64bit align    */
+};
+
+/**
+ * CT MAC mod stats
+ */
+struct bfa_fw_mac_mod_stats_s {
+	u32	mac_on;		/*  MAC got turned-on */
+	u32	link_up;	/*  link-up */
+	u32	signal_off;	/*  lost signal */
+	u32	dfe_on;		/*  DFE on */
+	u32	mac_reset;	/*  # of MAC reset to bring lnk up */
+	u32	pcs_reset;	/*  # of PCS reset to bring lnk up */
+	u32	loopback;	/*  MAC got into serdes loopback */
+	u32	lb_mac_reset;
+			/*  # of MAC reset to bring link up in loopback */
+	u32	lb_pcs_reset;
+			/*  # of PCS reset to bring link up in loopback */
+	u32	rsvd;		/*  64bit align    */
+};
+
+/**
+ * CT MOD stats
+ */
+struct bfa_fw_ct_mod_stats_s {
+	u32	rxa_rds_undrun;	/*  RxA RDS underrun */
+	u32	rad_bpc_ovfl;	/*  RAD BPC overflow */
+	u32	rad_rlb_bpc_ovfl; /*  RAD RLB BPC overflow */
+	u32	bpc_fcs_err;	/*  BPC FCS_ERR */
+	u32	txa_tso_hdr;	/*  TxA TSO header too long */
+	u32	rsvd;		/*  64bit align    */
+};
+
+/**
+ * IOC firmware stats
+ */
+struct bfa_fw_stats_s {
+	struct bfa_fw_ioc_stats_s	ioc_stats;
+	struct bfa_fw_iocfc_stats_s	iocfc_stats;
+	struct bfa_fw_io_stats_s	io_stats;
+	struct bfa_fw_port_stats_s	port_stats;
+	struct bfa_fw_fcxchg_stats_s	fcxchg_stats;
+	struct bfa_fw_lpsm_stats_s	lpsm_stats;
+	struct bfa_fw_lps_stats_s	lps_stats;
+	struct bfa_fw_trunk_stats_s	trunk_stats;
+	struct bfa_fw_advsm_stats_s	advsm_stats;
+	struct bfa_fw_mac_mod_stats_s	macmod_stats;
+	struct bfa_fw_ct_mod_stats_s	ctmod_stats;
+	struct bfa_fw_eth_sndrcv_stats_s	ethsndrcv_stats;
+};
+
+#define BFA_IOCFC_PATHTOV_MAX	60
+#define BFA_IOCFC_QDEPTH_MAX	2000
+
+/**
+ * QoS states
+ */
+enum bfa_qos_state {
+	BFA_QOS_ONLINE = 1,		/*  QoS is online */
+	BFA_QOS_OFFLINE = 2,		/*  QoS is offline */
+};
+
+/**
+ * QoS  Priority levels.
+ */
+enum bfa_qos_priority {
+	BFA_QOS_UNKNOWN = 0,
+	BFA_QOS_HIGH  = 1,	/*  QoS Priority Level High */
+	BFA_QOS_MED  =  2,	/*  QoS Priority Level Medium */
+	BFA_QOS_LOW  =  3,	/*  QoS Priority Level Low */
+};
+
+/**
+ * QoS  bandwidth allocation for each priority level
+ */
+enum bfa_qos_bw_alloc {
+	BFA_QOS_BW_HIGH  = 60,	/*  bandwidth allocation for High */
+	BFA_QOS_BW_MED  =  30,	/*  bandwidth allocation for Medium */
+	BFA_QOS_BW_LOW  =  10,	/*  bandwidth allocation for Low */
+};
+#pragma pack(1)
+/**
+ * QoS attribute returned in QoS Query
+ */
+struct bfa_qos_attr_s {
+	u8		state;		/*  QoS current state */
+	u8		rsvd[3];
+	u32  total_bb_cr;		/*  Total BB Credits */
+};
+
+/**
+ * These fields should be displayed only from the CLI.
+ * There will be a separate BFAL API (get_qos_vc_attr ?)
+ * to retrieve this.
+ *
+ */
+#define  BFA_QOS_MAX_VC  16
+
+struct bfa_qos_vc_info_s {
+	u8 vc_credit;
+	u8 borrow_credit;
+	u8 priority;
+	u8 resvd;
+};
+
+struct bfa_qos_vc_attr_s {
+	u16  total_vc_count;                    /*  Total VC Count */
+	u16  shared_credit;
+	u32  elp_opmode_flags;
+	struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC];  /*   as many as
+							    * total_vc_count */
+};
+
+/**
+ * QoS statistics
+ */
+struct bfa_qos_stats_s {
+	u32	flogi_sent;		/*  QoS Flogi sent */
+	u32	flogi_acc_recvd;	/*  QoS Flogi Acc received */
+	u32	flogi_rjt_recvd; /*  QoS Flogi rejects received */
+	u32	flogi_retries;		/*  QoS Flogi retries */
+
+	u32	elp_recvd;		/*  QoS ELP received */
+	u32	elp_accepted;		/*  QoS ELP Accepted */
+	u32	elp_rejected;       /*  QoS ELP rejected */
+	u32	elp_dropped;        /*  QoS ELP dropped  */
+
+	u32	qos_rscn_recvd;     /*  QoS RSCN received */
+	u32	rsvd;		    /* padding for 64 bit alignment */
+};
+
+/**
+ * FCoE statistics
+ */
+struct bfa_fcoe_stats_s {
+	u64	secs_reset;	/*  Seconds since stats reset	     */
+	u64	cee_linkups;	/*  CEE link up		     */
+	u64	cee_linkdns;	/*  CEE link down		     */
+	u64	fip_linkups;	/*  FIP link up		     */
+	u64	fip_linkdns;	/*  FIP link down		     */
+	u64	fip_fails;	/*  FIP failures		     */
+	u64	mac_invalids;	/*  Invalid mac assignments	     */
+	u64	vlan_req;	/*  Vlan requests		     */
+	u64	vlan_notify;	/*  Vlan notifications		     */
+	u64	vlan_err;	/*  Vlan notification errors	     */
+	u64	vlan_timeouts;	/*  Vlan request timeouts	     */
+	u64	vlan_invalids;	/*  Vlan invalids		     */
+	u64	disc_req;	/*  Discovery requests		     */
+	u64	disc_rsp;	/*  Discovery responses	     */
+	u64	disc_err;	/*  Discovery error frames	     */
+	u64	disc_unsol;	/*  Discovery unsolicited	     */
+	u64	disc_timeouts;	/*  Discovery timeouts		     */
+	u64	disc_fcf_unavail; /*  Discovery FCF not avail	     */
+	u64	linksvc_unsupp;	/*  FIP link service req unsupp.    */
+	u64	linksvc_err;	/*  FIP link service req errors     */
+	u64	logo_req;	/*  FIP logos received		     */
+	u64	clrvlink_req;	/*  Clear virtual link requests     */
+	u64	op_unsupp;	/*  FIP operation unsupp.	     */
+	u64	untagged;	/*  FIP untagged frames	     */
+	u64	txf_ucast;	/*  Tx FCoE unicast frames	     */
+	u64	txf_ucast_vlan;	/*  Tx FCoE unicast vlan frames     */
+	u64	txf_ucast_octets; /*  Tx FCoE unicast octets	     */
+	u64	txf_mcast;	/*  Tx FCoE multicast frames	     */
+	u64	txf_mcast_vlan;	/*  Tx FCoE multicast vlan frames   */
+	u64	txf_mcast_octets; /*  Tx FCoE multicast octets	     */
+	u64	txf_bcast;	/*  Tx FCoE broadcast frames	     */
+	u64	txf_bcast_vlan;	/*  Tx FCoE broadcast vlan frames   */
+	u64	txf_bcast_octets; /*  Tx FCoE broadcast octets	     */
+	u64	txf_timeout;	/*  Tx timeouts		     */
+	u64	txf_parity_errors; /*  Transmit parity err	     */
+	u64	txf_fid_parity_errors; /*  Transmit FID parity err  */
+	u64	rxf_ucast_octets; /*  Rx FCoE unicast octets	     */
+	u64	rxf_ucast;	/*  Rx FCoE unicast frames	     */
+	u64	rxf_ucast_vlan;	/*  Rx FCoE unicast vlan frames     */
+	u64	rxf_mcast_octets; /*  Rx FCoE multicast octets	     */
+	u64	rxf_mcast;	/*  Rx FCoE multicast frames	     */
+	u64	rxf_mcast_vlan;	/*  Rx FCoE multicast vlan frames   */
+	u64	rxf_bcast_octets; /*  Rx FCoE broadcast octets	     */
+	u64	rxf_bcast;	/*  Rx FCoE broadcast frames	     */
+	u64	rxf_bcast_vlan;	/*  Rx FCoE broadcast vlan frames   */
+};
+
+/**
+ * QoS or FCoE stats (fcport stats excluding physical FC port stats)
+ */
+union bfa_fcport_stats_u {
+	struct bfa_qos_stats_s	fcqos;
+	struct bfa_fcoe_stats_s	fcoe;
+};
+#pragma pack()
+
+struct bfa_fcpim_del_itn_stats_s {
+	u32	del_itn_iocomp_aborted;	   /* Aborted IO requests	      */
+	u32	del_itn_iocomp_timedout;   /* IO timeouts		      */
+	u32	del_itn_iocom_sqer_needed; /* IO retry for SQ error recovery  */
+	u32	del_itn_iocom_res_free;    /* Delayed freeing of IO resources */
+	u32	del_itn_iocom_hostabrts;   /* Host IO abort requests	      */
+	u32	del_itn_total_ios;	   /* Total IO count		      */
+	u32	del_io_iocdowns;	   /* IO cleaned-up due to IOC down   */
+	u32	del_tm_iocdowns;	   /* TM cleaned-up due to IOC down   */
+};
+
+struct bfa_itnim_iostats_s {
+
+	u32	total_ios;		/*  Total IO Requests		*/
+	u32	input_reqs;		/*  Data in-bound requests	*/
+	u32	output_reqs;		/*  Data out-bound requests	*/
+	u32	io_comps;		/*  Total IO Completions	*/
+	u32	wr_throughput;		/*  Write data transfered in bytes */
+	u32	rd_throughput;		/*  Read data transfered in bytes  */
+
+	u32	iocomp_ok;		/*  Slowpath IO completions	*/
+	u32	iocomp_underrun;	/*  IO underrun		*/
+	u32	iocomp_overrun;		/*  IO overrun			*/
+	u32	qwait;			/*  IO Request-Q wait		*/
+	u32	qresumes;		/*  IO Request-Q wait done	*/
+	u32	no_iotags;		/*  No free IO tag		*/
+	u32	iocomp_timedout;	/*  IO timeouts		*/
+	u32	iocom_nexus_abort;	/*  IO failure due to target offline */
+	u32	iocom_proto_err;	/*  IO protocol errors		*/
+	u32	iocom_dif_err;		/*  IO SBC-3 protection errors	*/
+
+	u32	iocom_sqer_needed;	/*  fcp-2 error recovery failed	*/
+	u32	iocom_res_free;		/*  Delayed freeing of IO tag	*/
+
+
+	u32	io_aborts;		/*  Host IO abort requests	*/
+	u32	iocom_hostabrts;	/*  Host IO abort completions	*/
+	u32	io_cleanups;		/*  IO clean-up requests	*/
+	u32	path_tov_expired;	/*  IO path tov expired	*/
+	u32	iocomp_aborted;		/*  IO abort completions	*/
+	u32	io_iocdowns;		/*  IO cleaned-up due to IOC down */
+	u32	iocom_utags;		/*  IO comp with unknown tags	*/
+
+	u32	io_tmaborts;		/*  Abort request due to TM command */
+	u32	tm_io_comps;		/* Abort completion due to TM command */
+
+	u32	creates;		/*  IT Nexus create requests	*/
+	u32	fw_create;		/*  IT Nexus FW create requests	*/
+	u32	create_comps;		/*  IT Nexus FW create completions */
+	u32	onlines;		/*  IT Nexus onlines		*/
+	u32	offlines;		/*  IT Nexus offlines		*/
+	u32	fw_delete;		/*  IT Nexus FW delete requests	*/
+	u32	delete_comps;		/*  IT Nexus FW delete completions */
+	u32	deletes;		/*  IT Nexus delete requests	   */
+	u32	sler_events;		/*  SLER events		*/
+	u32	ioc_disabled;		/*  Num IOC disables		*/
+	u32	cleanup_comps;		/*  IT Nexus cleanup completions    */
+
+	u32	tm_cmnds;		/*  TM Requests		*/
+	u32	tm_fw_rsps;		/*  TM Completions		*/
+	u32	tm_success;		/*  TM initiated IO cleanup success */
+	u32	tm_failures;		/*  TM initiated IO cleanup failure */
+	u32	no_tskims;		/*  No free TM tag		*/
+	u32	tm_qwait;		/*  TM Request-Q wait		*/
+	u32	tm_qresumes;		/*  TM Request-Q wait done	*/
+
+	u32	tm_iocdowns;		/*  TM cleaned-up due to IOC down   */
+	u32	tm_cleanups;		/*  TM cleanup requests	*/
+	u32	tm_cleanup_comps;	/*  TM cleanup completions	*/
+};
+
+/* Modify char* port_stt[] in bfal_port.c if a new state was added */
+enum bfa_port_states {
+	BFA_PORT_ST_UNINIT		= 1,
+	BFA_PORT_ST_ENABLING_QWAIT	= 2,
+	BFA_PORT_ST_ENABLING		= 3,
+	BFA_PORT_ST_LINKDOWN		= 4,
+	BFA_PORT_ST_LINKUP		= 5,
+	BFA_PORT_ST_DISABLING_QWAIT	= 6,
+	BFA_PORT_ST_DISABLING		= 7,
+	BFA_PORT_ST_DISABLED		= 8,
+	BFA_PORT_ST_STOPPED		= 9,
+	BFA_PORT_ST_IOCDOWN		= 10,
+	BFA_PORT_ST_IOCDIS		= 11,
+	BFA_PORT_ST_FWMISMATCH		= 12,
+	BFA_PORT_ST_PREBOOT_DISABLED	= 13,
+	BFA_PORT_ST_TOGGLING_QWAIT	= 14,
+	BFA_PORT_ST_MAX_STATE,
+};
+
+/**
+ *	Port operational type (in sync with SNIA port type).
+ */
+enum bfa_port_type {
+	BFA_PORT_TYPE_UNKNOWN	= 1,	/*  port type is unknown */
+	BFA_PORT_TYPE_NPORT	= 5,	/*  P2P with switched fabric */
+	BFA_PORT_TYPE_NLPORT	= 6,	/*  public loop */
+	BFA_PORT_TYPE_LPORT	= 20,	/*  private loop */
+	BFA_PORT_TYPE_P2P	= 21,	/*  P2P with no switched fabric */
+	BFA_PORT_TYPE_VPORT	= 22,	/*  NPIV - virtual port */
+};
+
+/**
+ *	Port topology setting. A port's topology and fabric login status
+ *	determine its operational type.
+ */
+enum bfa_port_topology {
+	BFA_PORT_TOPOLOGY_NONE = 0,	/*  No valid topology */
+	BFA_PORT_TOPOLOGY_P2P  = 1,	/*  P2P only */
+	BFA_PORT_TOPOLOGY_LOOP = 2,	/*  LOOP topology */
+	BFA_PORT_TOPOLOGY_AUTO = 3,	/*  auto topology selection */
+};
+
+/**
+ *	Physical port loopback types.
+ */
+enum bfa_port_opmode {
+	BFA_PORT_OPMODE_NORMAL   = 0x00, /*  normal non-loopback mode */
+	BFA_PORT_OPMODE_LB_INT   = 0x01, /*  internal loop back */
+	BFA_PORT_OPMODE_LB_SLW   = 0x02, /*  serial link wrapback (serdes) */
+	BFA_PORT_OPMODE_LB_EXT   = 0x04, /*  external loop back (serdes) */
+	BFA_PORT_OPMODE_LB_CBL   = 0x08, /*  cabled loop back */
+	BFA_PORT_OPMODE_LB_NLINT = 0x20, /*  NL_Port internal loopback */
+};
+
+#define BFA_PORT_OPMODE_LB_HARD(_mode)			\
+	((_mode == BFA_PORT_OPMODE_LB_INT) ||		\
+	(_mode == BFA_PORT_OPMODE_LB_SLW) ||		\
+	(_mode == BFA_PORT_OPMODE_LB_EXT))
+
+/**
+ *	Port link state
+ */
+enum bfa_port_linkstate {
+	BFA_PORT_LINKUP		= 1,	/*  Physical port/Trunk link up */
+	BFA_PORT_LINKDOWN	= 2,	/*  Physical port/Trunk link down */
+};
+
+/**
+ *	Port link state reason code
+ */
+enum bfa_port_linkstate_rsn {
+	BFA_PORT_LINKSTATE_RSN_NONE		= 0,
+	BFA_PORT_LINKSTATE_RSN_DISABLED		= 1,
+	BFA_PORT_LINKSTATE_RSN_RX_NOS		= 2,
+	BFA_PORT_LINKSTATE_RSN_RX_OLS		= 3,
+	BFA_PORT_LINKSTATE_RSN_RX_LIP		= 4,
+	BFA_PORT_LINKSTATE_RSN_RX_LIPF7		= 5,
+	BFA_PORT_LINKSTATE_RSN_SFP_REMOVED	= 6,
+	BFA_PORT_LINKSTATE_RSN_PORT_FAULT	= 7,
+	BFA_PORT_LINKSTATE_RSN_RX_LOS		= 8,
+	BFA_PORT_LINKSTATE_RSN_LOCAL_FAULT	= 9,
+	BFA_PORT_LINKSTATE_RSN_REMOTE_FAULT	= 10,
+	BFA_PORT_LINKSTATE_RSN_TIMEOUT		= 11,
+
+
+
+	/* CEE related reason codes/errors */
+	CEE_LLDP_INFO_AGED_OUT			= 20,
+	CEE_LLDP_SHUTDOWN_TLV_RCVD		= 21,
+	CEE_PEER_NOT_ADVERTISE_DCBX		= 22,
+	CEE_PEER_NOT_ADVERTISE_PG		= 23,
+	CEE_PEER_NOT_ADVERTISE_PFC		= 24,
+	CEE_PEER_NOT_ADVERTISE_FCOE		= 25,
+	CEE_PG_NOT_COMPATIBLE			= 26,
+	CEE_PFC_NOT_COMPATIBLE			= 27,
+	CEE_FCOE_NOT_COMPATIBLE			= 28,
+	CEE_BAD_PG_RCVD				= 29,
+	CEE_BAD_BW_RCVD				= 30,
+	CEE_BAD_PFC_RCVD			= 31,
+	CEE_BAD_APP_PRI_RCVD			= 32,
+	CEE_FCOE_PRI_PFC_OFF			= 33,
+	CEE_DUP_CONTROL_TLV_RCVD		= 34,
+	CEE_DUP_FEAT_TLV_RCVD			= 35,
+	CEE_APPLY_NEW_CFG			= 36, /* reason, not error */
+	CEE_PROTOCOL_INIT			= 37, /* reason, not error */
+	CEE_PHY_LINK_DOWN			= 38,
+	CEE_LLS_FCOE_ABSENT			= 39,
+	CEE_LLS_FCOE_DOWN			= 40,
+	CEE_ISCSI_NOT_COMPATIBLE		= 41,
+	CEE_ISCSI_PRI_PFC_OFF			= 42,
+	CEE_ISCSI_PRI_OVERLAP_FCOE_PRI		= 43
+};
+#pragma pack(1)
+/**
+ *      Physical port configuration
+ */
+struct bfa_port_cfg_s {
+	u8	 topology;	/*  bfa_port_topology		*/
+	u8	 speed;		/*  enum bfa_port_speed	*/
+	u8	 trunked;	/*  trunked or not		*/
+	u8	 qos_enabled;	/*  qos enabled or not		*/
+	u8	 cfg_hardalpa;	/*  is hard alpa configured	*/
+	u8	 hardalpa;	/*  configured hard alpa	*/
+	u16 maxfrsize;	/*  maximum frame size		*/
+	u8	 rx_bbcredit;	/*  receive buffer credits	*/
+	u8	 tx_bbcredit;	/*  transmit buffer credits	*/
+	u8	 ratelimit;	/*  ratelimit enabled or not	*/
+	u8	 trl_def_speed;	/*  ratelimit default speed	*/
+	u16 path_tov;	/*  device path timeout	*/
+	u16 q_depth;	/*  SCSI Queue depth		*/
+};
+#pragma pack()
+
+/**
+ *	Port attribute values.
+ */
+struct bfa_port_attr_s {
+	/*
+	 * Static fields
+	 */
+	wwn_t	   nwwn;		/*  node wwn */
+	wwn_t	   pwwn;		/*  port wwn */
+	wwn_t	   factorynwwn;	/*  factory node wwn */
+	wwn_t	   factorypwwn;	/*  factory port wwn */
+	enum fc_cos	cos_supported;	/*  supported class of services */
+	u32	rsvd;
+	struct fc_symname_s	port_symname;	/*  port symbolic name */
+	enum bfa_port_speed speed_supported; /*  supported speeds */
+	bfa_boolean_t   pbind_enabled;
+
+	/*
+	 * Configured values
+	 */
+	struct bfa_port_cfg_s pport_cfg;	/*  pport cfg */
+
+	/*
+	 * Dynamic field - info from BFA
+	 */
+	enum bfa_port_states	port_state;	/*  current port state */
+	enum bfa_port_speed	speed;		/*  current speed */
+	enum bfa_port_topology	topology;	/*  current topology */
+	bfa_boolean_t		beacon;		/*  current beacon status */
+	bfa_boolean_t		link_e2e_beacon; /*  link beacon is on */
+	bfa_boolean_t		plog_enabled;	/*  portlog is enabled */
+
+	/*
+	 * Dynamic field - info from FCS
+	 */
+	u32		pid;		/*  port ID */
+	enum bfa_port_type	port_type;	/*  current topology */
+	u32		loopback;	/*  external loopback */
+	u32		authfail;	/*  auth fail state */
+	bfa_boolean_t		io_profile;	/*  get it from fcpim mod */
+	u8			pad[4];		/*  for 64-bit alignement */
+
+	/* FCoE specific  */
+	u16		fcoe_vlan;
+	u8			rsvd1[6];
+};
+
+/**
+ *	      Port FCP mappings.
+ */
+struct bfa_port_fcpmap_s {
+	char		osdevname[256];
+	u32	bus;
+	u32	target;
+	u32	oslun;
+	u32	fcid;
+	wwn_t	   nwwn;
+	wwn_t	   pwwn;
+	u64	fcplun;
+	char		luid[256];
+};
+
+/**
+ *	      Port RNID info.
+ */
+struct bfa_port_rnid_s {
+	wwn_t	     wwn;
+	u32	  unittype;
+	u32	  portid;
+	u32	  attached_nodes_num;
+	u16	  ip_version;
+	u16	  udp_port;
+	u8	   ipaddr[16];
+	u16	  rsvd;
+	u16	  topologydiscoveryflags;
+};
+
+#pragma pack(1)
+struct bfa_fcport_fcf_s {
+	wwn_t	   name;	   /*  FCF name		 */
+	wwn_t	   fabric_name;    /*  Fabric Name	      */
+	u8		fipenabled;	/*  FIP enabled or not */
+	u8		fipfailed;	/*  FIP failed or not	*/
+	u8		resv[2];
+	u8	 pri;	    /*  FCF priority	     */
+	u8	 version;	/*  FIP version used	 */
+	u8	 available;      /*  Available  for  login    */
+	u8	 fka_disabled;   /*  FKA is disabled	  */
+	u8	 maxsz_verified; /*  FCoE max size verified   */
+	u8	 fc_map[3];      /*  FC map		   */
+	u16	vlan;	   /*  FCoE vlan tag/priority   */
+	u32	fka_adv_per;    /*  FIP  ka advert. period   */
+	mac_t	   mac;	    /*  FCF mac		  */
+};
+
+/**
+ *	Trunk states for BCU/BFAL
+ */
+enum bfa_trunk_state {
+	BFA_TRUNK_DISABLED	= 0,	/*  Trunk is not configured	*/
+	BFA_TRUNK_ONLINE	= 1,	/*  Trunk is online		*/
+	BFA_TRUNK_OFFLINE	= 2,	/*  Trunk is offline		*/
+};
+
+/**
+ *	VC attributes for trunked link
+ */
+struct bfa_trunk_vc_attr_s {
+	u32 bb_credit;
+	u32 elp_opmode_flags;
+	u32 req_credit;
+	u16 vc_credits[8];
+};
+
+/**
+ *	Link state information
+ */
+struct bfa_port_link_s {
+	u8	 linkstate;	/*  Link state bfa_port_linkstate */
+	u8	 linkstate_rsn;	/*  bfa_port_linkstate_rsn_t */
+	u8	 topology;	/*  P2P/LOOP bfa_port_topology */
+	u8	 speed;		/*  Link speed (1/2/4/8 G) */
+	u32	linkstate_opt;  /*  Linkstate optional data (debug) */
+	u8	 trunked;	/*  Trunked or not (1 or 0) */
+	u8	 resvd[3];
+	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
+	union {
+		struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
+		struct bfa_trunk_vc_attr_s trunk_vc_attr;
+		struct bfa_fcport_fcf_s fcf; /*  FCF information (for FCoE) */
+	} vc_fcf;
+};
+#pragma pack()
+
+enum bfa_trunk_link_fctl {
+	BFA_TRUNK_LINK_FCTL_NORMAL,
+	BFA_TRUNK_LINK_FCTL_VC,
+	BFA_TRUNK_LINK_FCTL_VC_QOS,
+};
+
+enum bfa_trunk_link_state {
+	BFA_TRUNK_LINK_STATE_UP = 1,		/* link part of trunk */
+	BFA_TRUNK_LINK_STATE_DN_LINKDN = 2,	/* physical link down */
+	BFA_TRUNK_LINK_STATE_DN_GRP_MIS = 3,	/* trunk group different */
+	BFA_TRUNK_LINK_STATE_DN_SPD_MIS = 4,	/* speed mismatch */
+	BFA_TRUNK_LINK_STATE_DN_MODE_MIS = 5,	/* remote port not trunked */
+};
+
+#define BFA_TRUNK_MAX_PORTS	2
+struct bfa_trunk_link_attr_s {
+	wwn_t    trunk_wwn;
+	enum bfa_trunk_link_fctl fctl;
+	enum bfa_trunk_link_state link_state;
+	enum bfa_port_speed	speed;
+	u32 deskew;
+};
+
+struct bfa_trunk_attr_s {
+	enum bfa_trunk_state	state;
+	enum bfa_port_speed	speed;
+	u32		port_id;
+	u32		rsvd;
+	struct bfa_trunk_link_attr_s link_attr[BFA_TRUNK_MAX_PORTS];
+};
+
+struct bfa_rport_hal_stats_s {
+	u32        sm_un_cr;	    /*  uninit: create events      */
+	u32        sm_un_unexp;	    /*  uninit: exception events   */
+	u32        sm_cr_on;	    /*  created: online events     */
+	u32        sm_cr_del;	    /*  created: delete events     */
+	u32        sm_cr_hwf;	    /*  created: IOC down          */
+	u32        sm_cr_unexp;	    /*  created: exception events  */
+	u32        sm_fwc_rsp;	    /*  fw create: f/w responses   */
+	u32        sm_fwc_del;	    /*  fw create: delete events   */
+	u32        sm_fwc_off;	    /*  fw create: offline events  */
+	u32        sm_fwc_hwf;	    /*  fw create: IOC down        */
+	u32        sm_fwc_unexp;	    /*  fw create: exception events*/
+	u32        sm_on_off;	    /*  online: offline events     */
+	u32        sm_on_del;	    /*  online: delete events      */
+	u32        sm_on_hwf;	    /*  online: IOC down events    */
+	u32        sm_on_unexp;	    /*  online: exception events   */
+	u32        sm_fwd_rsp;	    /*  fw delete: fw responses    */
+	u32        sm_fwd_del;	    /*  fw delete: delete events   */
+	u32        sm_fwd_hwf;	    /*  fw delete: IOC down events */
+	u32        sm_fwd_unexp;	    /*  fw delete: exception events*/
+	u32        sm_off_del;	    /*  offline: delete events     */
+	u32        sm_off_on;	    /*  offline: online events     */
+	u32        sm_off_hwf;	    /*  offline: IOC down events   */
+	u32        sm_off_unexp;	    /*  offline: exception events  */
+	u32        sm_del_fwrsp;	    /*  delete: fw responses       */
+	u32        sm_del_hwf;	    /*  delete: IOC down events    */
+	u32        sm_del_unexp;	    /*  delete: exception events   */
+	u32        sm_delp_fwrsp;	    /*  delete pend: fw responses  */
+	u32        sm_delp_hwf;	    /*  delete pend: IOC downs     */
+	u32        sm_delp_unexp;	    /*  delete pend: exceptions    */
+	u32        sm_offp_fwrsp;	    /*  off-pending: fw responses  */
+	u32        sm_offp_del;	    /*  off-pending: deletes       */
+	u32        sm_offp_hwf;	    /*  off-pending: IOC downs     */
+	u32        sm_offp_unexp;	    /*  off-pending: exceptions    */
+	u32        sm_iocd_off;	    /*  IOC down: offline events   */
+	u32        sm_iocd_del;	    /*  IOC down: delete events    */
+	u32        sm_iocd_on;	    /*  IOC down: online events    */
+	u32        sm_iocd_unexp;	    /*  IOC down: exceptions       */
+	u32        rsvd;
+};
+#pragma pack(1)
+/**
+ *  Rport's QoS attributes
+ */
+struct bfa_rport_qos_attr_s {
+	u8			qos_priority;  /*  rport's QoS priority   */
+	u8			rsvd[3];
+	u32	       qos_flow_id;	  /*  QoS flow Id	 */
+};
+#pragma pack()
+
+#define BFA_IOBUCKET_MAX 14
+
+struct bfa_itnim_latency_s {
+	u32 min[BFA_IOBUCKET_MAX];
+	u32 max[BFA_IOBUCKET_MAX];
+	u32 count[BFA_IOBUCKET_MAX];
+	u32 avg[BFA_IOBUCKET_MAX];
+};
+
+struct bfa_itnim_ioprofile_s {
+	u32 clock_res_mul;
+	u32 clock_res_div;
+	u32 index;
+	u32 io_profile_start_time;	/*  IO profile start time	*/
+	u32 iocomps[BFA_IOBUCKET_MAX];	/*  IO completed	*/
+	struct bfa_itnim_latency_s io_latency;
+};
+
+/**
+ * FC physical port statistics.
+ */
+struct bfa_port_fc_stats_s {
+	u64     secs_reset;     /*  Seconds since stats is reset */
+	u64     tx_frames;      /*  Tx frames                   */
+	u64     tx_words;       /*  Tx words                    */
+	u64     tx_lip;         /*  Tx LIP                      */
+	u64     tx_nos;         /*  Tx NOS                      */
+	u64     tx_ols;         /*  Tx OLS                      */
+	u64     tx_lr;          /*  Tx LR                       */
+	u64     tx_lrr;         /*  Tx LRR                      */
+	u64     rx_frames;      /*  Rx frames                   */
+	u64     rx_words;       /*  Rx words                    */
+	u64     lip_count;      /*  Rx LIP                      */
+	u64     nos_count;      /*  Rx NOS                      */
+	u64     ols_count;      /*  Rx OLS                      */
+	u64     lr_count;       /*  Rx LR                       */
+	u64     lrr_count;      /*  Rx LRR                      */
+	u64     invalid_crcs;   /*  Rx CRC err frames           */
+	u64     invalid_crc_gd_eof; /*  Rx CRC err good EOF frames */
+	u64     undersized_frm; /*  Rx undersized frames        */
+	u64     oversized_frm;  /*  Rx oversized frames */
+	u64     bad_eof_frm;    /*  Rx frames with bad EOF      */
+	u64     error_frames;   /*  Errored frames              */
+	u64     dropped_frames; /*  Dropped frames              */
+	u64     link_failures;  /*  Link Failure (LF) count     */
+	u64     loss_of_syncs;  /*  Loss of sync count          */
+	u64     loss_of_signals; /*  Loss of signal count       */
+	u64     primseq_errs;   /*  Primitive sequence protocol err. */
+	u64     bad_os_count;   /*  Invalid ordered sets        */
+	u64     err_enc_out;    /*  Encoding err nonframe_8b10b */
+	u64     err_enc;        /*  Encoding err frame_8b10b    */
+};
+
+/**
+ * Eth Physical Port statistics.
+ */
+struct bfa_port_eth_stats_s {
+	u64     secs_reset;     /*  Seconds since stats is reset */
+	u64     frame_64;       /*  Frames 64 bytes             */
+	u64     frame_65_127;   /*  Frames 65-127 bytes */
+	u64     frame_128_255;  /*  Frames 128-255 bytes        */
+	u64     frame_256_511;  /*  Frames 256-511 bytes        */
+	u64     frame_512_1023; /*  Frames 512-1023 bytes       */
+	u64     frame_1024_1518; /*  Frames 1024-1518 bytes     */
+	u64     frame_1519_1522; /*  Frames 1519-1522 bytes     */
+	u64     tx_bytes;       /*  Tx bytes                    */
+	u64     tx_packets;      /*  Tx packets         */
+	u64     tx_mcast_packets; /*  Tx multicast packets      */
+	u64     tx_bcast_packets; /*  Tx broadcast packets      */
+	u64     tx_control_frame; /*  Tx control frame          */
+	u64     tx_drop;        /*  Tx drops                    */
+	u64     tx_jabber;      /*  Tx jabber                   */
+	u64     tx_fcs_error;   /*  Tx FCS errors               */
+	u64     tx_fragments;   /*  Tx fragments                */
+	u64     rx_bytes;       /*  Rx bytes                    */
+	u64     rx_packets;     /*  Rx packets                  */
+	u64     rx_mcast_packets; /*  Rx multicast packets      */
+	u64     rx_bcast_packets; /*  Rx broadcast packets      */
+	u64     rx_control_frames; /*  Rx control frames        */
+	u64     rx_unknown_opcode; /*  Rx unknown opcode        */
+	u64     rx_drop;        /*  Rx drops                    */
+	u64     rx_jabber;      /*  Rx jabber                   */
+	u64     rx_fcs_error;   /*  Rx FCS errors               */
+	u64     rx_alignment_error; /*  Rx alignment errors     */
+	u64     rx_frame_length_error; /*  Rx frame len errors  */
+	u64     rx_code_error;  /*  Rx code errors              */
+	u64     rx_fragments;   /*  Rx fragments                */
+	u64     rx_pause;       /*  Rx pause                    */
+	u64     rx_zero_pause;  /*  Rx zero pause               */
+	u64     tx_pause;       /*  Tx pause                    */
+	u64     tx_zero_pause;  /*  Tx zero pause               */
+	u64     rx_fcoe_pause;  /*  Rx FCoE pause               */
+	u64     rx_fcoe_zero_pause; /*  Rx FCoE zero pause      */
+	u64     tx_fcoe_pause;  /*  Tx FCoE pause               */
+	u64     tx_fcoe_zero_pause; /*  Tx FCoE zero pause      */
+	u64     rx_iscsi_pause; /*  Rx iSCSI pause              */
+	u64     rx_iscsi_zero_pause; /*  Rx iSCSI zero pause    */
+	u64     tx_iscsi_pause; /*  Tx iSCSI pause              */
+	u64     tx_iscsi_zero_pause; /*  Tx iSCSI zero pause    */
+};
+
+/**
+ *              Port statistics.
+ */
+union bfa_port_stats_u {
+	struct bfa_port_fc_stats_s      fc;
+	struct bfa_port_eth_stats_s     eth;
+};
+
+#endif /* __BFA_DEFS_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfa_module.c b/drivers/scsi/bfa/bfa_drv.c
similarity index 75%
rename from drivers/scsi/bfa/bfa_module.c
rename to drivers/scsi/bfa/bfa_drv.c
index a7fcc80..1412764 100644
--- a/drivers/scsi/bfa/bfa_module.c
+++ b/drivers/scsi/bfa/bfa_drv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -14,10 +14,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  */
-#include <bfa.h>
-#include <defs/bfa_defs_pci.h>
-#include <cs/bfa_debug.h>
-#include <bfa_iocfc.h>
+
+#include "bfa_modules.h"
 
 /**
  * BFA module list terminated by NULL
@@ -30,9 +28,6 @@
 	&hal_mod_uf,
 	&hal_mod_rport,
 	&hal_mod_fcpim,
-#ifdef BFA_CFG_PBIND
-	&hal_mod_pbind,
-#endif
 	NULL
 };
 
@@ -74,17 +69,39 @@
 	bfa_isr_unhandled,	/* --------- */
 };
 
+
 /**
  * Message handlers for mailbox command classes
  */
 bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[BFI_MC_MAX] = {
 	NULL,
-	NULL,			/* BFI_MC_IOC	*/
-	NULL,			/* BFI_MC_DIAG	*/
+	NULL,			/* BFI_MC_IOC   */
+	NULL,			/* BFI_MC_DIAG  */
 	NULL,		/* BFI_MC_FLASH */
-	NULL,			/* BFI_MC_CEE	*/
-	NULL,			/* BFI_MC_PORT	*/
+	NULL,			/* BFI_MC_CEE   */
+	NULL,			/* BFI_MC_PORT  */
 	bfa_iocfc_isr,		/* BFI_MC_IOCFC */
 	NULL,
 };
 
+
+
+void
+bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi)
+{
+	struct bfa_port_s	*port = &bfa->modules.port;
+	u32		dm_len;
+	u8			*dm_kva;
+	u64		dm_pa;
+
+	dm_len = bfa_port_meminfo();
+	dm_kva = bfa_meminfo_dma_virt(mi);
+	dm_pa  = bfa_meminfo_dma_phys(mi);
+
+	memset(port, 0, sizeof(struct bfa_port_s));
+	bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod);
+	bfa_port_mem_claim(port, dm_kva, dm_pa);
+
+	bfa_meminfo_dma_virt(mi) = dm_kva + dm_len;
+	bfa_meminfo_dma_phys(mi) = dm_pa + dm_len;
+}
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
new file mode 100644
index 0000000..6eff705
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -0,0 +1,1916 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFA_FC_H__
+#define __BFA_FC_H__
+
+#include "bfa_os_inc.h"
+
+typedef u64 wwn_t;
+typedef u64 lun_t;
+
+#define WWN_NULL	(0)
+#define FC_SYMNAME_MAX	256	/*  max name server symbolic name size */
+#define FC_ALPA_MAX	128
+
+#pragma pack(1)
+
+#define MAC_ADDRLEN	(6)
+struct mac_s { u8 mac[MAC_ADDRLEN]; };
+#define mac_t struct mac_s
+
+/*
+ * generic SCSI cdb definition
+ */
+#define SCSI_MAX_CDBLEN     16
+struct scsi_cdb_s {
+	u8         scsi_cdb[SCSI_MAX_CDBLEN];
+};
+#define scsi_cdb_t struct scsi_cdb_s
+
+/* ------------------------------------------------------------
+ * SCSI status byte values
+ * ------------------------------------------------------------
+ */
+#define SCSI_STATUS_GOOD                   0x00
+#define SCSI_STATUS_CHECK_CONDITION        0x02
+#define SCSI_STATUS_CONDITION_MET          0x04
+#define SCSI_STATUS_BUSY                   0x08
+#define SCSI_STATUS_INTERMEDIATE           0x10
+#define SCSI_STATUS_ICM                    0x14 /* intermediate condition met */
+#define SCSI_STATUS_RESERVATION_CONFLICT   0x18
+#define SCSI_STATUS_COMMAND_TERMINATED     0x22
+#define SCSI_STATUS_QUEUE_FULL             0x28
+#define SCSI_STATUS_ACA_ACTIVE             0x30
+
+#define SCSI_MAX_ALLOC_LEN      0xFF    /* maximum allocarion length */
+
+/*
+ * Fibre Channel Header Structure (FCHS) definition
+ */
+struct fchs_s {
+#ifdef __BIGENDIAN
+	u32        routing:4;	/* routing bits */
+	u32        cat_info:4;	/* category info */
+#else
+	u32        cat_info:4;	/* category info */
+	u32        routing:4;	/* routing bits */
+#endif
+	u32        d_id:24;	/* destination identifier */
+
+	u32        cs_ctl:8;	/* class specific control */
+	u32        s_id:24;	/* source identifier */
+
+	u32        type:8;		/* data structure type */
+	u32        f_ctl:24;	/* initial frame control */
+
+	u8         seq_id;		/* sequence identifier */
+	u8         df_ctl;		/* data field control */
+	u16        seq_cnt;	/* sequence count */
+
+	u16        ox_id;		/* originator exchange ID */
+	u16        rx_id;		/* responder exchange ID */
+
+	u32        ro;		/* relative offset */
+};
+
+#define FC_SOF_LEN		4
+#define FC_EOF_LEN		4
+#define FC_CRC_LEN		4
+
+/*
+ * Fibre Channel BB_E Header Structure
+ */
+struct fcbbehs_s {
+	u16	ver_rsvd;
+	u32	rsvd[2];
+	u32	rsvd__sof;
+};
+
+#define FC_SEQ_ID_MAX		256
+
+/*
+ * routing bit definitions
+ */
+enum {
+	FC_RTG_FC4_DEV_DATA	= 0x0,	/* FC-4 Device Data */
+	FC_RTG_EXT_LINK		= 0x2,	/* Extended Link Data */
+	FC_RTG_FC4_LINK_DATA	= 0x3,	/* FC-4 Link Data */
+	FC_RTG_VIDEO_DATA	= 0x4,	/* Video Data */
+	FC_RTG_EXT_HDR		= 0x5,	/* VFT, IFR or Encapsuled */
+	FC_RTG_BASIC_LINK	= 0x8,	/* Basic Link data */
+	FC_RTG_LINK_CTRL	= 0xC,	/* Link Control */
+};
+
+/*
+ * information category for extended link data and FC-4 Link Data
+ */
+enum {
+	FC_CAT_LD_REQUEST	= 0x2,	/* Request */
+	FC_CAT_LD_REPLY		= 0x3,	/* Reply */
+	FC_CAT_LD_DIAG		= 0xF,	/* for DIAG use only */
+};
+
+/*
+ * information category for extended headers (VFT, IFR or encapsulation)
+ */
+enum {
+	FC_CAT_VFT_HDR = 0x0,	/* Virtual fabric tagging header */
+	FC_CAT_IFR_HDR = 0x1,	/* Inter-Fabric routing header */
+	FC_CAT_ENC_HDR = 0x2,	/* Encapsulation header */
+};
+
+/*
+ * information category for FC-4 device data
+ */
+enum {
+	FC_CAT_UNCATEG_INFO	= 0x0,	/* Uncategorized information */
+	FC_CAT_SOLICIT_DATA	= 0x1,	/* Solicited Data */
+	FC_CAT_UNSOLICIT_CTRL	= 0x2,	/* Unsolicited Control */
+	FC_CAT_SOLICIT_CTRL	= 0x3,	/* Solicited Control */
+	FC_CAT_UNSOLICIT_DATA	= 0x4,	/* Unsolicited Data */
+	FC_CAT_DATA_DESC	= 0x5,	/* Data Descriptor */
+	FC_CAT_UNSOLICIT_CMD	= 0x6,	/* Unsolicited Command */
+	FC_CAT_CMD_STATUS	= 0x7,	/* Command Status */
+};
+
+/*
+ * information category for Link Control
+ */
+enum {
+	FC_CAT_ACK_1		= 0x00,
+	FC_CAT_ACK_0_N		= 0x01,
+	FC_CAT_P_RJT		= 0x02,
+	FC_CAT_F_RJT		= 0x03,
+	FC_CAT_P_BSY		= 0x04,
+	FC_CAT_F_BSY_DATA	= 0x05,
+	FC_CAT_F_BSY_LINK_CTL	= 0x06,
+	FC_CAT_F_LCR		= 0x07,
+	FC_CAT_NTY		= 0x08,
+	FC_CAT_END		= 0x09,
+};
+
+/*
+ * Type Field Definitions. FC-PH Section 18.5 pg. 165
+ */
+enum {
+	FC_TYPE_BLS		= 0x0,	/* Basic Link Service */
+	FC_TYPE_ELS		= 0x1,	/* Extended Link Service */
+	FC_TYPE_IP		= 0x5,	/* IP */
+	FC_TYPE_FCP		= 0x8,	/* SCSI-FCP */
+	FC_TYPE_GPP		= 0x9,	/* SCSI_GPP */
+	FC_TYPE_SERVICES	= 0x20,	/* Fibre Channel Services */
+	FC_TYPE_FC_FSS		= 0x22,	/* Fabric Switch Services */
+	FC_TYPE_FC_AL		= 0x23,	/* FC-AL */
+	FC_TYPE_FC_SNMP		= 0x24,	/* FC-SNMP */
+	FC_TYPE_FC_SPINFAB	= 0xEE,	/* SPINFAB */
+	FC_TYPE_FC_DIAG		= 0xEF,	/* DIAG */
+	FC_TYPE_MAX		= 256,	/* 256 FC-4 types */
+};
+
+struct fc_fc4types_s {
+	u8         bits[FC_TYPE_MAX / 8];
+};
+
+/*
+ * Frame Control Definitions. FC-PH Table-45. pg. 168
+ */
+enum {
+	FCTL_EC_ORIG = 0x000000,	/* exchange originator */
+	FCTL_EC_RESP = 0x800000,	/* exchange responder */
+	FCTL_SEQ_INI = 0x000000,	/* sequence initiator */
+	FCTL_SEQ_REC = 0x400000,	/* sequence recipient */
+	FCTL_FS_EXCH = 0x200000,	/* first sequence of xchg */
+	FCTL_LS_EXCH = 0x100000,	/* last sequence of xchg */
+	FCTL_END_SEQ = 0x080000,	/* last frame of sequence */
+	FCTL_SI_XFER = 0x010000,	/* seq initiative transfer */
+	FCTL_RO_PRESENT = 0x000008,	/* relative offset present */
+	FCTL_FILLBYTE_MASK = 0x000003	/* , fill byte mask */
+};
+
+/*
+ * Fabric Well Known Addresses
+ */
+enum {
+	FC_MIN_WELL_KNOWN_ADDR		= 0xFFFFF0,
+	FC_DOMAIN_CONTROLLER_MASK	= 0xFFFC00,
+	FC_ALIAS_SERVER			= 0xFFFFF8,
+	FC_MGMT_SERVER			= 0xFFFFFA,
+	FC_TIME_SERVER			= 0xFFFFFB,
+	FC_NAME_SERVER			= 0xFFFFFC,
+	FC_FABRIC_CONTROLLER		= 0xFFFFFD,
+	FC_FABRIC_PORT			= 0xFFFFFE,
+	FC_BROADCAST_SERVER		= 0xFFFFFF
+};
+
+/*
+ * domain/area/port defines
+ */
+#define FC_DOMAIN_MASK  0xFF0000
+#define FC_DOMAIN_SHIFT 16
+#define FC_AREA_MASK    0x00FF00
+#define FC_AREA_SHIFT   8
+#define FC_PORT_MASK    0x0000FF
+#define FC_PORT_SHIFT   0
+
+#define FC_GET_DOMAIN(p)	(((p) & FC_DOMAIN_MASK) >> FC_DOMAIN_SHIFT)
+#define FC_GET_AREA(p)		(((p) & FC_AREA_MASK) >> FC_AREA_SHIFT)
+#define FC_GET_PORT(p)		(((p) & FC_PORT_MASK) >> FC_PORT_SHIFT)
+
+#define FC_DOMAIN_CTRLR(p)	(FC_DOMAIN_CONTROLLER_MASK | (FC_GET_DOMAIN(p)))
+
+enum {
+	FC_RXID_ANY = 0xFFFFU,
+};
+
+/*
+ * generic ELS command
+ */
+struct fc_els_cmd_s {
+	u32        els_code:8;	/* ELS Command Code */
+	u32        reserved:24;
+};
+
+/*
+ * ELS Command Codes. FC-PH Table-75. pg. 223
+ */
+enum {
+	FC_ELS_LS_RJT = 0x1,	/* Link Service Reject. */
+	FC_ELS_ACC = 0x02,	/* Accept */
+	FC_ELS_PLOGI = 0x03,	/* N_Port Login. */
+	FC_ELS_FLOGI = 0x04,	/* F_Port Login. */
+	FC_ELS_LOGO = 0x05,	/* Logout. */
+	FC_ELS_ABTX = 0x06,	/* Abort Exchange */
+	FC_ELS_RES = 0x08,	/* Read Exchange status */
+	FC_ELS_RSS = 0x09,	/* Read sequence status block */
+	FC_ELS_RSI = 0x0A,	/* Request Sequence Initiative */
+	FC_ELS_ESTC = 0x0C,	/* Estimate Credit. */
+	FC_ELS_RTV = 0x0E,	/* Read Timeout Value. */
+	FC_ELS_RLS = 0x0F,	/* Read Link Status. */
+	FC_ELS_ECHO = 0x10,	/* Echo */
+	FC_ELS_TEST = 0x11,	/* Test */
+	FC_ELS_RRQ = 0x12,	/* Reinstate Recovery Qualifier. */
+	FC_ELS_REC = 0x13,	/* Add this for TAPE support in FCR */
+	FC_ELS_PRLI = 0x20,	/* Process Login */
+	FC_ELS_PRLO = 0x21,	/* Process Logout. */
+	FC_ELS_SCN = 0x22,	/* State Change Notification. */
+	FC_ELS_TPRLO = 0x24,	/* Third Party Process Logout. */
+	FC_ELS_PDISC = 0x50,	/* Discover N_Port Parameters. */
+	FC_ELS_FDISC = 0x51,	/* Discover F_Port Parameters. */
+	FC_ELS_ADISC = 0x52,	/* Discover Address. */
+	FC_ELS_FARP_REQ = 0x54,	/* FARP Request. */
+	FC_ELS_FARP_REP = 0x55,	/* FARP Reply. */
+	FC_ELS_FAN = 0x60,	/* Fabric Address Notification */
+	FC_ELS_RSCN = 0x61,	/* Reg State Change Notification */
+	FC_ELS_SCR = 0x62,	/* State Change Registration. */
+	FC_ELS_RTIN = 0x77,	/* Mangement server request */
+	FC_ELS_RNID = 0x78,	/* Mangement server request */
+	FC_ELS_RLIR = 0x79,	/* Registered Link Incident Record */
+
+	FC_ELS_RPSC = 0x7D,	/* Report Port Speed Capabilities */
+	FC_ELS_QSA = 0x7E,	/* Query Security Attributes. Ref FC-SP */
+	FC_ELS_E2E_LBEACON = 0x81,
+				/* End-to-End Link Beacon */
+	FC_ELS_AUTH = 0x90,	/* Authentication. Ref FC-SP */
+	FC_ELS_RFCN = 0x97,	/* Request Fabric Change Notification. Ref
+				 *FC-SP */
+
+};
+
+/*
+ *  Version numbers for FC-PH standards,
+ *  used in login to indicate what port
+ *  supports. See FC-PH-X table 158.
+ */
+enum {
+	FC_PH_VER_4_3 = 0x09,
+	FC_PH_VER_PH_3 = 0x20,
+};
+
+/*
+ * PDU size defines
+ */
+enum {
+	FC_MIN_PDUSZ = 512,
+	FC_MAX_PDUSZ = 2112,
+};
+
+/*
+ * N_Port PLOGI Common Service Parameters.
+ * FC-PH-x. Figure-76. pg. 308.
+ */
+struct fc_plogi_csp_s {
+	u8         verhi;	/* FC-PH high version */
+	u8         verlo;	/* FC-PH low version */
+	u16        bbcred;	/* BB_Credit */
+
+#ifdef __BIGENDIAN
+	u8         ciro:1,		/* continuously increasing RO */
+			rro:1,		/* random relative offset */
+			npiv_supp:1,	/* NPIV supported */
+			port_type:1,	/* N_Port/F_port */
+			altbbcred:1,	/* alternate BB_Credit */
+			resolution:1,	/* ms/ns ED_TOV resolution */
+			vvl_info:1,	/* VVL Info included */
+			reserved1:1;
+
+	u8         hg_supp:1,
+			query_dbc:1,
+			security:1,
+			sync_cap:1,
+			r_t_tov:1,
+			dh_dup_supp:1,
+			cisc:1,		/* continuously increasing seq count */
+			payload:1;
+#else
+	u8         reserved2:2,
+			resolution:1,	/* ms/ns ED_TOV resolution */
+			altbbcred:1,	/* alternate BB_Credit */
+			port_type:1,	/* N_Port/F_port */
+			npiv_supp:1,	/* NPIV supported */
+			rro:1,		/* random relative offset */
+			ciro:1;		/* continuously increasing RO */
+
+	u8         payload:1,
+			cisc:1,		/* continuously increasing seq count */
+			dh_dup_supp:1,
+			r_t_tov:1,
+			sync_cap:1,
+			security:1,
+			query_dbc:1,
+			hg_supp:1;
+#endif
+
+	u16        rxsz;		/* recieve data_field size */
+
+	u16        conseq;
+	u16        ro_bitmap;
+
+	u32        e_d_tov;
+};
+
+/*
+ * N_Port PLOGI Class Specific Parameters.
+ * FC-PH-x. Figure 78. pg. 318.
+ */
+struct fc_plogi_clp_s {
+#ifdef __BIGENDIAN
+	u32        class_valid:1;
+	u32        intermix:1;	/* class intermix supported if set =1.
+					 * valid only for class1. Reserved for
+					 * class2 & class3
+					 */
+	u32        reserved1:2;
+	u32        sequential:1;
+	u32        reserved2:3;
+#else
+	u32        reserved2:3;
+	u32        sequential:1;
+	u32        reserved1:2;
+	u32        intermix:1;	/* class intermix supported if set =1.
+					 * valid only for class1. Reserved for
+					 * class2 & class3
+					 */
+	u32        class_valid:1;
+#endif
+
+	u32        reserved3:24;
+
+	u32        reserved4:16;
+	u32        rxsz:16;	/* Receive data_field size */
+
+	u32        reserved5:8;
+	u32        conseq:8;
+	u32        e2e_credit:16;	/* end to end credit */
+
+	u32        reserved7:8;
+	u32        ospx:8;
+	u32        reserved8:16;
+};
+
+/* ASCII value for each character in string "BRCD" */
+#define FLOGI_VVL_BRCD    0x42524344
+
+/*
+ * PLOGI els command and reply payload
+ */
+struct fc_logi_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	struct fc_plogi_csp_s csp;		/* common service params */
+	wwn_t           port_name;
+	wwn_t           node_name;
+	struct fc_plogi_clp_s class1;		/* class 1 service parameters */
+	struct fc_plogi_clp_s class2;		/* class 2 service parameters */
+	struct fc_plogi_clp_s class3;		/* class 3 service parameters */
+	struct fc_plogi_clp_s class4;		/* class 4 service parameters */
+	u8         vvl[16];	/* vendor version level */
+};
+
+/*
+ * LOGO els command payload
+ */
+struct fc_logo_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        nport_id:24;	/* N_Port identifier of source */
+	wwn_t           orig_port_name;	/* Port name of the LOGO originator */
+};
+
+/*
+ * ADISC els command payload
+ */
+struct fc_adisc_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        orig_HA:24;	/* originator hard address */
+	wwn_t           orig_port_name;	/* originator port name */
+	wwn_t           orig_node_name;	/* originator node name */
+	u32        res2:8;
+	u32        nport_id:24;	/* originator NPortID */
+};
+
+/*
+ * Exchange status block
+ */
+struct fc_exch_status_blk_s {
+	u32        oxid:16;
+	u32        rxid:16;
+	u32        res1:8;
+	u32        orig_np:24;	/* originator NPortID */
+	u32        res2:8;
+	u32        resp_np:24;	/* responder NPortID */
+	u32        es_bits;
+	u32        res3;
+	/*
+	 * un modified section of the fields
+	 */
+};
+
+/*
+ * RES els command payload
+ */
+struct fc_res_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        nport_id:24;	/* N_Port identifier of source */
+	u32        oxid:16;
+	u32        rxid:16;
+	u8         assoc_hdr[32];
+};
+
+/*
+ * RES els accept payload
+ */
+struct fc_res_acc_s {
+	struct fc_els_cmd_s		els_cmd;	/* ELS command code */
+	struct fc_exch_status_blk_s	fc_exch_blk; /* Exchange status block */
+};
+
+/*
+ * REC els command payload
+ */
+struct fc_rec_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        nport_id:24;	/* N_Port identifier of source */
+	u32        oxid:16;
+	u32        rxid:16;
+};
+
+#define FC_REC_ESB_OWN_RSP	0x80000000	/* responder owns */
+#define FC_REC_ESB_SI		0x40000000	/* SI is owned	*/
+#define FC_REC_ESB_COMP		0x20000000	/* exchange is complete	*/
+#define FC_REC_ESB_ENDCOND_ABN	0x10000000	/* abnormal ending	*/
+#define FC_REC_ESB_RQACT	0x04000000	/* recovery qual active	*/
+#define FC_REC_ESB_ERRP_MSK	0x03000000
+#define FC_REC_ESB_OXID_INV	0x00800000	/* invalid OXID		*/
+#define FC_REC_ESB_RXID_INV	0x00400000	/* invalid RXID		*/
+#define FC_REC_ESB_PRIO_INUSE	0x00200000
+
+/*
+ * REC els accept payload
+ */
+struct fc_rec_acc_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        oxid:16;
+	u32        rxid:16;
+	u32        res1:8;
+	u32        orig_id:24;	/* N_Port id of exchange originator */
+	u32        res2:8;
+	u32        resp_id:24;	/* N_Port id of exchange responder */
+	u32        count;		/* data transfer count */
+	u32        e_stat;		/* exchange status */
+};
+
+/*
+ * RSI els payload
+ */
+struct fc_rsi_s {
+	struct fc_els_cmd_s els_cmd;
+	u32        res1:8;
+	u32        orig_sid:24;
+	u32        oxid:16;
+	u32        rxid:16;
+};
+
+/*
+ * structure for PRLI paramater pages, both request & response
+ * see FC-PH-X table 113 & 115 for explanation also FCP table 8
+ */
+struct fc_prli_params_s {
+	u32        reserved:16;
+#ifdef __BIGENDIAN
+	u32        reserved1:5;
+	u32        rec_support:1;
+	u32        task_retry_id:1;
+	u32        retry:1;
+
+	u32        confirm:1;
+	u32        doverlay:1;
+	u32        initiator:1;
+	u32        target:1;
+	u32        cdmix:1;
+	u32        drmix:1;
+	u32        rxrdisab:1;
+	u32        wxrdisab:1;
+#else
+	u32        retry:1;
+	u32        task_retry_id:1;
+	u32        rec_support:1;
+	u32        reserved1:5;
+
+	u32        wxrdisab:1;
+	u32        rxrdisab:1;
+	u32        drmix:1;
+	u32        cdmix:1;
+	u32        target:1;
+	u32        initiator:1;
+	u32        doverlay:1;
+	u32        confirm:1;
+#endif
+};
+
+/*
+ * valid values for rspcode in PRLI ACC payload
+ */
+enum {
+	FC_PRLI_ACC_XQTD = 0x1,		/* request executed */
+	FC_PRLI_ACC_PREDEF_IMG = 0x5,	/* predefined image - no prli needed */
+};
+
+struct fc_prli_params_page_s {
+	u32        type:8;
+	u32        codext:8;
+#ifdef __BIGENDIAN
+	u32        origprocasv:1;
+	u32        rsppav:1;
+	u32        imagepair:1;
+	u32        reserved1:1;
+	u32        rspcode:4;
+#else
+	u32        rspcode:4;
+	u32        reserved1:1;
+	u32        imagepair:1;
+	u32        rsppav:1;
+	u32        origprocasv:1;
+#endif
+	u32        reserved2:8;
+
+	u32        origprocas;
+	u32        rspprocas;
+	struct fc_prli_params_s servparams;
+};
+
+/*
+ * PRLI request and accept payload, FC-PH-X tables 112 & 114
+ */
+struct fc_prli_s {
+	u32        command:8;
+	u32        pglen:8;
+	u32        pagebytes:16;
+	struct fc_prli_params_page_s parampage;
+};
+
+/*
+ * PRLO logout params page
+ */
+struct fc_prlo_params_page_s {
+	u32        type:8;
+	u32        type_ext:8;
+#ifdef __BIGENDIAN
+	u32        opa_valid:1;	/* originator process associator
+					 * valid
+					 */
+	u32        rpa_valid:1;	/* responder process associator valid */
+	u32        res1:14;
+#else
+	u32        res1:14;
+	u32        rpa_valid:1;	/* responder process associator valid */
+	u32        opa_valid:1;	/* originator process associator
+					 * valid
+					 */
+#endif
+	u32        orig_process_assc;
+	u32        resp_process_assc;
+
+	u32        res2;
+};
+
+/*
+ * PRLO els command payload
+ */
+struct fc_prlo_s {
+	u32	command:8;
+	u32	page_len:8;
+	u32	payload_len:16;
+	struct fc_prlo_params_page_s	prlo_params[1];
+};
+
+/*
+ * PRLO Logout response parameter page
+ */
+struct fc_prlo_acc_params_page_s {
+	u32        type:8;
+	u32        type_ext:8;
+
+#ifdef __BIGENDIAN
+	u32        opa_valid:1;	/* originator process associator
+					 * valid
+					 */
+	u32        rpa_valid:1;	/* responder process associator valid */
+	u32        res1:14;
+#else
+	u32        res1:14;
+	u32        rpa_valid:1;	/* responder process associator valid */
+	u32        opa_valid:1;	/* originator process associator
+					 * valid
+					 */
+#endif
+	u32        orig_process_assc;
+	u32        resp_process_assc;
+
+	u32        fc4type_csp;
+};
+
+/*
+ * PRLO els command ACC payload
+ */
+struct fc_prlo_acc_s {
+	u32        command:8;
+	u32        page_len:8;
+	u32        payload_len:16;
+	struct fc_prlo_acc_params_page_s prlo_acc_params[1];
+};
+
+/*
+ * SCR els command payload
+ */
+enum {
+	FC_SCR_REG_FUNC_FABRIC_DETECTED = 0x01,
+	FC_SCR_REG_FUNC_N_PORT_DETECTED = 0x02,
+	FC_SCR_REG_FUNC_FULL = 0x03,
+	FC_SCR_REG_FUNC_CLEAR_REG = 0xFF,
+};
+
+/* SCR VU registrations */
+enum {
+	FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE = 0x01
+};
+
+struct fc_scr_s {
+	u32 command:8;
+	u32 res:24;
+	u32 vu_reg_func:8; /* Vendor Unique Registrations */
+	u32 res1:16;
+	u32 reg_func:8;
+};
+
+/*
+ * Information category for Basic link data
+ */
+enum {
+	FC_CAT_NOP	= 0x0,
+	FC_CAT_ABTS	= 0x1,
+	FC_CAT_RMC	= 0x2,
+	FC_CAT_BA_ACC	= 0x4,
+	FC_CAT_BA_RJT	= 0x5,
+	FC_CAT_PRMT	= 0x6,
+};
+
+/*
+ * LS_RJT els reply payload
+ */
+struct fc_ls_rjt_s {
+	struct fc_els_cmd_s els_cmd;		/* ELS command code */
+	u32        res1:8;
+	u32        reason_code:8;		/* Reason code for reject */
+	u32        reason_code_expl:8;	/* Reason code explanation */
+	u32        vendor_unique:8;	/* Vendor specific */
+};
+
+/*
+ * LS_RJT reason codes
+ */
+enum {
+	FC_LS_RJT_RSN_INV_CMD_CODE	= 0x01,
+	FC_LS_RJT_RSN_LOGICAL_ERROR	= 0x03,
+	FC_LS_RJT_RSN_LOGICAL_BUSY	= 0x05,
+	FC_LS_RJT_RSN_PROTOCOL_ERROR	= 0x07,
+	FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD = 0x09,
+	FC_LS_RJT_RSN_CMD_NOT_SUPP	= 0x0B,
+};
+
+/*
+ * LS_RJT reason code explanation
+ */
+enum {
+	FC_LS_RJT_EXP_NO_ADDL_INFO		= 0x00,
+	FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS	= 0x01,
+	FC_LS_RJT_EXP_SPARMS_ERR_INI_CTL	= 0x03,
+	FC_LS_RJT_EXP_SPARMS_ERR_REC_CTL	= 0x05,
+	FC_LS_RJT_EXP_SPARMS_ERR_RXSZ		= 0x07,
+	FC_LS_RJT_EXP_SPARMS_ERR_CONSEQ		= 0x09,
+	FC_LS_RJT_EXP_SPARMS_ERR_CREDIT		= 0x0B,
+	FC_LS_RJT_EXP_INV_PORT_NAME		= 0x0D,
+	FC_LS_RJT_EXP_INV_NODE_FABRIC_NAME	= 0x0E,
+	FC_LS_RJT_EXP_INV_CSP			= 0x0F,
+	FC_LS_RJT_EXP_INV_ASSOC_HDR		= 0x11,
+	FC_LS_RJT_EXP_ASSOC_HDR_REQD		= 0x13,
+	FC_LS_RJT_EXP_INV_ORIG_S_ID		= 0x15,
+	FC_LS_RJT_EXP_INV_OXID_RXID_COMB	= 0x17,
+	FC_LS_RJT_EXP_CMD_ALREADY_IN_PROG	= 0x19,
+	FC_LS_RJT_EXP_LOGIN_REQUIRED		= 0x1E,
+	FC_LS_RJT_EXP_INVALID_NPORT_ID		= 0x1F,
+	FC_LS_RJT_EXP_INSUFF_RES		= 0x29,
+	FC_LS_RJT_EXP_CMD_NOT_SUPP		= 0x2C,
+	FC_LS_RJT_EXP_INV_PAYLOAD_LEN		= 0x2D,
+};
+
+/*
+ * RRQ els command payload
+ */
+struct fc_rrq_s {
+	struct fc_els_cmd_s els_cmd;	/* ELS command code */
+	u32        res1:8;
+	u32        s_id:24;	/* exchange originator S_ID */
+
+	u32        ox_id:16;	/* originator exchange ID */
+	u32        rx_id:16;	/* responder exchange ID */
+
+	u32        res2[8];	/* optional association header */
+};
+
+/*
+ * ABTS BA_ACC reply payload
+ */
+struct fc_ba_acc_s {
+	u32        seq_id_valid:8;	/* set to 0x00 for Abort Exchange */
+	u32        seq_id:8;	/* invalid for Abort Exchange */
+	u32        res2:16;
+	u32        ox_id:16;	/* OX_ID from ABTS frame */
+	u32        rx_id:16;	/* RX_ID from ABTS frame */
+	u32        low_seq_cnt:16;	/* set to 0x0000 for Abort Exchange */
+	u32        high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */
+};
+
+/*
+ * ABTS BA_RJT reject payload
+ */
+struct fc_ba_rjt_s {
+	u32        res1:8;		/* Reserved */
+	u32        reason_code:8;	/* reason code for reject */
+	u32        reason_expl:8;	/* reason code explanation */
+	u32        vendor_unique:8;/* vendor unique reason code,set to 0 */
+};
+
+/*
+ * TPRLO logout parameter page
+ */
+struct fc_tprlo_params_page_s {
+u32        type:8;
+u32        type_ext:8;
+
+#ifdef __BIGENDIAN
+	u32        opa_valid:1;
+	u32        rpa_valid:1;
+	u32        tpo_nport_valid:1;
+	u32        global_process_logout:1;
+	u32        res1:12;
+#else
+	u32        res1:12;
+	u32        global_process_logout:1;
+	u32        tpo_nport_valid:1;
+	u32        rpa_valid:1;
+	u32        opa_valid:1;
+#endif
+
+	u32        orig_process_assc;
+	u32        resp_process_assc;
+
+	u32        res2:8;
+	u32        tpo_nport_id;
+};
+
+/*
+ * TPRLO ELS command payload
+ */
+struct fc_tprlo_s {
+	u32        command:8;
+	u32        page_len:8;
+	u32        payload_len:16;
+
+	struct fc_tprlo_params_page_s tprlo_params[1];
+};
+
+enum fc_tprlo_type {
+	FC_GLOBAL_LOGO = 1,
+	FC_TPR_LOGO
+};
+
+/*
+ * TPRLO els command ACC payload
+ */
+struct fc_tprlo_acc_s {
+	u32	command:8;
+	u32	page_len:8;
+	u32	payload_len:16;
+	struct fc_prlo_acc_params_page_s tprlo_acc_params[1];
+};
+
+/*
+ * RSCN els command req payload
+ */
+#define FC_RSCN_PGLEN	0x4
+
+enum fc_rscn_format {
+	FC_RSCN_FORMAT_PORTID	= 0x0,
+	FC_RSCN_FORMAT_AREA	= 0x1,
+	FC_RSCN_FORMAT_DOMAIN	= 0x2,
+	FC_RSCN_FORMAT_FABRIC	= 0x3,
+};
+
+struct fc_rscn_event_s {
+	u32        format:2;
+	u32        qualifier:4;
+	u32        resvd:2;
+	u32        portid:24;
+};
+
+struct fc_rscn_pl_s {
+	u8         command;
+	u8         pagelen;
+	u16        payldlen;
+	struct fc_rscn_event_s event[1];
+};
+
+/*
+ * ECHO els command req payload
+ */
+struct fc_echo_s {
+	struct fc_els_cmd_s els_cmd;
+};
+
+/*
+ * RNID els command
+ */
+
+#define RNID_NODEID_DATA_FORMAT_COMMON			0x00
+#define RNID_NODEID_DATA_FORMAT_FCP3			0x08
+#define RNID_NODEID_DATA_FORMAT_DISCOVERY		0xDF
+
+#define RNID_ASSOCIATED_TYPE_UNKNOWN			0x00000001
+#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
+#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
+#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
+#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
+#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
+#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
+#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
+#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
+#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
+#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
+#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
+#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
+
+/*
+ * RNID els command payload
+ */
+struct fc_rnid_cmd_s {
+	struct fc_els_cmd_s els_cmd;
+	u32        node_id_data_format:8;
+	u32        reserved:24;
+};
+
+/*
+ * RNID els response payload
+ */
+
+struct fc_rnid_common_id_data_s {
+	wwn_t           port_name;
+	wwn_t           node_name;
+};
+
+struct fc_rnid_general_topology_data_s {
+	u32        vendor_unique[4];
+	u32        asso_type;
+	u32        phy_port_num;
+	u32        num_attached_nodes;
+	u32        node_mgmt:8;
+	u32        ip_version:8;
+	u32        udp_tcp_port_num:16;
+	u32        ip_address[4];
+	u32        reserved:16;
+	u32        vendor_specific:16;
+};
+
+struct fc_rnid_acc_s {
+	struct fc_els_cmd_s els_cmd;
+	u32        node_id_data_format:8;
+	u32        common_id_data_length:8;
+	u32        reserved:8;
+	u32        specific_id_data_length:8;
+	struct fc_rnid_common_id_data_s common_id_data;
+	struct fc_rnid_general_topology_data_s gen_topology_data;
+};
+
+#define RNID_ASSOCIATED_TYPE_UNKNOWN                    0x00000001
+#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
+#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
+#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
+#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
+#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
+#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
+#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
+#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
+#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
+#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
+#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
+#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
+
+enum fc_rpsc_speed_cap {
+	RPSC_SPEED_CAP_1G = 0x8000,
+	RPSC_SPEED_CAP_2G = 0x4000,
+	RPSC_SPEED_CAP_4G = 0x2000,
+	RPSC_SPEED_CAP_10G = 0x1000,
+	RPSC_SPEED_CAP_8G = 0x0800,
+	RPSC_SPEED_CAP_16G = 0x0400,
+
+	RPSC_SPEED_CAP_UNKNOWN = 0x0001,
+};
+
+enum fc_rpsc_op_speed {
+	RPSC_OP_SPEED_1G = 0x8000,
+	RPSC_OP_SPEED_2G = 0x4000,
+	RPSC_OP_SPEED_4G = 0x2000,
+	RPSC_OP_SPEED_10G = 0x1000,
+	RPSC_OP_SPEED_8G = 0x0800,
+	RPSC_OP_SPEED_16G = 0x0400,
+
+	RPSC_OP_SPEED_NOT_EST = 0x0001,	/*! speed not established */
+};
+
+struct fc_rpsc_speed_info_s {
+	u16        port_speed_cap;	/*! see enum fc_rpsc_speed_cap */
+	u16        port_op_speed;	/*! see enum fc_rpsc_op_speed */
+};
+
+enum link_e2e_beacon_subcmd {
+	LINK_E2E_BEACON_ON = 1,
+	LINK_E2E_BEACON_OFF = 2
+};
+
+enum beacon_type {
+	BEACON_TYPE_NORMAL	= 1,	/*! Normal Beaconing. Green */
+	BEACON_TYPE_WARN	= 2,	/*! Warning Beaconing. Yellow/Amber */
+	BEACON_TYPE_CRITICAL	= 3	/*! Critical Beaconing. Red */
+};
+
+struct link_e2e_beacon_param_s {
+	u8         beacon_type;	/* Beacon Type. See enum beacon_type */
+	u8         beacon_frequency;
+					/* Beacon frequency. Number of blinks
+					 * per 10 seconds
+					 */
+	u16        beacon_duration;/* Beacon duration (in Seconds). The
+					 * command operation should be
+					 * terminated at the end of this
+					 * timeout value.
+					 *
+					 * Ignored if diag_sub_cmd is
+					 * LINK_E2E_BEACON_OFF.
+					 *
+					 * If 0, beaconing will continue till a
+					 * BEACON OFF request is received
+					 */
+};
+
+/*
+ * Link E2E beacon request/good response format.
+ * For LS_RJTs use struct fc_ls_rjt_s
+ */
+struct link_e2e_beacon_req_s {
+	u32        ls_code;	/*! FC_ELS_E2E_LBEACON in requests *
+					 *or FC_ELS_ACC in good replies */
+	u32        ls_sub_cmd;	/*! See enum link_e2e_beacon_subcmd */
+	struct link_e2e_beacon_param_s beacon_parm;
+};
+
+/**
+ * If RPSC request is sent to the Domain Controller, the request is for
+ * all the ports within that domain (TODO - I don't think FOS implements
+ * this...).
+ */
+struct fc_rpsc_cmd_s {
+	struct fc_els_cmd_s els_cmd;
+};
+
+/*
+ * RPSC Acc
+ */
+struct fc_rpsc_acc_s {
+	u32        command:8;
+	u32        rsvd:8;
+	u32        num_entries:16;
+
+	struct fc_rpsc_speed_info_s speed_info[1];
+};
+
+/**
+ * If RPSC2 request is sent to the Domain Controller,
+ */
+#define FC_BRCD_TOKEN    0x42524344
+
+struct fc_rpsc2_cmd_s {
+	struct fc_els_cmd_s els_cmd;
+	u32	token;
+	u16	resvd;
+	u16	num_pids;	/* Number of pids in the request */
+	struct  {
+		u32	rsvd1:8;
+		u32	pid:24;		/* port identifier */
+	} pid_list[1];
+};
+
+enum fc_rpsc2_port_type {
+	RPSC2_PORT_TYPE_UNKNOWN = 0,
+	RPSC2_PORT_TYPE_NPORT   = 1,
+	RPSC2_PORT_TYPE_NLPORT  = 2,
+	RPSC2_PORT_TYPE_NPIV_PORT  = 0x5f,
+	RPSC2_PORT_TYPE_NPORT_TRUNK  = 0x6f,
+};
+/*
+ * RPSC2 portInfo entry structure
+ */
+struct fc_rpsc2_port_info_s {
+    u32    pid;        /* PID */
+    u16    resvd1;
+    u16    index;      /* port number / index */
+    u8     resvd2;
+    u8	   type;	/* port type N/NL/... */
+    u16    speed;      /* port Operating Speed */
+};
+
+/*
+ * RPSC2 Accept payload
+ */
+struct fc_rpsc2_acc_s {
+	u8        els_cmd;
+	u8        resvd;
+    u16       num_pids;  /* Number of pids in the request */
+    struct fc_rpsc2_port_info_s port_info[1];    /* port information */
+};
+
+/**
+ * bit fields so that multiple classes can be specified
+ */
+enum fc_cos {
+	FC_CLASS_2	= 0x04,
+	FC_CLASS_3	= 0x08,
+	FC_CLASS_2_3	= 0x0C,
+};
+
+/*
+ * symbolic name
+ */
+struct fc_symname_s {
+	u8         symname[FC_SYMNAME_MAX];
+};
+
+struct fc_alpabm_s {
+	u8         alpa_bm[FC_ALPA_MAX / 8];
+};
+
+/*
+ * protocol default timeout values
+ */
+#define FC_ED_TOV		2
+#define FC_REC_TOV		(FC_ED_TOV + 1)
+#define FC_RA_TOV		10
+#define FC_ELS_TOV		(2 * FC_RA_TOV)
+#define FC_FCCT_TOV		(3 * FC_RA_TOV)
+
+/*
+ * virtual fabric related defines
+ */
+#define FC_VF_ID_NULL    0	/*  must not be used as VF_ID */
+#define FC_VF_ID_MIN     1
+#define FC_VF_ID_MAX     0xEFF
+#define FC_VF_ID_CTL     0xFEF	/*  control VF_ID */
+
+/**
+ * Virtual Fabric Tagging header format
+ * @caution This is defined only in BIG ENDIAN format.
+ */
+struct fc_vft_s {
+	u32        r_ctl:8;
+	u32        ver:2;
+	u32        type:4;
+	u32        res_a:2;
+	u32        priority:3;
+	u32        vf_id:12;
+	u32        res_b:1;
+	u32        hopct:8;
+	u32        res_c:24;
+};
+
+/*
+ * FCP
+ */
+enum {
+	FCP_RJT		= 0x01000000,	/* SRR reject */
+	FCP_SRR_ACCEPT	= 0x02000000,	/* SRR accept */
+	FCP_SRR		= 0x14000000,	/* Sequence Retransmission Request */
+};
+
+/*
+ * SRR FC-4 LS payload
+ */
+struct fc_srr_s {
+	u32	ls_cmd;
+	u32        ox_id:16;	/* ox-id */
+	u32        rx_id:16;	/* rx-id */
+	u32        ro;		/* relative offset */
+	u32        r_ctl:8;		/* R_CTL for I.U. */
+	u32        res:24;
+};
+
+
+/*
+ * FCP_CMND definitions
+ */
+#define FCP_CMND_CDB_LEN    16
+#define FCP_CMND_LUN_LEN    8
+
+struct fcp_cmnd_s {
+	lun_t           lun;		/* 64-bit LU number */
+	u8         crn;		/* command reference number */
+#ifdef __BIGENDIAN
+	u8         resvd:1,
+			priority:4,	/* FCP-3: SAM-3 priority */
+			taskattr:3;	/* scsi task attribute */
+#else
+	u8         taskattr:3,	/* scsi task attribute */
+			priority:4,	/* FCP-3: SAM-3 priority */
+			resvd:1;
+#endif
+	u8         tm_flags;	/* task management flags */
+#ifdef __BIGENDIAN
+	u8         addl_cdb_len:6,	/* additional CDB length words */
+			iodir:2;	/* read/write FCP_DATA IUs */
+#else
+	u8         iodir:2,	/* read/write FCP_DATA IUs */
+			addl_cdb_len:6;	/* additional CDB length */
+#endif
+	scsi_cdb_t      cdb;
+
+	/*
+	 * !!! additional cdb bytes follows here!!!
+	 */
+	u32        fcp_dl;	/* bytes to be transferred */
+};
+
+#define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN)
+#define fcp_cmnd_fcpdl(_cmnd)	((&(_cmnd)->fcp_dl)[(_cmnd)->addl_cdb_len])
+
+/*
+ * struct fcp_cmnd_s .iodir field values
+ */
+enum fcp_iodir {
+	FCP_IODIR_NONE	= 0,
+	FCP_IODIR_WRITE = 1,
+	FCP_IODIR_READ	= 2,
+	FCP_IODIR_RW	= 3,
+};
+
+/*
+ * Task attribute field
+ */
+enum {
+	FCP_TASK_ATTR_SIMPLE	= 0,
+	FCP_TASK_ATTR_HOQ	= 1,
+	FCP_TASK_ATTR_ORDERED	= 2,
+	FCP_TASK_ATTR_ACA	= 4,
+	FCP_TASK_ATTR_UNTAGGED	= 5,	/* obsolete in FCP-3 */
+};
+
+/*
+ * Task management flags field - only one bit shall be set
+ */
+enum fcp_tm_cmnd {
+	FCP_TM_ABORT_TASK_SET	= BIT(1),
+	FCP_TM_CLEAR_TASK_SET	= BIT(2),
+	FCP_TM_LUN_RESET	= BIT(4),
+	FCP_TM_TARGET_RESET	= BIT(5),	/* obsolete in FCP-3 */
+	FCP_TM_CLEAR_ACA	= BIT(6),
+};
+
+/*
+ * FCP_XFER_RDY IU defines
+ */
+struct fcp_xfer_rdy_s {
+	u32        data_ro;
+	u32        burst_len;
+	u32        reserved;
+};
+
+/*
+ * FCP_RSP residue flags
+ */
+enum fcp_residue {
+	FCP_NO_RESIDUE = 0,	/* no residue */
+	FCP_RESID_OVER = 1,	/* more data left that was not sent */
+	FCP_RESID_UNDER = 2,	/* less data than requested */
+};
+
+enum {
+	FCP_RSPINFO_GOOD = 0,
+	FCP_RSPINFO_DATALEN_MISMATCH = 1,
+	FCP_RSPINFO_CMND_INVALID = 2,
+	FCP_RSPINFO_ROLEN_MISMATCH = 3,
+	FCP_RSPINFO_TM_NOT_SUPP = 4,
+	FCP_RSPINFO_TM_FAILED = 5,
+};
+
+struct fcp_rspinfo_s {
+	u32        res0:24;
+	u32        rsp_code:8;	/* response code (as above) */
+	u32        res1;
+};
+
+struct fcp_resp_s {
+	u32        reserved[2];	/* 2 words reserved */
+	u16        reserved2;
+#ifdef __BIGENDIAN
+	u8         reserved3:3;
+	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
+	u8         resid_flags:2;	/* underflow/overflow */
+	u8         sns_len_valid:1;/* sense len is valid */
+	u8         rsp_len_valid:1;/* response len is valid */
+#else
+	u8         rsp_len_valid:1;/* response len is valid */
+	u8         sns_len_valid:1;/* sense len is valid */
+	u8         resid_flags:2;	/* underflow/overflow */
+	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
+	u8         reserved3:3;
+#endif
+	u8         scsi_status;	/* one byte SCSI status */
+	u32        residue;	/* residual data bytes */
+	u32        sns_len;	/* length od sense info */
+	u32        rsp_len;	/* length of response info */
+};
+
+#define fcp_snslen(__fcprsp)	((__fcprsp)->sns_len_valid ?		\
+					(__fcprsp)->sns_len : 0)
+#define fcp_rsplen(__fcprsp)	((__fcprsp)->rsp_len_valid ?		\
+					(__fcprsp)->rsp_len : 0)
+#define fcp_rspinfo(__fcprsp)	((struct fcp_rspinfo_s *)((__fcprsp) + 1))
+#define fcp_snsinfo(__fcprsp)	(((u8 *)fcp_rspinfo(__fcprsp)) +	\
+						fcp_rsplen(__fcprsp))
+
+struct fcp_cmnd_fr_s {
+	struct fchs_s fchs;
+	struct fcp_cmnd_s fcp;
+};
+
+/*
+ * CT
+ */
+struct ct_hdr_s {
+	u32	rev_id:8;	/* Revision of the CT */
+	u32	in_id:24;	/* Initiator Id */
+	u32	gs_type:8;	/* Generic service Type */
+	u32	gs_sub_type:8;	/* Generic service sub type */
+	u32	options:8;	/* options */
+	u32	rsvrd:8;	/* reserved */
+	u32	cmd_rsp_code:16;/* ct command/response code */
+	u32	max_res_size:16;/* maximum/residual size */
+	u32	frag_id:8;	/* fragment ID */
+	u32	reason_code:8;	/* reason code */
+	u32	exp_code:8;	/* explanation code */
+	u32	vendor_unq:8;	/* vendor unique */
+};
+
+/*
+ * defines for the Revision
+ */
+enum {
+	CT_GS3_REVISION = 0x01,
+};
+
+/*
+ * defines for gs_type
+ */
+enum {
+	CT_GSTYPE_KEYSERVICE	= 0xF7,
+	CT_GSTYPE_ALIASSERVICE	= 0xF8,
+	CT_GSTYPE_MGMTSERVICE	= 0xFA,
+	CT_GSTYPE_TIMESERVICE	= 0xFB,
+	CT_GSTYPE_DIRSERVICE	= 0xFC,
+};
+
+/*
+ * defines for gs_sub_type for gs type directory service
+ */
+enum {
+	CT_GSSUBTYPE_NAMESERVER = 0x02,
+};
+
+/*
+ * defines for gs_sub_type for gs type management service
+ */
+enum {
+	CT_GSSUBTYPE_CFGSERVER	= 0x01,
+	CT_GSSUBTYPE_UNZONED_NS = 0x02,
+	CT_GSSUBTYPE_ZONESERVER = 0x03,
+	CT_GSSUBTYPE_LOCKSERVER = 0x04,
+	CT_GSSUBTYPE_HBA_MGMTSERVER = 0x10,	/* for FDMI */
+};
+
+/*
+ * defines for CT response code field
+ */
+enum {
+	CT_RSP_REJECT = 0x8001,
+	CT_RSP_ACCEPT = 0x8002,
+};
+
+/*
+ * defintions for CT reason code
+ */
+enum {
+	CT_RSN_INV_CMD		= 0x01,
+	CT_RSN_INV_VER		= 0x02,
+	CT_RSN_LOGIC_ERR	= 0x03,
+	CT_RSN_INV_SIZE		= 0x04,
+	CT_RSN_LOGICAL_BUSY	= 0x05,
+	CT_RSN_PROTO_ERR	= 0x07,
+	CT_RSN_UNABLE_TO_PERF	= 0x09,
+	CT_RSN_NOT_SUPP			= 0x0B,
+	CT_RSN_SERVER_NOT_AVBL  = 0x0D,
+	CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,
+	CT_RSN_VENDOR_SPECIFIC  = 0xFF,
+
+};
+
+/*
+ * definitions for explanations code for Name server
+ */
+enum {
+	CT_NS_EXP_NOADDITIONAL	= 0x00,
+	CT_NS_EXP_ID_NOT_REG	= 0x01,
+	CT_NS_EXP_PN_NOT_REG	= 0x02,
+	CT_NS_EXP_NN_NOT_REG	= 0x03,
+	CT_NS_EXP_CS_NOT_REG	= 0x04,
+	CT_NS_EXP_IPN_NOT_REG	= 0x05,
+	CT_NS_EXP_IPA_NOT_REG	= 0x06,
+	CT_NS_EXP_FT_NOT_REG	= 0x07,
+	CT_NS_EXP_SPN_NOT_REG	= 0x08,
+	CT_NS_EXP_SNN_NOT_REG	= 0x09,
+	CT_NS_EXP_PT_NOT_REG	= 0x0A,
+	CT_NS_EXP_IPP_NOT_REG	= 0x0B,
+	CT_NS_EXP_FPN_NOT_REG	= 0x0C,
+	CT_NS_EXP_HA_NOT_REG	= 0x0D,
+	CT_NS_EXP_FD_NOT_REG	= 0x0E,
+	CT_NS_EXP_FF_NOT_REG	= 0x0F,
+	CT_NS_EXP_ACCESSDENIED	= 0x10,
+	CT_NS_EXP_UNACCEPTABLE_ID = 0x11,
+	CT_NS_EXP_DATABASEEMPTY		= 0x12,
+	CT_NS_EXP_NOT_REG_IN_SCOPE	= 0x13,
+	CT_NS_EXP_DOM_ID_NOT_PRESENT	= 0x14,
+	CT_NS_EXP_PORT_NUM_NOT_PRESENT	= 0x15,
+	CT_NS_EXP_NO_DEVICE_ATTACHED	= 0x16
+};
+
+/*
+ * defintions for the explanation code for all servers
+ */
+enum {
+	CT_EXP_AUTH_EXCEPTION			= 0xF1,
+	CT_EXP_DB_FULL					= 0xF2,
+	CT_EXP_DB_EMPTY					= 0xF3,
+	CT_EXP_PROCESSING_REQ			= 0xF4,
+	CT_EXP_UNABLE_TO_VERIFY_CONN	= 0xF5,
+	CT_EXP_DEVICES_NOT_IN_CMN_ZONE  = 0xF6
+};
+
+/*
+ * Command codes for Name server
+ */
+enum {
+	GS_GID_PN	= 0x0121,	/* Get Id on port name */
+	GS_GPN_ID	= 0x0112,	/* Get port name on ID */
+	GS_GNN_ID	= 0x0113,	/* Get node name on ID */
+	GS_GID_FT	= 0x0171,	/* Get Id on FC4 type */
+	GS_GSPN_ID	= 0x0118,	/* Get symbolic PN on ID */
+	GS_RFT_ID	= 0x0217,	/* Register fc4type on ID */
+	GS_RSPN_ID	= 0x0218,	/* Register symbolic PN on ID */
+	GS_RPN_ID	= 0x0212,	/* Register port name */
+	GS_RNN_ID	= 0x0213,	/* Register node name */
+	GS_RCS_ID	= 0x0214,	/* Register class of service */
+	GS_RPT_ID	= 0x021A,	/* Register port type */
+	GS_GA_NXT	= 0x0100,	/* Get all next */
+	GS_RFF_ID	= 0x021F,	/* Register FC4 Feature		*/
+};
+
+struct fcgs_id_req_s{
+	u32 rsvd:8;
+	u32 dap:24; /* port identifier */
+};
+#define fcgs_gpnid_req_t struct fcgs_id_req_s
+#define fcgs_gnnid_req_t struct fcgs_id_req_s
+#define fcgs_gspnid_req_t struct fcgs_id_req_s
+
+struct fcgs_gidpn_req_s {
+	wwn_t	port_name;	/* port wwn */
+};
+
+struct fcgs_gidpn_resp_s {
+	u32	rsvd:8;
+	u32	dap:24;	/* port identifier */
+};
+
+/**
+ * RFT_ID
+ */
+struct fcgs_rftid_req_s {
+	u32	rsvd:8;
+	u32	dap:24;		/* port identifier */
+	u32	fc4_type[8];	/* fc4 types */
+};
+
+/**
+ * RFF_ID : Register FC4 features.
+ */
+
+#define FC_GS_FCP_FC4_FEATURE_INITIATOR  0x02
+#define FC_GS_FCP_FC4_FEATURE_TARGET	 0x01
+
+struct fcgs_rffid_req_s {
+    u32    rsvd:8;
+    u32    dap:24;		/* port identifier	*/
+    u32    rsvd1:16;
+    u32    fc4ftr_bits:8;		/* fc4 feature bits	*/
+    u32    fc4_type:8;		/* corresponding FC4 Type */
+};
+
+/**
+ * GID_FT Request
+ */
+struct fcgs_gidft_req_s {
+	u8	reserved;
+	u8	domain_id;	/* domain, 0 - all fabric */
+	u8	area_id;	/* area, 0 - whole domain */
+	u8	fc4_type;	/* FC_TYPE_FCP for SCSI devices */
+};		/* GID_FT Request */
+
+/**
+ * GID_FT Response
+ */
+struct fcgs_gidft_resp_s {
+	u8		last:1;	/* last port identifier flag */
+	u8		reserved:7;
+	u32	pid:24;	/* port identifier */
+};		/* GID_FT Response */
+
+/**
+ * RSPN_ID
+ */
+struct fcgs_rspnid_req_s {
+	u32	rsvd:8;
+	u32	dap:24;		/* port identifier */
+	u8		spn_len;	/* symbolic port name length */
+	u8		spn[256];	/* symbolic port name */
+};
+
+/**
+ * RPN_ID
+ */
+struct fcgs_rpnid_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+	wwn_t		port_name;
+};
+
+/**
+ * RNN_ID
+ */
+struct fcgs_rnnid_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+	wwn_t		node_name;
+};
+
+/**
+ * RCS_ID
+ */
+struct fcgs_rcsid_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+	u32	cos;
+};
+
+/**
+ * RPT_ID
+ */
+struct fcgs_rptid_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+	u32	port_type:8;
+	u32	rsvd1:24;
+};
+
+/**
+ * GA_NXT Request
+ */
+struct fcgs_ganxt_req_s {
+	u32	rsvd:8;
+	u32	port_id:24;
+};
+
+/**
+ * GA_NXT Response
+ */
+struct fcgs_ganxt_rsp_s {
+	u32	port_type:8;	/* Port Type */
+	u32	port_id:24;	/* Port Identifier */
+	wwn_t		port_name;	/* Port Name */
+	u8		spn_len;	/* Length of Symbolic Port Name */
+	char		spn[255];	/* Symbolic Port Name */
+	wwn_t		node_name;	/* Node Name */
+	u8		snn_len;	/* Length of Symbolic Node Name */
+	char		snn[255];	/* Symbolic Node Name */
+	u8		ipa[8];		/* Initial Process Associator */
+	u8		ip[16];		/* IP Address */
+	u32	cos;		/* Class of Service */
+	u32	fc4types[8];	/* FC-4 TYPEs */
+	wwn_t		fabric_port_name;
+					/* Fabric Port Name */
+	u32	rsvd:8;		/* Reserved */
+	u32	hard_addr:24;	/* Hard Address */
+};
+
+/*
+ * Fabric Config Server
+ */
+
+/*
+ * Command codes for Fabric Configuration Server
+ */
+enum {
+	GS_FC_GFN_CMD	= 0x0114,	/* GS FC Get Fabric Name  */
+	GS_FC_GMAL_CMD	= 0x0116,	/* GS FC GMAL  */
+	GS_FC_TRACE_CMD	= 0x0400,	/* GS FC Trace Route */
+	GS_FC_PING_CMD	= 0x0401,	/* GS FC Ping */
+};
+
+/*
+ * Source or Destination Port Tags.
+ */
+enum {
+	GS_FTRACE_TAG_NPORT_ID		= 1,
+	GS_FTRACE_TAG_NPORT_NAME	= 2,
+};
+
+/*
+* Port Value : Could be a Port id or wwn
+ */
+union fcgs_port_val_u {
+	u32	nport_id;
+	wwn_t		nport_wwn;
+};
+
+#define GS_FTRACE_MAX_HOP_COUNT	20
+#define GS_FTRACE_REVISION	1
+
+/*
+ * Ftrace Related Structures.
+ */
+
+/*
+ * STR (Switch Trace) Reject Reason Codes. From FC-SW.
+ */
+enum {
+	GS_FTRACE_STR_CMD_COMPLETED_SUCC	= 0,
+	GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH,
+	GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH,
+	GS_FTRACE_STR_MAX_HOP_CNT_REACHED,
+	GS_FTRACE_STR_SRC_PORT_NOT_FOUND,
+	GS_FTRACE_STR_DST_PORT_NOT_FOUND,
+	GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE,
+	GS_FTRACE_STR_NO_ROUTE_BW_PORTS,
+	GS_FTRACE_STR_NO_ADDL_EXPLN,
+	GS_FTRACE_STR_FABRIC_BUSY,
+	GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS,
+	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0,
+	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff,
+};
+
+/*
+ * Ftrace Request
+ */
+struct fcgs_ftrace_req_s {
+	u32	revision;
+	u16	src_port_tag;	/* Source Port tag */
+	u16	src_port_len;	/* Source Port len */
+	union fcgs_port_val_u src_port_val;	/* Source Port value */
+	u16	dst_port_tag;	/* Destination Port tag */
+	u16	dst_port_len;	/* Destination Port len */
+	union fcgs_port_val_u dst_port_val;	/* Destination Port value */
+	u32	token;
+	u8		vendor_id[8];	/* T10 Vendor Identifier */
+	u8		vendor_info[8];	/* Vendor specific Info */
+	u32	max_hop_cnt;	/* Max Hop Count */
+};
+
+/*
+ * Path info structure
+ */
+struct fcgs_ftrace_path_info_s {
+	wwn_t		switch_name;		/* Switch WWN */
+	u32	domain_id;
+	wwn_t		ingress_port_name;	/* Ingress ports wwn */
+	u32	ingress_phys_port_num;	/* Ingress ports physical port
+						 * number
+						 */
+	wwn_t		egress_port_name;	/* Ingress ports wwn */
+	u32	egress_phys_port_num;	/* Ingress ports physical port
+						 * number
+						 */
+};
+
+/*
+ * Ftrace Acc Response
+ */
+struct fcgs_ftrace_resp_s {
+	u32	revision;
+	u32	token;
+	u8		vendor_id[8];		/* T10 Vendor Identifier */
+	u8		vendor_info[8];		/* Vendor specific Info */
+	u32	str_rej_reason_code;	/* STR Reject Reason Code */
+	u32	num_path_info_entries;	/* No. of path info entries */
+	/*
+	 * path info entry/entries.
+	 */
+	struct fcgs_ftrace_path_info_s path_info[1];
+
+};
+
+/*
+* Fabric Config Server : FCPing
+ */
+
+/*
+ * FC Ping Request
+ */
+struct fcgs_fcping_req_s {
+	u32	revision;
+	u16	port_tag;
+	u16	port_len;	/* Port len */
+	union fcgs_port_val_u port_val;	/* Port value */
+	u32	token;
+};
+
+/*
+ * FC Ping Response
+ */
+struct fcgs_fcping_resp_s {
+	u32	token;
+};
+
+/*
+ * Command codes for zone server query.
+ */
+enum {
+	ZS_GZME = 0x0124,	/* Get zone member extended */
+};
+
+/*
+ * ZS GZME request
+ */
+#define ZS_GZME_ZNAMELEN	32
+struct zs_gzme_req_s {
+	u8	znamelen;
+	u8	rsvd[3];
+	u8	zname[ZS_GZME_ZNAMELEN];
+};
+
+enum zs_mbr_type {
+	ZS_MBR_TYPE_PWWN	= 1,
+	ZS_MBR_TYPE_DOMPORT	= 2,
+	ZS_MBR_TYPE_PORTID	= 3,
+	ZS_MBR_TYPE_NWWN	= 4,
+};
+
+struct zs_mbr_wwn_s {
+	u8	mbr_type;
+	u8	rsvd[3];
+	wwn_t	wwn;
+};
+
+struct zs_query_resp_s {
+	u32	nmbrs;	/*  number of zone members */
+	struct zs_mbr_wwn_s	mbr[1];
+};
+
+/*
+ * GMAL Command ( Get ( interconnect Element) Management Address List)
+ * To retrieve the IP Address of a Switch.
+ */
+
+#define CT_GMAL_RESP_PREFIX_TELNET	 "telnet://"
+#define CT_GMAL_RESP_PREFIX_HTTP	 "http://"
+
+/*  GMAL/GFN request */
+struct fcgs_req_s {
+	wwn_t    wwn;   /* PWWN/NWWN */
+};
+
+#define fcgs_gmal_req_t struct fcgs_req_s
+#define fcgs_gfn_req_t struct fcgs_req_s
+
+/* Accept Response to GMAL */
+struct fcgs_gmal_resp_s {
+	u32	ms_len;   /* Num of entries */
+	u8	ms_ma[256];
+};
+
+struct fcgs_gmal_entry_s {
+	u8  len;
+	u8  prefix[7]; /* like "http://" */
+	u8  ip_addr[248];
+};
+
+/*
+ * FDMI
+ */
+/*
+ * FDMI Command Codes
+ */
+#define	FDMI_GRHL		0x0100
+#define	FDMI_GHAT		0x0101
+#define	FDMI_GRPL		0x0102
+#define	FDMI_GPAT		0x0110
+#define	FDMI_RHBA		0x0200
+#define	FDMI_RHAT		0x0201
+#define	FDMI_RPRT		0x0210
+#define	FDMI_RPA		0x0211
+#define	FDMI_DHBA		0x0300
+#define	FDMI_DPRT		0x0310
+
+/*
+ * FDMI reason codes
+ */
+#define	FDMI_NO_ADDITIONAL_EXP		0x00
+#define	FDMI_HBA_ALREADY_REG		0x10
+#define	FDMI_HBA_ATTRIB_NOT_REG		0x11
+#define	FDMI_HBA_ATTRIB_MULTIPLE	0x12
+#define	FDMI_HBA_ATTRIB_LENGTH_INVALID	0x13
+#define	FDMI_HBA_ATTRIB_NOT_PRESENT	0x14
+#define	FDMI_PORT_ORIG_NOT_IN_LIST	0x15
+#define	FDMI_PORT_HBA_NOT_IN_LIST	0x16
+#define	FDMI_PORT_ATTRIB_NOT_REG	0x20
+#define	FDMI_PORT_NOT_REG		0x21
+#define	FDMI_PORT_ATTRIB_MULTIPLE	0x22
+#define	FDMI_PORT_ATTRIB_LENGTH_INVALID	0x23
+#define	FDMI_PORT_ALREADY_REGISTEREED	0x24
+
+/*
+ * FDMI Transmission Speed Mask values
+ */
+#define	FDMI_TRANS_SPEED_1G		0x00000001
+#define	FDMI_TRANS_SPEED_2G		0x00000002
+#define	FDMI_TRANS_SPEED_10G		0x00000004
+#define	FDMI_TRANS_SPEED_4G		0x00000008
+#define	FDMI_TRANS_SPEED_8G		0x00000010
+#define	FDMI_TRANS_SPEED_16G		0x00000020
+#define	FDMI_TRANS_SPEED_UNKNOWN	0x00008000
+
+/*
+ * FDMI HBA attribute types
+ */
+enum fdmi_hba_attribute_type {
+	FDMI_HBA_ATTRIB_NODENAME = 1,	/* 0x0001 */
+	FDMI_HBA_ATTRIB_MANUFACTURER,	/* 0x0002 */
+	FDMI_HBA_ATTRIB_SERIALNUM,	/* 0x0003 */
+	FDMI_HBA_ATTRIB_MODEL,		/* 0x0004 */
+	FDMI_HBA_ATTRIB_MODEL_DESC,	/* 0x0005 */
+	FDMI_HBA_ATTRIB_HW_VERSION,	/* 0x0006 */
+	FDMI_HBA_ATTRIB_DRIVER_VERSION,	/* 0x0007 */
+	FDMI_HBA_ATTRIB_ROM_VERSION,	/* 0x0008 */
+	FDMI_HBA_ATTRIB_FW_VERSION,	/* 0x0009 */
+	FDMI_HBA_ATTRIB_OS_NAME,	/* 0x000A */
+	FDMI_HBA_ATTRIB_MAX_CT,		/* 0x000B */
+
+	FDMI_HBA_ATTRIB_MAX_TYPE
+};
+
+/*
+ * FDMI Port attribute types
+ */
+enum fdmi_port_attribute_type {
+	FDMI_PORT_ATTRIB_FC4_TYPES = 1,	/* 0x0001 */
+	FDMI_PORT_ATTRIB_SUPP_SPEED,	/* 0x0002 */
+	FDMI_PORT_ATTRIB_PORT_SPEED,	/* 0x0003 */
+	FDMI_PORT_ATTRIB_FRAME_SIZE,	/* 0x0004 */
+	FDMI_PORT_ATTRIB_DEV_NAME,	/* 0x0005 */
+	FDMI_PORT_ATTRIB_HOST_NAME,	/* 0x0006 */
+
+	FDMI_PORT_ATTR_MAX_TYPE
+};
+
+/*
+ * FDMI attribute
+ */
+struct fdmi_attr_s {
+	u16        type;
+	u16        len;
+	u8         value[1];
+};
+
+/*
+ * HBA Attribute Block
+ */
+struct fdmi_hba_attr_s {
+	u32        attr_count;	/* # of attributes */
+	struct fdmi_attr_s hba_attr;	/* n attributes */
+};
+
+/*
+ * Registered Port List
+ */
+struct fdmi_port_list_s {
+	u32        num_ports;	/* number Of Port Entries */
+	wwn_t           port_entry;	/* one or more */
+};
+
+/*
+ * Port Attribute Block
+ */
+struct fdmi_port_attr_s {
+	u32        attr_count;	/* # of attributes */
+	struct fdmi_attr_s port_attr;	/* n attributes */
+};
+
+/*
+ * FDMI Register HBA Attributes
+ */
+struct fdmi_rhba_s {
+	wwn_t           hba_id;		/* HBA Identifier */
+	struct fdmi_port_list_s port_list;	/* Registered Port List */
+	struct fdmi_hba_attr_s hba_attr_blk;	/* HBA attribute block */
+};
+
+/*
+ * FDMI Register Port
+ */
+struct fdmi_rprt_s {
+	wwn_t           hba_id;		/* HBA Identifier */
+	wwn_t           port_name;	/* Port wwn */
+	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
+};
+
+/*
+ * FDMI Register Port Attributes
+ */
+struct fdmi_rpa_s {
+	wwn_t           port_name;	/* port wwn */
+	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
+};
+
+#pragma pack()
+
+#endif	/* __BFA_FC_H__ */
diff --git a/drivers/scsi/bfa/fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
similarity index 82%
rename from drivers/scsi/bfa/fcbuild.c
rename to drivers/scsi/bfa/bfa_fcbuild.c
index fee5456..b7d2657 100644
--- a/drivers/scsi/bfa/fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -18,25 +18,25 @@
  * fcbuild.c - FC link service frame building and parsing routines
  */
 
-#include <bfa_os_inc.h>
-#include "fcbuild.h"
+#include "bfa_os_inc.h"
+#include "bfa_fcbuild.h"
 
 /*
  * static build functions
  */
-static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id);
-static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id);
-static struct fchs_s   fc_els_req_tmpl;
-static struct fchs_s   fc_els_rsp_tmpl;
-static struct fchs_s   fc_bls_req_tmpl;
-static struct fchs_s   fc_bls_rsp_tmpl;
+static void     fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+				 u16 ox_id);
+static void     fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+				 u16 ox_id);
+static struct fchs_s fc_els_req_tmpl;
+static struct fchs_s fc_els_rsp_tmpl;
+static struct fchs_s fc_bls_req_tmpl;
+static struct fchs_s fc_bls_rsp_tmpl;
 static struct fc_ba_acc_s ba_acc_tmpl;
 static struct fc_logi_s plogi_tmpl;
 static struct fc_prli_s prli_tmpl;
 static struct fc_rrq_s rrq_tmpl;
-static struct fchs_s   fcp_fchs_tmpl;
+static struct fchs_s fcp_fchs_tmpl;
 
 void
 fcbuild_init(void)
@@ -123,7 +123,7 @@
 	rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
 
 	/*
-	 * fcp_fchs_tmpl
+	 * fcp_struct fchs_s mpl
 	 */
 	fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
 	fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
@@ -135,8 +135,7 @@
 }
 
 static void
-fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u32 ox_id)
+fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
 {
 	bfa_os_memset(fchs, 0, sizeof(struct fchs_s));
 
@@ -158,8 +157,7 @@
 }
 
 void
-fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id)
+fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
 {
 	bfa_os_memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
 	fchs->d_id = (d_id);
@@ -168,8 +166,7 @@
 }
 
 static void
-fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id)
+fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
 {
 	bfa_os_memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
 	fchs->d_id = d_id;
@@ -180,8 +177,8 @@
 enum fc_parse_status
 fc_els_rsp_parse(struct fchs_s *fchs, int len)
 {
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-	struct fc_ls_rjt_s    *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_ls_rjt_s *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
 
 	len = len;
 
@@ -199,8 +196,7 @@
 }
 
 static void
-fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id)
+fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
 {
 	bfa_os_memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
 	fchs->d_id = d_id;
@@ -213,7 +209,7 @@
 		 u16 ox_id, wwn_t port_name, wwn_t node_name,
 		 u16 pdu_size, u8 els_code)
 {
-	struct fc_logi_s     *plogi = (struct fc_logi_s *) (pld);
+	struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
 
 	bfa_os_memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
 
@@ -233,12 +229,11 @@
 
 u16
 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
-		u16 ox_id, wwn_t port_name, wwn_t node_name,
-		u16 pdu_size, u8 set_npiv, u8 set_auth,
-		u16 local_bb_credits)
+		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,
+	       u8 set_npiv, u8 set_auth, u16 local_bb_credits)
 {
 	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
-	u32 	*vvl_info;
+	u32	*vvl_info;
 
 	bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
 
@@ -292,8 +287,7 @@
 
 u16
 fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
-		u16 ox_id, wwn_t port_name, wwn_t node_name,
-		u16 pdu_size)
+		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
 {
 	u32        d_id = bfa_os_hton3b(FC_FABRIC_PORT);
 
@@ -330,9 +324,9 @@
 enum fc_parse_status
 fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
 {
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-	struct fc_logi_s     *plogi;
-	struct fc_ls_rjt_s    *ls_rjt;
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_logi_s *plogi;
+	struct fc_ls_rjt_s *ls_rjt;
 
 	switch (els_cmd->els_code) {
 	case FC_ELS_LS_RJT:
@@ -364,7 +358,7 @@
 enum fc_parse_status
 fc_plogi_parse(struct fchs_s *fchs)
 {
-	struct fc_logi_s     *plogi = (struct fc_logi_s *) (fchs + 1);
+	struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
 
 	if (plogi->class3.class_valid != 1)
 		return FC_PARSE_FAILURE;
@@ -381,7 +375,7 @@
 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 	      u16 ox_id)
 {
-	struct fc_prli_s      *prli = (struct fc_prli_s *) (pld);
+	struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
 
 	fc_els_req_build(fchs, d_id, s_id, ox_id);
 	bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
@@ -398,19 +392,16 @@
 
 u16
 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
-		  u16 ox_id, enum bfa_port_role role)
+		  u16 ox_id, enum bfa_lport_role role)
 {
-	struct fc_prli_s      *prli = (struct fc_prli_s *) (pld);
+	struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
 
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 	bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
 
 	prli->command = FC_ELS_ACC;
 
-	if ((role & BFA_PORT_ROLE_FCP_TM) == BFA_PORT_ROLE_FCP_TM)
-		prli->parampage.servparams.target = 1;
-	else
-		prli->parampage.servparams.initiator = 1;
+	prli->parampage.servparams.initiator = 1;
 
 	prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
 
@@ -452,12 +443,12 @@
 }
 
 u16
-fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
-			u32 s_id, u16 ox_id, wwn_t port_name)
+fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,
+	      u16 ox_id, wwn_t port_name)
 {
 	fc_els_req_build(fchs, d_id, s_id, ox_id);
 
-	memset(logo, '\0', sizeof(struct fc_logo_s));
+	bfa_os_memset(logo, '\0', sizeof(struct fc_logo_s));
 	logo->els_cmd.els_code = FC_ELS_LOGO;
 	logo->nport_id = (s_id);
 	logo->orig_port_name = port_name;
@@ -470,7 +461,7 @@
 		 u32 s_id, u16 ox_id, wwn_t port_name,
 		 wwn_t node_name, u8 els_code)
 {
-	memset(adisc, '\0', sizeof(struct fc_adisc_s));
+	bfa_os_memset(adisc, '\0', sizeof(struct fc_adisc_s));
 
 	adisc->els_cmd.els_code = els_code;
 
@@ -489,8 +480,7 @@
 
 u16
 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
-		u32 s_id, u16 ox_id, wwn_t port_name,
-		wwn_t node_name)
+		u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name)
 {
 	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
 				node_name, FC_ELS_ADISC);
@@ -523,10 +513,10 @@
 }
 
 enum fc_parse_status
-fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap,
-		 wwn_t node_name, wwn_t port_name)
+fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name,
+	       wwn_t port_name)
 {
-	struct fc_adisc_s     *adisc = (struct fc_adisc_s *) pld;
+	struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld;
 
 	if (adisc->els_cmd.els_code != FC_ELS_ACC)
 		return FC_PARSE_FAILURE;
@@ -542,13 +532,13 @@
 enum fc_parse_status
 fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
 {
-	struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
+	struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
 
 	if (pdisc->class3.class_valid != 1)
 		return FC_PARSE_FAILURE;
 
 	if ((bfa_os_ntohs(pdisc->class3.rxsz) <
-		 (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
+		(FC_MIN_PDUSZ - sizeof(struct fchs_s)))
 	    || (pdisc->class3.rxsz == 0))
 		return FC_PARSE_FAILURE;
 
@@ -584,8 +574,8 @@
 }
 
 u16
-fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id,
-			 u32 s_id, u16 ox_id, u16 rrq_oxid)
+fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id,
+	     u16 ox_id, u16 rrq_oxid)
 {
 	fc_els_req_build(fchs, d_id, s_id, ox_id);
 
@@ -604,11 +594,11 @@
 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
 		  u16 ox_id)
 {
-	struct fc_els_cmd_s   *acc = pld;
+	struct fc_els_cmd_s *acc = pld;
 
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 
-	memset(acc, 0, sizeof(struct fc_els_cmd_s));
+	bfa_os_memset(acc, 0, sizeof(struct fc_els_cmd_s));
 	acc->els_code = FC_ELS_ACC;
 
 	return sizeof(struct fc_els_cmd_s);
@@ -620,7 +610,7 @@
 		u8 reason_code_expl)
 {
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-	memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
+	bfa_os_memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
 
 	ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT;
 	ls_rjt->reason_code = reason_code;
@@ -647,11 +637,11 @@
 }
 
 u16
-fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
-			u32 d_id, u32 s_id, u16 ox_id)
+fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
+		u32 s_id, u16 ox_id)
 {
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-	memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
+	bfa_os_memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
 	els_cmd->els_code = FC_ELS_ACC;
 
 	return sizeof(struct fc_els_cmd_s);
@@ -661,8 +651,8 @@
 fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
 {
 	int             num_pages = 0;
-	struct fc_prlo_s      *prlo;
-	struct fc_tprlo_s     *tprlo;
+	struct fc_prlo_s *prlo;
+	struct fc_tprlo_s *tprlo;
 
 	if (els_code == FC_ELS_PRLO) {
 		prlo = (struct fc_prlo_s *) (fc_frame + 1);
@@ -676,14 +666,13 @@
 
 u16
 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			int num_pages)
+		u32 d_id, u32 s_id, u16 ox_id, int num_pages)
 {
 	int             page;
 
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 
-	memset(tprlo_acc, 0, (num_pages * 16) + 4);
+	bfa_os_memset(tprlo_acc, 0, (num_pages * 16) + 4);
 	tprlo_acc->command = FC_ELS_ACC;
 
 	tprlo_acc->page_len = 0x10;
@@ -700,15 +689,14 @@
 }
 
 u16
-fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			int num_pages)
+fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
+		  u32 s_id, u16 ox_id, int num_pages)
 {
 	int             page;
 
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 
-	memset(prlo_acc, 0, (num_pages * 16) + 4);
+	bfa_os_memset(prlo_acc, 0, (num_pages * 16) + 4);
 	prlo_acc->command = FC_ELS_ACC;
 	prlo_acc->page_len = 0x10;
 	prlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4);
@@ -726,11 +714,11 @@
 
 u16
 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
-			u32 s_id, u16 ox_id, u32 data_format)
+		u32 s_id, u16 ox_id, u32 data_format)
 {
 	fc_els_req_build(fchs, d_id, s_id, ox_id);
 
-	memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
+	bfa_os_memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
 
 	rnid->els_cmd.els_code = FC_ELS_RNID;
 	rnid->node_id_data_format = data_format;
@@ -739,13 +727,12 @@
 }
 
 u16
-fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u32 data_format,
-			struct fc_rnid_common_id_data_s *common_id_data,
-			struct fc_rnid_general_topology_data_s *gen_topo_data)
+fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
+		  u32 s_id, u16 ox_id, u32 data_format,
+		  struct fc_rnid_common_id_data_s *common_id_data,
+		  struct fc_rnid_general_topology_data_s *gen_topo_data)
 {
-	memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
+	bfa_os_memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
 
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 
@@ -769,27 +756,26 @@
 
 u16
 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
-			u32 s_id, u16 ox_id)
+		u32 s_id, u16 ox_id)
 {
 	fc_els_req_build(fchs, d_id, s_id, ox_id);
 
-	memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
+	bfa_os_memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
 
 	rpsc->els_cmd.els_code = FC_ELS_RPSC;
 	return sizeof(struct fc_rpsc_cmd_s);
 }
 
 u16
-fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2,
-			u32 d_id, u32 s_id, u32 *pid_list,
-			u16 npids)
+fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
+		u32 s_id, u32 *pid_list, u16 npids)
 {
 	u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id));
 	int i = 0;
 
 	fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0);
 
-	memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
+	bfa_os_memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
 
 	rpsc2->els_cmd.els_code = FC_ELS_RPSC;
 	rpsc2->token = bfa_os_htonl(FC_BRCD_TOKEN);
@@ -797,16 +783,15 @@
 	for (i = 0; i < npids; i++)
 		rpsc2->pid_list[i].pid = pid_list[i];
 
-	return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) *
-			(sizeof(u32)));
+	return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32)));
 }
 
 u16
 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			struct fc_rpsc_speed_info_s *oper_speed)
+		u32 d_id, u32 s_id, u16 ox_id,
+		  struct fc_rpsc_speed_info_s *oper_speed)
 {
-	memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
+	bfa_os_memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
 
 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
 
@@ -820,7 +805,6 @@
 		bfa_os_htons(oper_speed->port_op_speed);
 
 	return sizeof(struct fc_rpsc_acc_s);
-
 }
 
 /*
@@ -831,7 +815,7 @@
 u16
 fc_logo_rsp_parse(struct fchs_s *fchs, int len)
 {
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
 
 	len = len;
 	if (els_cmd->els_code != FC_ELS_ACC)
@@ -841,11 +825,10 @@
 }
 
 u16
-fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, wwn_t port_name, wwn_t node_name,
-			u16 pdu_size)
+fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+	       wwn_t port_name, wwn_t node_name, u16 pdu_size)
 {
-	struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
+	struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
 
 	bfa_os_memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
 
@@ -862,7 +845,7 @@
 u16
 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
 {
-	struct fc_logi_s     *pdisc = (struct fc_logi_s *) (fchs + 1);
+	struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
 
 	if (len < sizeof(struct fc_logi_s))
 		return FC_PARSE_LEN_INVAL;
@@ -886,11 +869,11 @@
 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
 	      int num_pages)
 {
-	struct fc_prlo_s      *prlo = (struct fc_prlo_s *) (fchs + 1);
+	struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1);
 	int             page;
 
 	fc_els_req_build(fchs, d_id, s_id, ox_id);
-	memset(prlo, 0, (num_pages * 16) + 4);
+	bfa_os_memset(prlo, 0, (num_pages * 16) + 4);
 	prlo->command = FC_ELS_PRLO;
 	prlo->page_len = 0x10;
 	prlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
@@ -909,7 +892,7 @@
 u16
 fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
 {
-	struct fc_prlo_acc_s  *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
+	struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
 	int             num_pages = 0;
 	int             page = 0;
 
@@ -941,15 +924,14 @@
 }
 
 u16
-fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, int num_pages,
-			enum fc_tprlo_type tprlo_type, u32 tpr_id)
+fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+	       int num_pages, enum fc_tprlo_type tprlo_type, u32 tpr_id)
 {
-	struct fc_tprlo_s     *tprlo = (struct fc_tprlo_s *) (fchs + 1);
+	struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1);
 	int             page;
 
 	fc_els_req_build(fchs, d_id, s_id, ox_id);
-	memset(tprlo, 0, (num_pages * 16) + 4);
+	bfa_os_memset(tprlo, 0, (num_pages * 16) + 4);
 	tprlo->command = FC_ELS_TPRLO;
 	tprlo->page_len = 0x10;
 	tprlo->payload_len = bfa_os_htons((num_pages * 16) + 4);
@@ -1003,7 +985,7 @@
 enum fc_parse_status
 fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
 {
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
 
 	len = len;
 	if (els_cmd->els_code != FC_ELS_ACC)
@@ -1013,11 +995,10 @@
 }
 
 u16
-fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, u32 reason_code,
-			u32 reason_expl)
+fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
+		u32 reason_code, u32 reason_expl)
 {
-	struct fc_ba_rjt_s    *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
+	struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
 
 	fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
 
@@ -1062,10 +1043,8 @@
 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 	       wwn_t port_name)
 {
-
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_gidpn_req_s *gidpn =
-			(struct fcgs_gidpn_req_s *) (cthdr + 1);
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1080,8 +1059,7 @@
 fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 	       u32 port_id)
 {
-
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
@@ -1097,8 +1075,7 @@
 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 	       u32 port_id)
 {
-
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
@@ -1124,8 +1101,8 @@
 }
 
 u16
-fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, u8 set_br_reg,
-			u32 s_id, u16 ox_id)
+fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
+		u8 set_br_reg, u32 s_id, u16 ox_id)
 {
 	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
 
@@ -1141,8 +1118,8 @@
 }
 
 u16
-fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
-			u16 ox_id)
+fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
+		u32 s_id, u16 ox_id)
 {
 	u32        d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER);
 	u16        payldlen;
@@ -1162,11 +1139,10 @@
 
 u16
 fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
-	       enum bfa_port_role roles)
+	       enum bfa_lport_role roles)
 {
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rftid_req_s *rftid =
-			(struct fcgs_rftid_req_s *) (cthdr + 1);
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
 	u32        type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER);
 	u8         index;
 
@@ -1182,23 +1158,15 @@
 	type_value = 1 << (FC_TYPE_FCP % 32);
 	rftid->fc4_type[index] = bfa_os_htonl(type_value);
 
-	if (roles & BFA_PORT_ROLE_FCP_IPFC) {
-		index = FC_TYPE_IP >> 5;
-		type_value = 1 << (FC_TYPE_IP % 32);
-		rftid->fc4_type[index] |= bfa_os_htonl(type_value);
-	}
-
 	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
 }
 
 u16
-fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, u8 *fc4_bitmap,
-			u32 bitmap_size)
+fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+		   u8 *fc4_bitmap, u32 bitmap_size)
 {
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rftid_req_s *rftid =
-			(struct fcgs_rftid_req_s *) (cthdr + 1);
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1208,7 +1176,7 @@
 
 	rftid->dap = s_id;
 	bfa_os_memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
-			(bitmap_size < 32 ? bitmap_size : 32));
+		(bitmap_size < 32 ? bitmap_size : 32));
 
 	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
 }
@@ -1217,9 +1185,8 @@
 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
 	       u8 fc4_type, u8 fc4_ftrs)
 {
-	struct ct_hdr_s         *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rffid_req_s *rffid =
-			(struct fcgs_rffid_req_s *) (cthdr + 1);
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1);
 	u32         d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1227,9 +1194,9 @@
 
 	bfa_os_memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
 
-	rffid->dap 		 	= s_id;
+	rffid->dap	    = s_id;
 	rffid->fc4ftr_bits  = fc4_ftrs;
-	rffid->fc4_type		= fc4_type;
+	rffid->fc4_type	    = fc4_type;
 
 	return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
 }
@@ -1239,9 +1206,9 @@
 		u8 *name)
 {
 
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rspnid_req_s *rspnid =
-			(struct fcgs_rspnid_req_s *) (cthdr + 1);
+			(struct fcgs_rspnid_req_s *)(cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
@@ -1257,13 +1224,11 @@
 }
 
 u16
-fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u8 fc4_type)
+fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
 {
 
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_gidft_req_s *gidft =
-			(struct fcgs_gidft_req_s *) (cthdr + 1);
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1282,9 +1247,8 @@
 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
 	       wwn_t port_name)
 {
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rpnid_req_s *rpnid =
-			(struct fcgs_rpnid_req_s *) (cthdr + 1);
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1301,9 +1265,8 @@
 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
 	       wwn_t node_name)
 {
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rnnid_req_s *rnnid =
-			(struct fcgs_rnnid_req_s *) (cthdr + 1);
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1320,7 +1283,7 @@
 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
 	       u32 cos)
 {
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	struct fcgs_rcsid_req_s *rcsid =
 			(struct fcgs_rcsid_req_s *) (cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
@@ -1339,9 +1302,8 @@
 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
 	       u8 port_type)
 {
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_rptid_req_s *rptid =
-			(struct fcgs_rptid_req_s *) (cthdr + 1);
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1357,9 +1319,8 @@
 u16
 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
 {
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
-	struct fcgs_ganxt_req_s *ganxt =
-			(struct fcgs_ganxt_req_s *) (cthdr + 1);
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
+	struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_NAME_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1379,7 +1340,7 @@
 		     u16 cmd_code)
 {
 
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
 
 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
@@ -1409,12 +1370,12 @@
 }
 
 /*
- * GMAL Request
+ *	GMAL Request
  */
 u16
 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
 {
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
 
@@ -1434,7 +1395,7 @@
 u16
 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
 {
-	struct ct_hdr_s       *cthdr = (struct ct_hdr_s *) pyld;
+	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
 	fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
 	u32        d_id = bfa_os_hton3b(FC_MGMT_SERVER);
 
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
new file mode 100644
index 0000000..73abd02
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+/*
+ * fcbuild.h - FC link service frame building and parsing routines
+ */
+
+#ifndef __FCBUILD_H__
+#define __FCBUILD_H__
+
+#include "bfa_os_inc.h"
+#include "bfa_fc.h"
+#include "bfa_defs_fcs.h"
+
+/*
+ * Utility Macros/functions
+ */
+
+#define wwn_is_equal(_wwn1, _wwn2)		\
+	(memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
+
+#define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
+
+/*
+ * Given the fc response length, this routine will return
+ * the length of the actual payload bytes following the CT header.
+ *
+ * Assumes the input response length does not include the crc, eof, etc.
+ */
+static inline   u32
+fc_get_ctresp_pyld_len(u32 resp_len)
+{
+	return resp_len - sizeof(struct ct_hdr_s);
+}
+
+/*
+ * Convert bfa speed to rpsc speed value.
+ */
+static inline  enum bfa_port_speed
+fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed speed)
+{
+	switch (speed) {
+
+	case RPSC_OP_SPEED_1G:
+		return BFA_PORT_SPEED_1GBPS;
+
+	case RPSC_OP_SPEED_2G:
+		return BFA_PORT_SPEED_2GBPS;
+
+	case RPSC_OP_SPEED_4G:
+		return BFA_PORT_SPEED_4GBPS;
+
+	case RPSC_OP_SPEED_8G:
+		return BFA_PORT_SPEED_8GBPS;
+
+	case RPSC_OP_SPEED_10G:
+		return BFA_PORT_SPEED_10GBPS;
+
+	default:
+		return BFA_PORT_SPEED_UNKNOWN;
+	}
+}
+
+/*
+ * Convert RPSC speed to bfa speed value.
+ */
+static inline   enum fc_rpsc_op_speed
+fc_bfa_speed_to_rpsc_operspeed(enum bfa_port_speed op_speed)
+{
+	switch (op_speed) {
+
+	case BFA_PORT_SPEED_1GBPS:
+		return RPSC_OP_SPEED_1G;
+
+	case BFA_PORT_SPEED_2GBPS:
+		return RPSC_OP_SPEED_2G;
+
+	case BFA_PORT_SPEED_4GBPS:
+		return RPSC_OP_SPEED_4G;
+
+	case BFA_PORT_SPEED_8GBPS:
+		return RPSC_OP_SPEED_8G;
+
+	case BFA_PORT_SPEED_10GBPS:
+		return RPSC_OP_SPEED_10G;
+
+	default:
+		return RPSC_OP_SPEED_NOT_EST;
+	}
+}
+
+enum fc_parse_status {
+	FC_PARSE_OK = 0,
+	FC_PARSE_FAILURE = 1,
+	FC_PARSE_BUSY = 2,
+	FC_PARSE_LEN_INVAL,
+	FC_PARSE_ACC_INVAL,
+	FC_PARSE_PWWN_NOT_EQUAL,
+	FC_PARSE_NWWN_NOT_EQUAL,
+	FC_PARSE_RXSZ_INVAL,
+	FC_PARSE_NOT_FCP,
+	FC_PARSE_OPAFLAG_INVAL,
+	FC_PARSE_RPAFLAG_INVAL,
+	FC_PARSE_OPA_INVAL,
+	FC_PARSE_RPA_INVAL,
+
+};
+
+struct fc_templates_s {
+	struct fchs_s fc_els_req;
+	struct fchs_s fc_bls_req;
+	struct fc_logi_s plogi;
+	struct fc_rrq_s rrq;
+};
+
+void            fcbuild_init(void);
+
+u16        fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
+			u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name,
+			       u16 pdu_size, u8 set_npiv, u8 set_auth,
+			       u16 local_bb_credits);
+
+u16        fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi, u32 s_id,
+			       u16 ox_id, wwn_t port_name, wwn_t node_name,
+			       u16 pdu_size);
+
+u16        fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
+				   u32 s_id, u16 ox_id,
+				   wwn_t port_name, wwn_t node_name,
+				   u16 pdu_size,
+				   u16 local_bb_credits);
+
+u16        fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
+			       u32 s_id, u16 ox_id, wwn_t port_name,
+			       wwn_t node_name, u16 pdu_size);
+
+enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
+
+u16        fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
+			      u16 ox_id);
+
+enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
+
+u16        fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
+			     u32 s_id, u16 ox_id, u16 rrq_oxid);
+enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
+
+u16        fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+				u16 ox_id, u8 *name);
+
+u16        fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+			       u16 ox_id, enum bfa_lport_role role);
+
+u16       fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
+				   u16 ox_id, u8 *fc4_bitmap,
+				   u32 bitmap_size);
+
+u16	fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
+
+u16        fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u16 ox_id, wwn_t port_name);
+
+u16        fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
+			       u16 ox_id, u32 port_id);
+
+u16        fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
+			u8 set_br_reg, u32 s_id, u16 ox_id);
+
+u16        fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+				   u32 s_id, u16 ox_id,
+				   wwn_t port_name, wwn_t node_name,
+				   u16 pdu_size);
+
+u16        fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
+			u32 d_id, u32 s_id, u16 ox_id, wwn_t port_name,
+			       wwn_t node_name);
+
+enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
+			u32 host_dap, wwn_t node_name, wwn_t port_name);
+
+enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
+				 wwn_t port_name, wwn_t node_name);
+
+u16        fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
+				   u32 d_id, u32 s_id, u16 ox_id,
+				   wwn_t port_name, wwn_t node_name);
+u16        fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
+				u32 d_id, u32 s_id, u16 ox_id,
+				u8 reason_code, u8 reason_code_expl);
+u16        fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
+				u32 d_id, u32 s_id, u16 ox_id);
+u16        fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
+			      u32 s_id, u16 ox_id);
+
+enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
+
+u16        fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+				  u32 s_id, u16 ox_id,
+				  enum bfa_lport_role role);
+
+u16        fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
+			      u32 d_id, u32 s_id, u16 ox_id,
+			      u32 data_format);
+
+u16        fc_rnid_acc_build(struct fchs_s *fchs,
+			struct fc_rnid_acc_s *rnid_acc, u32 d_id, u32 s_id,
+			u16 ox_id, u32 data_format,
+			struct fc_rnid_common_id_data_s *common_id_data,
+			struct fc_rnid_general_topology_data_s *gen_topo_data);
+
+u16	fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
+			u32 d_id, u32 s_id, u32 *pid_list, u16 npids);
+u16        fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
+			      u32 d_id, u32 s_id, u16 ox_id);
+u16        fc_rpsc_acc_build(struct fchs_s *fchs,
+			struct fc_rpsc_acc_s *rpsc_acc, u32 d_id, u32 s_id,
+			u16 ox_id, struct fc_rpsc_speed_info_s *oper_speed);
+u16        fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
+				u8 fc4_type);
+
+u16        fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id, wwn_t port_name);
+
+u16        fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id, wwn_t node_name);
+
+u16        fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id, u32 cos);
+
+u16        fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id, u8 port_type);
+
+u16        fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+			       u32 port_id);
+
+u16        fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
+			      u32 s_id, u16 ox_id, wwn_t port_name);
+
+u16        fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
+				  u32 s_id, u16 ox_id);
+
+u16        fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
+				     u16 cmd_code);
+u16	fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn);
+u16	fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn);
+
+void		fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
+
+void		fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+					 u16 ox_id);
+
+enum fc_parse_status	fc_els_rsp_parse(struct fchs_s *fchs, int len);
+
+enum fc_parse_status	fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
+					wwn_t port_name);
+
+enum fc_parse_status	fc_prli_parse(struct fc_prli_s *prli);
+
+enum fc_parse_status	fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
+					wwn_t port_name);
+
+u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
+		u32 s_id, u16 ox_id, u16 rx_id);
+
+int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
+
+u16 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
+		u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+
+u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
+		u32 d_id, u32 s_id, u16 ox_id, int num_pages);
+
+u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
+
+u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+		u16 ox_id, wwn_t port_name, wwn_t node_name,
+		u16 pdu_size);
+
+u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
+
+u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+		u16 ox_id, int num_pages);
+
+u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len);
+
+u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+		u16 ox_id, int num_pages, enum fc_tprlo_type tprlo_type,
+		u32 tpr_id);
+
+u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
+
+u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
+		u16 ox_id, u32 reason_code, u32 reason_expl);
+
+u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
+		u32 port_id);
+
+u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
+
+u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
+		u16 ox_id);
+#endif
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 8c703d8..33c8dd5 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,18 +15,291 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <log/bfa_log_hal.h>
+#include "bfa_modules.h"
+#include "bfa_cb_ioim.h"
 
 BFA_TRC_FILE(HAL, FCPIM);
 BFA_MODULE(fcpim);
 
+
+#define bfa_fcpim_add_iostats(__l, __r, __stats)	\
+	(__l->__stats += __r->__stats)
+
+
+/**
+ *  BFA ITNIM Related definitions
+ */
+static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
+
+#define BFA_ITNIM_FROM_TAG(_fcpim, _tag)                                \
+	(((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1))))
+
+#define bfa_fcpim_additn(__itnim)					\
+	list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
+#define bfa_fcpim_delitn(__itnim)	do {				\
+	bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));      \
+	bfa_itnim_update_del_itn_stats(__itnim);      \
+	list_del(&(__itnim)->qe);      \
+	bfa_assert(list_empty(&(__itnim)->io_q));      \
+	bfa_assert(list_empty(&(__itnim)->io_cleanup_q));      \
+	bfa_assert(list_empty(&(__itnim)->pending_q));      \
+} while (0)
+
+#define bfa_itnim_online_cb(__itnim) do {				\
+	if ((__itnim)->bfa->fcs)					\
+		bfa_cb_itnim_online((__itnim)->ditn);      \
+	else {								\
+		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
+		__bfa_cb_itnim_online, (__itnim));      \
+	}								\
+} while (0)
+
+#define bfa_itnim_offline_cb(__itnim) do {				\
+	if ((__itnim)->bfa->fcs)					\
+		bfa_cb_itnim_offline((__itnim)->ditn);      \
+	else {								\
+		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
+		__bfa_cb_itnim_offline, (__itnim));      \
+	}								\
+} while (0)
+
+#define bfa_itnim_sler_cb(__itnim) do {					\
+	if ((__itnim)->bfa->fcs)					\
+		bfa_cb_itnim_sler((__itnim)->ditn);      \
+	else {								\
+		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
+		__bfa_cb_itnim_sler, (__itnim));      \
+	}								\
+} while (0)
+
+/**
+ *  bfa_itnim_sm BFA itnim state machine
+ */
+
+
+enum bfa_itnim_event {
+	BFA_ITNIM_SM_CREATE = 1,	/*  itnim is created */
+	BFA_ITNIM_SM_ONLINE = 2,	/*  itnim is online */
+	BFA_ITNIM_SM_OFFLINE = 3,	/*  itnim is offline */
+	BFA_ITNIM_SM_FWRSP = 4,		/*  firmware response */
+	BFA_ITNIM_SM_DELETE = 5,	/*  deleting an existing itnim */
+	BFA_ITNIM_SM_CLEANUP = 6,	/*  IO cleanup completion */
+	BFA_ITNIM_SM_SLER = 7,		/*  second level error recovery */
+	BFA_ITNIM_SM_HWFAIL = 8,	/*  IOC h/w failure event */
+	BFA_ITNIM_SM_QRESUME = 9,	/*  queue space available */
+};
+
+/**
+ *  BFA IOIM related definitions
+ */
+#define bfa_ioim_move_to_comp_q(__ioim) do {				\
+	list_del(&(__ioim)->qe);					\
+	list_add_tail(&(__ioim)->qe, &(__ioim)->fcpim->ioim_comp_q);	\
+} while (0)
+
+
+#define bfa_ioim_cb_profile_comp(__fcpim, __ioim) do {			\
+	if ((__fcpim)->profile_comp)					\
+		(__fcpim)->profile_comp(__ioim);			\
+} while (0)
+
+#define bfa_ioim_cb_profile_start(__fcpim, __ioim) do {			\
+	if ((__fcpim)->profile_start)					\
+		(__fcpim)->profile_start(__ioim);			\
+} while (0)
+/**
+ *  hal_ioim_sm
+ */
+
+/**
+ * IO state machine events
+ */
+enum bfa_ioim_event {
+	BFA_IOIM_SM_START	= 1,	/*  io start request from host */
+	BFA_IOIM_SM_COMP_GOOD	= 2,	/*  io good comp, resource free */
+	BFA_IOIM_SM_COMP	= 3,	/*  io comp, resource is free */
+	BFA_IOIM_SM_COMP_UTAG	= 4,	/*  io comp, resource is free */
+	BFA_IOIM_SM_DONE	= 5,	/*  io comp, resource not free */
+	BFA_IOIM_SM_FREE	= 6,	/*  io resource is freed */
+	BFA_IOIM_SM_ABORT	= 7,	/*  abort request from scsi stack */
+	BFA_IOIM_SM_ABORT_COMP	= 8,	/*  abort from f/w */
+	BFA_IOIM_SM_ABORT_DONE	= 9,	/*  abort completion from f/w */
+	BFA_IOIM_SM_QRESUME	= 10,	/*  CQ space available to queue IO */
+	BFA_IOIM_SM_SGALLOCED	= 11,	/*  SG page allocation successful */
+	BFA_IOIM_SM_SQRETRY	= 12,	/*  sequence recovery retry */
+	BFA_IOIM_SM_HCB		= 13,	/*  bfa callback complete */
+	BFA_IOIM_SM_CLEANUP	= 14,	/*  IO cleanup from itnim */
+	BFA_IOIM_SM_TMSTART	= 15,	/*  IO cleanup from tskim */
+	BFA_IOIM_SM_TMDONE	= 16,	/*  IO cleanup from tskim */
+	BFA_IOIM_SM_HWFAIL	= 17,	/*  IOC h/w failure event */
+	BFA_IOIM_SM_IOTOV	= 18,	/*  ITN offline TOV */
+};
+
+
+/**
+ *  BFA TSKIM related definitions
+ */
+
+/**
+ * task management completion handling
+ */
+#define bfa_tskim_qcomp(__tskim, __cbfn) do {				\
+	bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, __cbfn, (__tskim));\
+	bfa_tskim_notify_comp(__tskim);      \
+} while (0)
+
+#define bfa_tskim_notify_comp(__tskim) do {				\
+	if ((__tskim)->notify)						\
+		bfa_itnim_tskdone((__tskim)->itnim);      \
+} while (0)
+
+
+enum bfa_tskim_event {
+	BFA_TSKIM_SM_START	= 1,	/*  TM command start		*/
+	BFA_TSKIM_SM_DONE	= 2,	/*  TM completion		*/
+	BFA_TSKIM_SM_QRESUME	= 3,	/*  resume after qfull		*/
+	BFA_TSKIM_SM_HWFAIL	= 5,	/*  IOC h/w failure event	*/
+	BFA_TSKIM_SM_HCB	= 6,	/*  BFA callback completion	*/
+	BFA_TSKIM_SM_IOS_DONE	= 7,	/*  IO and sub TM completions	*/
+	BFA_TSKIM_SM_CLEANUP	= 8,	/*  TM cleanup on ITN offline	*/
+	BFA_TSKIM_SM_CLEANUP_DONE = 9,	/*  TM abort completion	*/
+};
+
+/**
+ * forward declaration for BFA ITNIM functions
+ */
+static void     bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
+static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
+static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_cleanp_comp(void *itnim_cbarg);
+static void     bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
+static void     __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
+static void     bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov(void *itnim_arg);
+static void     bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
+static void     bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
+
+/**
+ * forward declaration of ITNIM state machine
+ */
+static void     bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+static void     bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
+					enum bfa_itnim_event event);
+
+/**
+ * forward declaration for BFA IOIM functions
+ */
+static bfa_boolean_t	bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
+static bfa_boolean_t	bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
+static void		bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
+static bfa_boolean_t	bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
+static void		bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
+static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
+static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
+static bfa_boolean_t    bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
+
+
+/**
+ * forward declaration of BFA IO state machine
+ */
+static void     bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_active(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void     bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+static void	bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim,
+					enum bfa_ioim_event event);
+
+/**
+ * forward declaration for BFA TSKIM functions
+ */
+static void     __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
+static void     __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
+static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
+					lun_t lun);
+static void     bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
+static void     bfa_tskim_cleanp_comp(void *tskim_cbarg);
+static void     bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
+static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
+static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
+static void     bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
+
+
+/**
+ * forward declaration of BFA TSKIM state machine
+ */
+static void     bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_active(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
+					enum bfa_tskim_event event);
+
 /**
  *  hal_fcpim_mod BFA FCP Initiator Mode module
  */
 
 /**
- * 		Compute and return memory needed by FCP(im) module.
+ *	Compute and return memory needed by FCP(im) module.
  */
 static void
 bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
@@ -58,7 +331,7 @@
 
 static void
 bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		     struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 
@@ -67,12 +340,14 @@
 	bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs);
 	bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs);
 
-	fcpim->bfa            = bfa;
-	fcpim->num_itnims     = cfg->fwcfg.num_rports;
+	fcpim->bfa		= bfa;
+	fcpim->num_itnims	= cfg->fwcfg.num_rports;
 	fcpim->num_ioim_reqs  = cfg->fwcfg.num_ioim_reqs;
 	fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs;
-	fcpim->path_tov       = cfg->drvcfg.path_tov;
-	fcpim->delay_comp	  = cfg->drvcfg.delay_comp;
+	fcpim->path_tov		= cfg->drvcfg.path_tov;
+	fcpim->delay_comp	= cfg->drvcfg.delay_comp;
+	fcpim->profile_comp = NULL;
+	fcpim->profile_start = NULL;
 
 	bfa_itnim_attach(fcpim, meminfo);
 	bfa_tskim_attach(fcpim, meminfo);
@@ -103,7 +378,7 @@
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 	struct bfa_itnim_s *itnim;
-	struct list_head        *qe, *qen;
+	struct list_head *qe, *qen;
 
 	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
 		itnim = (struct bfa_itnim_s *) qe;
@@ -112,6 +387,56 @@
 }
 
 void
+bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
+		struct bfa_itnim_iostats_s *rstats)
+{
+	bfa_fcpim_add_iostats(lstats, rstats, total_ios);
+	bfa_fcpim_add_iostats(lstats, rstats, qresumes);
+	bfa_fcpim_add_iostats(lstats, rstats, no_iotags);
+	bfa_fcpim_add_iostats(lstats, rstats, io_aborts);
+	bfa_fcpim_add_iostats(lstats, rstats, no_tskims);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_ok);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_underrun);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_overrun);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_aborted);
+	bfa_fcpim_add_iostats(lstats, rstats, iocomp_timedout);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_nexus_abort);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_proto_err);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_dif_err);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_sqer_needed);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_res_free);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_hostabrts);
+	bfa_fcpim_add_iostats(lstats, rstats, iocom_utags);
+	bfa_fcpim_add_iostats(lstats, rstats, io_cleanups);
+	bfa_fcpim_add_iostats(lstats, rstats, io_tmaborts);
+	bfa_fcpim_add_iostats(lstats, rstats, onlines);
+	bfa_fcpim_add_iostats(lstats, rstats, offlines);
+	bfa_fcpim_add_iostats(lstats, rstats, creates);
+	bfa_fcpim_add_iostats(lstats, rstats, deletes);
+	bfa_fcpim_add_iostats(lstats, rstats, create_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, delete_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, sler_events);
+	bfa_fcpim_add_iostats(lstats, rstats, fw_create);
+	bfa_fcpim_add_iostats(lstats, rstats, fw_delete);
+	bfa_fcpim_add_iostats(lstats, rstats, ioc_disabled);
+	bfa_fcpim_add_iostats(lstats, rstats, cleanup_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_cmnds);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_fw_rsps);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_success);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_failures);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_io_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_qresumes);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_iocdowns);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanups);
+	bfa_fcpim_add_iostats(lstats, rstats, tm_cleanup_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, io_comps);
+	bfa_fcpim_add_iostats(lstats, rstats, input_reqs);
+	bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
+	bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
+	bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
+}
+
+void
 bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
@@ -130,21 +455,113 @@
 }
 
 bfa_status_t
-bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_fcpim_stats_s *modstats)
+bfa_fcpim_port_iostats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *stats,
+	u8 lp_tag)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
+
+	/* accumulate IO stats from itnim */
+	bfa_os_memset(stats, 0, sizeof(struct bfa_itnim_iostats_s));
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		if (itnim->rport->rport_info.lp_tag != lp_tag)
+			continue;
+		bfa_fcpim_add_stats(stats, &(itnim->stats));
+	}
+	return BFA_STATUS_OK;
+}
+bfa_status_t
+bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_itnim_iostats_s *modstats)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
+
+	/* accumulate IO stats from itnim */
+	bfa_os_memset(modstats, 0, sizeof(struct bfa_itnim_iostats_s));
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		bfa_fcpim_add_stats(modstats, &(itnim->stats));
+	}
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
+	 struct bfa_fcpim_del_itn_stats_s *modstats)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 
-	*modstats = fcpim->stats;
+	*modstats = fcpim->del_itn_stats;
 
 	return BFA_STATUS_OK;
 }
 
+
+bfa_status_t
+bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time)
+{
+	struct bfa_itnim_s *itnim;
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+
+	/* accumulate IO stats from itnim */
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		bfa_itnim_clear_stats(itnim);
+	}
+	fcpim->io_profile = BFA_TRUE;
+	fcpim->io_profile_start_time = time;
+	fcpim->profile_comp = bfa_ioim_profile_comp;
+	fcpim->profile_start = bfa_ioim_profile_start;
+
+	return BFA_STATUS_OK;
+}
+bfa_status_t
+bfa_fcpim_profile_off(struct bfa_s *bfa)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	fcpim->io_profile = BFA_FALSE;
+	fcpim->io_profile_start_time = 0;
+	fcpim->profile_comp = NULL;
+	fcpim->profile_start = NULL;
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
+
+	/* clear IO stats from all active itnims */
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		if (itnim->rport->rport_info.lp_tag != lp_tag)
+			continue;
+		bfa_itnim_clear_stats(itnim);
+	}
+	return BFA_STATUS_OK;
+
+}
+
 bfa_status_t
 bfa_fcpim_clr_modstats(struct bfa_s *bfa)
 {
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct list_head *qe, *qen;
+	struct bfa_itnim_s *itnim;
 
-	memset(&fcpim->stats, 0, sizeof(struct bfa_fcpim_stats_s));
+	/* clear IO stats from all active itnims */
+	list_for_each_safe(qe, qen, &fcpim->itnim_q) {
+		itnim = (struct bfa_itnim_s *) qe;
+		bfa_itnim_clear_stats(itnim);
+	}
+	bfa_os_memset(&fcpim->del_itn_stats, 0,
+		sizeof(struct bfa_fcpim_del_itn_stats_s));
 
 	return BFA_STATUS_OK;
 }
@@ -176,14 +593,6 @@
 	 * IO redirection is turned off when QoS is enabled and vice versa
 	 */
 	ioredirect = bfa_fcport_is_qos_enabled(bfa) ? BFA_FALSE : BFA_TRUE;
-
-	/*
-	 * Notify the bfad module of a possible state change in
-	 * IO redirection capability, due to a QoS state change. bfad will
-	 * check on the support for io redirection and update the
-	 * fcpim's ioredirect state accordingly.
-	 */
-	bfa_cb_ioredirect_state_change((void *)(bfa->bfad), ioredirect);
 }
 
 void
@@ -192,3 +601,3012 @@
 	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
 	fcpim->ioredirect = state;
 }
+
+
+
+/**
+ *  BFA ITNIM module state machine functions
+ */
+
+/**
+ *	Beginning/unallocated state - no events expected.
+ */
+static void
+bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_CREATE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_created);
+		itnim->is_online = BFA_FALSE;
+		bfa_fcpim_additn(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Beginning state, only online event expected.
+ */
+static void
+bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_ONLINE:
+		if (bfa_itnim_send_fwcreate(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Waiting for itnim create response from firmware.
+ */
+static void
+bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_FWRSP:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_online);
+		itnim->is_online = BFA_TRUE;
+		bfa_itnim_iotov_online(itnim);
+		bfa_itnim_online_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
+		break;
+
+	case BFA_ITNIM_SM_OFFLINE:
+		if (bfa_itnim_send_fwdelete(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+static void
+bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
+			enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_QRESUME:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+		bfa_itnim_send_fwcreate(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	case BFA_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Waiting for itnim create response from firmware, a delete is pending.
+ */
+static void
+bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
+				enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_FWRSP:
+		if (bfa_itnim_send_fwdelete(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Online state - normal parking state.
+ */
+static void
+bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
+		itnim->is_online = BFA_FALSE;
+		bfa_itnim_iotov_start(itnim);
+		bfa_itnim_cleanup(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+		itnim->is_online = BFA_FALSE;
+		bfa_itnim_cleanup(itnim);
+		break;
+
+	case BFA_ITNIM_SM_SLER:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
+		itnim->is_online = BFA_FALSE;
+		bfa_itnim_iotov_start(itnim);
+		bfa_itnim_sler_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		itnim->is_online = BFA_FALSE;
+		bfa_itnim_iotov_start(itnim);
+		bfa_itnim_iocdisable_cleanup(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Second level error recovery need.
+ */
+static void
+bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_OFFLINE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
+		bfa_itnim_cleanup(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+		bfa_itnim_cleanup(itnim);
+		bfa_itnim_iotov_delete(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_itnim_iocdisable_cleanup(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Going offline. Waiting for active IO cleanup.
+ */
+static void
+bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
+				 enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_CLEANUP:
+		if (bfa_itnim_send_fwdelete(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
+		bfa_itnim_iotov_delete(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_itnim_iocdisable_cleanup(itnim);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_SLER:
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Deleting itnim. Waiting for active IO cleanup.
+ */
+static void
+bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
+				enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_CLEANUP:
+		if (bfa_itnim_send_fwdelete(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_itnim_iocdisable_cleanup(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
+ */
+static void
+bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_FWRSP:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+static void
+bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
+			enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_QRESUME:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
+		bfa_itnim_send_fwdelete(itnim);
+		break;
+
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Offline state.
+ */
+static void
+bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_itnim_iotov_delete(itnim);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	case BFA_ITNIM_SM_ONLINE:
+		if (bfa_itnim_send_fwcreate(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	IOC h/w failed state.
+ */
+static void
+bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
+				enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_DELETE:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_itnim_iotov_delete(itnim);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	case BFA_ITNIM_SM_OFFLINE:
+		bfa_itnim_offline_cb(itnim);
+		break;
+
+	case BFA_ITNIM_SM_ONLINE:
+		if (bfa_itnim_send_fwcreate(itnim))
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
+		else
+			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Itnim is deleted, waiting for firmware response to delete.
+ */
+static void
+bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_FWRSP:
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+static void
+bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
+		enum bfa_itnim_event event)
+{
+	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
+	bfa_trc(itnim->bfa, event);
+
+	switch (event) {
+	case BFA_ITNIM_SM_QRESUME:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
+		bfa_itnim_send_fwdelete(itnim);
+		break;
+
+	case BFA_ITNIM_SM_HWFAIL:
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+		bfa_reqq_wcancel(&itnim->reqq_wait);
+		bfa_fcpim_delitn(itnim);
+		break;
+
+	default:
+		bfa_sm_fault(itnim->bfa, event);
+	}
+}
+
+/**
+ *	Initiate cleanup of all IOs on an IOC failure.
+ */
+static void
+bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
+{
+	struct bfa_tskim_s *tskim;
+	struct bfa_ioim_s *ioim;
+	struct list_head	*qe, *qen;
+
+	list_for_each_safe(qe, qen, &itnim->tsk_q) {
+		tskim = (struct bfa_tskim_s *) qe;
+		bfa_tskim_iocdisable(tskim);
+	}
+
+	list_for_each_safe(qe, qen, &itnim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_ioim_iocdisable(ioim);
+	}
+
+	/**
+	 * For IO request in pending queue, we pretend an early timeout.
+	 */
+	list_for_each_safe(qe, qen, &itnim->pending_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_ioim_tov(ioim);
+	}
+
+	list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_ioim_iocdisable(ioim);
+	}
+}
+
+/**
+ *	IO cleanup completion
+ */
+static void
+bfa_itnim_cleanp_comp(void *itnim_cbarg)
+{
+	struct bfa_itnim_s *itnim = itnim_cbarg;
+
+	bfa_stats(itnim, cleanup_comps);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
+}
+
+/**
+ *	Initiate cleanup of all IOs.
+ */
+static void
+bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
+{
+	struct bfa_ioim_s  *ioim;
+	struct bfa_tskim_s *tskim;
+	struct list_head	*qe, *qen;
+
+	bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
+
+	list_for_each_safe(qe, qen, &itnim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+
+		/**
+		 * Move IO to a cleanup queue from active queue so that a later
+		 * TM will not pickup this IO.
+		 */
+		list_del(&ioim->qe);
+		list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
+
+		bfa_wc_up(&itnim->wc);
+		bfa_ioim_cleanup(ioim);
+	}
+
+	list_for_each_safe(qe, qen, &itnim->tsk_q) {
+		tskim = (struct bfa_tskim_s *) qe;
+		bfa_wc_up(&itnim->wc);
+		bfa_tskim_cleanup(tskim);
+	}
+
+	bfa_wc_wait(&itnim->wc);
+}
+
+static void
+__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_itnim_s *itnim = cbarg;
+
+	if (complete)
+		bfa_cb_itnim_online(itnim->ditn);
+}
+
+static void
+__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_itnim_s *itnim = cbarg;
+
+	if (complete)
+		bfa_cb_itnim_offline(itnim->ditn);
+}
+
+static void
+__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_itnim_s *itnim = cbarg;
+
+	if (complete)
+		bfa_cb_itnim_sler(itnim->ditn);
+}
+
+/**
+ * Call to resume any I/O requests waiting for room in request queue.
+ */
+static void
+bfa_itnim_qresume(void *cbarg)
+{
+	struct bfa_itnim_s *itnim = cbarg;
+
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
+}
+
+
+
+
+/**
+ *  bfa_itnim_public
+ */
+
+void
+bfa_itnim_iodone(struct bfa_itnim_s *itnim)
+{
+	bfa_wc_down(&itnim->wc);
+}
+
+void
+bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
+{
+	bfa_wc_down(&itnim->wc);
+}
+
+void
+bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		u32 *dm_len)
+{
+	/**
+	 * ITN memory
+	 */
+	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
+}
+
+void
+bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+	struct bfa_s	*bfa = fcpim->bfa;
+	struct bfa_itnim_s *itnim;
+	int	i, j;
+
+	INIT_LIST_HEAD(&fcpim->itnim_q);
+
+	itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
+	fcpim->itnim_arr = itnim;
+
+	for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
+		bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s));
+		itnim->bfa = bfa;
+		itnim->fcpim = fcpim;
+		itnim->reqq = BFA_REQQ_QOS_LO;
+		itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
+		itnim->iotov_active = BFA_FALSE;
+		bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
+
+		INIT_LIST_HEAD(&itnim->io_q);
+		INIT_LIST_HEAD(&itnim->io_cleanup_q);
+		INIT_LIST_HEAD(&itnim->pending_q);
+		INIT_LIST_HEAD(&itnim->tsk_q);
+		INIT_LIST_HEAD(&itnim->delay_comp_q);
+		for (j = 0; j < BFA_IOBUCKET_MAX; j++)
+			itnim->ioprofile.io_latency.min[j] = ~0;
+		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
+	}
+
+	bfa_meminfo_kva(minfo) = (u8 *) itnim;
+}
+
+void
+bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
+{
+	bfa_stats(itnim, ioc_disabled);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
+}
+
+static bfa_boolean_t
+bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
+{
+	struct bfi_itnim_create_req_s *m;
+
+	itnim->msg_no++;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
+	if (!m) {
+		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
+			bfa_lpuid(itnim->bfa));
+	m->fw_handle = itnim->rport->fw_handle;
+	m->class = FC_CLASS_3;
+	m->seq_rec = itnim->seq_rec;
+	m->msg_no = itnim->msg_no;
+	bfa_stats(itnim, fw_create);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(itnim->bfa, itnim->reqq);
+	return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
+{
+	struct bfi_itnim_delete_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
+	if (!m) {
+		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
+			bfa_lpuid(itnim->bfa));
+	m->fw_handle = itnim->rport->fw_handle;
+	bfa_stats(itnim, fw_delete);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(itnim->bfa, itnim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ * Cleanup all pending failed inflight requests.
+ */
+static void
+bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
+{
+	struct bfa_ioim_s *ioim;
+	struct list_head *qe, *qen;
+
+	list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
+		ioim = (struct bfa_ioim_s *)qe;
+		bfa_ioim_delayed_comp(ioim, iotov);
+	}
+}
+
+/**
+ * Start all pending IO requests.
+ */
+static void
+bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
+{
+	struct bfa_ioim_s *ioim;
+
+	bfa_itnim_iotov_stop(itnim);
+
+	/**
+	 * Abort all inflight IO requests in the queue
+	 */
+	bfa_itnim_delayed_comp(itnim, BFA_FALSE);
+
+	/**
+	 * Start all pending IO requests.
+	 */
+	while (!list_empty(&itnim->pending_q)) {
+		bfa_q_deq(&itnim->pending_q, &ioim);
+		list_add_tail(&ioim->qe, &itnim->io_q);
+		bfa_ioim_start(ioim);
+	}
+}
+
+/**
+ * Fail all pending IO requests
+ */
+static void
+bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
+{
+	struct bfa_ioim_s *ioim;
+
+	/**
+	 * Fail all inflight IO requests in the queue
+	 */
+	bfa_itnim_delayed_comp(itnim, BFA_TRUE);
+
+	/**
+	 * Fail any pending IO requests.
+	 */
+	while (!list_empty(&itnim->pending_q)) {
+		bfa_q_deq(&itnim->pending_q, &ioim);
+		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+		bfa_ioim_tov(ioim);
+	}
+}
+
+/**
+ * IO TOV timer callback. Fail any pending IO requests.
+ */
+static void
+bfa_itnim_iotov(void *itnim_arg)
+{
+	struct bfa_itnim_s *itnim = itnim_arg;
+
+	itnim->iotov_active = BFA_FALSE;
+
+	bfa_cb_itnim_tov_begin(itnim->ditn);
+	bfa_itnim_iotov_cleanup(itnim);
+	bfa_cb_itnim_tov(itnim->ditn);
+}
+
+/**
+ * Start IO TOV timer for failing back pending IO requests in offline state.
+ */
+static void
+bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
+{
+	if (itnim->fcpim->path_tov > 0) {
+
+		itnim->iotov_active = BFA_TRUE;
+		bfa_assert(bfa_itnim_hold_io(itnim));
+		bfa_timer_start(itnim->bfa, &itnim->timer,
+			bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
+	}
+}
+
+/**
+ * Stop IO TOV timer.
+ */
+static void
+bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
+{
+	if (itnim->iotov_active) {
+		itnim->iotov_active = BFA_FALSE;
+		bfa_timer_stop(&itnim->timer);
+	}
+}
+
+/**
+ * Stop IO TOV timer.
+ */
+static void
+bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
+{
+	bfa_boolean_t pathtov_active = BFA_FALSE;
+
+	if (itnim->iotov_active)
+		pathtov_active = BFA_TRUE;
+
+	bfa_itnim_iotov_stop(itnim);
+	if (pathtov_active)
+		bfa_cb_itnim_tov_begin(itnim->ditn);
+	bfa_itnim_iotov_cleanup(itnim);
+	if (pathtov_active)
+		bfa_cb_itnim_tov(itnim->ditn);
+}
+
+static void
+bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
+	fcpim->del_itn_stats.del_itn_iocomp_aborted +=
+		itnim->stats.iocomp_aborted;
+	fcpim->del_itn_stats.del_itn_iocomp_timedout +=
+		itnim->stats.iocomp_timedout;
+	fcpim->del_itn_stats.del_itn_iocom_sqer_needed +=
+		itnim->stats.iocom_sqer_needed;
+	fcpim->del_itn_stats.del_itn_iocom_res_free +=
+		itnim->stats.iocom_res_free;
+	fcpim->del_itn_stats.del_itn_iocom_hostabrts +=
+		itnim->stats.iocom_hostabrts;
+	fcpim->del_itn_stats.del_itn_total_ios += itnim->stats.total_ios;
+	fcpim->del_itn_stats.del_io_iocdowns += itnim->stats.io_iocdowns;
+	fcpim->del_itn_stats.del_tm_iocdowns += itnim->stats.tm_iocdowns;
+}
+
+
+
+/**
+ *  bfa_itnim_public
+ */
+
+/**
+ *	Itnim interrupt processing.
+ */
+void
+bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	union bfi_itnim_i2h_msg_u msg;
+	struct bfa_itnim_s *itnim;
+
+	bfa_trc(bfa, m->mhdr.msg_id);
+
+	msg.msg = m;
+
+	switch (m->mhdr.msg_id) {
+	case BFI_ITNIM_I2H_CREATE_RSP:
+		itnim = BFA_ITNIM_FROM_TAG(fcpim,
+						msg.create_rsp->bfa_handle);
+		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+		bfa_stats(itnim, create_comps);
+		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
+		break;
+
+	case BFI_ITNIM_I2H_DELETE_RSP:
+		itnim = BFA_ITNIM_FROM_TAG(fcpim,
+						msg.delete_rsp->bfa_handle);
+		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+		bfa_stats(itnim, delete_comps);
+		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
+		break;
+
+	case BFI_ITNIM_I2H_SLER_EVENT:
+		itnim = BFA_ITNIM_FROM_TAG(fcpim,
+						msg.sler_event->bfa_handle);
+		bfa_stats(itnim, sler_events);
+		bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
+		break;
+
+	default:
+		bfa_trc(bfa, m->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+
+
+/**
+ *  bfa_itnim_api
+ */
+
+struct bfa_itnim_s *
+bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_itnim_s *itnim;
+
+	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
+	bfa_assert(itnim->rport == rport);
+
+	itnim->ditn = ditn;
+
+	bfa_stats(itnim, creates);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
+
+	return itnim;
+}
+
+void
+bfa_itnim_delete(struct bfa_itnim_s *itnim)
+{
+	bfa_stats(itnim, deletes);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
+}
+
+void
+bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
+{
+	itnim->seq_rec = seq_rec;
+	bfa_stats(itnim, onlines);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
+}
+
+void
+bfa_itnim_offline(struct bfa_itnim_s *itnim)
+{
+	bfa_stats(itnim, offlines);
+	bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
+}
+
+/**
+ * Return true if itnim is considered offline for holding off IO request.
+ * IO is not held if itnim is being deleted.
+ */
+bfa_boolean_t
+bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
+{
+	return itnim->fcpim->path_tov && itnim->iotov_active &&
+		(bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
+		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable));
+}
+
+bfa_status_t
+bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
+		struct bfa_itnim_ioprofile_s *ioprofile)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(itnim->bfa);
+	if (!fcpim->io_profile)
+		return BFA_STATUS_IOPROFILE_OFF;
+
+	itnim->ioprofile.index = BFA_IOBUCKET_MAX;
+	itnim->ioprofile.io_profile_start_time =
+		bfa_io_profile_start_time(itnim->bfa);
+	itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;
+	itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;
+	*ioprofile = itnim->ioprofile;
+
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
+	struct bfa_itnim_iostats_s *stats)
+{
+	*stats = itnim->stats;
+}
+
+void
+bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
+{
+	int j;
+	bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
+	bfa_os_memset(&itnim->ioprofile, 0, sizeof(itnim->ioprofile));
+	for (j = 0; j < BFA_IOBUCKET_MAX; j++)
+		itnim->ioprofile.io_latency.min[j] = ~0;
+}
+
+/**
+ *  BFA IO module state machine functions
+ */
+
+/**
+ *	IO is not started (unallocated).
+ */
+static void
+bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_trc_fp(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_START:
+		if (!bfa_itnim_is_online(ioim->itnim)) {
+			if (!bfa_itnim_hold_io(ioim->itnim)) {
+				bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+				list_del(&ioim->qe);
+				list_add_tail(&ioim->qe,
+					&ioim->fcpim->ioim_comp_q);
+				bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+						__bfa_cb_ioim_pathtov, ioim);
+			} else {
+				list_del(&ioim->qe);
+				list_add_tail(&ioim->qe,
+					&ioim->itnim->pending_q);
+			}
+			break;
+		}
+
+		if (ioim->nsges > BFI_SGE_INLINE) {
+			if (!bfa_ioim_sge_setup(ioim)) {
+				bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
+				return;
+			}
+		}
+
+		if (!bfa_ioim_send_ioreq(ioim)) {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+			break;
+		}
+
+		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+		break;
+
+	case BFA_IOIM_SM_IOTOV:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+				__bfa_cb_ioim_pathtov, ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		/**
+		 * IO in pending queue can get abort requests. Complete abort
+		 * requests immediately.
+		 */
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+				__bfa_cb_ioim_abort, ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	IO is waiting for SG pages.
+ */
+static void
+bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_SGALLOCED:
+		if (!bfa_ioim_send_ioreq(ioim)) {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+			break;
+		}
+		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	IO is active.
+ */
+static void
+bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_trc_fp(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_COMP_GOOD:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+			      __bfa_cb_ioim_good_comp, ioim);
+		break;
+
+	case BFA_IOIM_SM_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		ioim->iosp->abort_explicit = BFA_TRUE;
+		ioim->io_cbfn = __bfa_cb_ioim_abort;
+
+		if (bfa_ioim_send_abort(ioim))
+			bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
+		else {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);
+			bfa_stats(ioim->itnim, qwait);
+			bfa_reqq_wait(ioim->bfa, ioim->reqq,
+					  &ioim->iosp->reqq_wait);
+		}
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		ioim->iosp->abort_explicit = BFA_FALSE;
+		ioim->io_cbfn = __bfa_cb_ioim_failed;
+
+		if (bfa_ioim_send_abort(ioim))
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+		else {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+			bfa_stats(ioim->itnim, qwait);
+			bfa_reqq_wait(ioim->bfa, ioim->reqq,
+					  &ioim->iosp->reqq_wait);
+		}
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_SQRETRY:
+		if (bfa_ioim_get_iotag(ioim) != BFA_TRUE) {
+			/* max retry completed free IO */
+			bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+			bfa_ioim_move_to_comp_q(ioim);
+			bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+					__bfa_cb_ioim_failed, ioim);
+			break;
+		}
+		/* waiting for IO tag resource free */
+		bfa_sm_set_state(ioim, bfa_ioim_sm_cmnd_retry);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+*	IO is retried with new tag.
+*/
+static void
+bfa_ioim_sm_cmnd_retry(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_trc_fp(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_FREE:
+		/* abts and rrq done. Now retry the IO with new tag */
+		if (!bfa_ioim_send_ioreq(ioim)) {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
+			break;
+		}
+		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+	break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		ioim->iosp->abort_explicit = BFA_FALSE;
+		ioim->io_cbfn = __bfa_cb_ioim_failed;
+
+		if (bfa_ioim_send_abort(ioim))
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+		else {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+			bfa_stats(ioim->itnim, qwait);
+			bfa_reqq_wait(ioim->bfa, ioim->reqq,
+					  &ioim->iosp->reqq_wait);
+		}
+	break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
+			 __bfa_cb_ioim_failed, ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		/** in this state IO abort is done.
+		 * Waiting for IO tag resource free.
+		 */
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	IO is being aborted, waiting for completion from firmware.
+ */
+static void
+bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_COMP_GOOD:
+	case BFA_IOIM_SM_COMP:
+	case BFA_IOIM_SM_DONE:
+	case BFA_IOIM_SM_FREE:
+		break;
+
+	case BFA_IOIM_SM_ABORT_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_COMP_UTAG:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+		ioim->iosp->abort_explicit = BFA_FALSE;
+
+		if (bfa_ioim_send_abort(ioim))
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+		else {
+			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+			bfa_stats(ioim->itnim, qwait);
+			bfa_reqq_wait(ioim->bfa, ioim->reqq,
+					  &ioim->iosp->reqq_wait);
+		}
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ * IO is being cleaned up (implicit abort), waiting for completion from
+ * firmware.
+ */
+static void
+bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_COMP_GOOD:
+	case BFA_IOIM_SM_COMP:
+	case BFA_IOIM_SM_DONE:
+	case BFA_IOIM_SM_FREE:
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		/**
+		 * IO is already being aborted implicitly
+		 */
+		ioim->io_cbfn = __bfa_cb_ioim_abort;
+		break;
+
+	case BFA_IOIM_SM_ABORT_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_COMP_UTAG:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		/**
+		 * IO can be in cleanup state already due to TM command.
+		 * 2nd cleanup request comes from ITN offline event.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	IO is waiting for room in request CQ
+ */
+static void
+bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_QRESUME:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
+		bfa_ioim_send_ioreq(ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	Active IO is being aborted, waiting for room in request CQ.
+ */
+static void
+bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_QRESUME:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
+		bfa_ioim_send_abort(ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
+		ioim->iosp->abort_explicit = BFA_FALSE;
+		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
+		break;
+
+	case BFA_IOIM_SM_COMP_GOOD:
+	case BFA_IOIM_SM_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
+			      ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ *	Active IO is being cleaned up, waiting for room in request CQ.
+ */
+static void
+bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_QRESUME:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
+		bfa_ioim_send_abort(ioim);
+		break;
+
+	case BFA_IOIM_SM_ABORT:
+		/**
+		 * IO is alraedy being cleaned up implicitly
+		 */
+		ioim->io_cbfn = __bfa_cb_ioim_abort;
+		break;
+
+	case BFA_IOIM_SM_COMP_GOOD:
+	case BFA_IOIM_SM_COMP:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_DONE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
+		bfa_ioim_move_to_comp_q(ioim);
+		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
+			      ioim);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ * IO bfa callback is pending.
+ */
+static void
+bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_trc_fp(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_HCB:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+		bfa_ioim_free(ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ * IO bfa callback is pending. IO resource cannot be freed.
+ */
+static void
+bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_HCB:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);
+		list_del(&ioim->qe);
+		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);
+		break;
+
+	case BFA_IOIM_SM_FREE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+/**
+ * IO is completed, waiting resource free from firmware.
+ */
+static void
+bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, event);
+
+	switch (event) {
+	case BFA_IOIM_SM_FREE:
+		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+		bfa_ioim_free(ioim);
+		break;
+
+	case BFA_IOIM_SM_CLEANUP:
+		bfa_ioim_notify_cleanup(ioim);
+		break;
+
+	case BFA_IOIM_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_sm_fault(ioim->bfa, event);
+	}
+}
+
+
+
+/**
+ *  hal_ioim_private
+ */
+
+static void
+__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);
+}
+
+static void
+__bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s	*ioim = cbarg;
+	struct bfi_ioim_rsp_s *m;
+	u8	*snsinfo = NULL;
+	u8	sns_len = 0;
+	s32	residue = 0;
+
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
+	if (m->io_status == BFI_IOIM_STS_OK) {
+		/**
+		 * setup sense information, if present
+		 */
+		if ((m->scsi_status == SCSI_STATUS_CHECK_CONDITION) &&
+					m->sns_len) {
+			sns_len = m->sns_len;
+			snsinfo = ioim->iosp->snsinfo;
+		}
+
+		/**
+		 * setup residue value correctly for normal completions
+		 */
+		if (m->resid_flags == FCP_RESID_UNDER) {
+			residue = bfa_os_ntohl(m->residue);
+			bfa_stats(ioim->itnim, iocomp_underrun);
+		}
+		if (m->resid_flags == FCP_RESID_OVER) {
+			residue = bfa_os_ntohl(m->residue);
+			residue = -residue;
+			bfa_stats(ioim->itnim, iocomp_overrun);
+		}
+	}
+
+	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,
+			  m->scsi_status, sns_len, snsinfo, residue);
+}
+
+static void
+__bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
+			  0, 0, NULL, 0);
+}
+
+static void
+__bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	bfa_stats(ioim->itnim, path_tov_expired);
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
+			  0, 0, NULL, 0);
+}
+
+static void
+__bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
+		return;
+	}
+
+	bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
+}
+
+static void
+bfa_ioim_sgpg_alloced(void *cbarg)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
+	list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
+	bfa_ioim_sgpg_setup(ioim);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
+}
+
+/**
+ * Send I/O request to firmware.
+ */
+static	bfa_boolean_t
+bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
+{
+	struct bfa_itnim_s *itnim = ioim->itnim;
+	struct bfi_ioim_req_s *m;
+	static struct fcp_cmnd_s cmnd_z0 = { 0 };
+	struct bfi_sge_s      *sge;
+	u32	pgdlen = 0;
+	u32	fcp_dl;
+	u64 addr;
+	struct scatterlist *sg;
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
+	if (!m) {
+		bfa_stats(ioim->itnim, qwait);
+		bfa_reqq_wait(ioim->bfa, ioim->reqq,
+				  &ioim->iosp->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	/**
+	 * build i/o request message next
+	 */
+	m->io_tag = bfa_os_htons(ioim->iotag);
+	m->rport_hdl = ioim->itnim->rport->fw_handle;
+	m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
+
+	/**
+	 * build inline IO SG element here
+	 */
+	sge = &m->sges[0];
+	if (ioim->nsges) {
+		sg = (struct scatterlist *)scsi_sglist(cmnd);
+		addr = bfa_os_sgaddr(sg_dma_address(sg));
+		sge->sga = *(union bfi_addr_u *) &addr;
+		pgdlen = sg_dma_len(sg);
+		sge->sg_len = pgdlen;
+		sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
+					BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
+		bfa_sge_to_be(sge);
+		sge++;
+	}
+
+	if (ioim->nsges > BFI_SGE_INLINE) {
+		sge->sga = ioim->sgpg->sgpg_pa;
+	} else {
+		sge->sga.a32.addr_lo = 0;
+		sge->sga.a32.addr_hi = 0;
+	}
+	sge->sg_len = pgdlen;
+	sge->flags = BFI_SGE_PGDLEN;
+	bfa_sge_to_be(sge);
+
+	/**
+	 * set up I/O command parameters
+	 */
+	bfa_os_assign(m->cmnd, cmnd_z0);
+	m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
+	m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
+	bfa_os_assign(m->cmnd.cdb,
+			*(scsi_cdb_t *)bfa_cb_ioim_get_cdb(ioim->dio));
+	fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
+	m->cmnd.fcp_dl = bfa_os_htonl(fcp_dl);
+
+	/**
+	 * set up I/O message header
+	 */
+	switch (m->cmnd.iodir) {
+	case FCP_IODIR_READ:
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
+		bfa_stats(itnim, input_reqs);
+		ioim->itnim->stats.rd_throughput += fcp_dl;
+		break;
+	case FCP_IODIR_WRITE:
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
+		bfa_stats(itnim, output_reqs);
+		ioim->itnim->stats.wr_throughput += fcp_dl;
+		break;
+	case FCP_IODIR_RW:
+		bfa_stats(itnim, input_reqs);
+		bfa_stats(itnim, output_reqs);
+	default:
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+	}
+	if (itnim->seq_rec ||
+	    (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
+		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
+
+#ifdef IOIM_ADVANCED
+	m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
+	m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
+	m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
+
+	/**
+	 * Handle large CDB (>16 bytes).
+	 */
+	m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
+					FCP_CMND_CDB_LEN) / sizeof(u32);
+	if (m->cmnd.addl_cdb_len) {
+		bfa_os_memcpy(&m->cmnd.cdb + 1, (scsi_cdb_t *)
+				bfa_cb_ioim_get_cdb(ioim->dio) + 1,
+				m->cmnd.addl_cdb_len * sizeof(u32));
+		fcp_cmnd_fcpdl(&m->cmnd) =
+				bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
+	}
+#endif
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(ioim->bfa, ioim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ * Setup any additional SG pages needed.Inline SG element is setup
+ * at queuing time.
+ */
+static bfa_boolean_t
+bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
+{
+	u16	nsgpgs;
+
+	bfa_assert(ioim->nsges > BFI_SGE_INLINE);
+
+	/**
+	 * allocate SG pages needed
+	 */
+	nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
+	if (!nsgpgs)
+		return BFA_TRUE;
+
+	if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)
+	    != BFA_STATUS_OK) {
+		bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);
+		return BFA_FALSE;
+	}
+
+	ioim->nsgpgs = nsgpgs;
+	bfa_ioim_sgpg_setup(ioim);
+
+	return BFA_TRUE;
+}
+
+static void
+bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
+{
+	int		sgeid, nsges, i;
+	struct bfi_sge_s      *sge;
+	struct bfa_sgpg_s *sgpg;
+	u32	pgcumsz;
+	u64        addr;
+	struct scatterlist *sg;
+	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
+
+	sgeid = BFI_SGE_INLINE;
+	ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
+
+	sg = scsi_sglist(cmnd);
+	sg = sg_next(sg);
+
+	do {
+		sge = sgpg->sgpg->sges;
+		nsges = ioim->nsges - sgeid;
+		if (nsges > BFI_SGPG_DATA_SGES)
+			nsges = BFI_SGPG_DATA_SGES;
+
+		pgcumsz = 0;
+		for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
+			addr = bfa_os_sgaddr(sg_dma_address(sg));
+			sge->sga = *(union bfi_addr_u *) &addr;
+			sge->sg_len = sg_dma_len(sg);
+			pgcumsz += sge->sg_len;
+
+			/**
+			 * set flags
+			 */
+			if (i < (nsges - 1))
+				sge->flags = BFI_SGE_DATA;
+			else if (sgeid < (ioim->nsges - 1))
+				sge->flags = BFI_SGE_DATA_CPL;
+			else
+				sge->flags = BFI_SGE_DATA_LAST;
+
+			bfa_sge_to_le(sge);
+		}
+
+		sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
+
+		/**
+		 * set the link element of each page
+		 */
+		if (sgeid == ioim->nsges) {
+			sge->flags = BFI_SGE_PGDLEN;
+			sge->sga.a32.addr_lo = 0;
+			sge->sga.a32.addr_hi = 0;
+		} else {
+			sge->flags = BFI_SGE_LINK;
+			sge->sga = sgpg->sgpg_pa;
+		}
+		sge->sg_len = pgcumsz;
+
+		bfa_sge_to_le(sge);
+	} while (sgeid < ioim->nsges);
+}
+
+/**
+ * Send I/O abort request to firmware.
+ */
+static	bfa_boolean_t
+bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
+{
+	struct bfi_ioim_abort_req_s *m;
+	enum bfi_ioim_h2i	msgop;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
+	if (!m)
+		return BFA_FALSE;
+
+	/**
+	 * build i/o request message next
+	 */
+	if (ioim->iosp->abort_explicit)
+		msgop = BFI_IOIM_H2I_IOABORT_REQ;
+	else
+		msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
+
+	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
+	m->io_tag    = bfa_os_htons(ioim->iotag);
+	m->abort_tag = ++ioim->abort_tag;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(ioim->bfa, ioim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ * Call to resume any I/O requests waiting for room in request queue.
+ */
+static void
+bfa_ioim_qresume(void *cbarg)
+{
+	struct bfa_ioim_s *ioim = cbarg;
+
+	bfa_stats(ioim->itnim, qresumes);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);
+}
+
+
+static void
+bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
+{
+	/**
+	 * Move IO from itnim queue to fcpim global queue since itnim will be
+	 * freed.
+	 */
+	list_del(&ioim->qe);
+	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+
+	if (!ioim->iosp->tskim) {
+		if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {
+			bfa_cb_dequeue(&ioim->hcb_qe);
+			list_del(&ioim->qe);
+			list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);
+		}
+		bfa_itnim_iodone(ioim->itnim);
+	} else
+		bfa_tskim_iodone(ioim->iosp->tskim);
+}
+
+static bfa_boolean_t
+bfa_ioim_is_abortable(struct bfa_ioim_s *ioim)
+{
+	if ((bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit) &&
+	    (!bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)))	||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort))		||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_abort_qfull))	||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb))		||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_hcb_free))	||
+	    (bfa_sm_cmp_state(ioim, bfa_ioim_sm_resfree)))
+		return BFA_FALSE;
+
+	return BFA_TRUE;
+}
+
+/**
+ *	or after the link comes back.
+ */
+void
+bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
+{
+	/**
+	 * If path tov timer expired, failback with PATHTOV status - these
+	 * IO requests are not normally retried by IO stack.
+	 *
+	 * Otherwise device cameback online and fail it with normal failed
+	 * status so that IO stack retries these failed IO requests.
+	 */
+	if (iotov)
+		ioim->io_cbfn = __bfa_cb_ioim_pathtov;
+	else {
+		ioim->io_cbfn = __bfa_cb_ioim_failed;
+		bfa_stats(ioim->itnim, iocom_nexus_abort);
+	}
+	bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
+
+	/**
+	 * Move IO to fcpim global queue since itnim will be
+	 * freed.
+	 */
+	list_del(&ioim->qe);
+	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+}
+
+
+
+/**
+ *  hal_ioim_friend
+ */
+
+/**
+ * Memory allocation and initialization.
+ */
+void
+bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+	struct bfa_ioim_s		*ioim;
+	struct bfa_ioim_sp_s	*iosp;
+	u16		i;
+	u8			*snsinfo;
+	u32		snsbufsz;
+
+	/**
+	 * claim memory first
+	 */
+	ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
+	fcpim->ioim_arr = ioim;
+	bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
+
+	iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
+	fcpim->ioim_sp_arr = iosp;
+	bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
+
+	/**
+	 * Claim DMA memory for per IO sense data.
+	 */
+	snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
+	fcpim->snsbase.pa  = bfa_meminfo_dma_phys(minfo);
+	bfa_meminfo_dma_phys(minfo) += snsbufsz;
+
+	fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
+	bfa_meminfo_dma_virt(minfo) += snsbufsz;
+	snsinfo = fcpim->snsbase.kva;
+	bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
+
+	/**
+	 * Initialize ioim free queues
+	 */
+	INIT_LIST_HEAD(&fcpim->ioim_free_q);
+	INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
+	INIT_LIST_HEAD(&fcpim->ioim_comp_q);
+
+	for (i = 0; i < fcpim->num_ioim_reqs;
+	     i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
+		/*
+		 * initialize IOIM
+		 */
+		bfa_os_memset(ioim, 0, sizeof(struct bfa_ioim_s));
+		ioim->iotag   = i;
+		ioim->bfa     = fcpim->bfa;
+		ioim->fcpim   = fcpim;
+		ioim->iosp    = iosp;
+		iosp->snsinfo = snsinfo;
+		INIT_LIST_HEAD(&ioim->sgpg_q);
+		bfa_reqq_winit(&ioim->iosp->reqq_wait,
+				   bfa_ioim_qresume, ioim);
+		bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
+				   bfa_ioim_sgpg_alloced, ioim);
+		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
+
+		list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
+	}
+}
+
+/**
+ * Driver detach time call.
+ */
+void
+bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
+{
+}
+
+void
+bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
+	struct bfa_ioim_s *ioim;
+	u16	iotag;
+	enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;
+
+	iotag = bfa_os_ntohs(rsp->io_tag);
+
+	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
+	bfa_assert(ioim->iotag == iotag);
+
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_trc(ioim->bfa, rsp->io_status);
+	bfa_trc(ioim->bfa, rsp->reuse_io_tag);
+
+	if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))
+		bfa_os_assign(ioim->iosp->comp_rspmsg, *m);
+
+	switch (rsp->io_status) {
+	case BFI_IOIM_STS_OK:
+		bfa_stats(ioim->itnim, iocomp_ok);
+		if (rsp->reuse_io_tag == 0)
+			evt = BFA_IOIM_SM_DONE;
+		else
+			evt = BFA_IOIM_SM_COMP;
+		break;
+
+	case BFI_IOIM_STS_TIMEDOUT:
+		bfa_stats(ioim->itnim, iocomp_timedout);
+	case BFI_IOIM_STS_ABORTED:
+		rsp->io_status = BFI_IOIM_STS_ABORTED;
+		bfa_stats(ioim->itnim, iocomp_aborted);
+		if (rsp->reuse_io_tag == 0)
+			evt = BFA_IOIM_SM_DONE;
+		else
+			evt = BFA_IOIM_SM_COMP;
+		break;
+
+	case BFI_IOIM_STS_PROTO_ERR:
+		bfa_stats(ioim->itnim, iocom_proto_err);
+		bfa_assert(rsp->reuse_io_tag);
+		evt = BFA_IOIM_SM_COMP;
+		break;
+
+	case BFI_IOIM_STS_SQER_NEEDED:
+		bfa_stats(ioim->itnim, iocom_sqer_needed);
+		bfa_assert(rsp->reuse_io_tag == 0);
+		evt = BFA_IOIM_SM_SQRETRY;
+		break;
+
+	case BFI_IOIM_STS_RES_FREE:
+		bfa_stats(ioim->itnim, iocom_res_free);
+		evt = BFA_IOIM_SM_FREE;
+		break;
+
+	case BFI_IOIM_STS_HOST_ABORTED:
+		bfa_stats(ioim->itnim, iocom_hostabrts);
+		if (rsp->abort_tag != ioim->abort_tag) {
+			bfa_trc(ioim->bfa, rsp->abort_tag);
+			bfa_trc(ioim->bfa, ioim->abort_tag);
+			return;
+		}
+
+		if (rsp->reuse_io_tag)
+			evt = BFA_IOIM_SM_ABORT_COMP;
+		else
+			evt = BFA_IOIM_SM_ABORT_DONE;
+		break;
+
+	case BFI_IOIM_STS_UTAG:
+		bfa_stats(ioim->itnim, iocom_utags);
+		evt = BFA_IOIM_SM_COMP_UTAG;
+		break;
+
+	default:
+		bfa_assert(0);
+	}
+
+	bfa_sm_send_event(ioim, evt);
+}
+
+void
+bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
+	struct bfa_ioim_s *ioim;
+	u16	iotag;
+
+	iotag = bfa_os_ntohs(rsp->io_tag);
+
+	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
+	bfa_assert(ioim->iotag == iotag);
+
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_ioim_cb_profile_comp(fcpim, ioim);
+
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
+}
+
+void
+bfa_ioim_profile_start(struct bfa_ioim_s *ioim)
+{
+	ioim->start_time = bfa_os_get_clock();
+}
+
+void
+bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)
+{
+	u32 fcp_dl = bfa_cb_ioim_get_size(ioim->dio);
+	u32 index = bfa_ioim_get_index(fcp_dl);
+	u64 end_time = bfa_os_get_clock();
+	struct bfa_itnim_latency_s *io_lat =
+			&(ioim->itnim->ioprofile.io_latency);
+	u32 val = (u32)(end_time - ioim->start_time);
+
+	bfa_itnim_ioprofile_update(ioim->itnim, index);
+
+	io_lat->count[index]++;
+	io_lat->min[index] = (io_lat->min[index] < val) ?
+		io_lat->min[index] : val;
+	io_lat->max[index] = (io_lat->max[index] > val) ?
+		io_lat->max[index] : val;
+	io_lat->avg[index] += val;
+}
+/**
+ * Called by itnim to clean up IO while going offline.
+ */
+void
+bfa_ioim_cleanup(struct bfa_ioim_s *ioim)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_stats(ioim->itnim, io_cleanups);
+
+	ioim->iosp->tskim = NULL;
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
+}
+
+void
+bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_stats(ioim->itnim, io_tmaborts);
+
+	ioim->iosp->tskim = tskim;
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
+}
+
+/**
+ * IOC failure handling.
+ */
+void
+bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_stats(ioim->itnim, io_iocdowns);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);
+}
+
+/**
+ * IO offline TOV popped. Fail the pending IO.
+ */
+void
+bfa_ioim_tov(struct bfa_ioim_s *ioim)
+{
+	bfa_trc(ioim->bfa, ioim->iotag);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);
+}
+
+
+
+/**
+ *  hal_ioim_api
+ */
+
+/**
+ * Allocate IOIM resource for initiator mode I/O request.
+ */
+struct bfa_ioim_s *
+bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
+		struct bfa_itnim_s *itnim, u16 nsges)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_ioim_s *ioim;
+
+	/**
+	 * alocate IOIM resource
+	 */
+	bfa_q_deq(&fcpim->ioim_free_q, &ioim);
+	if (!ioim) {
+		bfa_stats(itnim, no_iotags);
+		return NULL;
+	}
+
+	ioim->dio = dio;
+	ioim->itnim = itnim;
+	ioim->nsges = nsges;
+	ioim->nsgpgs = 0;
+
+	bfa_stats(itnim, total_ios);
+	fcpim->ios_active++;
+
+	list_add_tail(&ioim->qe, &itnim->io_q);
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+
+	return ioim;
+}
+
+void
+bfa_ioim_free(struct bfa_ioim_s *ioim)
+{
+	struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
+
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+	bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
+
+	bfa_assert_fp(list_empty(&ioim->sgpg_q) ||
+			(ioim->nsges > BFI_SGE_INLINE));
+
+	if (ioim->nsgpgs > 0)
+		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
+
+	bfa_stats(ioim->itnim, io_comps);
+	fcpim->ios_active--;
+
+	list_del(&ioim->qe);
+	list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
+}
+
+void
+bfa_ioim_start(struct bfa_ioim_s *ioim)
+{
+	bfa_trc_fp(ioim->bfa, ioim->iotag);
+
+	bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
+
+	/**
+	 * Obtain the queue over which this request has to be issued
+	 */
+	ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?
+			bfa_cb_ioim_get_reqq(ioim->dio) :
+			bfa_itnim_get_reqq(ioim);
+
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
+}
+
+/**
+ * Driver I/O abort request.
+ */
+bfa_status_t
+bfa_ioim_abort(struct bfa_ioim_s *ioim)
+{
+
+	bfa_trc(ioim->bfa, ioim->iotag);
+
+	if (!bfa_ioim_is_abortable(ioim))
+		return BFA_STATUS_FAILED;
+
+	bfa_stats(ioim->itnim, io_aborts);
+	bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);
+
+	return BFA_STATUS_OK;
+}
+
+
+/**
+ *  BFA TSKIM state machine functions
+ */
+
+/**
+ *	Task management command beginning state.
+ */
+static void
+bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_START:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
+		bfa_tskim_gather_ios(tskim);
+
+		/**
+		 * If device is offline, do not send TM on wire. Just cleanup
+		 * any pending IO requests and complete TM request.
+		 */
+		if (!bfa_itnim_is_online(tskim->itnim)) {
+			bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+			tskim->tsk_status = BFI_TSKIM_STS_OK;
+			bfa_tskim_cleanup_ios(tskim);
+			return;
+		}
+
+		if (!bfa_tskim_send(tskim)) {
+			bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);
+			bfa_stats(tskim->itnim, tm_qwait);
+			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
+					  &tskim->reqq_wait);
+		}
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ * brief
+ *	TM command is active, awaiting completion from firmware to
+ *	cleanup IO requests in TM scope.
+ */
+static void
+bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_DONE:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+		bfa_tskim_cleanup_ios(tskim);
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
+		if (!bfa_tskim_send_abort(tskim)) {
+			bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);
+			bfa_stats(tskim->itnim, tm_qwait);
+			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
+				&tskim->reqq_wait);
+		}
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ *	An active TM is being cleaned up since ITN is offline. Awaiting cleanup
+ *	completion event from firmware.
+ */
+static void
+bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_DONE:
+		/**
+		 * Ignore and wait for ABORT completion from firmware.
+		 */
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP_DONE:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+		bfa_tskim_cleanup_ios(tskim);
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+static void
+bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_IOS_DONE:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP:
+		/**
+		 * Ignore, TM command completed on wire.
+		 * Notify TM conmpletion on IO cleanup completion.
+		 */
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ *	Task management command is waiting for room in request CQ
+ */
+static void
+bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_QRESUME:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
+		bfa_tskim_send(tskim);
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP:
+		/**
+		 * No need to send TM on wire since ITN is offline.
+		 */
+		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
+		bfa_reqq_wcancel(&tskim->reqq_wait);
+		bfa_tskim_cleanup_ios(tskim);
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_reqq_wcancel(&tskim->reqq_wait);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ *	Task management command is active, awaiting for room in request CQ
+ *	to send clean up request.
+ */
+static void
+bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
+		enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_DONE:
+		bfa_reqq_wcancel(&tskim->reqq_wait);
+		/**
+		 *
+		 * Fall through !!!
+		 */
+
+	case BFA_TSKIM_SM_QRESUME:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
+		bfa_tskim_send_abort(tskim);
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
+		bfa_reqq_wcancel(&tskim->reqq_wait);
+		bfa_tskim_iocdisable_ios(tskim);
+		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+/**
+ *	BFA callback is pending
+ */
+static void
+bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
+{
+	bfa_trc(tskim->bfa, event);
+
+	switch (event) {
+	case BFA_TSKIM_SM_HCB:
+		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
+		bfa_tskim_free(tskim);
+		break;
+
+	case BFA_TSKIM_SM_CLEANUP:
+		bfa_tskim_notify_comp(tskim);
+		break;
+
+	case BFA_TSKIM_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_sm_fault(tskim->bfa, event);
+	}
+}
+
+
+
+/**
+ *  hal_tskim_private
+ */
+
+static void
+__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_tskim_s *tskim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
+		return;
+	}
+
+	bfa_stats(tskim->itnim, tm_success);
+	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);
+}
+
+static void
+__bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_tskim_s *tskim = cbarg;
+
+	if (!complete) {
+		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
+		return;
+	}
+
+	bfa_stats(tskim->itnim, tm_failures);
+	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,
+				BFI_TSKIM_STS_FAILED);
+}
+
+static	bfa_boolean_t
+bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
+{
+	switch (tskim->tm_cmnd) {
+	case FCP_TM_TARGET_RESET:
+		return BFA_TRUE;
+
+	case FCP_TM_ABORT_TASK_SET:
+	case FCP_TM_CLEAR_TASK_SET:
+	case FCP_TM_LUN_RESET:
+	case FCP_TM_CLEAR_ACA:
+		return (tskim->lun == lun);
+
+	default:
+		bfa_assert(0);
+	}
+
+	return BFA_FALSE;
+}
+
+/**
+ *	Gather affected IO requests and task management commands.
+ */
+static void
+bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
+{
+	struct bfa_itnim_s *itnim = tskim->itnim;
+	struct bfa_ioim_s *ioim;
+	struct list_head	*qe, *qen;
+
+	INIT_LIST_HEAD(&tskim->io_q);
+
+	/**
+	 * Gather any active IO requests first.
+	 */
+	list_for_each_safe(qe, qen, &itnim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		if (bfa_tskim_match_scope
+			(tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+			list_del(&ioim->qe);
+			list_add_tail(&ioim->qe, &tskim->io_q);
+		}
+	}
+
+	/**
+	 * Failback any pending IO requests immediately.
+	 */
+	list_for_each_safe(qe, qen, &itnim->pending_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		if (bfa_tskim_match_scope
+			(tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
+			list_del(&ioim->qe);
+			list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
+			bfa_ioim_tov(ioim);
+		}
+	}
+}
+
+/**
+ *	IO cleanup completion
+ */
+static void
+bfa_tskim_cleanp_comp(void *tskim_cbarg)
+{
+	struct bfa_tskim_s *tskim = tskim_cbarg;
+
+	bfa_stats(tskim->itnim, tm_io_comps);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);
+}
+
+/**
+ *	Gather affected IO requests and task management commands.
+ */
+static void
+bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
+{
+	struct bfa_ioim_s *ioim;
+	struct list_head	*qe, *qen;
+
+	bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);
+
+	list_for_each_safe(qe, qen, &tskim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_wc_up(&tskim->wc);
+		bfa_ioim_cleanup_tm(ioim, tskim);
+	}
+
+	bfa_wc_wait(&tskim->wc);
+}
+
+/**
+ *	Send task management request to firmware.
+ */
+static bfa_boolean_t
+bfa_tskim_send(struct bfa_tskim_s *tskim)
+{
+	struct bfa_itnim_s *itnim = tskim->itnim;
+	struct bfi_tskim_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
+	if (!m)
+		return BFA_FALSE;
+
+	/**
+	 * build i/o request message next
+	 */
+	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
+			bfa_lpuid(tskim->bfa));
+
+	m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
+	m->itn_fhdl = tskim->itnim->rport->fw_handle;
+	m->t_secs = tskim->tsecs;
+	m->lun = tskim->lun;
+	m->tm_flags = tskim->tm_cmnd;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(tskim->bfa, itnim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ *	Send abort request to cleanup an active TM to firmware.
+ */
+static bfa_boolean_t
+bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
+{
+	struct bfa_itnim_s	*itnim = tskim->itnim;
+	struct bfi_tskim_abortreq_s	*m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
+	if (!m)
+		return BFA_FALSE;
+
+	/**
+	 * build i/o request message next
+	 */
+	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
+			bfa_lpuid(tskim->bfa));
+
+	m->tsk_tag  = bfa_os_htons(tskim->tsk_tag);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(tskim->bfa, itnim->reqq);
+	return BFA_TRUE;
+}
+
+/**
+ *	Call to resume task management cmnd waiting for room in request queue.
+ */
+static void
+bfa_tskim_qresume(void *cbarg)
+{
+	struct bfa_tskim_s *tskim = cbarg;
+
+	bfa_stats(tskim->itnim, tm_qresumes);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);
+}
+
+/**
+ * Cleanup IOs associated with a task mangement command on IOC failures.
+ */
+static void
+bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
+{
+	struct bfa_ioim_s *ioim;
+	struct list_head	*qe, *qen;
+
+	list_for_each_safe(qe, qen, &tskim->io_q) {
+		ioim = (struct bfa_ioim_s *) qe;
+		bfa_ioim_iocdisable(ioim);
+	}
+}
+
+
+
+/**
+ *  hal_tskim_friend
+ */
+
+/**
+ * Notification on completions from related ioim.
+ */
+void
+bfa_tskim_iodone(struct bfa_tskim_s *tskim)
+{
+	bfa_wc_down(&tskim->wc);
+}
+
+/**
+ * Handle IOC h/w failure notification from itnim.
+ */
+void
+bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)
+{
+	tskim->notify = BFA_FALSE;
+	bfa_stats(tskim->itnim, tm_iocdowns);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);
+}
+
+/**
+ * Cleanup TM command and associated IOs as part of ITNIM offline.
+ */
+void
+bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
+{
+	tskim->notify = BFA_TRUE;
+	bfa_stats(tskim->itnim, tm_cleanups);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);
+}
+
+/**
+ *	Memory allocation and initialization.
+ */
+void
+bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
+{
+	struct bfa_tskim_s *tskim;
+	u16	i;
+
+	INIT_LIST_HEAD(&fcpim->tskim_free_q);
+
+	tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
+	fcpim->tskim_arr = tskim;
+
+	for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
+		/*
+		 * initialize TSKIM
+		 */
+		bfa_os_memset(tskim, 0, sizeof(struct bfa_tskim_s));
+		tskim->tsk_tag = i;
+		tskim->bfa	= fcpim->bfa;
+		tskim->fcpim	= fcpim;
+		tskim->notify  = BFA_FALSE;
+		bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,
+					tskim);
+		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
+
+		list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
+	}
+
+	bfa_meminfo_kva(minfo) = (u8 *) tskim;
+}
+
+void
+bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
+{
+	/**
+	* @todo
+	*/
+}
+
+void
+bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
+	struct bfa_tskim_s *tskim;
+	u16	tsk_tag = bfa_os_ntohs(rsp->tsk_tag);
+
+	tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
+	bfa_assert(tskim->tsk_tag == tsk_tag);
+
+	tskim->tsk_status = rsp->tsk_status;
+
+	/**
+	 * Firmware sends BFI_TSKIM_STS_ABORTED status for abort
+	 * requests. All other statuses are for normal completions.
+	 */
+	if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
+		bfa_stats(tskim->itnim, tm_cleanup_comps);
+		bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
+	} else {
+		bfa_stats(tskim->itnim, tm_fw_rsps);
+		bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
+	}
+}
+
+
+
+/**
+ *  hal_tskim_api
+ */
+
+
+struct bfa_tskim_s *
+bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
+{
+	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
+	struct bfa_tskim_s *tskim;
+
+	bfa_q_deq(&fcpim->tskim_free_q, &tskim);
+
+	if (tskim)
+		tskim->dtsk = dtsk;
+
+	return tskim;
+}
+
+void
+bfa_tskim_free(struct bfa_tskim_s *tskim)
+{
+	bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
+	list_del(&tskim->qe);
+	list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
+}
+
+/**
+ *	Start a task management command.
+ *
+ * @param[in]	tskim	BFA task management command instance
+ * @param[in]	itnim	i-t nexus for the task management command
+ * @param[in]	lun	lun, if applicable
+ * @param[in]	tm_cmnd	Task management command code.
+ * @param[in]	t_secs	Timeout in seconds
+ *
+ * @return None.
+ */
+void
+bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
+			enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
+{
+	tskim->itnim	= itnim;
+	tskim->lun	= lun;
+	tskim->tm_cmnd = tm_cmnd;
+	tskim->tsecs	= tsecs;
+	tskim->notify  = BFA_FALSE;
+	bfa_stats(itnim, tm_cmnds);
+
+	list_add_tail(&tskim->qe, &itnim->tsk_q);
+	bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
+}
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
new file mode 100644
index 0000000..3bf3431
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFA_FCPIM_H__
+#define __BFA_FCPIM_H__
+
+#include "bfa.h"
+#include "bfa_svc.h"
+#include "bfi_ms.h"
+#include "bfa_defs_svc.h"
+#include "bfa_cs.h"
+
+
+#define BFA_ITNIM_MIN   32
+#define BFA_ITNIM_MAX   1024
+
+#define BFA_IOIM_MIN	8
+#define BFA_IOIM_MAX	2000
+
+#define BFA_TSKIM_MIN   4
+#define BFA_TSKIM_MAX   512
+#define BFA_FCPIM_PATHTOV_DEF	(30 * 1000)	/* in millisecs */
+#define BFA_FCPIM_PATHTOV_MAX	(90 * 1000)	/* in millisecs */
+
+
+#define bfa_itnim_ioprofile_update(__itnim, __index)			\
+	(__itnim->ioprofile.iocomps[__index]++)
+
+#define BFA_IOIM_RETRY_TAG_OFFSET 11
+#define BFA_IOIM_RETRY_TAG_MASK 0x07ff /* 2K IOs */
+#define BFA_IOIM_RETRY_MAX 7
+
+/* Buckets are are 512 bytes to 2MB */
+static inline u32
+bfa_ioim_get_index(u32 n) {
+	int pos = 0;
+	if (n >= (1UL)<<22)
+		return BFA_IOBUCKET_MAX - 1;
+	n >>= 8;
+	if (n >= (1UL)<<16)
+		n >>= 16; pos += 16;
+	if (n >= 1 << 8)
+		n >>= 8; pos += 8;
+	if (n >= 1 << 4)
+		n >>= 4; pos += 4;
+	if (n >= 1 << 2)
+		n >>= 2; pos += 2;
+	if (n >= 1 << 1)
+		pos += 1;
+
+	return (n == 0) ? (0) : pos;
+}
+
+/*
+ * forward declarations
+ */
+struct bfa_ioim_s;
+struct bfa_tskim_s;
+struct bfad_ioim_s;
+struct bfad_tskim_s;
+
+typedef void    (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
+
+struct bfa_fcpim_mod_s {
+	struct bfa_s		*bfa;
+	struct bfa_itnim_s	*itnim_arr;
+	struct bfa_ioim_s	*ioim_arr;
+	struct bfa_ioim_sp_s	*ioim_sp_arr;
+	struct bfa_tskim_s	*tskim_arr;
+	struct bfa_dma_s	snsbase;
+	int			num_itnims;
+	int			num_ioim_reqs;
+	int			num_tskim_reqs;
+	u32			path_tov;
+	u16			q_depth;
+	u8			reqq;		/*  Request queue to be used */
+	u8			rsvd;
+	struct list_head	itnim_q;	/*  queue of active itnim */
+	struct list_head	ioim_free_q;	/*  free IO resources	*/
+	struct list_head	ioim_resfree_q; /*  IOs waiting for f/w */
+	struct list_head	ioim_comp_q;	/*  IO global comp Q	*/
+	struct list_head	tskim_free_q;
+	u32		ios_active;	/*  current active IOs	*/
+	u32		delay_comp;
+	struct bfa_fcpim_del_itn_stats_s del_itn_stats;
+	bfa_boolean_t		ioredirect;
+	bfa_boolean_t		io_profile;
+	u32		io_profile_start_time;
+	bfa_fcpim_profile_t     profile_comp;
+	bfa_fcpim_profile_t     profile_start;
+};
+
+/**
+ * BFA IO (initiator mode)
+ */
+struct bfa_ioim_s {
+	struct list_head	qe;		/*  queue elememt	*/
+	bfa_sm_t		sm;		/*  BFA ioim state machine */
+	struct bfa_s		*bfa;		/*  BFA module	*/
+	struct bfa_fcpim_mod_s	*fcpim;		/*  parent fcpim module */
+	struct bfa_itnim_s	*itnim;		/*  i-t-n nexus for this IO  */
+	struct bfad_ioim_s	*dio;		/*  driver IO handle	*/
+	u16		iotag;		/*  FWI IO tag	*/
+	u16		abort_tag;	/*  unqiue abort request tag */
+	u16		nsges;		/*  number of SG elements */
+	u16		nsgpgs;		/*  number of SG pages	*/
+	struct bfa_sgpg_s	*sgpg;		/*  first SG page	*/
+	struct list_head	sgpg_q;		/*  allocated SG pages	*/
+	struct bfa_cb_qe_s	hcb_qe;		/*  bfa callback qelem	*/
+	bfa_cb_cbfn_t		io_cbfn;	/*  IO completion handler */
+	struct bfa_ioim_sp_s *iosp;		/*  slow-path IO handling */
+	u8		reqq;		/*  Request queue for I/O */
+	u64 start_time;			/*  IO's Profile start val */
+};
+
+
+struct bfa_ioim_sp_s {
+	struct bfi_msg_s	comp_rspmsg;	/*  IO comp f/w response */
+	u8			*snsinfo;	/*  sense info for this IO   */
+	struct bfa_sgpg_wqe_s sgpg_wqe;	/*  waitq elem for sgpg	*/
+	struct bfa_reqq_wait_s reqq_wait;	/*  to wait for room in reqq */
+	bfa_boolean_t		abort_explicit;	/*  aborted by OS	*/
+	struct bfa_tskim_s	*tskim;		/*  Relevant TM cmd	*/
+};
+
+/**
+ * BFA Task management command (initiator mode)
+ */
+struct bfa_tskim_s {
+	struct list_head	qe;
+	bfa_sm_t		sm;
+	struct bfa_s	*bfa;	/*  BFA module  */
+	struct bfa_fcpim_mod_s  *fcpim;	/*  parent fcpim module	*/
+	struct bfa_itnim_s	*itnim;	/*  i-t-n nexus for this IO  */
+	struct bfad_tskim_s	*dtsk;   /*  driver task mgmt cmnd	*/
+	bfa_boolean_t	notify;	/*  notify itnim on TM comp  */
+	lun_t	lun;	/*  lun if applicable	*/
+	enum fcp_tm_cmnd	tm_cmnd;	/*  task management command  */
+	u16	tsk_tag;	/*  FWI IO tag	*/
+	u8	tsecs;	/*  timeout in seconds	*/
+	struct bfa_reqq_wait_s  reqq_wait;   /*  to wait for room in reqq */
+	struct list_head	io_q;	/*  queue of affected IOs	*/
+	struct bfa_wc_s	wc;	/*  waiting counter	*/
+	struct bfa_cb_qe_s	hcb_qe;	/*  bfa callback qelem	*/
+	enum bfi_tskim_status   tsk_status;  /*  TM status	*/
+};
+
+
+/**
+ * BFA i-t-n (initiator mode)
+ */
+struct bfa_itnim_s {
+	struct list_head	qe;		/*  queue element	*/
+	bfa_sm_t	  sm;		/*  i-t-n im BFA state machine  */
+	struct bfa_s	*bfa;		/*  bfa instance	*/
+	struct bfa_rport_s *rport;	/*  bfa rport	*/
+	void	*ditn;		/*  driver i-t-n structure	*/
+	struct bfi_mhdr_s	mhdr;	/*  pre-built mhdr	*/
+	u8	msg_no;		/*  itnim/rport firmware handle */
+	u8	reqq;		/*  CQ for requests	*/
+	struct bfa_cb_qe_s	hcb_qe;	/*  bfa callback qelem	*/
+	struct list_head pending_q;	/*  queue of pending IO requests */
+	struct list_head io_q;		/*  queue of active IO requests */
+	struct list_head io_cleanup_q;	/*  IO being cleaned up	*/
+	struct list_head tsk_q;		/*  queue of active TM commands */
+	struct list_head  delay_comp_q; /*  queue of failed inflight cmds */
+	bfa_boolean_t   seq_rec;	/*  SQER supported	*/
+	bfa_boolean_t   is_online;	/*  itnim is ONLINE for IO	*/
+	bfa_boolean_t   iotov_active;	/*  IO TOV timer is active	 */
+	struct bfa_wc_s	wc;	/*  waiting counter	*/
+	struct bfa_timer_s timer;	/*  pending IO TOV		 */
+	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
+	struct bfa_fcpim_mod_s *fcpim;	/*  fcpim module	*/
+	struct bfa_itnim_iostats_s	stats;
+	struct bfa_itnim_ioprofile_s  ioprofile;
+};
+
+
+#define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
+#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
+#define BFA_IOIM_FROM_TAG(_fcpim, _iotag)	\
+	(&fcpim->ioim_arr[(_iotag & BFA_IOIM_RETRY_TAG_MASK)])
+#define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag)	\
+	(&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
+
+#define bfa_io_profile_start_time(_bfa)	\
+	(_bfa->modules.fcpim_mod.io_profile_start_time)
+#define bfa_fcpim_get_io_profile(_bfa)	\
+	(_bfa->modules.fcpim_mod.io_profile)
+
+static inline bfa_boolean_t
+bfa_ioim_get_iotag(struct bfa_ioim_s *ioim)
+{
+	u16 k = ioim->iotag;
+
+	k >>= BFA_IOIM_RETRY_TAG_OFFSET; k++;
+
+	if (k > BFA_IOIM_RETRY_MAX)
+		return BFA_FALSE;
+	ioim->iotag &= BFA_IOIM_RETRY_TAG_MASK;
+	ioim->iotag |= k<<BFA_IOIM_RETRY_TAG_OFFSET;
+	return BFA_TRUE;
+}
+/*
+ * function prototypes
+ */
+void	bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
+					struct bfa_meminfo_s *minfo);
+void	bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
+void	bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void	bfa_ioim_good_comp_isr(struct bfa_s *bfa,
+					struct bfi_msg_s *msg);
+void	bfa_ioim_cleanup(struct bfa_ioim_s *ioim);
+void	bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
+					struct bfa_tskim_s *tskim);
+void	bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
+void	bfa_ioim_tov(struct bfa_ioim_s *ioim);
+
+void	bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
+					struct bfa_meminfo_s *minfo);
+void	bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
+void	bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void	bfa_tskim_iodone(struct bfa_tskim_s *tskim);
+void	bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
+void	bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
+
+void	bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+					u32 *dm_len);
+void	bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
+					struct bfa_meminfo_s *minfo);
+void	bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
+void	bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
+void	bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+void	bfa_itnim_iodone(struct bfa_itnim_s *itnim);
+void	bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
+bfa_boolean_t   bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
+void bfa_ioim_profile_comp(struct bfa_ioim_s *ioim);
+void bfa_ioim_profile_start(struct bfa_ioim_s *ioim);
+
+
+/*
+ * bfa fcpim module API functions
+ */
+void		bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
+u16	bfa_fcpim_path_tov_get(struct bfa_s *bfa);
+void		bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);
+u16	bfa_fcpim_qdepth_get(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa,
+	 struct bfa_itnim_iostats_s *modstats);
+bfa_status_t bfa_fcpim_port_iostats(struct bfa_s *bfa,
+		struct bfa_itnim_iostats_s *stats, u8 lp_tag);
+bfa_status_t bfa_fcpim_get_del_itn_stats(struct bfa_s *bfa,
+	 struct bfa_fcpim_del_itn_stats_s *modstats);
+bfa_status_t bfa_fcpim_port_clear_iostats(struct bfa_s *bfa, u8 lp_tag);
+void bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *fcpim_stats,
+		struct bfa_itnim_iostats_s *itnim_stats);
+bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa);
+void		bfa_fcpim_set_ioredirect(struct bfa_s *bfa,
+				bfa_boolean_t state);
+void		bfa_fcpim_update_ioredirect(struct bfa_s *bfa);
+bfa_status_t bfa_fcpim_profile_on(struct bfa_s *bfa, u32 time);
+bfa_status_t bfa_fcpim_profile_off(struct bfa_s *bfa);
+#define bfa_fcpim_ioredirect_enabled(__bfa)				\
+	(((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
+
+#define bfa_fcpim_get_next_reqq(__bfa, __qid)				\
+{									\
+	struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa);      \
+	__fcpim->reqq++;						\
+	__fcpim->reqq &= (BFI_IOC_MAX_CQS - 1);      \
+	*(__qid) = __fcpim->reqq;					\
+}
+
+#define bfa_iocfc_map_msg_to_qid(__msg, __qid)				\
+	*(__qid) = (u8)((__msg) & (BFI_IOC_MAX_CQS - 1));
+/*
+ * bfa itnim API functions
+ */
+struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa,
+					struct bfa_rport_s *rport, void *itnim);
+void		bfa_itnim_delete(struct bfa_itnim_s *itnim);
+void		bfa_itnim_online(struct bfa_itnim_s *itnim,
+				 bfa_boolean_t seq_rec);
+void		bfa_itnim_offline(struct bfa_itnim_s *itnim);
+void		bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
+			struct bfa_itnim_iostats_s *stats);
+void		bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
+bfa_status_t	bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
+		struct bfa_itnim_ioprofile_s *ioprofile);
+#define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq)
+
+/**
+ *	BFA completion callback for bfa_itnim_online().
+ *
+ * @param[in]		itnim		FCS or driver itnim instance
+ *
+ * return None
+ */
+void	bfa_cb_itnim_online(void *itnim);
+
+/**
+ *	BFA completion callback for bfa_itnim_offline().
+ *
+ * @param[in]		itnim		FCS or driver itnim instance
+ *
+ * return None
+ */
+void	bfa_cb_itnim_offline(void *itnim);
+void	bfa_cb_itnim_tov_begin(void *itnim);
+void	bfa_cb_itnim_tov(void *itnim);
+
+/**
+ *	BFA notification to FCS/driver for second level error recovery.
+ *
+ * Atleast one I/O request has timedout and target is unresponsive to
+ * repeated abort requests. Second level error recovery should be initiated
+ * by starting implicit logout and recovery procedures.
+ *
+ * @param[in]		itnim		FCS or driver itnim instance
+ *
+ * return None
+ */
+void	bfa_cb_itnim_sler(void *itnim);
+
+/*
+ * bfa ioim API functions
+ */
+struct bfa_ioim_s	*bfa_ioim_alloc(struct bfa_s *bfa,
+					struct bfad_ioim_s *dio,
+					struct bfa_itnim_s *itnim,
+					u16 nsgles);
+
+void		bfa_ioim_free(struct bfa_ioim_s *ioim);
+void		bfa_ioim_start(struct bfa_ioim_s *ioim);
+bfa_status_t	bfa_ioim_abort(struct bfa_ioim_s *ioim);
+void		bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
+				      bfa_boolean_t iotov);
+
+
+/**
+ *	I/O completion notification.
+ *
+ * @param[in]		dio			driver IO structure
+ * @param[in]		io_status		IO completion status
+ * @param[in]		scsi_status		SCSI status returned by target
+ * @param[in]		sns_len			SCSI sense length, 0 if none
+ * @param[in]		sns_info		SCSI sense data, if any
+ * @param[in]		residue			Residual length
+ *
+ * @return None
+ */
+void	bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
+				  enum bfi_ioim_status io_status,
+				  u8 scsi_status, int sns_len,
+				  u8 *sns_info, s32 residue);
+
+/**
+ *	I/O good completion notification.
+ *
+ * @param[in]		dio			driver IO structure
+ *
+ * @return None
+ */
+void	bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
+
+/**
+ *	I/O abort completion notification
+ *
+ * @param[in]		dio			driver IO that was aborted
+ *
+ * @return None
+ */
+void	bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
+
+/*
+ * bfa tskim API functions
+ */
+struct bfa_tskim_s	*bfa_tskim_alloc(struct bfa_s *bfa,
+					struct bfad_tskim_s *dtsk);
+void		bfa_tskim_free(struct bfa_tskim_s *tskim);
+void		bfa_tskim_start(struct bfa_tskim_s *tskim,
+				struct bfa_itnim_s *itnim, lun_t lun,
+				enum fcp_tm_cmnd tm, u8 t_secs);
+void		bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
+				  enum bfi_tskim_status tsk_status);
+
+#endif /* __BFA_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/bfa_fcpim_priv.h b/drivers/scsi/bfa/bfa_fcpim_priv.h
deleted file mode 100644
index 762516c..0000000
--- a/drivers/scsi/bfa/bfa_fcpim_priv.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_FCPIM_PRIV_H__
-#define __BFA_FCPIM_PRIV_H__
-
-#include <bfa_fcpim.h>
-#include <defs/bfa_defs_fcpim.h>
-#include <cs/bfa_wc.h>
-#include "bfa_sgpg_priv.h"
-
-#define BFA_ITNIM_MIN   32
-#define BFA_ITNIM_MAX   1024
-
-#define BFA_IOIM_MIN    8
-#define BFA_IOIM_MAX    2000
-
-#define BFA_TSKIM_MIN   4
-#define BFA_TSKIM_MAX   512
-#define BFA_FCPIM_PATHTOV_DEF	(30 * 1000)	/* in millisecs */
-#define BFA_FCPIM_PATHTOV_MAX	(90 * 1000)	/* in millisecs */
-
-#define bfa_fcpim_stats(__fcpim, __stats)   \
-    ((__fcpim)->stats.__stats++)
-
-struct bfa_fcpim_mod_s {
-	struct bfa_s 	*bfa;
-	struct bfa_itnim_s 	*itnim_arr;
-	struct bfa_ioim_s 	*ioim_arr;
-	struct bfa_ioim_sp_s *ioim_sp_arr;
-	struct bfa_tskim_s 	*tskim_arr;
-	struct bfa_dma_s	snsbase;
-	int			num_itnims;
-	int			num_ioim_reqs;
-	int			num_tskim_reqs;
-	u32		path_tov;
-	u16		q_depth;
-	u8              reqq;           /* Request queue to be used */
-	u8		rsvd;
-	struct list_head 	itnim_q;        /*  queue of active itnim    */
-	struct list_head 	ioim_free_q;    /*  free IO resources        */
-	struct list_head 	ioim_resfree_q; /*  IOs waiting for f/w      */
-	struct list_head 	ioim_comp_q;    /*  IO global comp Q         */
-	struct list_head 	tskim_free_q;
-	u32	ios_active;	/*  current active IOs	      */
-	u32	delay_comp;
-	struct bfa_fcpim_stats_s stats;
-	bfa_boolean_t           ioredirect;
-};
-
-struct bfa_ioim_s;
-struct bfa_tskim_s;
-
-/**
- * BFA IO (initiator mode)
- */
-struct bfa_ioim_s {
-	struct list_head qe;		/*  queue elememt            */
-	bfa_sm_t		sm; 	/*  BFA ioim state machine   */
-	struct bfa_s 	        *bfa;	/*  BFA module               */
-	struct bfa_fcpim_mod_s	*fcpim;	/*  parent fcpim module      */
-	struct bfa_itnim_s 	*itnim;	/*  i-t-n nexus for this IO  */
-	struct bfad_ioim_s 	*dio;	/*  driver IO handle         */
-	u16	iotag;		/*  FWI IO tag               */
-	u16	abort_tag;	/*  unqiue abort request tag */
-	u16	nsges;		/*  number of SG elements    */
-	u16	nsgpgs;		/*  number of SG pages       */
-	struct bfa_sgpg_s *sgpg;	/*  first SG page            */
-	struct list_head sgpg_q;		/*  allocated SG pages       */
-	struct bfa_cb_qe_s hcb_qe;	/*  bfa callback qelem       */
-	bfa_cb_cbfn_t io_cbfn;		/*  IO completion handler    */
-	struct bfa_ioim_sp_s *iosp;	/*  slow-path IO handling    */
-	u8 reqq;           		/* Request queue for I/O    */
-};
-
-struct bfa_ioim_sp_s {
-	struct bfi_msg_s 	comp_rspmsg;	/*  IO comp f/w response     */
-	u8			*snsinfo;	/*  sense info for this IO   */
-	struct bfa_sgpg_wqe_s sgpg_wqe;	/*  waitq elem for sgpg      */
-	struct bfa_reqq_wait_s reqq_wait;	/*  to wait for room in reqq */
-	bfa_boolean_t		abort_explicit;	/*  aborted by OS            */
-	struct bfa_tskim_s	*tskim;		/*  Relevant TM cmd          */
-};
-
-/**
- * BFA Task management command (initiator mode)
- */
-struct bfa_tskim_s {
-	struct list_head          qe;
-	bfa_sm_t		sm;
-	struct bfa_s            *bfa;        /*  BFA module  */
-	struct bfa_fcpim_mod_s  *fcpim;      /*  parent fcpim module      */
-	struct bfa_itnim_s      *itnim;      /*  i-t-n nexus for this IO  */
-	struct bfad_tskim_s         *dtsk;   /*  driver task mgmt cmnd    */
-	bfa_boolean_t        notify;         /*  notify itnim on TM comp  */
-	lun_t                lun;            /*  lun if applicable        */
-	enum fcp_tm_cmnd        tm_cmnd;     /*  task management command  */
-	u16             tsk_tag;        /*  FWI IO tag               */
-	u8              tsecs;          /*  timeout in seconds       */
-	struct bfa_reqq_wait_s  reqq_wait;   /*  to wait for room in reqq */
-	struct list_head              io_q;    /*  queue of affected IOs    */
-	struct bfa_wc_s             wc;      /*  waiting counter          */
-	struct bfa_cb_qe_s	hcb_qe;      /*  bfa callback qelem       */
-	enum bfi_tskim_status   tsk_status;  /*  TM status                */
-};
-
-/**
- * BFA i-t-n (initiator mode)
- */
-struct bfa_itnim_s {
-	struct list_head    qe;		/*  queue element               */
-	bfa_sm_t	  sm;		/*  i-t-n im BFA state machine  */
-	struct bfa_s      *bfa;		/*  bfa instance                */
-	struct bfa_rport_s *rport;	/*  bfa rport                   */
-	void           *ditn;		/*  driver i-t-n structure      */
-	struct bfi_mhdr_s      mhdr;	/*  pre-built mhdr              */
-	u8         msg_no;		/*  itnim/rport firmware handle */
-	u8         reqq;		/*  CQ for requests             */
-	struct bfa_cb_qe_s    hcb_qe;	/*  bfa callback qelem          */
-	struct list_head pending_q;	/*  queue of pending IO requests*/
-	struct list_head io_q;		/*  queue of active IO requests */
-	struct list_head io_cleanup_q;	/*  IO being cleaned up         */
-	struct list_head tsk_q;		/*  queue of active TM commands */
-	struct list_head  delay_comp_q;/*  queue of failed inflight cmds */
-	bfa_boolean_t   seq_rec;	/*  SQER supported              */
-	bfa_boolean_t   is_online;	/*  itnim is ONLINE for IO      */
-	bfa_boolean_t   iotov_active;	/*  IO TOV timer is active	 */
-	struct bfa_wc_s        wc;	/*  waiting counter             */
-	struct bfa_timer_s timer;	/*  pending IO TOV		 */
-	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
-	struct bfa_fcpim_mod_s *fcpim;	/*  fcpim module                */
-	struct bfa_itnim_hal_stats_s	stats;
-	struct bfa_itnim_latency_s  io_latency;
-};
-
-#define bfa_itnim_is_online(_itnim) ((_itnim)->is_online)
-#define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod)
-#define BFA_IOIM_FROM_TAG(_fcpim, _iotag)	\
-	(&fcpim->ioim_arr[_iotag])
-#define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag)                  \
-    (&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)])
-
-/*
- * function prototypes
- */
-void            bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim,
-				    struct bfa_meminfo_s *minfo);
-void            bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim);
-void            bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-void            bfa_ioim_good_comp_isr(struct bfa_s *bfa,
-					struct bfi_msg_s *msg);
-void            bfa_ioim_cleanup(struct bfa_ioim_s *ioim);
-void            bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim,
-					struct bfa_tskim_s *tskim);
-void            bfa_ioim_iocdisable(struct bfa_ioim_s *ioim);
-void            bfa_ioim_tov(struct bfa_ioim_s *ioim);
-
-void            bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim,
-				     struct bfa_meminfo_s *minfo);
-void            bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim);
-void            bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-void            bfa_tskim_iodone(struct bfa_tskim_s *tskim);
-void            bfa_tskim_iocdisable(struct bfa_tskim_s *tskim);
-void            bfa_tskim_cleanup(struct bfa_tskim_s *tskim);
-
-void            bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-				      u32 *dm_len);
-void            bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim,
-				     struct bfa_meminfo_s *minfo);
-void            bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim);
-void            bfa_itnim_iocdisable(struct bfa_itnim_s *itnim);
-void            bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-void            bfa_itnim_iodone(struct bfa_itnim_s *itnim);
-void            bfa_itnim_tskdone(struct bfa_itnim_s *itnim);
-bfa_boolean_t   bfa_itnim_hold_io(struct bfa_itnim_s *itnim);
-
-#endif /* __BFA_FCPIM_PRIV_H__ */
-
diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c
deleted file mode 100644
index 76867b5..0000000
--- a/drivers/scsi/bfa/bfa_fcport.c
+++ /dev/null
@@ -1,1962 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_pport.h>
-#include <bfi/bfi_pbc.h>
-#include <cs/bfa_debug.h>
-#include <aen/bfa_aen.h>
-#include <cs/bfa_plog.h>
-#include <aen/bfa_aen_port.h>
-
-BFA_TRC_FILE(HAL, FCPORT);
-BFA_MODULE(fcport);
-
-/*
- * The port is considered disabled if corresponding physical port or IOC are
- * disabled explicitly
- */
-#define BFA_PORT_IS_DISABLED(bfa) \
-	((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
-	(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
-
-/*
- * forward declarations
- */
-static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
-static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
-static void     bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
-static void     bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
-static void     bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
-static void     __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
-static void     bfa_fcport_callback(struct bfa_fcport_s *fcport,
-				enum bfa_pport_linkstate event);
-static void     bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
-				enum bfa_pport_linkstate event);
-static void     __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
-static void     bfa_fcport_stats_get_timeout(void *cbarg);
-static void     bfa_fcport_stats_clr_timeout(void *cbarg);
-
-/**
- *  bfa_pport_private
- */
-
-/**
- * BFA port state machine events
- */
-enum bfa_fcport_sm_event {
-	BFA_FCPORT_SM_START = 1,	/*  start port state machine */
-	BFA_FCPORT_SM_STOP = 2,	/*  stop port state machine */
-	BFA_FCPORT_SM_ENABLE = 3,	/*  enable port */
-	BFA_FCPORT_SM_DISABLE = 4,	/*  disable port state machine */
-	BFA_FCPORT_SM_FWRSP = 5,	/*  firmware enable/disable rsp */
-	BFA_FCPORT_SM_LINKUP = 6,	/*  firmware linkup event */
-	BFA_FCPORT_SM_LINKDOWN = 7,	/*  firmware linkup down */
-	BFA_FCPORT_SM_QRESUME = 8,	/*  CQ space available */
-	BFA_FCPORT_SM_HWFAIL = 9,	/*  IOC h/w failure */
-};
-
-/**
- * BFA port link notification state machine events
- */
-
-enum bfa_fcport_ln_sm_event {
-	BFA_FCPORT_LN_SM_LINKUP         = 1,    /*  linkup event */
-	BFA_FCPORT_LN_SM_LINKDOWN       = 2,    /*  linkdown event */
-	BFA_FCPORT_LN_SM_NOTIFICATION   = 3     /*  done notification */
-};
-
-static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
-					enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
-						enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
-					 enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
-					 enum bfa_fcport_sm_event event);
-static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
-					 enum bfa_fcport_sm_event event);
-
-static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
-					 enum bfa_fcport_ln_sm_event event);
-
-static struct bfa_sm_table_s hal_pport_sm_table[] = {
-	{BFA_SM(bfa_fcport_sm_uninit), BFA_PPORT_ST_UNINIT},
-	{BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT},
-	{BFA_SM(bfa_fcport_sm_enabling), BFA_PPORT_ST_ENABLING},
-	{BFA_SM(bfa_fcport_sm_linkdown), BFA_PPORT_ST_LINKDOWN},
-	{BFA_SM(bfa_fcport_sm_linkup), BFA_PPORT_ST_LINKUP},
-	{BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PPORT_ST_DISABLING_QWAIT},
-	{BFA_SM(bfa_fcport_sm_disabling), BFA_PPORT_ST_DISABLING},
-	{BFA_SM(bfa_fcport_sm_disabled), BFA_PPORT_ST_DISABLED},
-	{BFA_SM(bfa_fcport_sm_stopped), BFA_PPORT_ST_STOPPED},
-	{BFA_SM(bfa_fcport_sm_iocdown), BFA_PPORT_ST_IOCDOWN},
-	{BFA_SM(bfa_fcport_sm_iocfail), BFA_PPORT_ST_IOCDOWN},
-};
-
-static void
-bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = fcport->bfa->logm;
-	wwn_t           pwwn = fcport->pwwn;
-	char            pwwn_ptr[BFA_STRING_32];
-
-	memset(&aen_data, 0, sizeof(aen_data));
-	wwn2str(pwwn_ptr, pwwn);
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, event), pwwn_ptr);
-
-	aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
-	aen_data.port.pwwn = pwwn;
-}
-
-static void
-bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		/**
-		 * Start event after IOC is configured and BFA is started.
-		 */
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Port is persistently configured to be in enabled state. Do
-		 * not change state. Port enabling is done when START event is
-		 * received.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * If a port is persistently configured to be disabled, the
-		 * first event will a port disable request.
-		 */
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
-			    enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_QRESUME:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		bfa_fcport_send_enable(fcport);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Already enable is in progress.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * Just send disable request to firmware when room becomes
-		 * available in request queue.
-		 */
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
-		break;
-
-	case BFA_FCPORT_SM_LINKUP:
-	case BFA_FCPORT_SM_LINKDOWN:
-		/**
-		 * Possible to get link events when doing back-to-back
-		 * enable/disables.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
-		enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_FWRSP:
-	case BFA_FCPORT_SM_LINKDOWN:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
-		break;
-
-	case BFA_FCPORT_SM_LINKUP:
-		bfa_fcport_update_linkinfo(fcport);
-		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
-
-		bfa_assert(fcport->event_cbfn);
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKUP);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Already being enabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		if (bfa_fcport_send_disable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
-
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_LINKUP:
-		bfa_fcport_update_linkinfo(fcport);
-		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
-		bfa_assert(fcport->event_cbfn);
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
-
-		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
-
-			bfa_trc(fcport->bfa,
-				pevent->link_state.vc_fcf.fcf.fipenabled);
-			bfa_trc(fcport->bfa,
-				pevent->link_state.vc_fcf.fcf.fipfailed);
-
-			if (pevent->link_state.vc_fcf.fcf.fipfailed)
-				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-					BFA_PL_EID_FIP_FCF_DISC, 0,
-					"FIP FCF Discovery Failed");
-			else
-				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-					BFA_PL_EID_FIP_FCF_DISC, 0,
-					"FIP FCF Discovered");
-		}
-
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKUP);
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
-		/**
-		 * If QoS is enabled and it is not online,
-		 * Send a separate event.
-		 */
-		if ((fcport->cfg.qos_enabled)
-		    && (bfa_os_ntohl(fcport->qos_attr.state) != BFA_QOS_ONLINE))
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
-
-		break;
-
-	case BFA_FCPORT_SM_LINKDOWN:
-		/**
-		 * Possible to get link down event.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Already enabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		if (bfa_fcport_send_disable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
-
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_ENABLE:
-		/**
-		 * Already enabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		if (bfa_fcport_send_disable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
-
-		bfa_fcport_reset_linkinfo(fcport);
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKDOWN);
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
-		break;
-
-	case BFA_FCPORT_SM_LINKDOWN:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
-		bfa_fcport_reset_linkinfo(fcport);
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKDOWN);
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
-		if (BFA_PORT_IS_DISABLED(fcport->bfa))
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
-		else
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		bfa_fcport_reset_linkinfo(fcport);
-		if (BFA_PORT_IS_DISABLED(fcport->bfa))
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
-		else
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		bfa_fcport_reset_linkinfo(fcport);
-		bfa_fcport_callback(fcport, BFA_PPORT_LINKDOWN);
-		if (BFA_PORT_IS_DISABLED(fcport->bfa))
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
-		else
-			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
-			     enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_QRESUME:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
-		bfa_fcport_send_disable(fcport);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * Already being disabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_LINKUP:
-	case BFA_FCPORT_SM_LINKDOWN:
-		/**
-		 * Possible to get link events when doing back-to-back
-		 * enable/disables.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
-		bfa_reqq_wcancel(&fcport->reqq_wait);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_FWRSP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * Already being disabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_LINKUP:
-	case BFA_FCPORT_SM_LINKDOWN:
-		/**
-		 * Possible to get link events when doing back-to-back
-		 * enable/disables.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		/**
-		 * Ignore start event for a port that is disabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_STOP:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-
-		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
-			     BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
-		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
-		break;
-
-	case BFA_FCPORT_SM_DISABLE:
-		/**
-		 * Already disabled.
-		 */
-		break;
-
-	case BFA_FCPORT_SM_HWFAIL:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
-		break;
-
-	default:
-		bfa_sm_fault(fcport->bfa, event);
-	}
-}
-
-static void
-bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-		break;
-
-	default:
-		/**
-		 * Ignore all other events.
-		 */
-		;
-	}
-}
-
-/**
- * Port is enabled. IOC is down/failed.
- */
-static void
-bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		if (bfa_fcport_send_enable(fcport))
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
-		else
-			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling_qwait);
-		break;
-
-	default:
-		/**
-		 * Ignore all events.
-		 */
-		;
-	}
-}
-
-/**
- * Port is disabled. IOC is down/failed.
- */
-static void
-bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
-			enum bfa_fcport_sm_event event)
-{
-	bfa_trc(fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_SM_START:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
-		break;
-
-	case BFA_FCPORT_SM_ENABLE:
-		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
-		break;
-
-	default:
-		/**
-		 * Ignore all events.
-		 */
-		;
-	}
-}
-
-/**
- * Link state is down
- */
-static void
-bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKUP:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKUP);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for down notification
- */
-static void
-bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKUP:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for down notification and there is a pending up
- */
-static void
-bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKDOWN:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKUP);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is up
- */
-static void
-bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKDOWN:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKDOWN);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for up notification
- */
-static void
-bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKDOWN:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for up notification and there is a pending down
- */
-static void
-bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
-		enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKUP:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKDOWN);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- * Link state is waiting for up notification and there are pending down and up
- */
-static void
-bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
-			enum bfa_fcport_ln_sm_event event)
-{
-	bfa_trc(ln->fcport->bfa, event);
-
-	switch (event) {
-	case BFA_FCPORT_LN_SM_LINKDOWN:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
-		break;
-
-	case BFA_FCPORT_LN_SM_NOTIFICATION:
-		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
-		bfa_fcport_queue_cb(ln, BFA_PPORT_LINKDOWN);
-		break;
-
-	default:
-		bfa_sm_fault(ln->fcport->bfa, event);
-	}
-}
-
-/**
- *  bfa_pport_private
- */
-
-static void
-__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_fcport_ln_s *ln = cbarg;
-
-	if (complete)
-		ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
-	else
-		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
-}
-
-static void
-bfa_fcport_callback(struct bfa_fcport_s *fcport, enum bfa_pport_linkstate event)
-{
-	if (fcport->bfa->fcs) {
-		fcport->event_cbfn(fcport->event_cbarg, event);
-		return;
-	}
-
-	switch (event) {
-	case BFA_PPORT_LINKUP:
-		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
-		break;
-	case BFA_PPORT_LINKDOWN:
-		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
-		break;
-	default:
-		bfa_assert(0);
-	}
-}
-
-static void
-bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_pport_linkstate event)
-{
-	ln->ln_event = event;
-	bfa_cb_queue(ln->fcport->bfa, &ln->ln_qe, __bfa_cb_fcport_event, ln);
-}
-
-#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
-							BFA_CACHELINE_SZ))
-
-static void
-bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-		  u32 *dm_len)
-{
-	*dm_len += FCPORT_STATS_DMA_SZ;
-}
-
-static void
-bfa_fcport_qresume(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = cbarg;
-
-	bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
-}
-
-static void
-bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
-{
-	u8        *dm_kva;
-	u64        dm_pa;
-
-	dm_kva = bfa_meminfo_dma_virt(meminfo);
-	dm_pa = bfa_meminfo_dma_phys(meminfo);
-
-	fcport->stats_kva = dm_kva;
-	fcport->stats_pa = dm_pa;
-	fcport->stats = (union bfa_fcport_stats_u *)dm_kva;
-
-	dm_kva += FCPORT_STATS_DMA_SZ;
-	dm_pa += FCPORT_STATS_DMA_SZ;
-
-	bfa_meminfo_dma_virt(meminfo) = dm_kva;
-	bfa_meminfo_dma_phys(meminfo) = dm_pa;
-}
-
-/**
- * Memory initialization.
- */
-static void
-bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_pport_cfg_s *port_cfg = &fcport->cfg;
-	struct bfa_fcport_ln_s *ln = &fcport->ln;
-	struct bfa_timeval_s tv;
-
-	bfa_os_memset(fcport, 0, sizeof(struct bfa_fcport_s));
-	fcport->bfa = bfa;
-	ln->fcport = fcport;
-
-	bfa_fcport_mem_claim(fcport, meminfo);
-
-	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
-	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
-
-	/**
-	 * initialize time stamp for stats reset
-	 */
-	bfa_os_gettimeofday(&tv);
-	fcport->stats_reset_time = tv.tv_sec;
-
-	/**
-	 * initialize and set default configuration
-	 */
-	port_cfg->topology = BFA_PPORT_TOPOLOGY_P2P;
-	port_cfg->speed = BFA_PPORT_SPEED_AUTO;
-	port_cfg->trunked = BFA_FALSE;
-	port_cfg->maxfrsize = 0;
-
-	port_cfg->trl_def_speed = BFA_PPORT_SPEED_1GBPS;
-
-	bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
-}
-
-static void
-bfa_fcport_detach(struct bfa_s *bfa)
-{
-}
-
-/**
- * Called when IOC is ready.
- */
-static void
-bfa_fcport_start(struct bfa_s *bfa)
-{
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
-}
-
-/**
- * Called before IOC is stopped.
- */
-static void
-bfa_fcport_stop(struct bfa_s *bfa)
-{
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_STOP);
-}
-
-/**
- * Called when IOC failure is detected.
- */
-static void
-bfa_fcport_iocdisable(struct bfa_s *bfa)
-{
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_HWFAIL);
-}
-
-static void
-bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
-{
-	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
-
-	fcport->speed = pevent->link_state.speed;
-	fcport->topology = pevent->link_state.topology;
-
-	if (fcport->topology == BFA_PPORT_TOPOLOGY_LOOP)
-		fcport->myalpa = 0;
-
-	/*
-	 * QoS Details
-	 */
-	bfa_os_assign(fcport->qos_attr, pevent->link_state.qos_attr);
-	bfa_os_assign(fcport->qos_vc_attr,
-		pevent->link_state.vc_fcf.qos_vc_attr);
-
-
-	bfa_trc(fcport->bfa, fcport->speed);
-	bfa_trc(fcport->bfa, fcport->topology);
-}
-
-static void
-bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
-{
-	fcport->speed = BFA_PPORT_SPEED_UNKNOWN;
-	fcport->topology = BFA_PPORT_TOPOLOGY_NONE;
-}
-
-/**
- * Send port enable message to firmware.
- */
-static          bfa_boolean_t
-bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
-{
-	struct bfi_fcport_enable_req_s *m;
-
-	/**
-	 * Increment message tag before queue check, so that responses to old
-	 * requests are discarded.
-	 */
-	fcport->msgtag++;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-	if (!m) {
-		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
-							&fcport->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
-				bfa_lpuid(fcport->bfa));
-	m->nwwn = fcport->nwwn;
-	m->pwwn = fcport->pwwn;
-	m->port_cfg = fcport->cfg;
-	m->msgtag = fcport->msgtag;
-	m->port_cfg.maxfrsize = bfa_os_htons(fcport->cfg.maxfrsize);
-	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
-	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
-	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-	return BFA_TRUE;
-}
-
-/**
- * Send port disable message to firmware.
- */
-static          bfa_boolean_t
-bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
-{
-	struct bfi_fcport_req_s *m;
-
-	/**
-	 * Increment message tag before queue check, so that responses to old
-	 * requests are discarded.
-	 */
-	fcport->msgtag++;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-	if (!m) {
-		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
-							&fcport->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
-			bfa_lpuid(fcport->bfa));
-	m->msgtag = fcport->msgtag;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-
-	return BFA_TRUE;
-}
-
-static void
-bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
-{
-	fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc);
-	fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc);
-
-	bfa_trc(fcport->bfa, fcport->pwwn);
-	bfa_trc(fcport->bfa, fcport->nwwn);
-}
-
-static void
-bfa_fcport_send_txcredit(void *port_cbarg)
-{
-
-	struct bfa_fcport_s *fcport = port_cbarg;
-	struct bfi_fcport_set_svc_params_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-	if (!m) {
-		bfa_trc(fcport->bfa, fcport->cfg.tx_bbcredit);
-		return;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
-			bfa_lpuid(fcport->bfa));
-	m->tx_bbcredit = bfa_os_htons((u16) fcport->cfg.tx_bbcredit);
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-}
-
-static void
-bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
-	struct bfa_qos_stats_s *s)
-{
-	u32     *dip = (u32 *) d;
-	u32     *sip = (u32 *) s;
-	int             i;
-
-	/* Now swap the 32 bit fields */
-	for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
-		dip[i] = bfa_os_ntohl(sip[i]);
-}
-
-static void
-bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
-	struct bfa_fcoe_stats_s *s)
-{
-	u32     *dip = (u32 *) d;
-	u32     *sip = (u32 *) s;
-	int             i;
-
-	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
-		i = i + 2) {
-#ifdef __BIGENDIAN
-		dip[i] = bfa_os_ntohl(sip[i]);
-		dip[i + 1] = bfa_os_ntohl(sip[i + 1]);
-#else
-		dip[i] = bfa_os_ntohl(sip[i + 1]);
-		dip[i + 1] = bfa_os_ntohl(sip[i]);
-#endif
-	}
-}
-
-static void
-__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_fcport_s *fcport = cbarg;
-
-	if (complete) {
-		if (fcport->stats_status == BFA_STATUS_OK) {
-			struct bfa_timeval_s tv;
-
-			/* Swap FC QoS or FCoE stats */
-			if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
-				bfa_fcport_qos_stats_swap(
-					&fcport->stats_ret->fcqos,
-					&fcport->stats->fcqos);
-			} else {
-				bfa_fcport_fcoe_stats_swap(
-					&fcport->stats_ret->fcoe,
-					&fcport->stats->fcoe);
-
-				bfa_os_gettimeofday(&tv);
-				fcport->stats_ret->fcoe.secs_reset =
-					tv.tv_sec - fcport->stats_reset_time;
-			}
-		}
-		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
-	} else {
-		fcport->stats_busy = BFA_FALSE;
-		fcport->stats_status = BFA_STATUS_OK;
-	}
-}
-
-static void
-bfa_fcport_stats_get_timeout(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-
-	bfa_trc(fcport->bfa, fcport->stats_qfull);
-
-	if (fcport->stats_qfull) {
-		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
-		fcport->stats_qfull = BFA_FALSE;
-	}
-
-	fcport->stats_status = BFA_STATUS_ETIMER;
-	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
-		fcport);
-}
-
-static void
-bfa_fcport_send_stats_get(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-	struct bfi_fcport_req_s *msg;
-
-	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-
-	if (!msg) {
-		fcport->stats_qfull = BFA_TRUE;
-		bfa_reqq_winit(&fcport->stats_reqq_wait,
-				bfa_fcport_send_stats_get, fcport);
-		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
-				&fcport->stats_reqq_wait);
-		return;
-	}
-	fcport->stats_qfull = BFA_FALSE;
-
-	bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
-	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
-		bfa_lpuid(fcport->bfa));
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-}
-
-static void
-__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_fcport_s *fcport = cbarg;
-
-	if (complete) {
-		struct bfa_timeval_s tv;
-
-		/**
-		 * re-initialize time stamp for stats reset
-		 */
-		bfa_os_gettimeofday(&tv);
-		fcport->stats_reset_time = tv.tv_sec;
-
-		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
-	} else {
-		fcport->stats_busy = BFA_FALSE;
-		fcport->stats_status = BFA_STATUS_OK;
-	}
-}
-
-static void
-bfa_fcport_stats_clr_timeout(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-
-	bfa_trc(fcport->bfa, fcport->stats_qfull);
-
-	if (fcport->stats_qfull) {
-		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
-		fcport->stats_qfull = BFA_FALSE;
-	}
-
-	fcport->stats_status = BFA_STATUS_ETIMER;
-	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
-			__bfa_cb_fcport_stats_clr, fcport);
-}
-
-static void
-bfa_fcport_send_stats_clear(void *cbarg)
-{
-	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
-	struct bfi_fcport_req_s *msg;
-
-	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
-
-	if (!msg) {
-		fcport->stats_qfull = BFA_TRUE;
-		bfa_reqq_winit(&fcport->stats_reqq_wait,
-				bfa_fcport_send_stats_clear, fcport);
-		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
-				&fcport->stats_reqq_wait);
-		return;
-	}
-	fcport->stats_qfull = BFA_FALSE;
-
-	bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
-	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
-			bfa_lpuid(fcport->bfa));
-	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
-}
-
-/**
- *  bfa_pport_public
- */
-
-/**
- * Called to initialize port attributes
- */
-void
-bfa_fcport_init(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	/**
-	 * Initialize port attributes from IOC hardware data.
-	 */
-	bfa_fcport_set_wwns(fcport);
-	if (fcport->cfg.maxfrsize == 0)
-		fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
-	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
-	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
-
-	bfa_assert(fcport->cfg.maxfrsize);
-	bfa_assert(fcport->cfg.rx_bbcredit);
-	bfa_assert(fcport->speed_sup);
-}
-
-
-/**
- * Firmware message handler.
- */
-void
-bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	union bfi_fcport_i2h_msg_u i2hmsg;
-
-	i2hmsg.msg = msg;
-	fcport->event_arg.i2hmsg = i2hmsg;
-
-	switch (msg->mhdr.msg_id) {
-	case BFI_FCPORT_I2H_ENABLE_RSP:
-		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
-			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
-		break;
-
-	case BFI_FCPORT_I2H_DISABLE_RSP:
-		if (fcport->msgtag == i2hmsg.pdisable_rsp->msgtag)
-			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
-		break;
-
-	case BFI_FCPORT_I2H_EVENT:
-		switch (i2hmsg.event->link_state.linkstate) {
-		case BFA_PPORT_LINKUP:
-			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
-			break;
-		case BFA_PPORT_LINKDOWN:
-			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
-			break;
-		case BFA_PPORT_TRUNK_LINKDOWN:
-			/** todo: event notification */
-			break;
-		}
-		break;
-
-	case BFI_FCPORT_I2H_STATS_GET_RSP:
-		/*
-		 * check for timer pop before processing the rsp
-		 */
-		if (fcport->stats_busy == BFA_FALSE ||
-			fcport->stats_status == BFA_STATUS_ETIMER)
-			break;
-
-		bfa_timer_stop(&fcport->timer);
-		fcport->stats_status = i2hmsg.pstatsget_rsp->status;
-		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
-				__bfa_cb_fcport_stats_get, fcport);
-		break;
-
-	case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
-		/*
-		 * check for timer pop before processing the rsp
-		 */
-		if (fcport->stats_busy == BFA_FALSE ||
-			fcport->stats_status == BFA_STATUS_ETIMER)
-			break;
-
-		bfa_timer_stop(&fcport->timer);
-		fcport->stats_status = BFA_STATUS_OK;
-		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
-				__bfa_cb_fcport_stats_clr, fcport);
-		break;
-
-	default:
-		bfa_assert(0);
-	break;
-	}
-}
-
-/**
- *  bfa_pport_api
- */
-
-/**
- * Registered callback for port events.
- */
-void
-bfa_fcport_event_register(struct bfa_s *bfa,
-			 void (*cbfn) (void *cbarg, bfa_pport_event_t event),
-			 void *cbarg)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	fcport->event_cbfn = cbfn;
-	fcport->event_cbarg = cbarg;
-}
-
-bfa_status_t
-bfa_fcport_enable(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	/* if port is PBC disabled, return error */
-	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
-		bfa_trc(bfa, fcport->pwwn);
-		return BFA_STATUS_PBC;
-	}
-
-	if (bfa_ioc_is_disabled(&bfa->ioc))
-		return BFA_STATUS_IOC_DISABLED;
-
-	if (fcport->diag_busy)
-		return BFA_STATUS_DIAG_BUSY;
-	else if (bfa_sm_cmp_state
-		 (BFA_FCPORT_MOD(bfa), bfa_fcport_sm_disabling_qwait))
-		return BFA_STATUS_DEVBUSY;
-
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcport_disable(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	/* if port is PBC disabled, return error */
-	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
-		bfa_trc(bfa, fcport->pwwn);
-		return BFA_STATUS_PBC;
-	}
-
-	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Configure port speed.
- */
-bfa_status_t
-bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, speed);
-
-	if ((speed != BFA_PPORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
-		bfa_trc(bfa, fcport->speed_sup);
-		return BFA_STATUS_UNSUPP_SPEED;
-	}
-
-	fcport->cfg.speed = speed;
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * Get current speed.
- */
-enum bfa_pport_speed
-bfa_fcport_get_speed(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->speed;
-}
-
-/**
- * Configure port topology.
- */
-bfa_status_t
-bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_pport_topology topology)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, topology);
-	bfa_trc(bfa, fcport->cfg.topology);
-
-	switch (topology) {
-	case BFA_PPORT_TOPOLOGY_P2P:
-	case BFA_PPORT_TOPOLOGY_LOOP:
-	case BFA_PPORT_TOPOLOGY_AUTO:
-		break;
-
-	default:
-		return BFA_STATUS_EINVAL;
-	}
-
-	fcport->cfg.topology = topology;
-	return BFA_STATUS_OK;
-}
-
-/**
- * Get current topology.
- */
-enum bfa_pport_topology
-bfa_fcport_get_topology(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->topology;
-}
-
-bfa_status_t
-bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, alpa);
-	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
-	bfa_trc(bfa, fcport->cfg.hardalpa);
-
-	fcport->cfg.cfg_hardalpa = BFA_TRUE;
-	fcport->cfg.hardalpa = alpa;
-
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
-	bfa_trc(bfa, fcport->cfg.hardalpa);
-
-	fcport->cfg.cfg_hardalpa = BFA_FALSE;
-	return BFA_STATUS_OK;
-}
-
-bfa_boolean_t
-bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	*alpa = fcport->cfg.hardalpa;
-	return fcport->cfg.cfg_hardalpa;
-}
-
-u8
-bfa_fcport_get_myalpa(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->myalpa;
-}
-
-bfa_status_t
-bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, maxfrsize);
-	bfa_trc(bfa, fcport->cfg.maxfrsize);
-
-	/*
-	 * with in range
-	 */
-	if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
-		return BFA_STATUS_INVLD_DFSZ;
-
-	/*
-	 * power of 2, if not the max frame size of 2112
-	 */
-	if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
-		return BFA_STATUS_INVLD_DFSZ;
-
-	fcport->cfg.maxfrsize = maxfrsize;
-	return BFA_STATUS_OK;
-}
-
-u16
-bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->cfg.maxfrsize;
-}
-
-u32
-bfa_fcport_mypid(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->mypid;
-}
-
-u8
-bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->cfg.rx_bbcredit;
-}
-
-void
-bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	fcport->cfg.tx_bbcredit = (u8) tx_bbcredit;
-	bfa_fcport_send_txcredit(fcport);
-}
-
-/**
- * Get port attributes.
- */
-
-wwn_t
-bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	if (node)
-		return fcport->nwwn;
-	else
-		return fcport->pwwn;
-}
-
-void
-bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	bfa_os_memset(attr, 0, sizeof(struct bfa_pport_attr_s));
-
-	attr->nwwn = fcport->nwwn;
-	attr->pwwn = fcport->pwwn;
-
-	attr->factorypwwn =  bfa_ioc_get_mfg_pwwn(&bfa->ioc);
-	attr->factorynwwn =  bfa_ioc_get_mfg_nwwn(&bfa->ioc);
-
-	bfa_os_memcpy(&attr->pport_cfg, &fcport->cfg,
-		      sizeof(struct bfa_pport_cfg_s));
-	/*
-	 * speed attributes
-	 */
-	attr->pport_cfg.speed = fcport->cfg.speed;
-	attr->speed_supported = fcport->speed_sup;
-	attr->speed = fcport->speed;
-	attr->cos_supported = FC_CLASS_3;
-
-	/*
-	 * topology attributes
-	 */
-	attr->pport_cfg.topology = fcport->cfg.topology;
-	attr->topology = fcport->topology;
-
-	/*
-	 * beacon attributes
-	 */
-	attr->beacon = fcport->beacon;
-	attr->link_e2e_beacon = fcport->link_e2e_beacon;
-	attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog);
-
-	attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa);
-	attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa);
-
-	/* PBC Disabled State */
-	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED)
-		attr->port_state = BFA_PPORT_ST_PREBOOT_DISABLED;
-	else {
-		attr->port_state = bfa_sm_to_state(
-				hal_pport_sm_table, fcport->sm);
-		if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
-			attr->port_state = BFA_PPORT_ST_IOCDIS;
-		else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
-			attr->port_state = BFA_PPORT_ST_FWMISMATCH;
-	}
-}
-
-#define BFA_FCPORT_STATS_TOV	1000
-
-/**
- * Fetch port attributes (FCQoS or FCoE).
- */
-bfa_status_t
-bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
-		    bfa_cb_pport_t cbfn, void *cbarg)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	if (fcport->stats_busy) {
-		bfa_trc(bfa, fcport->stats_busy);
-		return BFA_STATUS_DEVBUSY;
-	}
-
-	fcport->stats_busy  = BFA_TRUE;
-	fcport->stats_ret   = stats;
-	fcport->stats_cbfn  = cbfn;
-	fcport->stats_cbarg = cbarg;
-
-	bfa_fcport_send_stats_get(fcport);
-
-	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
-		fcport, BFA_FCPORT_STATS_TOV);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Reset port statistics (FCQoS or FCoE).
- */
-bfa_status_t
-bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	if (fcport->stats_busy) {
-		bfa_trc(bfa, fcport->stats_busy);
-		return BFA_STATUS_DEVBUSY;
-	}
-
-	fcport->stats_busy = BFA_TRUE;
-	fcport->stats_cbfn = cbfn;
-	fcport->stats_cbarg = cbarg;
-
-	bfa_fcport_send_stats_clear(fcport);
-
-	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
-			fcport, BFA_FCPORT_STATS_TOV);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
-	bfa_cb_pport_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FC mode */
-	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/**
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FC mode */
-	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-/**
- * Fetch FCQoS port statistics
- */
-bfa_status_t
-bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
-	bfa_cb_pport_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FCoE mode */
-	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
-}
-
-/**
- * Reset FCoE port statistics
- */
-bfa_status_t
-bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg)
-{
-	/* Meaningful only for FCoE mode */
-	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
-
-	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
-}
-
-bfa_status_t
-bfa_fcport_trunk_enable(struct bfa_s *bfa, u8 bitmap)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, bitmap);
-	bfa_trc(bfa, fcport->cfg.trunked);
-	bfa_trc(bfa, fcport->cfg.trunk_ports);
-
-	if (!bitmap || (bitmap & (bitmap - 1)))
-		return BFA_STATUS_EINVAL;
-
-	fcport->cfg.trunked = BFA_TRUE;
-	fcport->cfg.trunk_ports = bitmap;
-
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	qos_attr->state = bfa_os_ntohl(fcport->qos_attr.state);
-	qos_attr->total_bb_cr = bfa_os_ntohl(fcport->qos_attr.total_bb_cr);
-}
-
-void
-bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
-			  struct bfa_qos_vc_attr_s *qos_vc_attr)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr;
-	u32        i = 0;
-
-	qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count);
-	qos_vc_attr->shared_credit = bfa_os_ntohs(bfa_vc_attr->shared_credit);
-	qos_vc_attr->elp_opmode_flags =
-		bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags);
-
-	/*
-	 * Individual VC info
-	 */
-	while (i < qos_vc_attr->total_vc_count) {
-		qos_vc_attr->vc_info[i].vc_credit =
-			bfa_vc_attr->vc_info[i].vc_credit;
-		qos_vc_attr->vc_info[i].borrow_credit =
-			bfa_vc_attr->vc_info[i].borrow_credit;
-		qos_vc_attr->vc_info[i].priority =
-			bfa_vc_attr->vc_info[i].priority;
-		++i;
-	}
-}
-
-/**
- * Fetch port attributes.
- */
-bfa_status_t
-bfa_fcport_trunk_disable(struct bfa_s *bfa)
-{
-	return BFA_STATUS_OK;
-}
-
-bfa_boolean_t
-bfa_fcport_trunk_query(struct bfa_s *bfa, u32 *bitmap)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	*bitmap = fcport->cfg.trunk_ports;
-	return fcport->cfg.trunked;
-}
-
-bfa_boolean_t
-bfa_fcport_is_disabled(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return bfa_sm_to_state(hal_pport_sm_table, fcport->sm) ==
-		BFA_PPORT_ST_DISABLED;
-
-}
-
-bfa_boolean_t
-bfa_fcport_is_ratelim(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
-
-}
-
-void
-bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
-
-	bfa_trc(bfa, on_off);
-	bfa_trc(bfa, fcport->cfg.qos_enabled);
-
-	bfa_trc(bfa, ioc_type);
-
-	if (ioc_type == BFA_IOC_TYPE_FC) {
-		fcport->cfg.qos_enabled = on_off;
-		/**
-		 * Notify fcpim of the change in QoS state
-		 */
-		bfa_fcpim_update_ioredirect(bfa);
-	}
-}
-
-void
-bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, on_off);
-	bfa_trc(bfa, fcport->cfg.ratelimit);
-
-	fcport->cfg.ratelimit = on_off;
-	if (fcport->cfg.trl_def_speed == BFA_PPORT_SPEED_UNKNOWN)
-		fcport->cfg.trl_def_speed = BFA_PPORT_SPEED_1GBPS;
-}
-
-/**
- * Configure default minimum ratelim speed
- */
-bfa_status_t
-bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_pport_speed speed)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, speed);
-
-	/*
-	 * Auto and speeds greater than the supported speed, are invalid
-	 */
-	if ((speed == BFA_PPORT_SPEED_AUTO) || (speed > fcport->speed_sup)) {
-		bfa_trc(bfa, fcport->speed_sup);
-		return BFA_STATUS_UNSUPP_SPEED;
-	}
-
-	fcport->cfg.trl_def_speed = speed;
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * Get default minimum ratelim speed
- */
-enum bfa_pport_speed
-bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, fcport->cfg.trl_def_speed);
-	return fcport->cfg.trl_def_speed;
-
-}
-
-void
-bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, status);
-	bfa_trc(bfa, fcport->diag_busy);
-
-	fcport->diag_busy = status;
-}
-
-void
-bfa_fcport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
-		 bfa_boolean_t link_e2e_beacon)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	bfa_trc(bfa, beacon);
-	bfa_trc(bfa, link_e2e_beacon);
-	bfa_trc(bfa, fcport->beacon);
-	bfa_trc(bfa, fcport->link_e2e_beacon);
-
-	fcport->beacon = beacon;
-	fcport->link_e2e_beacon = link_e2e_beacon;
-}
-
-bfa_boolean_t
-bfa_fcport_is_linkup(struct bfa_s *bfa)
-{
-	return bfa_sm_cmp_state(BFA_FCPORT_MOD(bfa), bfa_fcport_sm_linkup);
-}
-
-bfa_boolean_t
-bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
-{
-	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
-
-	return fcport->cfg.qos_enabled;
-}
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index d1a9920..9cebbe3 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -19,35 +19,28 @@
  *  bfa_fcs.c BFA FCS main
  */
 
-#include <fcs/bfa_fcs.h>
-#include "fcs_port.h"
-#include "fcs_uf.h"
-#include "fcs_vport.h"
-#include "fcs_rport.h"
-#include "fcs_fabric.h"
-#include "fcs_fcpim.h"
-#include "fcs_fcptm.h"
-#include "fcbuild.h"
-#include "fcs.h"
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
 #include "bfad_drv.h"
-#include <fcb/bfa_fcb.h>
+
+BFA_TRC_FILE(FCS, FCS);
 
 /**
  * FCS sub-modules
  */
 struct bfa_fcs_mod_s {
 	void		(*attach) (struct bfa_fcs_s *fcs);
-	void            (*modinit) (struct bfa_fcs_s *fcs);
-	void            (*modexit) (struct bfa_fcs_s *fcs);
+	void		(*modinit) (struct bfa_fcs_s *fcs);
+	void		(*modexit) (struct bfa_fcs_s *fcs);
 };
 
 #define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
 
 static struct bfa_fcs_mod_s fcs_modules[] = {
-	{ bfa_fcs_pport_attach, NULL, NULL },
+	{ bfa_fcs_port_attach, NULL, NULL },
 	{ bfa_fcs_uf_attach, NULL, NULL },
 	{ bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit,
-	 bfa_fcs_fabric_modexit },
+	  bfa_fcs_fabric_modexit },
 };
 
 /**
@@ -57,8 +50,8 @@
 static void
 bfa_fcs_exit_comp(void *fcs_cbarg)
 {
-	struct bfa_fcs_s *fcs = fcs_cbarg;
-	struct bfad_s *bfad = fcs->bfad;
+	struct bfa_fcs_s      *fcs = fcs_cbarg;
+	struct bfad_s         *bfad = fcs->bfad;
 
 	complete(&bfad->comp);
 }
@@ -74,9 +67,9 @@
  */
 void
 bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
-			bfa_boolean_t min_cfg)
+	       bfa_boolean_t min_cfg)
 {
-	int             i;
+	int		i;
 	struct bfa_fcs_mod_s  *mod;
 
 	fcs->bfa = bfa;
@@ -86,7 +79,7 @@
 	bfa_attach_fcs(bfa);
 	fcbuild_init();
 
-	for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
+	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
 		mod = &fcs_modules[i];
 		if (mod->attach)
 			mod->attach(fcs);
@@ -99,11 +92,11 @@
 void
 bfa_fcs_init(struct bfa_fcs_s *fcs)
 {
-	int i, npbc_vports;
+	int		i, npbc_vports;
 	struct bfa_fcs_mod_s  *mod;
 	struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
 
-	for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
+	for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
 		mod = &fcs_modules[i];
 		if (mod->modinit)
 			mod->modinit(fcs);
@@ -111,7 +104,7 @@
 	/* Initialize pbc vports */
 	if (!fcs->min_cfg) {
 		npbc_vports =
-			bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
+		    bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
 		for (i = 0; i < npbc_vports; i++)
 			bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
 	}
@@ -127,12 +120,13 @@
 }
 
 /**
- * 		FCS driver details initialization.
+ *	brief
+ *		FCS driver details initialization.
  *
- * 	param[in]		fcs		FCS instance
- * 	param[in]		driver_info	Driver Details
+ *	param[in]		fcs		FCS instance
+ *	param[in]		driver_info	Driver Details
  *
- * 	return None
+ *	return None
  */
 void
 bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
@@ -145,13 +139,13 @@
 }
 
 /**
- *      @brief
- *              FCS FDMI Driver Parameter Initialization
+ *	brief
+ *		FCS FDMI Driver Parameter Initialization
  *
- *      @param[in]              fcs             FCS instance
- *      @param[in]              fdmi_enable     TRUE/FALSE
+ *	param[in]		fcs		FCS instance
+ *	param[in]		fdmi_enable	TRUE/FALSE
  *
- *      @return None
+ *	return None
  */
 void
 bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable)
@@ -160,22 +154,24 @@
 	fcs->fdmi_enabled = fdmi_enable;
 
 }
-
 /**
- * 		FCS instance cleanup and exit.
+ *	brief
+ *		FCS instance cleanup and exit.
  *
- * 	param[in]		fcs			FCS instance
- * 	return None
+ *	param[in]		fcs			FCS instance
+ *	return None
  */
 void
 bfa_fcs_exit(struct bfa_fcs_s *fcs)
 {
 	struct bfa_fcs_mod_s  *mod;
-	int i;
+	int		nmods, i;
 
 	bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
 
-	for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
+	nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
+
+	for (i = 0; i < nmods; i++) {
 
 		mod = &fcs_modules[i];
 		if (mod->modexit) {
@@ -194,24 +190,1547 @@
 	fcs->trcmod = trcmod;
 }
 
-
-void
-bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod)
-{
-	fcs->logm = logmod;
-}
-
-
-void
-bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen)
-{
-	fcs->aen = aen;
-}
-
 void
 bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs)
 {
 	bfa_wc_down(&fcs->wc);
 }
 
+/**
+ * Fabric module implementation.
+ */
 
+#define BFA_FCS_FABRIC_RETRY_DELAY	(2000)	/* Milliseconds */
+#define BFA_FCS_FABRIC_CLEANUP_DELAY	(10000)	/* Milliseconds */
+
+#define bfa_fcs_fabric_set_opertype(__fabric) do {			\
+		if (bfa_fcport_get_topology((__fabric)->fcs->bfa)	\
+		    == BFA_PORT_TOPOLOGY_P2P)				\
+			(__fabric)->oper_type = BFA_PORT_TYPE_NPORT;	\
+		else							\
+			(__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;	\
+} while (0)
+
+/*
+ * forward declarations
+ */
+static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_delay(void *cbarg);
+static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_delete_comp(void *cbarg);
+static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
+				      struct fchs_s *fchs, u16 len);
+static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
+					 struct fchs_s *fchs, u16 len);
+static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
+static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
+					 struct bfa_fcxp_s *fcxp, void *cbarg,
+					 bfa_status_t status,
+					 u32 rsp_len,
+					 u32 resid_len,
+					 struct fchs_s *rspfchs);
+/**
+ *  fcs_fabric_sm fabric state machine functions
+ */
+
+/**
+ * Fabric state machine events
+ */
+enum bfa_fcs_fabric_event {
+	BFA_FCS_FABRIC_SM_CREATE	= 1,	/*  create from driver	      */
+	BFA_FCS_FABRIC_SM_DELETE	= 2,	/*  delete from driver	      */
+	BFA_FCS_FABRIC_SM_LINK_DOWN	= 3,	/*  link down from port      */
+	BFA_FCS_FABRIC_SM_LINK_UP	= 4,	/*  link up from port	      */
+	BFA_FCS_FABRIC_SM_CONT_OP	= 5,	/*  flogi/auth continue op   */
+	BFA_FCS_FABRIC_SM_RETRY_OP	= 6,	/*  flogi/auth retry op      */
+	BFA_FCS_FABRIC_SM_NO_FABRIC	= 7,	/*  from flogi/auth	      */
+	BFA_FCS_FABRIC_SM_PERF_EVFP	= 8,	/*  from flogi/auth	      */
+	BFA_FCS_FABRIC_SM_ISOLATE	= 9,	/*  from EVFP processing     */
+	BFA_FCS_FABRIC_SM_NO_TAGGING	= 10,	/*  no VFT tagging from EVFP */
+	BFA_FCS_FABRIC_SM_DELAYED	= 11,	/*  timeout delay event      */
+	BFA_FCS_FABRIC_SM_AUTH_FAILED	= 12,	/*  auth failed	      */
+	BFA_FCS_FABRIC_SM_AUTH_SUCCESS	= 13,	/*  auth successful	      */
+	BFA_FCS_FABRIC_SM_DELCOMP	= 14,	/*  all vports deleted event */
+	BFA_FCS_FABRIC_SM_LOOPBACK	= 15,	/*  Received our own FLOGI   */
+	BFA_FCS_FABRIC_SM_START		= 16,	/*  from driver	      */
+};
+
+static void	bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
+					 enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
+					  enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
+					enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
+					      enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
+				       enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+					      enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+					 enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
+				       enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
+					    enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+static void	bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
+					   enum bfa_fcs_fabric_event event);
+/**
+ *   Beginning state before fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
+			 enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_CREATE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
+		bfa_fcs_fabric_init(fabric);
+		bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_UP:
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Beginning state before fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
+			  enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_START:
+		if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
+			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+			bfa_fcs_fabric_login(fabric);
+		} else
+			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_UP:
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+		bfa_fcs_modexit_comp(fabric->fcs);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Link is down, awaiting LINK UP event from port. This is also the
+ *   first state at fabric creation.
+ */
+static void
+bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_UP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+		bfa_fcs_fabric_login(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_RETRY_OP:
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   FLOGI is in progress, awaiting FLOGI reply.
+ */
+static void
+bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
+			enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_CONT_OP:
+
+		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
+					   fabric->bb_credit);
+		fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
+
+		if (fabric->auth_reqd && fabric->is_auth) {
+			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
+			bfa_trc(fabric->fcs, event);
+		} else {
+			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+			bfa_fcs_fabric_notify_online(fabric);
+		}
+		break;
+
+	case BFA_FCS_FABRIC_SM_RETRY_OP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
+		bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
+				bfa_fcs_fabric_delay, fabric,
+				BFA_FCS_FABRIC_RETRY_DELAY);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LOOPBACK:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
+		bfa_lps_discard(fabric->lps);
+		bfa_fcs_fabric_set_opertype(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_NO_FABRIC:
+		fabric->fab_type = BFA_FCS_FABRIC_N2N;
+		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
+					   fabric->bb_credit);
+		bfa_fcs_fabric_notify_online(fabric);
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_lps_discard(fabric->lps);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_lps_discard(fabric->lps);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+
+static void
+bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
+			      enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_DELAYED:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
+		bfa_fcs_fabric_login(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_timer_stop(&fabric->delay_timer);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_timer_stop(&fabric->delay_timer);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Authentication is in progress, awaiting authentication results.
+ */
+static void
+bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
+		       enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+		bfa_lps_discard(fabric->lps);
+		break;
+
+	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
+		bfa_fcs_fabric_notify_online(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_PERF_EVFP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_lps_discard(fabric->lps);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Authentication failed
+ */
+static void
+bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
+			      enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Port is in loopback mode.
+ */
+static void
+bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   There is no attached fabric - private loop or NPort-to-NPort topology.
+ */
+static void
+bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_lps_discard(fabric->lps);
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_NO_FABRIC:
+		bfa_trc(fabric->fcs, fabric->bb_credit);
+		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
+					   fabric->bb_credit);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Fabric is online - normal operating state.
+ */
+static void
+bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
+			 enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
+		bfa_lps_discard(fabric->lps);
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_DELETE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
+		bfa_fcs_fabric_delete(fabric);
+		break;
+
+	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+		bfa_lps_discard(fabric->lps);
+		break;
+
+	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   Exchanging virtual fabric parameters.
+ */
+static void
+bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
+		       enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_CONT_OP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
+		break;
+
+	case BFA_FCS_FABRIC_SM_ISOLATE:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+/**
+ *   EVFP exchange complete and VFT tagging is enabled.
+ */
+static void
+bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
+			    enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+}
+
+/**
+ *   Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
+ */
+static void
+bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
+	char	pwwn_ptr[BFA_STRING_32];
+
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+	wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn);
+
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"Port is isolated due to VF_ID mismatch. "
+		"PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",
+		pwwn_ptr, fabric->fcs->port_vfid,
+		fabric->event_arg.swp_vfid);
+}
+
+/**
+ *   Fabric is being deleted, awaiting vport delete completions.
+ */
+static void
+bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
+			   enum bfa_fcs_fabric_event event)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, event);
+
+	switch (event) {
+	case BFA_FCS_FABRIC_SM_DELCOMP:
+		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+		bfa_fcs_modexit_comp(fabric->fcs);
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_UP:
+		break;
+
+	case BFA_FCS_FABRIC_SM_LINK_DOWN:
+		bfa_fcs_fabric_notify_offline(fabric);
+		break;
+
+	default:
+		bfa_sm_fault(fabric->fcs, event);
+	}
+}
+
+
+
+/**
+ *  fcs_fabric_private fabric private functions
+ */
+
+static void
+bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+
+	port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;
+	port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
+	port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
+}
+
+/**
+ * Port Symbolic Name Creation for base port.
+ */
+void
+bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
+	char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
+	struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
+
+	bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
+
+	/* Model name/number */
+	strncpy((char *)&port_cfg->sym_name, model,
+		BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
+	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+	/* Driver Version */
+	strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
+		BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
+	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+	/* Host machine name */
+	strncat((char *)&port_cfg->sym_name,
+		(char *)driver_info->host_machine_name,
+		BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
+	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+	/*
+	 * Host OS Info :
+	 * If OS Patch Info is not there, do not truncate any bytes from the
+	 * OS name string and instead copy the entire OS info string (64 bytes).
+	 */
+	if (driver_info->host_os_patch[0] == '\0') {
+		strncat((char *)&port_cfg->sym_name,
+			(char *)driver_info->host_os_name,
+			BFA_FCS_OS_STR_LEN);
+		strncat((char *)&port_cfg->sym_name,
+			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+	} else {
+		strncat((char *)&port_cfg->sym_name,
+			(char *)driver_info->host_os_name,
+			BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
+		strncat((char *)&port_cfg->sym_name,
+			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+
+		/* Append host OS Patch Info */
+		strncat((char *)&port_cfg->sym_name,
+			(char *)driver_info->host_os_patch,
+			BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
+	}
+
+	/* null terminate */
+	port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
+}
+
+/**
+ * bfa lps login completion callback
+ */
+void
+bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
+{
+	struct bfa_fcs_fabric_s *fabric = uarg;
+
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_trc(fabric->fcs, status);
+
+	switch (status) {
+	case BFA_STATUS_OK:
+		fabric->stats.flogi_accepts++;
+		break;
+
+	case BFA_STATUS_INVALID_MAC:
+		/* Only for CNA */
+		fabric->stats.flogi_acc_err++;
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+
+		return;
+
+	case BFA_STATUS_EPROTOCOL:
+		switch (bfa_lps_get_extstatus(fabric->lps)) {
+		case BFA_EPROTO_BAD_ACCEPT:
+			fabric->stats.flogi_acc_err++;
+			break;
+
+		case BFA_EPROTO_UNKNOWN_RSP:
+			fabric->stats.flogi_unknown_rsp++;
+			break;
+
+		default:
+			break;
+		}
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+
+		return;
+
+	case BFA_STATUS_FABRIC_RJT:
+		fabric->stats.flogi_rejects++;
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+		return;
+
+	default:
+		fabric->stats.flogi_rsp_err++;
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
+		return;
+	}
+
+	fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
+	bfa_trc(fabric->fcs, fabric->bb_credit);
+
+	if (!bfa_lps_is_brcd_fabric(fabric->lps))
+		fabric->fabric_name =  bfa_lps_get_peer_nwwn(fabric->lps);
+
+	/*
+	 * Check port type. It should be 1 = F-port.
+	 */
+	if (bfa_lps_is_fport(fabric->lps)) {
+		fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
+		fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
+		fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
+	} else {
+		/*
+		 * Nport-2-Nport direct attached
+		 */
+		fabric->bport.port_topo.pn2n.rem_port_wwn =
+			bfa_lps_get_peer_pwwn(fabric->lps);
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
+	}
+
+	bfa_trc(fabric->fcs, fabric->bport.pid);
+	bfa_trc(fabric->fcs, fabric->is_npiv);
+	bfa_trc(fabric->fcs, fabric->is_auth);
+}
+/**
+ *		Allocate and send FLOGI.
+ */
+static void
+bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_s		*bfa = fabric->fcs->bfa;
+	struct bfa_lport_cfg_s	*pcfg = &fabric->bport.port_cfg;
+	u8			alpa = 0;
+
+	if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
+		alpa = bfa_fcport_get_myalpa(bfa);
+
+	bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
+		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
+
+	fabric->stats.flogi_sent++;
+}
+
+static void
+bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe, *qen;
+
+	bfa_trc(fabric->fcs, fabric->fabric_name);
+
+	bfa_fcs_fabric_set_opertype(fabric);
+	fabric->stats.fabric_onlines++;
+
+	/**
+	 * notify online event to base and then virtual ports
+	 */
+	bfa_fcs_lport_online(&fabric->bport);
+
+	list_for_each_safe(qe, qen, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		bfa_fcs_vport_online(vport);
+	}
+}
+
+static void
+bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe, *qen;
+
+	bfa_trc(fabric->fcs, fabric->fabric_name);
+	fabric->stats.fabric_offlines++;
+
+	/**
+	 * notify offline event first to vports and then base port.
+	 */
+	list_for_each_safe(qe, qen, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		bfa_fcs_vport_offline(vport);
+	}
+
+	bfa_fcs_lport_offline(&fabric->bport);
+
+	fabric->fabric_name = 0;
+	fabric->fabric_ip_addr[0] = 0;
+}
+
+static void
+bfa_fcs_fabric_delay(void *cbarg)
+{
+	struct bfa_fcs_fabric_s *fabric = cbarg;
+
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
+}
+
+/**
+ * Delete all vports and wait for vport delete completions.
+ */
+static void
+bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe, *qen;
+
+	list_for_each_safe(qe, qen, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		bfa_fcs_vport_fcs_delete(vport);
+	}
+
+	bfa_fcs_lport_delete(&fabric->bport);
+	bfa_wc_wait(&fabric->wc);
+}
+
+static void
+bfa_fcs_fabric_delete_comp(void *cbarg)
+{
+	struct bfa_fcs_fabric_s *fabric = cbarg;
+
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
+}
+
+/**
+ *  fcs_fabric_public fabric public functions
+ */
+
+/**
+ * Attach time initialization.
+ */
+void
+bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
+{
+	struct bfa_fcs_fabric_s *fabric;
+
+	fabric = &fcs->fabric;
+	bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
+
+	/**
+	 * Initialize base fabric.
+	 */
+	fabric->fcs = fcs;
+	INIT_LIST_HEAD(&fabric->vport_q);
+	INIT_LIST_HEAD(&fabric->vf_q);
+	fabric->lps = bfa_lps_alloc(fcs->bfa);
+	bfa_assert(fabric->lps);
+
+	/**
+	 * Initialize fabric delete completion handler. Fabric deletion is
+	 * complete when the last vport delete is complete.
+	 */
+	bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
+	bfa_wc_up(&fabric->wc); /* For the base port */
+
+	bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
+	bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
+}
+
+void
+bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
+{
+	bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
+	bfa_trc(fcs, 0);
+}
+
+/**
+ *   Module cleanup
+ */
+void
+bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
+{
+	struct bfa_fcs_fabric_s *fabric;
+
+	bfa_trc(fcs, 0);
+
+	/**
+	 * Cleanup base fabric.
+	 */
+	fabric = &fcs->fabric;
+	bfa_lps_delete(fabric->lps);
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
+}
+
+/**
+ * Fabric module start -- kick starts FCS actions
+ */
+void
+bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
+{
+	struct bfa_fcs_fabric_s *fabric;
+
+	bfa_trc(fcs, 0);
+	fabric = &fcs->fabric;
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
+}
+
+/**
+ *   Suspend fabric activity as part of driver suspend.
+ */
+void
+bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
+{
+}
+
+bfa_boolean_t
+bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
+{
+	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
+}
+
+bfa_boolean_t
+bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric)
+{
+	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed);
+}
+
+enum bfa_port_type
+bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
+{
+	return fabric->oper_type;
+}
+
+/**
+ *   Link up notification from BFA physical port module.
+ */
+void
+bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
+}
+
+/**
+ *   Link down notification from BFA physical port module.
+ */
+void
+bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
+{
+	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
+}
+
+/**
+ *   A child vport is being created in the fabric.
+ *
+ *   Call from vport module at vport creation. A list of base port and vports
+ *   belonging to a fabric is maintained to propagate link events.
+ *
+ *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *   param[in] vport  - Vport being created.
+ *
+ *   @return None (always succeeds)
+ */
+void
+bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
+			struct bfa_fcs_vport_s *vport)
+{
+	/**
+	 * - add vport to fabric's vport_q
+	 */
+	bfa_trc(fabric->fcs, fabric->vf_id);
+
+	list_add_tail(&vport->qe, &fabric->vport_q);
+	fabric->num_vports++;
+	bfa_wc_up(&fabric->wc);
+}
+
+/**
+ *   A child vport is being deleted from fabric.
+ *
+ *   Vport is being deleted.
+ */
+void
+bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
+			struct bfa_fcs_vport_s *vport)
+{
+	list_del(&vport->qe);
+	fabric->num_vports--;
+	bfa_wc_down(&fabric->wc);
+}
+
+/**
+ *   Base port is deleted.
+ */
+void
+bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
+{
+	bfa_wc_down(&fabric->wc);
+}
+
+
+/**
+ *    Check if fabric is online.
+ *
+ *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *
+ *   @return  TRUE/FALSE
+ */
+int
+bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
+{
+	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
+}
+
+/**
+ *	brief
+ *
+ */
+bfa_status_t
+bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
+		     struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
+{
+	bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Lookup for a vport withing a fabric given its pwwn
+ */
+struct bfa_fcs_vport_s *
+bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe;
+
+	list_for_each(qe, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		if (bfa_fcs_lport_get_pwwn(&vport->lport) == pwwn)
+			return vport;
+	}
+
+	return NULL;
+}
+
+/**
+ *    In a given fabric, return the number of lports.
+ *
+ *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
+ *
+ *   @return : 1 or more.
+ */
+u16
+bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
+{
+	return fabric->num_vports;
+}
+
+/*
+ *  Get OUI of the attached switch.
+ *
+ *  Note : Use of this function should be avoided as much as possible.
+ *         This function should be used only if there is any requirement
+*          to check for FOS version below 6.3.
+ *         To check if the attached fabric is a brocade fabric, use
+ *         bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
+ *         or above only.
+ */
+
+u16
+bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
+{
+	wwn_t fab_nwwn;
+	u8 *tmp;
+	u16 oui;
+
+	fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps);
+
+	tmp = (u8 *)&fab_nwwn;
+	oui = (tmp[3] << 8) | tmp[4];
+
+	return oui;
+}
+/**
+ *		Unsolicited frame receive handling.
+ */
+void
+bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
+		       u16 len)
+{
+	u32	pid = fchs->d_id;
+	struct bfa_fcs_vport_s *vport;
+	struct list_head	      *qe;
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;
+
+	bfa_trc(fabric->fcs, len);
+	bfa_trc(fabric->fcs, pid);
+
+	/**
+	 * Look for our own FLOGI frames being looped back. This means an
+	 * external loopback cable is in place. Our own FLOGI frames are
+	 * sometimes looped back when switch port gets temporarily bypassed.
+	 */
+	if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT)) &&
+	    (els_cmd->els_code == FC_ELS_FLOGI) &&
+	    (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {
+		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
+		return;
+	}
+
+	/**
+	 * FLOGI/EVFP exchanges should be consumed by base fabric.
+	 */
+	if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
+		bfa_trc(fabric->fcs, pid);
+		bfa_fcs_fabric_process_uf(fabric, fchs, len);
+		return;
+	}
+
+	if (fabric->bport.pid == pid) {
+		/**
+		 * All authentication frames should be routed to auth
+		 */
+		bfa_trc(fabric->fcs, els_cmd->els_code);
+		if (els_cmd->els_code == FC_ELS_AUTH) {
+			bfa_trc(fabric->fcs, els_cmd->els_code);
+			return;
+		}
+
+		bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
+		bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
+		return;
+	}
+
+	/**
+	 * look for a matching local port ID
+	 */
+	list_for_each(qe, &fabric->vport_q) {
+		vport = (struct bfa_fcs_vport_s *) qe;
+		if (vport->lport.pid == pid) {
+			bfa_fcs_lport_uf_recv(&vport->lport, fchs, len);
+			return;
+		}
+	}
+	bfa_trc(fabric->fcs, els_cmd->els_code);
+	bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
+}
+
+/**
+ *		Unsolicited frames to be processed by fabric.
+ */
+static void
+bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
+			  u16 len)
+{
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+	bfa_trc(fabric->fcs, els_cmd->els_code);
+
+	switch (els_cmd->els_code) {
+	case FC_ELS_FLOGI:
+		bfa_fcs_fabric_process_flogi(fabric, fchs, len);
+		break;
+
+	default:
+		/*
+		 * need to generate a LS_RJT
+		 */
+		break;
+	}
+}
+
+/**
+ *	Process	incoming FLOGI
+ */
+static void
+bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
+			struct fchs_s *fchs, u16 len)
+{
+	struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);
+	struct bfa_fcs_lport_s *bport = &fabric->bport;
+
+	bfa_trc(fabric->fcs, fchs->s_id);
+
+	fabric->stats.flogi_rcvd++;
+	/*
+	 * Check port type. It should be 0 = n-port.
+	 */
+	if (flogi->csp.port_type) {
+		/*
+		 * @todo: may need to send a LS_RJT
+		 */
+		bfa_trc(fabric->fcs, flogi->port_name);
+		fabric->stats.flogi_rejected++;
+		return;
+	}
+
+	fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred);
+	bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
+	bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
+
+	/*
+	 * Send a Flogi Acc
+	 */
+	bfa_fcs_fabric_send_flogi_acc(fabric);
+	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
+}
+
+static void
+bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
+{
+	struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
+	struct bfa_fcs_lport_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
+	struct bfa_s	  *bfa = fabric->fcs->bfa;
+	struct bfa_fcxp_s *fcxp;
+	u16	reqlen;
+	struct fchs_s	fchs;
+
+	fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
+	/**
+	 * Do not expect this failure -- expect remote node to retry
+	 */
+	if (!fcxp)
+		return;
+
+	reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				    bfa_os_hton3b(FC_FABRIC_PORT),
+				    n2n_port->reply_oxid, pcfg->pwwn,
+				    pcfg->nwwn,
+				    bfa_fcport_get_maxfrsize(bfa),
+				    bfa_fcport_get_rx_bbcredit(bfa));
+
+	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
+		      BFA_FALSE, FC_CLASS_3,
+		      reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
+		      FC_MAX_PDUSZ, 0);
+}
+
+/**
+ *   Flogi Acc completion callback.
+ */
+static void
+bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+			     bfa_status_t status, u32 rsp_len,
+			     u32 resid_len, struct fchs_s *rspfchs)
+{
+	struct bfa_fcs_fabric_s *fabric = cbarg;
+
+	bfa_trc(fabric->fcs, status);
+}
+
+/*
+ *
+ * @param[in] fabric - fabric
+ * @param[in] wwn_t - new fabric name
+ *
+ * @return - none
+ */
+void
+bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
+			       wwn_t fabric_name)
+{
+	struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
+	char	pwwn_ptr[BFA_STRING_32];
+	char	fwwn_ptr[BFA_STRING_32];
+
+	bfa_trc(fabric->fcs, fabric_name);
+
+	if (fabric->fabric_name == 0) {
+		/*
+		 * With BRCD switches, we don't get Fabric Name in FLOGI.
+		 * Don't generate a fabric name change event in this case.
+		 */
+		fabric->fabric_name = fabric_name;
+	} else {
+		fabric->fabric_name = fabric_name;
+		wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));
+		wwn2str(fwwn_ptr,
+			bfa_fcs_lport_get_fabric_name(&fabric->bport));
+		BFA_LOG(KERN_WARNING, bfad, log_level,
+			"Base port WWN = %s Fabric WWN = %s\n",
+			pwwn_ptr, fwwn_ptr);
+	}
+}
+
+/**
+ *  fcs_vf_api virtual fabrics API
+ */
+
+/**
+ * Enable VF mode.
+ *
+ * @param[in]		fcs		fcs module instance
+ * @param[in]		vf_id		default vf_id of port, FC_VF_ID_NULL
+ *					to use standard default vf_id of 1.
+ *
+ * @retval	BFA_STATUS_OK		vf mode is enabled
+ * @retval	BFA_STATUS_BUSY		Port is active. Port must be disabled
+ *					before VF mode can be enabled.
+ */
+bfa_status_t
+bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id)
+{
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Disable VF mode.
+ *
+ * @param[in]		fcs		fcs module instance
+ *
+ * @retval	BFA_STATUS_OK		vf mode is disabled
+ * @retval	BFA_STATUS_BUSY		VFs are present and being used. All
+ *					VFs must be deleted before disabling
+ *					VF mode.
+ */
+bfa_status_t
+bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs)
+{
+	return BFA_STATUS_OK;
+}
+
+/**
+ *  Create a new VF instance.
+ *
+ *  A new VF is created using the given VF configuration. A VF is identified
+ *  by VF id. No duplicate VF creation is allowed with the same VF id. Once
+ *  a VF is created, VF is automatically started after link initialization
+ *  and EVFP exchange is completed.
+ *
+ *	param[in] vf	 -	FCS vf data structure. Memory is
+ *				allocated by caller (driver)
+ *	param[in] fcs	 -	FCS module
+ *	param[in] vf_cfg -	VF configuration
+ *	param[in] vf_drv -	Opaque handle back to the driver's
+ *				virtual vf structure
+ *
+ *	retval BFA_STATUS_OK VF creation is successful
+ *	retval BFA_STATUS_FAILED VF creation failed
+ *	retval BFA_STATUS_EEXIST A VF exists with the given vf_id
+ */
+bfa_status_t
+bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, u16 vf_id,
+		  struct bfa_lport_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
+{
+	bfa_trc(fcs, vf_id);
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function to delete a BFA VF object. VF object should
+ *	be stopped before this function call.
+ *
+ *	param[in] vf - pointer to bfa_vf_t.
+ *
+ *	retval BFA_STATUS_OK	On vf deletion success
+ *	retval BFA_STATUS_BUSY VF is not in a stopped state
+ *	retval BFA_STATUS_INPROGRESS VF deletion in in progress
+ */
+bfa_status_t
+bfa_fcs_vf_delete(bfa_fcs_vf_t *vf)
+{
+	bfa_trc(vf->fcs, vf->vf_id);
+	return BFA_STATUS_OK;
+}
+
+
+/**
+ *	Returns attributes of the given VF.
+ *
+ *	param[in]	vf	pointer to bfa_vf_t.
+ *	param[out] vf_attr	vf attributes returned
+ *
+ *	return None
+ */
+void
+bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr)
+{
+	bfa_trc(vf->fcs, vf->vf_id);
+}
+
+/**
+ *	Return statistics associated with the given vf.
+ *
+ *	param[in] vf		pointer to bfa_vf_t.
+ *	param[out] vf_stats	vf statistics returned
+ *
+ *	@return None
+ */
+void
+bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, struct bfa_vf_stats_s *vf_stats)
+{
+	bfa_os_memcpy(vf_stats, &vf->stats, sizeof(struct bfa_vf_stats_s));
+}
+
+/**
+ *	clear statistics associated with the given vf.
+ *
+ *	param[in]	vf	pointer to bfa_vf_t.
+ *
+ *	@return None
+ */
+void
+bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf)
+{
+	bfa_os_memset(&vf->stats, 0, sizeof(struct bfa_vf_stats_s));
+}
+
+/**
+ *	Returns FCS vf structure for a given vf_id.
+ *
+ *	param[in]	vf_id - VF_ID
+ *
+ *	return
+ *	If lookup succeeds, retuns fcs vf object, otherwise returns NULL
+ */
+bfa_fcs_vf_t   *
+bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
+{
+	bfa_trc(fcs, vf_id);
+	if (vf_id == FC_VF_ID_NULL)
+		return &fcs->fabric;
+
+	return NULL;
+}
+
+/**
+ *	Return the list of VFs configured.
+ *
+ *	param[in]	fcs	fcs module instance
+ *	param[out]	vf_ids	returned list of vf_ids
+ *	param[in,out]	nvfs	in:size of vf_ids array,
+ *				out:total elements present,
+ *				actual elements returned is limited by the size
+ *
+ *	return Driver VF structure
+ */
+void
+bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
+{
+	bfa_trc(fcs, *nvfs);
+}
+
+/**
+ *	Return the list of all VFs visible from fabric.
+ *
+ *	param[in]	fcs	fcs module instance
+ *	param[out]	vf_ids	returned list of vf_ids
+ *	param[in,out]	nvfs	in:size of vf_ids array,
+ *				out:total elements present,
+ *				actual elements returned is limited by the size
+ *
+ *	return Driver VF structure
+ */
+void
+bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
+{
+	bfa_trc(fcs, *nvfs);
+}
+
+/**
+ *	Return the list of local logical ports present in the given VF.
+ *
+ *	param[in]	vf	vf for which logical ports are returned
+ *	param[out]	lpwwn	returned logical port wwn list
+ *	param[in,out]	nlports	in:size of lpwwn list;
+ *				out:total elements present,
+ *				actual elements returned is limited by the size
+ */
+void
+bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
+{
+	struct list_head	*qe;
+	struct bfa_fcs_vport_s *vport;
+	int	i;
+	struct bfa_fcs_s      *fcs;
+
+	if (vf == NULL || lpwwn == NULL || *nlports == 0)
+		return;
+
+	fcs = vf->fcs;
+
+	bfa_trc(fcs, vf->vf_id);
+	bfa_trc(fcs, (u32) *nlports);
+
+	i = 0;
+	lpwwn[i++] = vf->bport.port_cfg.pwwn;
+
+	list_for_each(qe, &vf->vport_q) {
+		if (i >= *nlports)
+			break;
+
+		vport = (struct bfa_fcs_vport_s *) qe;
+		lpwwn[i++] = vport->lport.port_cfg.pwwn;
+	}
+
+	bfa_trc(fcs, i);
+	*nlports = i;
+}
+
+/**
+ * BFA FCS PPORT ( physical port)
+ */
+static void
+bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)
+{
+	struct bfa_fcs_s      *fcs = cbarg;
+
+	bfa_trc(fcs, event);
+
+	switch (event) {
+	case BFA_PORT_LINKUP:
+		bfa_fcs_fabric_link_up(&fcs->fabric);
+		break;
+
+	case BFA_PORT_LINKDOWN:
+		bfa_fcs_fabric_link_down(&fcs->fabric);
+		break;
+
+	default:
+		bfa_assert(0);
+	}
+}
+
+void
+bfa_fcs_port_attach(struct bfa_fcs_s *fcs)
+{
+	bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);
+}
+
+/**
+ * BFA FCS UF ( Unsolicited Frames)
+ */
+
+/**
+ *		BFA callback for unsolicited frame receive handler.
+ *
+ * @param[in]		cbarg		callback arg for receive handler
+ * @param[in]		uf		unsolicited frame descriptor
+ *
+ * @return None
+ */
+static void
+bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
+{
+	struct bfa_fcs_s	*fcs = (struct bfa_fcs_s *) cbarg;
+	struct fchs_s	*fchs = bfa_uf_get_frmbuf(uf);
+	u16	len = bfa_uf_get_frmlen(uf);
+	struct fc_vft_s *vft;
+	struct bfa_fcs_fabric_s *fabric;
+
+	/**
+	 * check for VFT header
+	 */
+	if (fchs->routing == FC_RTG_EXT_HDR &&
+	    fchs->cat_info == FC_CAT_VFT_HDR) {
+		bfa_stats(fcs, uf.tagged);
+		vft = bfa_uf_get_frmbuf(uf);
+		if (fcs->port_vfid == vft->vf_id)
+			fabric = &fcs->fabric;
+		else
+			fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
+
+		/**
+		 * drop frame if vfid is unknown
+		 */
+		if (!fabric) {
+			bfa_assert(0);
+			bfa_stats(fcs, uf.vfid_unknown);
+			bfa_uf_free(uf);
+			return;
+		}
+
+		/**
+		 * skip vft header
+		 */
+		fchs = (struct fchs_s *) (vft + 1);
+		len -= sizeof(struct fc_vft_s);
+
+		bfa_trc(fcs, vft->vf_id);
+	} else {
+		bfa_stats(fcs, uf.untagged);
+		fabric = &fcs->fabric;
+	}
+
+	bfa_trc(fcs, ((u32 *) fchs)[0]);
+	bfa_trc(fcs, ((u32 *) fchs)[1]);
+	bfa_trc(fcs, ((u32 *) fchs)[2]);
+	bfa_trc(fcs, ((u32 *) fchs)[3]);
+	bfa_trc(fcs, ((u32 *) fchs)[4]);
+	bfa_trc(fcs, ((u32 *) fchs)[5]);
+	bfa_trc(fcs, len);
+
+	bfa_fcs_fabric_uf_recv(fabric, fchs, len);
+	bfa_uf_free(uf);
+}
+
+void
+bfa_fcs_uf_attach(struct bfa_fcs_s *fcs)
+{
+	bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
+}
diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h
new file mode 100644
index 0000000..d75045d
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcs.h
@@ -0,0 +1,779 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFA_FCS_H__
+#define __BFA_FCS_H__
+
+#include "bfa_cs.h"
+#include "bfa_defs.h"
+#include "bfa_defs_fcs.h"
+#include "bfa_modules.h"
+#include "bfa_fc.h"
+
+#define BFA_FCS_OS_STR_LEN		64
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+	BFA_TRC_FCS_FCS		= 1,
+	BFA_TRC_FCS_PORT	= 2,
+	BFA_TRC_FCS_RPORT	= 3,
+	BFA_TRC_FCS_FCPIM	= 4,
+};
+
+
+struct bfa_fcs_s;
+
+#define __fcs_min_cfg(__fcs)       ((__fcs)->min_cfg)
+void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
+
+#define BFA_FCS_BRCD_SWITCH_OUI  0x051e
+#define N2N_LOCAL_PID	    0x010000
+#define N2N_REMOTE_PID		0x020000
+#define	BFA_FCS_RETRY_TIMEOUT 2000
+#define BFA_FCS_PID_IS_WKA(pid)  ((bfa_os_ntoh3b(pid) > 0xFFF000) ?  1 : 0)
+
+
+
+struct bfa_fcs_lport_ns_s {
+	bfa_sm_t        sm;		/*  state machine */
+	struct bfa_timer_s timer;
+	struct bfa_fcs_lport_s *port;	/*  parent port */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+};
+
+
+struct bfa_fcs_lport_scn_s {
+	bfa_sm_t        sm;		/*  state machine */
+	struct bfa_timer_s timer;
+	struct bfa_fcs_lport_s *port;	/*  parent port */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+};
+
+
+struct bfa_fcs_lport_fdmi_s {
+	bfa_sm_t        sm;		/*  state machine */
+	struct bfa_timer_s timer;
+	struct bfa_fcs_lport_ms_s *ms;	/*  parent ms */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+	u8	retry_cnt;	/*  retry count */
+	u8	rsvd[3];
+};
+
+
+struct bfa_fcs_lport_ms_s {
+	bfa_sm_t        sm;		/*  state machine */
+	struct bfa_timer_s timer;
+	struct bfa_fcs_lport_s *port;	/*  parent port */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+	struct bfa_fcs_lport_fdmi_s fdmi;	/*  FDMI component of MS */
+	u8         retry_cnt;	/*  retry count */
+	u8	rsvd[3];
+};
+
+
+struct bfa_fcs_lport_fab_s {
+	struct bfa_fcs_lport_ns_s ns;	/*  NS component of port */
+	struct bfa_fcs_lport_scn_s scn;	/*  scn component of port */
+	struct bfa_fcs_lport_ms_s ms;	/*  MS component of port */
+};
+
+#define	MAX_ALPA_COUNT	127
+
+struct bfa_fcs_lport_loop_s {
+	u8         num_alpa;	/*  Num of ALPA entries in the map */
+	u8         alpa_pos_map[MAX_ALPA_COUNT];	/*  ALPA Positional
+							 *Map */
+	struct bfa_fcs_lport_s *port;	/*  parent port */
+};
+
+struct bfa_fcs_lport_n2n_s {
+	u32        rsvd;
+	u16        reply_oxid;	/*  ox_id from the req flogi to be
+					 *used in flogi acc */
+	wwn_t           rem_port_wwn;	/*  Attached port's wwn */
+};
+
+
+union bfa_fcs_lport_topo_u {
+	struct bfa_fcs_lport_fab_s pfab;
+	struct bfa_fcs_lport_loop_s ploop;
+	struct bfa_fcs_lport_n2n_s pn2n;
+};
+
+
+struct bfa_fcs_lport_s {
+	struct list_head         qe;	/*  used by port/vport */
+	bfa_sm_t               sm;	/*  state machine */
+	struct bfa_fcs_fabric_s *fabric;	/*  parent fabric */
+	struct bfa_lport_cfg_s  port_cfg;	/*  port configuration */
+	struct bfa_timer_s link_timer;	/*  timer for link offline */
+	u32        pid:24;	/*  FC address */
+	u8         lp_tag;		/*  lport tag */
+	u16        num_rports;	/*  Num of r-ports */
+	struct list_head         rport_q; /*  queue of discovered r-ports */
+	struct bfa_fcs_s *fcs;	/*  FCS instance */
+	union bfa_fcs_lport_topo_u port_topo;	/*  fabric/loop/n2n details */
+	struct bfad_port_s *bfad_port;	/*  driver peer instance */
+	struct bfa_fcs_vport_s *vport;	/*  NULL for base ports */
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_fcxp_wqe_s fcxp_wqe;
+	struct bfa_lport_stats_s stats;
+	struct bfa_wc_s        wc;	/*  waiting counter for events */
+};
+#define BFA_FCS_GET_HAL_FROM_PORT(port)  (port->fcs->bfa)
+#define BFA_FCS_GET_NS_FROM_PORT(port)  (&port->port_topo.pfab.ns)
+#define BFA_FCS_GET_SCN_FROM_PORT(port)  (&port->port_topo.pfab.scn)
+#define BFA_FCS_GET_MS_FROM_PORT(port)  (&port->port_topo.pfab.ms)
+#define BFA_FCS_GET_FDMI_FROM_PORT(port)  (&port->port_topo.pfab.ms.fdmi)
+#define	BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \
+		(port->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)
+
+/*
+ * forward declaration
+ */
+struct bfad_vf_s;
+
+enum bfa_fcs_fabric_type {
+	BFA_FCS_FABRIC_UNKNOWN = 0,
+	BFA_FCS_FABRIC_SWITCHED = 1,
+	BFA_FCS_FABRIC_N2N = 2,
+};
+
+
+struct bfa_fcs_fabric_s {
+	struct list_head   qe;		/*  queue element */
+	bfa_sm_t	 sm;		/*  state machine */
+	struct bfa_fcs_s *fcs;		/*  FCS instance */
+	struct bfa_fcs_lport_s  bport;	/*  base logical port */
+	enum bfa_fcs_fabric_type fab_type; /*  fabric type */
+	enum bfa_port_type oper_type;	/*  current link topology */
+	u8         is_vf;		/*  is virtual fabric? */
+	u8         is_npiv;	/*  is NPIV supported ? */
+	u8         is_auth;	/*  is Security/Auth supported ? */
+	u16        bb_credit;	/*  BB credit from fabric */
+	u16        vf_id;		/*  virtual fabric ID */
+	u16        num_vports;	/*  num vports */
+	u16        rsvd;
+	struct list_head         vport_q;	/*  queue of virtual ports */
+	struct list_head         vf_q;	/*  queue of virtual fabrics */
+	struct bfad_vf_s      *vf_drv;	/*  driver vf structure */
+	struct bfa_timer_s link_timer;	/*  Link Failure timer. Vport */
+	wwn_t           fabric_name;	/*  attached fabric name */
+	bfa_boolean_t   auth_reqd;	/*  authentication required	*/
+	struct bfa_timer_s delay_timer;	/*  delay timer		*/
+	union {
+		u16        swp_vfid;/*  switch port VF id		*/
+	} event_arg;
+	struct bfa_wc_s        wc;	/*  wait counter for delete	*/
+	struct bfa_vf_stats_s	stats;	/*  fabric/vf stats		*/
+	struct bfa_lps_s	*lps;	/*  lport login services	*/
+	u8	fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];
+					/*  attached fabric's ip addr  */
+};
+
+#define bfa_fcs_fabric_npiv_capable(__f)    ((__f)->is_npiv)
+#define bfa_fcs_fabric_is_switched(__f)			\
+	((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED)
+
+/**
+ *   The design calls for a single implementation of base fabric and vf.
+ */
+#define bfa_fcs_vf_t struct bfa_fcs_fabric_s
+
+struct bfa_vf_event_s {
+	u32        undefined;
+};
+
+struct bfa_fcs_s;
+struct bfa_fcs_fabric_s;
+
+/*
+ * @todo : need to move to a global config file.
+ * Maximum Rports supported per port (physical/logical).
+ */
+#define BFA_FCS_MAX_RPORTS_SUPP  256	/* @todo : tentative value */
+
+#define bfa_fcs_lport_t struct bfa_fcs_lport_s
+
+/**
+ * Symbolic Name related defines
+ *  Total bytes 255.
+ *  Physical Port's symbolic name 128 bytes.
+ *  For Vports, Vport's symbolic name is appended to the Physical port's
+ *  Symbolic Name.
+ *
+ *  Physical Port's symbolic name Format : (Total 128 bytes)
+ *  Adapter Model number/name : 12 bytes
+ *  Driver Version     : 10 bytes
+ *  Host Machine Name  : 30 bytes
+ *  Host OS Info	   : 48 bytes
+ *  Host OS PATCH Info : 16 bytes
+ *  ( remaining 12 bytes reserved to be used for separator)
+ */
+#define BFA_FCS_PORT_SYMBNAME_SEPARATOR			" | "
+
+#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ			12
+#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ		10
+#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ		30
+#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ			48
+#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ		16
+
+/**
+ * Get FC port ID for a logical port.
+ */
+#define bfa_fcs_lport_get_fcid(_lport)	((_lport)->pid)
+#define bfa_fcs_lport_get_pwwn(_lport)	((_lport)->port_cfg.pwwn)
+#define bfa_fcs_lport_get_nwwn(_lport)	((_lport)->port_cfg.nwwn)
+#define bfa_fcs_lport_get_psym_name(_lport)	((_lport)->port_cfg.sym_name)
+#define bfa_fcs_lport_is_initiator(_lport)			\
+	((_lport)->port_cfg.roles & BFA_LPORT_ROLE_FCP_IM)
+#define bfa_fcs_lport_get_nrports(_lport)	\
+	((_lport) ? (_lport)->num_rports : 0)
+
+static inline struct bfad_port_s *
+bfa_fcs_lport_get_drvport(struct bfa_fcs_lport_s *port)
+{
+	return port->bfad_port;
+}
+
+#define bfa_fcs_lport_get_opertype(_lport)	((_lport)->fabric->oper_type)
+#define bfa_fcs_lport_get_fabric_name(_lport)	((_lport)->fabric->fabric_name)
+#define bfa_fcs_lport_get_fabric_ipaddr(_lport)		\
+		((_lport)->fabric->fabric_ip_addr)
+
+/**
+ * bfa fcs port public functions
+ */
+
+bfa_boolean_t   bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port);
+struct bfa_fcs_lport_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
+void bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
+			      wwn_t rport_wwns[], int *nrports);
+
+wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
+			      int index, int nrports, bfa_boolean_t bwwn);
+
+struct bfa_fcs_lport_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
+					    u16 vf_id, wwn_t lpwwn);
+
+void bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
+			    struct bfa_lport_info_s *port_info);
+void bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s *port,
+			    struct bfa_lport_attr_s *port_attr);
+void bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
+			     struct bfa_lport_stats_s *port_stats);
+void bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port);
+enum bfa_port_speed bfa_fcs_lport_get_rport_max_speed(
+			struct bfa_fcs_lport_s *port);
+
+/* MS FCS routines */
+void bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port);
+void bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port);
+
+/* FDMI FCS routines */
+void bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms);
+void bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms);
+void bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms);
+void bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport, struct fchs_s *fchs,
+				     u16 len);
+void bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
+			u16 vf_id, struct bfa_fcs_vport_s *vport);
+void bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
+				struct bfa_lport_cfg_s *port_cfg);
+void            bfa_fcs_lport_online(struct bfa_fcs_lport_s *port);
+void            bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port);
+void            bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pid(
+		struct bfa_fcs_lport_s *port, u32 pid);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_pwwn(
+		struct bfa_fcs_lport_s *port, wwn_t pwwn);
+struct bfa_fcs_rport_s *bfa_fcs_lport_get_rport_by_nwwn(
+		struct bfa_fcs_lport_s *port, wwn_t nwwn);
+void            bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s *port,
+				       struct bfa_fcs_rport_s *rport);
+void            bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s *port,
+				       struct bfa_fcs_rport_s *rport);
+void bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs);
+void            bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port);
+void            bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *vport);
+void            bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
+					      struct fchs_s *rx_frame, u32 len);
+
+struct bfa_fcs_vport_s {
+	struct list_head		qe;		/*  queue elem	*/
+	bfa_sm_t		sm;		/*  state machine	*/
+	bfa_fcs_lport_t		lport;		/*  logical port	*/
+	struct bfa_timer_s	timer;
+	struct bfad_vport_s	*vport_drv;	/*  Driver private	*/
+	struct bfa_vport_stats_s vport_stats;	/*  vport statistics	*/
+	struct bfa_lps_s	*lps;		/*  Lport login service*/
+	int			fdisc_retries;
+};
+
+#define bfa_fcs_vport_get_port(vport)			\
+	((struct bfa_fcs_lport_s  *)(&vport->port))
+
+/**
+ * bfa fcs vport public functions
+ */
+bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport,
+				  struct bfa_fcs_s *fcs, u16 vf_id,
+				  struct bfa_lport_cfg_s *port_cfg,
+				  struct bfad_vport_s *vport_drv);
+bfa_status_t bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport,
+				      struct bfa_fcs_s *fcs, u16 vf_id,
+				      struct bfa_lport_cfg_s *port_cfg,
+				      struct bfad_vport_s *vport_drv);
+bfa_boolean_t bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport);
+bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
+			    struct bfa_vport_attr_s *vport_attr);
+void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
+			     struct bfa_vport_stats_s *vport_stats);
+void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);
+struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,
+					     u16 vf_id, wwn_t vpwwn);
+void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
+void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
+
+#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT	90	/* in secs */
+#define BFA_FCS_RPORT_MAX_RETRIES	(5)
+
+/*
+ * forward declarations
+ */
+struct bfad_rport_s;
+
+struct bfa_fcs_itnim_s;
+struct bfa_fcs_tin_s;
+struct bfa_fcs_iprp_s;
+
+/* Rport Features (RPF) */
+struct bfa_fcs_rpf_s {
+	bfa_sm_t	sm;	/*  state machine */
+	struct bfa_fcs_rport_s *rport;	/*  parent rport */
+	struct bfa_timer_s	timer;	/*  general purpose timer */
+	struct bfa_fcxp_s	*fcxp;	/*  FCXP needed for discarding */
+	struct bfa_fcxp_wqe_s	fcxp_wqe; /*  fcxp wait queue element */
+	int	rpsc_retries;	/*  max RPSC retry attempts */
+	enum bfa_port_speed	rpsc_speed;
+	/*  Current Speed from RPSC. O if RPSC fails */
+	enum bfa_port_speed	assigned_speed;
+	/**
+	 * Speed assigned by the user.  will be used if RPSC is
+	 * not supported by the rport.
+	 */
+};
+
+struct bfa_fcs_rport_s {
+	struct list_head	qe;	/*  used by port/vport */
+	struct bfa_fcs_lport_s *port;	/*  parent FCS port */
+	struct bfa_fcs_s	*fcs;	/*  fcs instance */
+	struct bfad_rport_s	*rp_drv;	/*  driver peer instance */
+	u32	pid;	/*  port ID of rport */
+	u16	maxfrsize;	/*  maximum frame size */
+	u16	reply_oxid;	/*  OX_ID of inbound requests */
+	enum fc_cos	fc_cos;	/*  FC classes of service supp */
+	bfa_boolean_t	cisc;	/*  CISC capable device */
+	bfa_boolean_t	prlo;	/*  processing prlo or LOGO */
+	wwn_t	pwwn;	/*  port wwn of rport */
+	wwn_t	nwwn;	/*  node wwn of rport */
+	struct bfa_rport_symname_s psym_name; /*  port symbolic name  */
+	bfa_sm_t	sm;		/*  state machine */
+	struct bfa_timer_s timer;	/*  general purpose timer */
+	struct bfa_fcs_itnim_s *itnim;	/*  ITN initiator mode role */
+	struct bfa_fcs_tin_s *tin;	/*  ITN initiator mode role */
+	struct bfa_fcs_iprp_s *iprp;	/*  IP/FC role */
+	struct bfa_rport_s *bfa_rport;	/*  BFA Rport */
+	struct bfa_fcxp_s *fcxp;	/*  FCXP needed for discarding */
+	int	plogi_retries;	/*  max plogi retry attempts */
+	int	ns_retries;	/*  max NS query retry attempts */
+	struct bfa_fcxp_wqe_s	fcxp_wqe; /*  fcxp wait queue element */
+	struct bfa_rport_stats_s stats;	/*  rport stats */
+	enum bfa_rport_function	scsi_function;  /*  Initiator/Target */
+	struct bfa_fcs_rpf_s rpf;	/* Rport features module */
+};
+
+static inline struct bfa_rport_s *
+bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
+{
+	return rport->bfa_rport;
+}
+
+/**
+ * bfa fcs rport API functions
+ */
+bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
+			       struct bfa_fcs_rport_s *rport,
+			       struct bfad_rport_s *rport_drv);
+bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+			    struct bfa_rport_attr_s *attr);
+void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
+			     struct bfa_rport_stats_s *stats);
+void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport);
+struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port,
+					     wwn_t rpwwn);
+struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
+	struct bfa_fcs_lport_s *port, wwn_t rnwwn);
+void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
+
+void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
+			     enum bfa_port_speed speed);
+void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
+	 struct fchs_s *fchs, u16 len);
+void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
+
+struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_lport_s *port,
+	 u32 pid);
+void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
+			 struct fc_logi_s *plogi_rsp);
+void bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port,
+				struct fchs_s *rx_fchs,
+				struct fc_logi_s *plogi);
+void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
+			 struct fc_logi_s *plogi);
+void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id);
+
+void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
+int  bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
+struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(
+			struct bfa_fcs_lport_s *port, wwn_t wwn);
+void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport);
+void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport);
+void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport);
+
+/*
+ * forward declarations
+ */
+struct bfad_itnim_s;
+
+struct bfa_fcs_itnim_s {
+	bfa_sm_t		sm;		/*  state machine */
+	struct bfa_fcs_rport_s	*rport;		/*  parent remote rport  */
+	struct bfad_itnim_s	*itnim_drv;	/*  driver peer instance */
+	struct bfa_fcs_s	*fcs;		/*  fcs instance	*/
+	struct bfa_timer_s	timer;		/*  timer functions	*/
+	struct bfa_itnim_s	*bfa_itnim;	/*  BFA itnim struct	*/
+	u32		prli_retries;	/*  max prli retry attempts */
+	bfa_boolean_t		seq_rec;	/*  seq recovery support */
+	bfa_boolean_t		rec_support;	/*  REC supported	*/
+	bfa_boolean_t		conf_comp;	/*  FCP_CONF	support */
+	bfa_boolean_t		task_retry_id;	/*  task retry id supp	*/
+	struct bfa_fcxp_wqe_s	fcxp_wqe;	/*  wait qelem for fcxp  */
+	struct bfa_fcxp_s	*fcxp;		/*  FCXP in use	*/
+	struct bfa_itnim_stats_s	stats;	/*  itn statistics	*/
+};
+#define bfa_fcs_fcxp_alloc(__fcs)	\
+	bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
+
+#define bfa_fcs_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg) \
+	bfa_fcxp_alloc_wait(__bfa, __wqe, __alloc_cbfn, __alloc_cbarg, \
+					NULL, 0, 0, NULL, NULL, NULL, NULL)
+
+static inline struct bfad_port_s *
+bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->port->bfad_port;
+}
+
+
+static inline struct bfa_fcs_lport_s *
+bfa_fcs_itnim_get_port(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->port;
+}
+
+
+static inline wwn_t
+bfa_fcs_itnim_get_nwwn(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->nwwn;
+}
+
+
+static inline wwn_t
+bfa_fcs_itnim_get_pwwn(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->pwwn;
+}
+
+
+static inline u32
+bfa_fcs_itnim_get_fcid(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->pid;
+}
+
+
+static inline	u32
+bfa_fcs_itnim_get_maxfrsize(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->maxfrsize;
+}
+
+
+static inline	enum fc_cos
+bfa_fcs_itnim_get_cos(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->rport->fc_cos;
+}
+
+
+static inline struct bfad_itnim_s *
+bfa_fcs_itnim_get_drvitn(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->itnim_drv;
+}
+
+
+static inline struct bfa_itnim_s *
+bfa_fcs_itnim_get_halitn(struct bfa_fcs_itnim_s *itnim)
+{
+	return itnim->bfa_itnim;
+}
+
+/**
+ * bfa fcs FCP Initiator mode API functions
+ */
+void bfa_fcs_itnim_get_attr(struct bfa_fcs_itnim_s *itnim,
+			    struct bfa_itnim_attr_s *attr);
+void bfa_fcs_itnim_get_stats(struct bfa_fcs_itnim_s *itnim,
+			     struct bfa_itnim_stats_s *stats);
+struct bfa_fcs_itnim_s *bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port,
+					     wwn_t rpwwn);
+bfa_status_t bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
+				    struct bfa_itnim_attr_s *attr);
+bfa_status_t bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
+				     struct bfa_itnim_stats_s *stats);
+bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port,
+				       wwn_t rpwwn);
+struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
+void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim);
+bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
+void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
+			struct fchs_s *fchs, u16 len);
+
+#define	BFA_FCS_FDMI_SUPORTED_SPEEDS  (FDMI_TRANS_SPEED_1G  |	\
+				       FDMI_TRANS_SPEED_2G |	\
+				       FDMI_TRANS_SPEED_4G |	\
+				       FDMI_TRANS_SPEED_8G)
+
+/*
+ * HBA Attribute Block : BFA internal representation. Note : Some variable
+ * sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
+ * on this the size has been reduced to 16 bytes from the standard's 64 bytes.
+ */
+struct bfa_fcs_fdmi_hba_attr_s {
+	wwn_t           node_name;
+	u8         manufacturer[64];
+	u8         serial_num[64];
+	u8         model[16];
+	u8         model_desc[256];
+	u8         hw_version[8];
+	u8         driver_version[8];
+	u8         option_rom_ver[BFA_VERSION_LEN];
+	u8         fw_version[8];
+	u8         os_name[256];
+	u32        max_ct_pyld;
+};
+
+/*
+ * Port Attribute Block
+ */
+struct bfa_fcs_fdmi_port_attr_s {
+	u8         supp_fc4_types[32];	/* supported FC4 types */
+	u32        supp_speed;	/* supported speed */
+	u32        curr_speed;	/* current Speed */
+	u32        max_frm_size;	/* max frame size */
+	u8         os_device_name[256];	/* OS device Name */
+	u8         host_name[256];	/* host name */
+};
+
+struct bfa_fcs_stats_s {
+	struct {
+		u32	untagged; /*  untagged receive frames */
+		u32	tagged;	/*  tagged receive frames */
+		u32	vfid_unknown;	/*  VF id is unknown */
+	} uf;
+};
+
+struct bfa_fcs_driver_info_s {
+	u8	 version[BFA_VERSION_LEN];		/* Driver Version */
+	u8	 host_machine_name[BFA_FCS_OS_STR_LEN];
+	u8	 host_os_name[BFA_FCS_OS_STR_LEN]; /* OS name and version */
+	u8	 host_os_patch[BFA_FCS_OS_STR_LEN]; /* patch or service pack */
+	u8	 os_device_name[BFA_FCS_OS_STR_LEN]; /* Driver Device Name */
+};
+
+struct bfa_fcs_s {
+	struct bfa_s	  *bfa;	/*  corresponding BFA bfa instance */
+	struct bfad_s	      *bfad; /*  corresponding BDA driver instance */
+	struct bfa_trc_mod_s  *trcmod;	/*  tracing module */
+	bfa_boolean_t	vf_enabled;	/*  VF mode is enabled */
+	bfa_boolean_t	fdmi_enabled;	/*  FDMI is enabled */
+	bfa_boolean_t min_cfg;		/* min cfg enabled/disabled */
+	u16	port_vfid;	/*  port default VF ID */
+	struct bfa_fcs_driver_info_s driver_info;
+	struct bfa_fcs_fabric_s fabric; /*  base fabric state machine */
+	struct bfa_fcs_stats_s	stats;	/*  FCS statistics */
+	struct bfa_wc_s		wc;	/*  waiting counter */
+};
+
+/*
+ * bfa fcs API functions
+ */
+void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
+		    struct bfad_s *bfad,
+		    bfa_boolean_t min_cfg);
+void bfa_fcs_init(struct bfa_fcs_s *fcs);
+void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
+			      struct bfa_fcs_driver_info_s *driver_info);
+void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable);
+void bfa_fcs_exit(struct bfa_fcs_s *fcs);
+void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod);
+void		bfa_fcs_start(struct bfa_fcs_s *fcs);
+
+/**
+ * bfa fcs vf public functions
+ */
+bfa_status_t bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id);
+bfa_status_t bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs);
+bfa_status_t bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs,
+			       u16 vf_id, struct bfa_lport_cfg_s *port_cfg,
+			       struct bfad_vf_s *vf_drv);
+bfa_status_t bfa_fcs_vf_delete(bfa_fcs_vf_t *vf);
+void bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
+void bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
+void bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr);
+void bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf,
+			  struct bfa_vf_stats_s *vf_stats);
+void bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf);
+void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
+bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
+u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
+
+/*
+ * fabric protected interface functions
+ */
+void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
+	struct bfa_fcs_vport_s *vport);
+void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
+	struct bfa_fcs_vport_s *vport);
+int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
+struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
+		struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
+void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
+void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
+		struct fchs_s *fchs, u16 len);
+bfa_boolean_t	bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
+bfa_boolean_t	bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric);
+enum bfa_port_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
+void	bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
+void	bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
+bfa_status_t	bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
+			struct bfa_fcs_s *fcs, struct bfa_lport_cfg_s *port_cfg,
+			struct bfad_vf_s *vf_drv);
+void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
+	       wwn_t fabric_name);
+u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
+void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
+void bfa_fcs_port_attach(struct bfa_fcs_s *fcs);
+
+/**
+ * BFA FCS callback interfaces
+ */
+
+/**
+ * fcb Main fcs callbacks
+ */
+
+struct bfad_port_s;
+struct bfad_vf_s;
+struct bfad_vport_s;
+struct bfad_rport_s;
+
+/**
+ * lport callbacks
+ */
+struct bfad_port_s *bfa_fcb_lport_new(struct bfad_s *bfad,
+				      struct bfa_fcs_lport_s *port,
+				      enum bfa_lport_role roles,
+				      struct bfad_vf_s *vf_drv,
+				      struct bfad_vport_s *vp_drv);
+void bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
+			  struct bfad_vf_s *vf_drv,
+			  struct bfad_vport_s *vp_drv);
+
+/**
+ * vport callbacks
+ */
+void bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s);
+
+/**
+ * rport callbacks
+ */
+bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad,
+				 struct bfa_fcs_rport_s **rport,
+				 struct bfad_rport_s **rport_drv);
+
+/**
+ * itnim callbacks
+ */
+void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
+			 struct bfad_itnim_s **itnim_drv);
+void bfa_fcb_itnim_free(struct bfad_s *bfad,
+			struct bfad_itnim_s *itnim_drv);
+void bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv);
+void bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv);
+
+#endif /* __BFA_FCS_H__ */
diff --git a/drivers/scsi/bfa/fcpim.c b/drivers/scsi/bfa/bfa_fcs_fcpim.c
similarity index 75%
rename from drivers/scsi/bfa/fcpim.c
rename to drivers/scsi/bfa/bfa_fcs_fcpim.c
index 6b8976a..569dfef 100644
--- a/drivers/scsi/bfa/fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcs_fcpim.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -19,36 +19,24 @@
  *  fcpim.c - FCP initiator mode i-t nexus state machine
  */
 
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_fcpim.h"
-#include "fcs_rport.h"
-#include "fcs_lport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include <fcs/bfa_fcs_fcpim.h>
-#include <fcb/bfa_fcb_fcpim.h>
-#include <aen/bfa_aen_itnim.h>
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
+#include "bfad_drv.h"
+#include "bfad_im.h"
 
 BFA_TRC_FILE(FCS, FCPIM);
 
 /*
  * forward declarations
  */
-static void     bfa_fcs_itnim_timeout(void *arg);
-static void     bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
-static void     bfa_fcs_itnim_send_prli(void *itnim_cbarg,
+static void	bfa_fcs_itnim_timeout(void *arg);
+static void	bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
+static void	bfa_fcs_itnim_send_prli(void *itnim_cbarg,
 					struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_itnim_prli_response(void *fcsarg,
-					    struct bfa_fcxp_s *fcxp,
-					    void *cbarg,
-					    bfa_status_t req_status,
-					    u32 rsp_len,
-					    u32 resid_len,
-					    struct fchs_s *rsp_fchs);
-static void     bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
-				       enum bfa_itnim_aen_event event);
+static void	bfa_fcs_itnim_prli_response(void *fcsarg,
+			 struct bfa_fcxp_s *fcxp, void *cbarg,
+			    bfa_status_t req_status, u32 rsp_len,
+			    u32 resid_len, struct fchs_s *rsp_fchs);
 
 /**
  *  fcs_itnim_sm FCS itnim state machine events
@@ -61,28 +49,28 @@
 	BFA_FCS_ITNIM_SM_RSP_OK = 4,	/*  good response */
 	BFA_FCS_ITNIM_SM_RSP_ERROR = 5,	/*  error response */
 	BFA_FCS_ITNIM_SM_TIMEOUT = 6,	/*  delay timeout */
-	BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7,	/*  BFA online callback */
-	BFA_FCS_ITNIM_SM_HCB_ONLINE = 8,	/*  BFA offline callback */
+	BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /*  BFA online callback */
+	BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /*  BFA offline callback */
 	BFA_FCS_ITNIM_SM_INITIATOR = 9,	/*  rport is initiator */
 	BFA_FCS_ITNIM_SM_DELETE = 10,	/*  delete event from rport */
 	BFA_FCS_ITNIM_SM_PRLO = 11,	/*  delete event from rport */
 };
 
-static void     bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
+static void	bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
 					 enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
+static void	bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
 					   enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
+static void	bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
 				      enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
+static void	bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
 					    enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
+static void	bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
 					    enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
+static void	bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
 					enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
+static void	bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
 					     enum bfa_fcs_itnim_event event);
-static void     bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
+static void	bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
 					   enum bfa_fcs_itnim_event event);
 
 static struct bfa_sm_table_s itnim_sm_table[] = {
@@ -102,7 +90,7 @@
 
 static void
 bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
-			 enum bfa_fcs_itnim_event event)
+		 enum bfa_fcs_itnim_event event)
 {
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 	bfa_trc(itnim->fcs, event);
@@ -134,7 +122,7 @@
 
 static void
 bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
-			   enum bfa_fcs_itnim_event event)
+		 enum bfa_fcs_itnim_event event)
 {
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 	bfa_trc(itnim->fcs, event);
@@ -168,7 +156,7 @@
 
 static void
 bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
-		      enum bfa_fcs_itnim_event event)
+		 enum bfa_fcs_itnim_event event)
 {
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 	bfa_trc(itnim->fcs, event);
@@ -233,6 +221,7 @@
 		}
 		break;
 
+
 	case BFA_FCS_ITNIM_SM_OFFLINE:
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
 		bfa_timer_stop(&itnim->timer);
@@ -259,6 +248,10 @@
 bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
 			    enum bfa_fcs_itnim_event event)
 {
+	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+	char	rpwwn_buf[BFA_STRING_32];
+
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 	bfa_trc(itnim->fcs, event);
 
@@ -266,7 +259,11 @@
 	case BFA_FCS_ITNIM_SM_HCB_ONLINE:
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
 		bfa_fcb_itnim_online(itnim->itnim_drv);
-		bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
+		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
+		wwn2str(rpwwn_buf, itnim->rport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+		"Target (WWN = %s) is online for initiator (WWN = %s)\n",
+		rpwwn_buf, lpwwn_buf);
 		break;
 
 	case BFA_FCS_ITNIM_SM_OFFLINE:
@@ -287,8 +284,12 @@
 
 static void
 bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
-			enum bfa_fcs_itnim_event event)
+		 enum bfa_fcs_itnim_event event)
 {
+	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+	char	rpwwn_buf[BFA_STRING_32];
+
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 	bfa_trc(itnim->fcs, event);
 
@@ -297,10 +298,16 @@
 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
 		bfa_fcb_itnim_offline(itnim->itnim_drv);
 		bfa_itnim_offline(itnim->bfa_itnim);
-		if (bfa_fcs_port_is_online(itnim->rport->port) == BFA_TRUE)
-			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
+		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
+		wwn2str(rpwwn_buf, itnim->rport->pwwn);
+		if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE)
+			BFA_LOG(KERN_ERR, bfad, log_level,
+			"Target (WWN = %s) connectivity lost for "
+			"initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
 		else
-			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
+			BFA_LOG(KERN_INFO, bfad, log_level,
+			"Target (WWN = %s) offlined by initiator (WWN = %s)\n",
+			rpwwn_buf, lpwwn_buf);
 		break;
 
 	case BFA_FCS_ITNIM_SM_DELETE:
@@ -343,7 +350,7 @@
  */
 static void
 bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
-			   enum bfa_fcs_itnim_event event)
+		 enum bfa_fcs_itnim_event event)
 {
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 	bfa_trc(itnim->fcs, event);
@@ -369,71 +376,34 @@
 	}
 }
 
-
-
-/**
- *  itnim_private FCS ITNIM private interfaces
- */
-
-static void
-bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
-		       enum bfa_itnim_aen_event event)
-{
-	struct bfa_fcs_rport_s *rport = itnim->rport;
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = rport->fcs->logm;
-	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(rport->port);
-	wwn_t           rpwwn = rport->pwwn;
-	char            lpwwn_ptr[BFA_STRING_32];
-	char            rpwwn_ptr[BFA_STRING_32];
-
-	/*
-	 * Don't post events for well known addresses
-	 */
-	if (BFA_FCS_PID_IS_WKA(rport->pid))
-		return;
-
-	wwn2str(lpwwn_ptr, lpwwn);
-	wwn2str(rpwwn_ptr, rpwwn);
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, event),
-		rpwwn_ptr, lpwwn_ptr);
-
-	aen_data.itnim.vf_id = rport->port->fabric->vf_id;
-	aen_data.itnim.ppwwn =
-		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(itnim->fcs));
-	aen_data.itnim.lpwwn = lpwwn;
-	aen_data.itnim.rpwwn = rpwwn;
-}
-
 static void
 bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 {
 	struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
 	struct bfa_fcs_rport_s *rport = itnim->rport;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
 	struct bfa_fcxp_s *fcxp;
-	int             len;
+	int		len;
 
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 
 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
 	if (!fcxp) {
 		itnim->stats.fcxp_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
 				    bfa_fcs_itnim_send_prli, itnim);
 		return;
 	}
 	itnim->fcxp = fcxp;
 
-	len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), itnim->rport->pid,
-			    bfa_fcs_port_get_fcid(port), 0);
+	len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			    itnim->rport->pid, bfa_fcs_lport_get_fcid(port), 0);
 
 	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
 		      BFA_FALSE, FC_CLASS_3, len, &fchs,
-		      bfa_fcs_itnim_prli_response, (void *)itnim, FC_MAX_PDUSZ,
-		      FC_ELS_TOV);
+		      bfa_fcs_itnim_prli_response, (void *)itnim,
+		      FC_MAX_PDUSZ, FC_ELS_TOV);
 
 	itnim->stats.prli_sent++;
 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
@@ -444,10 +414,10 @@
 			    bfa_status_t req_status, u32 rsp_len,
 			    u32 resid_len, struct fchs_s *rsp_fchs)
 {
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
-	struct fc_els_cmd_s   *els_cmd;
-	struct fc_prli_s      *prli_resp;
-	struct fc_ls_rjt_s    *ls_rjt;
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
+	struct fc_els_cmd_s *els_cmd;
+	struct fc_prli_s *prli_resp;
+	struct fc_ls_rjt_s *ls_rjt;
 	struct fc_prli_params_s *sparams;
 
 	bfa_trc(itnim->fcs, req_status);
@@ -475,7 +445,7 @@
 			if (prli_resp->parampage.servparams.initiator) {
 				bfa_trc(itnim->fcs, prli_resp->parampage.type);
 				itnim->rport->scsi_function =
-					BFA_RPORT_INITIATOR;
+					 BFA_RPORT_INITIATOR;
 				itnim->stats.prli_rsp_acc++;
 				bfa_sm_send_event(itnim,
 						  BFA_FCS_ITNIM_SM_RSP_OK);
@@ -488,10 +458,10 @@
 		itnim->rport->scsi_function = BFA_RPORT_TARGET;
 
 		sparams = &prli_resp->parampage.servparams;
-		itnim->seq_rec = sparams->retry;
-		itnim->rec_support = sparams->rec_support;
+		itnim->seq_rec	     = sparams->retry;
+		itnim->rec_support   = sparams->rec_support;
 		itnim->task_retry_id = sparams->task_retry_id;
-		itnim->conf_comp = sparams->confirm;
+		itnim->conf_comp     = sparams->confirm;
 
 		itnim->stats.prli_rsp_acc++;
 		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
@@ -509,7 +479,7 @@
 static void
 bfa_fcs_itnim_timeout(void *arg)
 {
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)arg;
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) arg;
 
 	itnim->stats.timeout++;
 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
@@ -529,16 +499,16 @@
  */
 
 /**
- * 	Called by rport when a new rport is created.
+ *	Called by rport when a new rport is created.
  *
  * @param[in] rport	-  remote port.
  */
 struct bfa_fcs_itnim_s *
 bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
 {
-	struct bfa_fcs_port_s *port = rport->port;
+	struct bfa_fcs_lport_s *port = rport->port;
 	struct bfa_fcs_itnim_s *itnim;
-	struct bfad_itnim_s *itnim_drv;
+	struct bfad_itnim_s   *itnim_drv;
 	struct bfa_itnim_s *bfa_itnim;
 
 	/*
@@ -560,7 +530,8 @@
 	/*
 	 * call BFA to create the itnim
 	 */
-	bfa_itnim = bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
+	bfa_itnim =
+		bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
 
 	if (bfa_itnim == NULL) {
 		bfa_trc(port->fcs, rport->pwwn);
@@ -569,10 +540,10 @@
 		return NULL;
 	}
 
-	itnim->bfa_itnim = bfa_itnim;
-	itnim->seq_rec = BFA_FALSE;
-	itnim->rec_support = BFA_FALSE;
-	itnim->conf_comp = BFA_FALSE;
+	itnim->bfa_itnim     = bfa_itnim;
+	itnim->seq_rec	     = BFA_FALSE;
+	itnim->rec_support   = BFA_FALSE;
+	itnim->conf_comp     = BFA_FALSE;
 	itnim->task_retry_id = BFA_FALSE;
 
 	/*
@@ -584,7 +555,7 @@
 }
 
 /**
- * 	Called by rport to delete  the instance of FCPIM.
+ *	Called by rport to delete  the instance of FCPIM.
  *
  * @param[in] rport	-  remote port.
  */
@@ -607,8 +578,8 @@
 		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
 	} else {
 		/*
-		 * For well known addresses, we set the itnim to initiator
-		 * state
+		 *  For well known addresses, we set the itnim to initiator
+		 *  state
 		 */
 		itnim->stats.initiator++;
 		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
@@ -651,7 +622,6 @@
 
 	default:
 		return BFA_STATUS_NO_FCPIM_NEXUS;
-
 	}
 }
 
@@ -661,7 +631,7 @@
 void
 bfa_cb_itnim_online(void *cbarg)
 {
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg;
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
 
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
@@ -673,7 +643,7 @@
 void
 bfa_cb_itnim_offline(void *cb_arg)
 {
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
 
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
@@ -686,7 +656,7 @@
 void
 bfa_cb_itnim_tov_begin(void *cb_arg)
 {
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
 
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
 }
@@ -697,14 +667,15 @@
 void
 bfa_cb_itnim_tov(void *cb_arg)
 {
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
+	struct bfad_itnim_s *itnim_drv = itnim->itnim_drv;
 
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
-	bfa_fcb_itnim_tov(itnim->itnim_drv);
+	itnim_drv->state = ITNIM_STATE_TIMEOUT;
 }
 
 /**
- * 		BFA notification to FCS/driver for second level error recovery.
+ *		BFA notification to FCS/driver for second level error recovery.
  *
  * Atleast one I/O request has timedout and target is unresponsive to
  * repeated abort requests. Second level error recovery should be initiated
@@ -713,7 +684,7 @@
 void
 bfa_cb_itnim_sler(void *cb_arg)
 {
-	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg;
+	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
 
 	itnim->stats.sler++;
 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
@@ -721,7 +692,7 @@
 }
 
 struct bfa_fcs_itnim_s *
-bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
+bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
 {
 	struct bfa_fcs_rport_s *rport;
 	rport = bfa_fcs_rport_lookup(port, rpwwn);
@@ -734,7 +705,7 @@
 }
 
 bfa_status_t
-bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
+bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
 		       struct bfa_itnim_attr_s *attr)
 {
 	struct bfa_fcs_itnim_s *itnim = NULL;
@@ -744,18 +715,16 @@
 	if (itnim == NULL)
 		return BFA_STATUS_NO_FCPIM_NEXUS;
 
-	attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
-	attr->retry = itnim->seq_rec;
-	attr->rec_support = itnim->rec_support;
-	attr->conf_comp = itnim->conf_comp;
+	attr->state	    = bfa_sm_to_state(itnim_sm_table, itnim->sm);
+	attr->retry	    = itnim->seq_rec;
+	attr->rec_support   = itnim->rec_support;
+	attr->conf_comp	    = itnim->conf_comp;
 	attr->task_retry_id = itnim->task_retry_id;
-	bfa_os_memset(&attr->io_latency, 0, sizeof(struct bfa_itnim_latency_s));
-
 	return BFA_STATUS_OK;
 }
 
 bfa_status_t
-bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
+bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
 			struct bfa_itnim_stats_s *stats)
 {
 	struct bfa_fcs_itnim_s *itnim = NULL;
@@ -773,7 +742,7 @@
 }
 
 bfa_status_t
-bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port, wwn_t rpwwn)
+bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
 {
 	struct bfa_fcs_itnim_s *itnim = NULL;
 
@@ -789,10 +758,10 @@
 }
 
 void
-bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
-		      u16 len)
+bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
+			struct fchs_s *fchs, u16 len)
 {
-	struct fc_els_cmd_s   *els_cmd;
+	struct fc_els_cmd_s *els_cmd;
 
 	bfa_trc(itnim->fcs, fchs->type);
 
@@ -812,13 +781,3 @@
 		bfa_assert(0);
 	}
 }
-
-void
-bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim)
-{
-}
-
-void
-bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim)
-{
-}
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 35df20e..b522bf3 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -16,23 +16,13 @@
  */
 
 /**
- *  bfa_fcs_port.c BFA FCS port
+ *  bfa_fcs_lport.c BFA FCS port
  */
 
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <fcb/bfa_fcb_port.h>
-#include <bfa_svc.h>
-#include <log/bfa_log_fcs.h>
-#include "fcs.h"
-#include "fcs_lport.h"
-#include "fcs_vport.h"
-#include "fcs_rport.h"
-#include "fcs_fcxp.h"
-#include "fcs_trcmod.h"
-#include "lport_priv.h"
-#include <aen/bfa_aen_lport.h>
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
+#include "bfa_fc.h"
+#include "bfad_drv.h"
 
 BFA_TRC_FILE(FCS, PORT);
 
@@ -40,49 +30,53 @@
  * Forward declarations
  */
 
-static void     bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
-				      enum bfa_lport_aen_event event);
-static void     bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port,
-			struct fchs_s *rx_fchs, u8 reason_code,
-			u8 reason_code_expl);
-static void     bfa_fcs_port_plogi(struct bfa_fcs_port_s *port,
-			struct fchs_s *rx_fchs,
-			struct fc_logi_s *plogi);
-static void     bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_deleted(struct bfa_fcs_port_s *port);
-static void     bfa_fcs_port_echo(struct bfa_fcs_port_s *port,
+static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
+					 struct fchs_s *rx_fchs, u8 reason_code,
+					 u8 reason_code_expl);
+static void     bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
+			struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
+static void     bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
+static void     bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
 			struct fchs_s *rx_fchs,
 			struct fc_echo_s *echo, u16 len);
-static void     bfa_fcs_port_rnid(struct bfa_fcs_port_s *port,
+static void     bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
 			struct fchs_s *rx_fchs,
 			struct fc_rnid_cmd_s *rnid, u16 len);
-static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
+static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
 			struct fc_rnid_general_topology_data_s *gen_topo_data);
 
+static void	bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
+static void	bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
+static void	bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
+
+static void	bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
+static void	bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
+static void	bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
+
 static struct {
-	void            (*init) (struct bfa_fcs_port_s *port);
-	void            (*online) (struct bfa_fcs_port_s *port);
-	void            (*offline) (struct bfa_fcs_port_s *port);
+	void		(*init) (struct bfa_fcs_lport_s *port);
+	void		(*online) (struct bfa_fcs_lport_s *port);
+	void		(*offline) (struct bfa_fcs_lport_s *port);
 } __port_action[] = {
 	{
-	bfa_fcs_port_unknown_init, bfa_fcs_port_unknown_online,
-			bfa_fcs_port_unknown_offline}, {
-	bfa_fcs_port_fab_init, bfa_fcs_port_fab_online,
-			bfa_fcs_port_fab_offline}, {
-	bfa_fcs_port_loop_init, bfa_fcs_port_loop_online,
-			bfa_fcs_port_loop_offline}, {
-bfa_fcs_port_n2n_init, bfa_fcs_port_n2n_online,
-			bfa_fcs_port_n2n_offline},};
+	bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
+			bfa_fcs_lport_unknown_offline}, {
+	bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
+			bfa_fcs_lport_fab_offline}, {
+	bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
+			bfa_fcs_lport_n2n_offline},
+	};
 
 /**
  *  fcs_port_sm FCS logical port state machine
  */
 
-enum bfa_fcs_port_event {
+enum bfa_fcs_lport_event {
 	BFA_FCS_PORT_SM_CREATE = 1,
 	BFA_FCS_PORT_SM_ONLINE = 2,
 	BFA_FCS_PORT_SM_OFFLINE = 3,
@@ -90,27 +84,28 @@
 	BFA_FCS_PORT_SM_DELRPORT = 5,
 };
 
-static void     bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
-				       enum bfa_fcs_port_event event);
-static void     bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port,
-				     enum bfa_fcs_port_event event);
-static void     bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
-				       enum bfa_fcs_port_event event);
-static void     bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
-					enum bfa_fcs_port_event event);
-static void     bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
-					 enum bfa_fcs_port_event event);
+static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
+static void     bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
+static void     bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
+static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
+static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
+					enum bfa_fcs_lport_event event);
 
 static void
-bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port,
-			enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_uninit(
+	struct bfa_fcs_lport_s *port,
+	enum bfa_fcs_lport_event event)
 {
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
 
 	switch (event) {
 	case BFA_FCS_PORT_SM_CREATE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_init);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
 		break;
 
 	default:
@@ -119,20 +114,21 @@
 }
 
 static void
-bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
+			enum bfa_fcs_lport_event event)
 {
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
 
 	switch (event) {
 	case BFA_FCS_PORT_SM_ONLINE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_online);
-		bfa_fcs_port_online_actions(port);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
+		bfa_fcs_lport_online_actions(port);
 		break;
 
 	case BFA_FCS_PORT_SM_DELETE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
-		bfa_fcs_port_deleted(port);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+		bfa_fcs_lport_deleted(port);
 		break;
 
 	case BFA_FCS_PORT_SM_OFFLINE:
@@ -144,19 +140,20 @@
 }
 
 static void
-bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port,
-			enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_online(
+	struct bfa_fcs_lport_s *port,
+	enum bfa_fcs_lport_event event)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe, *qen;
+	struct list_head		*qe, *qen;
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
 
 	switch (event) {
 	case BFA_FCS_PORT_SM_OFFLINE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_offline);
-		bfa_fcs_port_offline_actions(port);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
+		bfa_fcs_lport_offline_actions(port);
 		break;
 
 	case BFA_FCS_PORT_SM_DELETE:
@@ -164,12 +161,12 @@
 		__port_action[port->fabric->fab_type].offline(port);
 
 		if (port->num_rports == 0) {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
-			bfa_fcs_port_deleted(port);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+			bfa_fcs_lport_deleted(port);
 		} else {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
 			list_for_each_safe(qe, qen, &port->rport_q) {
-				rport = (struct bfa_fcs_rport_s *)qe;
+				rport = (struct bfa_fcs_rport_s *) qe;
 				bfa_fcs_rport_delete(rport);
 			}
 		}
@@ -184,29 +181,30 @@
 }
 
 static void
-bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port,
-			enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_offline(
+	struct bfa_fcs_lport_s *port,
+	enum bfa_fcs_lport_event event)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe, *qen;
+	struct list_head		*qe, *qen;
 
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
 
 	switch (event) {
 	case BFA_FCS_PORT_SM_ONLINE:
-		bfa_sm_set_state(port, bfa_fcs_port_sm_online);
-		bfa_fcs_port_online_actions(port);
+		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
+		bfa_fcs_lport_online_actions(port);
 		break;
 
 	case BFA_FCS_PORT_SM_DELETE:
 		if (port->num_rports == 0) {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
-			bfa_fcs_port_deleted(port);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+			bfa_fcs_lport_deleted(port);
 		} else {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_deleting);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
 			list_for_each_safe(qe, qen, &port->rport_q) {
-				rport = (struct bfa_fcs_rport_s *)qe;
+				rport = (struct bfa_fcs_rport_s *) qe;
 				bfa_fcs_rport_delete(rport);
 			}
 		}
@@ -222,8 +220,9 @@
 }
 
 static void
-bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port,
-			 enum bfa_fcs_port_event event)
+bfa_fcs_lport_sm_deleting(
+	struct bfa_fcs_lport_s *port,
+	enum bfa_fcs_lport_event event)
 {
 	bfa_trc(port->fcs, port->port_cfg.pwwn);
 	bfa_trc(port->fcs, event);
@@ -231,8 +230,8 @@
 	switch (event) {
 	case BFA_FCS_PORT_SM_DELRPORT:
 		if (port->num_rports == 0) {
-			bfa_sm_set_state(port, bfa_fcs_port_sm_uninit);
-			bfa_fcs_port_deleted(port);
+			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
+			bfa_fcs_lport_deleted(port);
 		}
 		break;
 
@@ -241,74 +240,44 @@
 	}
 }
 
-
-
 /**
  *  fcs_port_pvt
  */
 
-/**
- * Send AEN notification
- */
-static void
-bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port,
-		      enum bfa_lport_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = port->fcs->logm;
-	enum bfa_port_role role = port->port_cfg.roles;
-	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(port);
-	char            lpwwn_ptr[BFA_STRING_32];
-	char           *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
-		{ "Initiator", "Target", "IPFC" };
-
-	wwn2str(lpwwn_ptr, lpwwn);
-
-	bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, event), lpwwn_ptr,
-		role_str[role/2]);
-
-	aen_data.lport.vf_id = port->fabric->vf_id;
-	aen_data.lport.roles = role;
-	aen_data.lport.ppwwn =
-		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
-	aen_data.lport.lpwwn = lpwwn;
-}
-
 /*
  * Send a LS reject
  */
 static void
-bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
+bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
 			 u8 reason_code, u8 reason_code_expl)
 {
-	struct fchs_s          fchs;
+	struct fchs_s	fchs;
 	struct bfa_fcxp_s *fcxp;
 	struct bfa_rport_s *bfa_rport = NULL;
-	int             len;
+	int		len;
 
+	bfa_trc(port->fcs, rx_fchs->d_id);
 	bfa_trc(port->fcs, rx_fchs->s_id);
 
 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
 	if (!fcxp)
 		return;
 
-	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-			      reason_code, reason_code_expl);
+	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+			      rx_fchs->ox_id, reason_code, reason_code_expl);
 
 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
-		      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
-		      FC_MAX_PDUSZ, 0);
+			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			  FC_MAX_PDUSZ, 0);
 }
 
 /**
  * Process incoming plogi from a remote port.
  */
 static void
-bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
-			struct fc_logi_s *plogi)
+bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
+		struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
 {
 	struct bfa_fcs_rport_s *rport;
 
@@ -328,46 +297,40 @@
 		/*
 		 * send a LS reject
 		 */
-		bfa_fcs_port_send_ls_rjt(port, rx_fchs,
-					 FC_LS_RJT_RSN_PROTOCOL_ERROR,
-					 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
+		bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
+					FC_LS_RJT_RSN_PROTOCOL_ERROR,
+					FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
 		return;
 	}
 
 	/**
-* Direct Attach P2P mode : verify address assigned by the r-port.
+	 * Direct Attach P2P mode : verify address assigned by the r-port.
 	 */
-	if ((!bfa_fcs_fabric_is_switched(port->fabric))
-	    &&
-	    (memcmp
-	     ((void *)&bfa_fcs_port_get_pwwn(port), (void *)&plogi->port_name,
-	      sizeof(wwn_t)) < 0)) {
+	if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
+		(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
+			   (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
 		if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
-			/*
-			 * Address assigned to us cannot be a WKA
-			 */
-			bfa_fcs_port_send_ls_rjt(port, rx_fchs,
+			/* Address assigned to us cannot be a WKA */
+			bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
 					FC_LS_RJT_RSN_PROTOCOL_ERROR,
 					FC_LS_RJT_EXP_INVALID_NPORT_ID);
 			return;
 		}
-		port->pid = rx_fchs->d_id;
+		port->pid  = rx_fchs->d_id;
 	}
 
 	/**
 	 * First, check if we know the device by pwwn.
 	 */
-	rport = bfa_fcs_port_get_rport_by_pwwn(port, plogi->port_name);
+	rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
 	if (rport) {
 		/**
-		 * Direct Attach P2P mode: handle address assigned by the rport.
+		 * Direct Attach P2P mode : handle address assigned by r-port.
 		 */
-		if ((!bfa_fcs_fabric_is_switched(port->fabric))
-		    &&
-		    (memcmp
-		     ((void *)&bfa_fcs_port_get_pwwn(port),
-		      (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
-			port->pid = rx_fchs->d_id;
+		if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
+			(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
+			(void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
+			port->pid  = rx_fchs->d_id;
 			rport->pid = rx_fchs->s_id;
 		}
 		bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
@@ -377,7 +340,7 @@
 	/**
 	 * Next, lookup rport by PID.
 	 */
-	rport = bfa_fcs_port_get_rport_by_pid(port, rx_fchs->s_id);
+	rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
 	if (!rport) {
 		/**
 		 * Inbound PLOGI from a new device.
@@ -416,39 +379,40 @@
  * Since it does not require a login, it is processed here.
  */
 static void
-bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
-			struct fc_echo_s *echo, u16 rx_len)
+bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
+		struct fc_echo_s *echo, u16 rx_len)
 {
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_rport_s *bfa_rport = NULL;
-	int             len, pyld_len;
+	struct fchs_s		fchs;
+	struct bfa_fcxp_s	*fcxp;
+	struct bfa_rport_s	*bfa_rport = NULL;
+	int			len, pyld_len;
 
 	bfa_trc(port->fcs, rx_fchs->s_id);
 	bfa_trc(port->fcs, rx_fchs->d_id);
-	bfa_trc(port->fcs, rx_len);
 
 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
 	if (!fcxp)
 		return;
 
-	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
+	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id);
 
 	/*
 	 * Copy the payload (if any) from the echo frame
 	 */
 	pyld_len = rx_len - sizeof(struct fchs_s);
+	bfa_trc(port->fcs, rx_len);
 	bfa_trc(port->fcs, pyld_len);
 
 	if (pyld_len > len)
 		memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
-		       sizeof(struct fc_echo_s), (echo + 1),
-		       (pyld_len - sizeof(struct fc_echo_s)));
+			sizeof(struct fc_echo_s), (echo + 1),
+			(pyld_len - sizeof(struct fc_echo_s)));
 
 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
-		      BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
-		      FC_MAX_PDUSZ, 0);
+			BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
+			FC_MAX_PDUSZ, 0);
 }
 
 /*
@@ -456,16 +420,16 @@
  * Since it does not require a login, it is processed here.
  */
 static void
-bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
-			struct fc_rnid_cmd_s *rnid, u16 rx_len)
+bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
+		struct fc_rnid_cmd_s *rnid, u16 rx_len)
 {
 	struct fc_rnid_common_id_data_s common_id_data;
 	struct fc_rnid_general_topology_data_s gen_topo_data;
-	struct fchs_s          fchs;
+	struct fchs_s	fchs;
 	struct bfa_fcxp_s *fcxp;
 	struct bfa_rport_s *bfa_rport = NULL;
-	u16        len;
-	u32        data_format;
+	u16	len;
+	u32	data_format;
 
 	bfa_trc(port->fcs, rx_fchs->s_id);
 	bfa_trc(port->fcs, rx_fchs->d_id);
@@ -495,28 +459,26 @@
 	/*
 	 * Copy the Node Id Info
 	 */
-	common_id_data.port_name = bfa_fcs_port_get_pwwn(port);
-	common_id_data.node_name = bfa_fcs_port_get_nwwn(port);
+	common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
+	common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
 
-	len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-				bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-				data_format, &common_id_data, &gen_topo_data);
+	len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id, data_format, &common_id_data,
+				&gen_topo_data);
 
 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
-		      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
-		      FC_MAX_PDUSZ, 0);
-
-	return;
+			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			FC_MAX_PDUSZ, 0);
 }
 
 /*
  *  Fill out General Topolpgy Discovery Data for RNID ELS.
  */
 static void
-bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port,
+bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
 			struct fc_rnid_general_topology_data_s *gen_topo_data)
 {
-
 	bfa_os_memset(gen_topo_data, 0,
 		      sizeof(struct fc_rnid_general_topology_data_s));
 
@@ -526,76 +488,111 @@
 }
 
 static void
-bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
 {
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+
 	bfa_trc(port->fcs, port->fabric->oper_type);
 
 	__port_action[port->fabric->fab_type].init(port);
 	__port_action[port->fabric->fab_type].online(port);
 
-	bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_ONLINE);
-	bfa_fcb_port_online(port->fcs->bfad, port->port_cfg.roles,
-			port->fabric->vf_drv, (port->vport == NULL) ?
-			NULL : port->vport->vport_drv);
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"Logical port online: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
+
+	bfad->bfad_flags |= BFAD_PORT_ONLINE;
 }
 
 static void
-bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
 {
-	struct list_head *qe, *qen;
+	struct list_head	*qe, *qen;
 	struct bfa_fcs_rport_s *rport;
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char    lpwwn_buf[BFA_STRING_32];
 
 	bfa_trc(port->fcs, port->fabric->oper_type);
 
 	__port_action[port->fabric->fab_type].offline(port);
 
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
 	if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
-		bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
+		BFA_LOG(KERN_ERR, bfad, log_level,
+		"Logical port lost fabric connectivity: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
 	else
-		bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE);
-	bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles,
-			port->fabric->vf_drv,
-			(port->vport == NULL) ? NULL : port->vport->vport_drv);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+		"Logical port taken offline: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
 
 	list_for_each_safe(qe, qen, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
+		rport = (struct bfa_fcs_rport_s *) qe;
 		bfa_fcs_rport_offline(rport);
 	}
 }
 
 static void
-bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
 {
 	bfa_assert(0);
 }
 
 static void
-bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
 {
 	bfa_assert(0);
 }
 
 static void
-bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
 {
 	bfa_assert(0);
 }
 
 static void
-bfa_fcs_port_deleted(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
 {
-	bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DELETE);
+	struct fchs_s fchs;
+	struct bfa_fcxp_s *fcxp;
+	int		len;
 
-	/*
-	 * Base port will be deleted by the OS driver
-	 */
+	bfa_trc(port->fcs, rx_fchs->d_id);
+	bfa_trc(port->fcs, rx_fchs->s_id);
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+			rx_fchs->ox_id, 0);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
+			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			  FC_MAX_PDUSZ, 0);
+}
+static void
+bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
+{
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char    lpwwn_buf[BFA_STRING_32];
+
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"Logical port deleted: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
+
+	/* Base port will be deleted by the OS driver */
 	if (port->vport) {
-		bfa_fcb_port_delete(port->fcs->bfad, port->port_cfg.roles,
-			port->fabric->vf_drv,
-			port->vport ? port->vport->vport_drv : NULL);
+		bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
+				port->fabric->vf_drv,
+				port->vport ? port->vport->vport_drv : NULL);
 		bfa_fcs_vport_delete_comp(port->vport);
 	} else {
-		bfa_fcs_fabric_port_delete_comp(port->fabric);
+		 bfa_fcs_fabric_port_delete_comp(port->fabric);
 	}
 }
 
@@ -608,7 +605,7 @@
  *   Module initialization
  */
 void
-bfa_fcs_port_modinit(struct bfa_fcs_s *fcs)
+bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs)
 {
 
 }
@@ -617,25 +614,25 @@
  *   Module cleanup
  */
 void
-bfa_fcs_port_modexit(struct bfa_fcs_s *fcs)
+bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs)
 {
 	bfa_fcs_modexit_comp(fcs);
 }
 
 /**
- * 		Unsolicited frame receive handling.
+ * Unsolicited frame receive handling.
  */
 void
-bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
-			u16 len)
+bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
+			struct fchs_s *fchs, u16 len)
 {
-	u32        pid = fchs->s_id;
+	u32	pid = fchs->s_id;
 	struct bfa_fcs_rport_s *rport = NULL;
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
 
 	bfa_stats(lport, uf_recvs);
 
-	if (!bfa_fcs_port_is_online(lport)) {
+	if (!bfa_fcs_lport_is_online(lport)) {
 		bfa_stats(lport, uf_recv_drops);
 		return;
 	}
@@ -648,7 +645,7 @@
 	 */
 	if ((fchs->type == FC_TYPE_ELS) &&
 		(els_cmd->els_code == FC_ELS_PLOGI)) {
-		bfa_fcs_port_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
+		bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
 		return;
 	}
 
@@ -656,8 +653,8 @@
 	 * Handle ECHO separately.
 	 */
 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
-		bfa_fcs_port_echo(lport, fchs,
-			(struct fc_echo_s *) els_cmd, len);
+		bfa_fcs_lport_echo(lport, fchs,
+				(struct fc_echo_s *)els_cmd, len);
 		return;
 	}
 
@@ -665,15 +662,21 @@
 	 * Handle RNID separately.
 	 */
 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
-		bfa_fcs_port_rnid(lport, fchs,
+		bfa_fcs_lport_rnid(lport, fchs,
 			(struct fc_rnid_cmd_s *) els_cmd, len);
 		return;
 	}
 
+	if (fchs->type == FC_TYPE_BLS) {
+		if ((fchs->routing == FC_RTG_BASIC_LINK) &&
+				(fchs->cat_info == FC_CAT_ABTS))
+			bfa_fcs_lport_abts_acc(lport, fchs);
+		return;
+	}
 	/**
 	 * look for a matching remote port ID
 	 */
-	rport = bfa_fcs_port_get_rport_by_pid(lport, pid);
+	rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
 	if (rport) {
 		bfa_trc(rport->fcs, fchs->s_id);
 		bfa_trc(rport->fcs, fchs->d_id);
@@ -694,7 +697,7 @@
 
 	bfa_trc(lport->fcs, els_cmd->els_code);
 	if (els_cmd->els_code == FC_ELS_RSCN) {
-		bfa_fcs_port_scn_process_rscn(lport, fchs, len);
+		bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
 		return;
 	}
 
@@ -702,7 +705,6 @@
 		/**
 		 * @todo Handle LOGO frames received.
 		 */
-		bfa_trc(lport->fcs, els_cmd->els_code);
 		return;
 	}
 
@@ -710,14 +712,13 @@
 		/**
 		 * @todo Handle PRLI frames received.
 		 */
-		bfa_trc(lport->fcs, els_cmd->els_code);
 		return;
 	}
 
 	/**
 	 * Unhandled ELS frames. Send a LS_RJT.
 	 */
-	bfa_fcs_port_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
+	bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
 				 FC_LS_RJT_EXP_NO_ADDL_INFO);
 
 }
@@ -726,13 +727,13 @@
  *   PID based Lookup for a R-Port in the Port R-Port Queue
  */
 struct bfa_fcs_rport_s *
-bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid)
+bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe;
+	struct list_head	*qe;
 
 	list_for_each(qe, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
+		rport = (struct bfa_fcs_rport_s *) qe;
 		if (rport->pid == pid)
 			return rport;
 	}
@@ -745,13 +746,13 @@
  *   PWWN based Lookup for a R-Port in the Port R-Port Queue
  */
 struct bfa_fcs_rport_s *
-bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn)
+bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe;
+	struct list_head	*qe;
 
 	list_for_each(qe, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
+		rport = (struct bfa_fcs_rport_s *) qe;
 		if (wwn_is_equal(rport->pwwn, pwwn))
 			return rport;
 	}
@@ -764,13 +765,13 @@
  *   NWWN based Lookup for a R-Port in the Port R-Port Queue
  */
 struct bfa_fcs_rport_s *
-bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn)
+bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
 {
 	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe;
+	struct list_head	*qe;
 
 	list_for_each(qe, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
+		rport = (struct bfa_fcs_rport_s *) qe;
 		if (wwn_is_equal(rport->nwwn, nwwn))
 			return rport;
 	}
@@ -783,8 +784,9 @@
  * Called by rport module when new rports are discovered.
  */
 void
-bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
-		       struct bfa_fcs_rport_s *rport)
+bfa_fcs_lport_add_rport(
+	struct bfa_fcs_lport_s *port,
+	struct bfa_fcs_rport_s *rport)
 {
 	list_add_tail(&rport->qe, &port->rport_q);
 	port->num_rports++;
@@ -794,8 +796,9 @@
  * Called by rport module to when rports are deleted.
  */
 void
-bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
-		       struct bfa_fcs_rport_s *rport)
+bfa_fcs_lport_del_rport(
+	struct bfa_fcs_lport_s *port,
+	struct bfa_fcs_rport_s *rport)
 {
 	bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
 	list_del(&rport->qe);
@@ -809,7 +812,7 @@
  * Called by vport for virtual ports when FDISC is complete.
  */
 void
-bfa_fcs_port_online(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
 {
 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
 }
@@ -819,7 +822,7 @@
  * Called by vport for virtual ports when virtual port becomes offline.
  */
 void
-bfa_fcs_port_offline(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
 {
 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
 }
@@ -831,40 +834,32 @@
  * bfa_fcs_vport_delete_comp() for vports on completion.
  */
 void
-bfa_fcs_port_delete(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
 {
 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
 }
 
 /**
- * Called by fabric in private loop topology to process LIP event.
- */
-void
-bfa_fcs_port_lip(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
  * Return TRUE if port is online, else return FALSE
  */
 bfa_boolean_t
-bfa_fcs_port_is_online(struct bfa_fcs_port_s *port)
+bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
 {
-	return bfa_sm_cmp_state(port, bfa_fcs_port_sm_online);
+	return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
 }
 
 /**
- * Attach time initialization of logical ports.
+  * Attach time initialization of logical ports.
  */
 void
-bfa_fcs_lport_attach(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
-		uint16_t vf_id, struct bfa_fcs_vport_s *vport)
+bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
+		   u16 vf_id, struct bfa_fcs_vport_s *vport)
 {
 	lport->fcs = fcs;
 	lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
 	lport->vport = vport;
 	lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
-			 bfa_lps_get_tag(lport->fabric->lps);
+				  bfa_lps_get_tag(lport->fabric->lps);
 
 	INIT_LIST_HEAD(&lport->rport_q);
 	lport->num_rports = 0;
@@ -876,21 +871,26 @@
  */
 
 void
-bfa_fcs_lport_init(struct bfa_fcs_port_s *lport,
-		struct bfa_port_cfg_s *port_cfg)
+bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
+	struct bfa_lport_cfg_s *port_cfg)
 {
 	struct bfa_fcs_vport_s *vport = lport->vport;
+	struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
+	char    lpwwn_buf[BFA_STRING_32];
 
 	bfa_os_assign(lport->port_cfg, *port_cfg);
 
-	lport->bfad_port = bfa_fcb_port_new(lport->fcs->bfad, lport,
-				lport->port_cfg.roles,
-				lport->fabric->vf_drv,
-				vport ? vport->vport_drv : NULL);
+	lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
+					lport->port_cfg.roles,
+					lport->fabric->vf_drv,
+					vport ? vport->vport_drv : NULL);
 
-	bfa_fcs_port_aen_post(lport, BFA_LPORT_AEN_NEW);
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"New logical port created: WWN = %s Role = %s\n",
+		lpwwn_buf, "Initiator");
 
-	bfa_sm_set_state(lport, bfa_fcs_port_sm_uninit);
+	bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
 	bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
 }
 
@@ -899,10 +899,11 @@
  */
 
 void
-bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
-		      struct bfa_port_attr_s *port_attr)
+bfa_fcs_lport_get_attr(
+	struct bfa_fcs_lport_s *port,
+	struct bfa_lport_attr_s *port_attr)
 {
-	if (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online))
+	if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
 		port_attr->pid = port->pid;
 	else
 		port_attr->pid = 0;
@@ -913,25 +914,4895 @@
 		port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
 		port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
 		port_attr->authfail =
-				bfa_fcs_fabric_is_auth_failed(port->fabric);
-		port_attr->fabric_name = bfa_fcs_port_get_fabric_name(port);
+			bfa_fcs_fabric_is_auth_failed(port->fabric);
+		port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);
 		memcpy(port_attr->fabric_ip_addr,
-		       bfa_fcs_port_get_fabric_ipaddr(port),
-		       BFA_FCS_FABRIC_IPADDR_SZ);
+			bfa_fcs_lport_get_fabric_ipaddr(port),
+			BFA_FCS_FABRIC_IPADDR_SZ);
 
 		if (port->vport != NULL) {
-			port_attr->port_type = BFA_PPORT_TYPE_VPORT;
+			port_attr->port_type = BFA_PORT_TYPE_VPORT;
 			port_attr->fpma_mac =
 				bfa_lps_get_lp_mac(port->vport->lps);
-		} else
+		} else {
 			port_attr->fpma_mac =
 				bfa_lps_get_lp_mac(port->fabric->lps);
-
+		}
 	} else {
-		port_attr->port_type = BFA_PPORT_TYPE_UNKNOWN;
-		port_attr->state = BFA_PORT_UNINIT;
+		port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
+		port_attr->state = BFA_LPORT_UNINIT;
 	}
+}
+
+/**
+ *  bfa_fcs_lport_fab port fab functions
+ */
+
+/**
+ *   Called by port to initialize fabric services of the base port.
+ */
+static void
+bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
+{
+	bfa_fcs_lport_ns_init(port);
+	bfa_fcs_lport_scn_init(port);
+	bfa_fcs_lport_ms_init(port);
+}
+
+/**
+ *   Called by port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
+{
+	bfa_fcs_lport_ns_online(port);
+	bfa_fcs_lport_scn_online(port);
+}
+
+/**
+ *   Called by port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
+{
+	bfa_fcs_lport_ns_offline(port);
+	bfa_fcs_lport_scn_offline(port);
+	bfa_fcs_lport_ms_offline(port);
+}
+
+/**
+ *  bfa_fcs_lport_n2n  functions
+ */
+
+/**
+ *   Called by fcs/port to initialize N2N topology.
+ */
+static void
+bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
+{
+}
+
+/**
+ *   Called by fcs/port to notify transition to online state.
+ */
+static void
+bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
+	struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
+	struct bfa_fcs_rport_s *rport;
+
+	bfa_trc(port->fcs, pcfg->pwwn);
+
+	/*
+	 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
+	 * and assign an Address. if not, we need to wait for its PLOGI.
+	 *
+	 * If our PWWN is < than that of the remote port, it will send a PLOGI
+	 * with the PIDs assigned. The rport state machine take care of this
+	 * incoming PLOGI.
+	 */
+	if (memcmp
+	    ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
+	     sizeof(wwn_t)) > 0) {
+		port->pid = N2N_LOCAL_PID;
+		/**
+		 * First, check if we know the device by pwwn.
+		 */
+		rport = bfa_fcs_lport_get_rport_by_pwwn(port,
+							n2n_port->rem_port_wwn);
+		if (rport) {
+			bfa_trc(port->fcs, rport->pid);
+			bfa_trc(port->fcs, rport->pwwn);
+			rport->pid = N2N_REMOTE_PID;
+			bfa_fcs_rport_online(rport);
+			return;
+		}
+
+		/*
+		 * In n2n there can be only one rport. Delete the old one
+		 * whose pid should be zero, because it is offline.
+		 */
+		if (port->num_rports > 0) {
+			rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
+			bfa_assert(rport != NULL);
+			if (rport) {
+				bfa_trc(port->fcs, rport->pwwn);
+				bfa_fcs_rport_delete(rport);
+			}
+		}
+		bfa_fcs_rport_create(port, N2N_REMOTE_PID);
+	}
+}
+
+/**
+ *   Called by fcs/port to notify transition to offline state.
+ */
+static void
+bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
+
+	bfa_trc(port->fcs, port->pid);
+	port->pid = 0;
+	n2n_port->rem_port_wwn = 0;
+	n2n_port->reply_oxid = 0;
+}
+
+#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
+					   struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_fdmi_timeout(void *arg);
+static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
+						  u8 *pyld);
+static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
+						  u8 *pyld);
+static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
+						 u8 *pyld);
+static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
+						       fdmi, u8 *pyld);
+static void	bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+				 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
+static void	bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+				  struct bfa_fcs_fdmi_port_attr_s *port_attr);
+/**
+ *  fcs_fdmi_sm FCS FDMI state machine
+ */
+
+/**
+ *  FDMI State Machine events
+ */
+enum port_fdmi_event {
+	FDMISM_EVENT_PORT_ONLINE = 1,
+	FDMISM_EVENT_PORT_OFFLINE = 2,
+	FDMISM_EVENT_RSP_OK = 4,
+	FDMISM_EVENT_RSP_ERROR = 5,
+	FDMISM_EVENT_TIMEOUT = 6,
+	FDMISM_EVENT_RHBA_SENT = 7,
+	FDMISM_EVENT_RPRT_SENT = 8,
+	FDMISM_EVENT_RPA_SENT = 9,
+};
+
+static void     bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
+					     enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_sending_rhba(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
+					  enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rhba_retry(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_sending_rprt(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
+					  enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rprt_retry(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_sending_rpa(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
+					 enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_rpa_retry(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
+					    enum port_fdmi_event event);
+static void     bfa_fcs_lport_fdmi_sm_disabled(
+				struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event);
+/**
+ *	Start in offline state - awaiting MS to send start.
+ */
+static void
+bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
+			     enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	fdmi->retry_cnt = 0;
+
+	switch (event) {
+	case FDMISM_EVENT_PORT_ONLINE:
+		if (port->vport) {
+			/*
+			 * For Vports, register a new port.
+			 */
+			bfa_sm_set_state(fdmi,
+					 bfa_fcs_lport_fdmi_sm_sending_rprt);
+			bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
+		} else {
+			/*
+			 * For a base port, we should first register the HBA
+			 * atribute. The HBA attribute also contains the base
+			 *  port registration.
+			 */
+			bfa_sm_set_state(fdmi,
+					 bfa_fcs_lport_fdmi_sm_sending_rhba);
+			bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
+		}
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
+				  enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RHBA_SENT:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+					   &fdmi->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
+			enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RSP_ERROR:
+		/*
+		 * if max retries have not been reached, start timer for a
+		 * delayed retry
+		 */
+		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(fdmi,
+					bfa_fcs_lport_fdmi_sm_rhba_retry);
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+					    &fdmi->timer,
+					    bfa_fcs_lport_fdmi_timeout, fdmi,
+					    BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			/*
+			 * set state to offline
+			 */
+			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		}
+		break;
+
+	case FDMISM_EVENT_RSP_OK:
+		/*
+		 * Initiate Register Port Attributes
+		 */
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
+		fdmi->retry_cnt = 0;
+		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_fcxp_discard(fdmi->fcxp);
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
+		bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_timer_stop(&fdmi->timer);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+/*
+* RPRT : Register Port
+ */
+static void
+bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
+				  enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RPRT_SENT:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+					   &fdmi->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
+			enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RSP_ERROR:
+		/*
+		 * if max retries have not been reached, start timer for a
+		 * delayed retry
+		 */
+		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(fdmi,
+					bfa_fcs_lport_fdmi_sm_rprt_retry);
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+					    &fdmi->timer,
+					    bfa_fcs_lport_fdmi_timeout, fdmi,
+					    BFA_FCS_RETRY_TIMEOUT);
+
+		} else {
+			/*
+			 * set state to offline
+			 */
+			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+			fdmi->retry_cnt = 0;
+		}
+		break;
+
+	case FDMISM_EVENT_RSP_OK:
+		fdmi->retry_cnt = 0;
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_fcxp_discard(fdmi->fcxp);
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
+		bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_timer_stop(&fdmi->timer);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+/*
+ * Register Port Attributes
+ */
+static void
+bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
+				 enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RPA_SENT:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
+					   &fdmi->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
+			enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_RSP_ERROR:
+		/*
+		 * if max retries have not been reached, start timer for a
+		 * delayed retry
+		 */
+		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
+					    &fdmi->timer,
+					    bfa_fcs_lport_fdmi_timeout, fdmi,
+					    BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			/*
+			 * set state to offline
+			 */
+			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+			fdmi->retry_cnt = 0;
+		}
+		break;
+
+	case FDMISM_EVENT_RSP_OK:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
+		fdmi->retry_cnt = 0;
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_fcxp_discard(fdmi->fcxp);
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
+			       enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
+		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
+		break;
+
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		bfa_timer_stop(&fdmi->timer);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
+				enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	switch (event) {
+	case FDMISM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+/**
+ *  FDMI is disabled state.
+ */
+static void
+bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
+			     enum port_fdmi_event event)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+	bfa_trc(port->fcs, event);
+
+	/* No op State. It can only be enabled at Driver Init. */
+}
+
+/**
+*  RHBA : Register HBA Attributes.
+ */
+static void
+bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fchs_s fchs;
+	int             len, attr_len;
+	struct bfa_fcxp_s *fcxp;
+	u8        *pyld;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+					bfa_fcs_lport_fdmi_send_rhba, fdmi);
+		return;
+	}
+	fdmi->fcxp = fcxp;
+
+	pyld = bfa_fcxp_get_reqbuf(fcxp);
+	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
+				   FDMI_RHBA);
+
+	attr_len =
+		bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
+					  (u8 *) ((struct ct_hdr_s *) pyld
+						       + 1));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, (len + attr_len), &fchs,
+			  bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
+}
+
+static          u16
+bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct bfa_fcs_fdmi_hba_attr_s hba_attr;
+	struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
+	struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
+	struct fdmi_attr_s *attr;
+	u8        *curr_ptr;
+	u16        len, count;
+
+	/*
+	 * get hba attributes
+	 */
+	bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
+
+	rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
+	rhba->port_list.num_ports = bfa_os_htonl(1);
+	rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
+
+	len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
+
+	count = 0;
+	len += sizeof(rhba->hba_attr_blk.attr_count);
+
+	/*
+	 * fill out the invididual entries of the HBA attrib Block
+	 */
+	curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
+
+	/*
+	 * Node Name
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME);
+	attr->len = sizeof(wwn_t);
+	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Manufacturer
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER);
+	attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
+	memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Serial Number
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM);
+	attr->len = (u16) strlen(fcs_hba_attr->serial_num);
+	memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Model
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL);
+	attr->len = (u16) strlen(fcs_hba_attr->model);
+	memcpy(attr->value, fcs_hba_attr->model, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Model Desc
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC);
+	attr->len = (u16) strlen(fcs_hba_attr->model_desc);
+	memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							 *fields need
+							 *to be 4 byte
+							 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * H/W Version
+	 */
+	if (fcs_hba_attr->hw_version[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION);
+		attr->len = (u16) strlen(fcs_hba_attr->hw_version);
+		memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		count++;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+					 sizeof(attr->len));
+	}
+
+	/*
+	 * Driver Version
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION);
+	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
+	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							 *fields need
+							 *to be 4 byte
+							 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Option Rom Version
+	 */
+	if (fcs_hba_attr->option_rom_ver[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION);
+		attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
+		memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+								 *fields need
+								 *to be 4 byte
+								 *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		count++;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+					 sizeof(attr->len));
+	}
+
+	/*
+	 * f/w Version = driver version
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION);
+	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
+	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
+	attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							 *fields need
+							 *to be 4 byte
+							 *aligned */
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * OS Name
+	 */
+	if (fcs_hba_attr->os_name[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME);
+		attr->len = (u16) strlen(fcs_hba_attr->os_name);
+		memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							     *fields need
+							     *to be 4 byte
+							     *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		count++;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+					sizeof(attr->len));
+	}
+
+	/*
+	 * MAX_CT_PAYLOAD
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT);
+	attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
+	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
+	len += attr->len;
+	count++;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Update size of payload
+	 */
+	len += ((sizeof(attr->type) +
+		 sizeof(attr->len)) * count);
+
+	rhba->hba_attr_blk.attr_count = bfa_os_htonl(count);
+	return len;
+}
+
+static void
+bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi =
+				(struct bfa_fcs_lport_fdmi_s *) cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+/**
+*  RPRT : Register Port
+ */
+static void
+bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fchs_s fchs;
+	u16        len, attr_len;
+	struct bfa_fcxp_s *fcxp;
+	u8        *pyld;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+					bfa_fcs_lport_fdmi_send_rprt, fdmi);
+		return;
+	}
+	fdmi->fcxp = fcxp;
+
+	pyld = bfa_fcxp_get_reqbuf(fcxp);
+	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
+				   FDMI_RPRT);
+
+	attr_len =
+		bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
+					  (u8 *) ((struct ct_hdr_s *) pyld
+						       + 1));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len + attr_len, &fchs,
+			  bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
+}
+
+/**
+ * This routine builds Port Attribute Block that used in RPA, RPRT commands.
+ */
+static          u16
+bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
+				       u8 *pyld)
+{
+	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
+	struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
+	struct fdmi_attr_s *attr;
+	u8        *curr_ptr;
+	u16        len;
+	u8	count = 0;
+
+	/*
+	 * get port attributes
+	 */
+	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
+
+	len = sizeof(port_attrib->attr_count);
+
+	/*
+	 * fill out the invididual entries
+	 */
+	curr_ptr = (u8 *) &port_attrib->port_attr;
+
+	/*
+	 * FC4 Types
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES);
+	attr->len = sizeof(fcs_port_attr.supp_fc4_types);
+	memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	++count;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * Supported Speed
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED);
+	attr->len = sizeof(fcs_port_attr.supp_speed);
+	memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	++count;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * current Port Speed
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED);
+	attr->len = sizeof(fcs_port_attr.curr_speed);
+	memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	++count;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * max frame size
+	 */
+	attr = (struct fdmi_attr_s *) curr_ptr;
+	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE);
+	attr->len = sizeof(fcs_port_attr.max_frm_size);
+	memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
+	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+	len += attr->len;
+	++count;
+	attr->len =
+		bfa_os_htons(attr->len + sizeof(attr->type) +
+			     sizeof(attr->len));
+
+	/*
+	 * OS Device Name
+	 */
+	if (fcs_port_attr.os_device_name[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME);
+		attr->len = (u16) strlen(fcs_port_attr.os_device_name);
+		memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							     *fields need
+							     *to be 4 byte
+							     *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		++count;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+					sizeof(attr->len));
+	}
+	/*
+	 * Host Name
+	 */
+	if (fcs_port_attr.host_name[0] != '\0') {
+		attr = (struct fdmi_attr_s *) curr_ptr;
+		attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME);
+		attr->len = (u16) strlen(fcs_port_attr.host_name);
+		memcpy(attr->value, fcs_port_attr.host_name, attr->len);
+		attr->len = fc_roundup(attr->len, sizeof(u32));	/* variable
+							     *fields need
+							     *to be 4 byte
+							     *aligned */
+		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
+		len += attr->len;
+		++count;
+		attr->len =
+			bfa_os_htons(attr->len + sizeof(attr->type) +
+				sizeof(attr->len));
+	}
+
+	/*
+	 * Update size of payload
+	 */
+	port_attrib->attr_count = bfa_os_htonl(count);
+	len += ((sizeof(attr->type) +
+		 sizeof(attr->len)) * count);
+	return len;
+}
+
+static          u16
+bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
+	u16        len;
+
+	rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
+	rprt->port_name = bfa_fcs_lport_get_pwwn(port);
+
+	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
+				(u8 *) &rprt->port_attr_blk);
+
+	len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
+
+	return len;
+}
+
+static void
+bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi =
+			(struct bfa_fcs_lport_fdmi_s *) cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+/**
+*  RPA : Register Port Attributes.
+ */
+static void
+bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fchs_s fchs;
+	u16        len, attr_len;
+	struct bfa_fcxp_s *fcxp;
+	u8        *pyld;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
+					bfa_fcs_lport_fdmi_send_rpa, fdmi);
+		return;
+	}
+	fdmi->fcxp = fcxp;
+
+	pyld = bfa_fcxp_get_reqbuf(fcxp);
+	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
+
+	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
+				   FDMI_RPA);
+
+	attr_len =
+		bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
+					 (u8 *) ((struct ct_hdr_s *) pyld
+						      + 1));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len + attr_len, &fchs,
+			  bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
+}
+
+static          u16
+bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
+	u16        len;
+
+	rpa->port_name = bfa_fcs_lport_get_pwwn(port);
+
+	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
+				(u8 *) &rpa->port_attr_blk);
+
+	len += sizeof(rpa->port_name);
+
+	return len;
+}
+
+static void
+bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status, u32 rsp_len,
+			u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi =
+				(struct bfa_fcs_lport_fdmi_s *) cbarg;
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
+}
+
+static void
+bfa_fcs_lport_fdmi_timeout(void *arg)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
+
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
+}
+
+void
+bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
+
+	bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
+
+	bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
+					hba_attr->manufacturer);
+	bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
+					hba_attr->serial_num);
+	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
+					hba_attr->model);
+	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
+					hba_attr->model_desc);
+	bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
+					hba_attr->hw_version);
+	bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
+					hba_attr->option_rom_ver);
+	bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
+					hba_attr->fw_version);
+
+	strncpy(hba_attr->driver_version, (char *)driver_info->version,
+		sizeof(hba_attr->driver_version));
+
+	strncpy(hba_attr->os_name, driver_info->host_os_name,
+		sizeof(hba_attr->os_name));
+
+	/*
+	 * If there is a patch level, append it
+	 * to the os name along with a separator
+	 */
+	if (driver_info->host_os_patch[0] != '\0') {
+		strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
+		strncat(hba_attr->os_name, driver_info->host_os_patch,
+				sizeof(driver_info->host_os_patch));
+	}
+
+	hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ);
+}
+
+void
+bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
+			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
+{
+	struct bfa_fcs_lport_s *port = fdmi->ms->port;
+	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
+	struct bfa_port_attr_s pport_attr;
+
+	bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
+
+	/*
+	 * get pport attributes from hal
+	 */
+	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
+
+	/*
+	 * get FC4 type Bitmask
+	 */
+	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
+
+	/*
+	 * Supported Speeds
+	 */
+	port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS);
+
+	/*
+	 * Current Speed
+	 */
+	port_attr->curr_speed = bfa_os_htonl(pport_attr.speed);
+
+	/*
+	 * Max PDU Size.
+	 */
+	port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ);
+
+	/*
+	 * OS device Name
+	 */
+	strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
+		sizeof(port_attr->os_device_name));
+
+	/*
+	 * Host name
+	 */
+	strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
+		sizeof(port_attr->host_name));
 
 }
 
 
+void
+bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
+
+	fdmi->ms = ms;
+	if (ms->port->fcs->fdmi_enabled)
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
+	else
+		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
+}
+
+void
+bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
+
+	fdmi->ms = ms;
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
+{
+	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
+
+	fdmi->ms = ms;
+	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
+}
+
+#define BFA_FCS_MS_CMD_MAX_RETRIES  2
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
+					   struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ms_timeout(void *arg);
+static void     bfa_fcs_lport_ms_plogi_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+
+static void	bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
+					struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ms_gmal_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+static void	bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
+					struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ms_gfn_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+/**
+ *  fcs_ms_sm FCS MS state machine
+ */
+
+/**
+ *  MS State Machine events
+ */
+enum port_ms_event {
+	MSSM_EVENT_PORT_ONLINE = 1,
+	MSSM_EVENT_PORT_OFFLINE = 2,
+	MSSM_EVENT_RSP_OK = 3,
+	MSSM_EVENT_RSP_ERROR = 4,
+	MSSM_EVENT_TIMEOUT = 5,
+	MSSM_EVENT_FCXP_SENT = 6,
+	MSSM_EVENT_PORT_FABRIC_RSCN = 7
+};
+
+static void     bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
+					   enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
+						 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
+					 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
+					       enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
+						 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
+					 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
+					       enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
+						 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
+					 enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
+					       enum port_ms_event event);
+static void     bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
+					  enum port_ms_event event);
+/**
+ *	Start in offline state - awaiting NS to send start.
+ */
+static void
+bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_PORT_ONLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
+		bfa_fcs_lport_ms_send_plogi(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+					   &ms->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
+		ms->port->stats.ms_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+				    &ms->timer, bfa_fcs_lport_ms_timeout, ms,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case MSSM_EVENT_RSP_OK:
+		/*
+		 * since plogi is done, now invoke MS related sub-modules
+		 */
+		bfa_fcs_lport_fdmi_online(ms);
+
+		/**
+		 * if this is a Vport, go to online state.
+		 */
+		if (ms->port->vport) {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
+			break;
+		}
+
+		/*
+		 * For a base port we need to get the
+		 * switch's IP address.
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
+		bfa_fcs_lport_ms_send_gmal(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_discard(ms->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
+		bfa_fcs_lport_ms_send_plogi(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_timer_stop(&ms->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		break;
+
+	case MSSM_EVENT_PORT_FABRIC_RSCN:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+		ms->retry_cnt = 0;
+		bfa_fcs_lport_ms_send_gfn(ms, NULL);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+					   &ms->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
+			ms->port->stats.ms_retries++;
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
+				BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+			bfa_fcs_lport_ms_send_gfn(ms, NULL);
+			ms->retry_cnt = 0;
+		}
+		break;
+
+	case MSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+		bfa_fcs_lport_ms_send_gfn(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_discard(ms->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
+		bfa_fcs_lport_ms_send_gmal(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_timer_stop(&ms->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+/**
+ *  ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
+	bfa_fcs_lport_t *port = ms->port;
+	struct fchs_s	fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+					bfa_fcs_lport_ms_send_gmal, ms);
+		return;
+	}
+	ms->fcxp = fcxp;
+
+	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_fcs_lport_get_fcid(port),
+				 bfa_lps_get_peer_nwwn(port->fabric->lps));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ms_gmal_response, (void *)ms,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
+	bfa_fcs_lport_t *port = ms->port;
+	struct ct_hdr_s		*cthdr = NULL;
+	struct fcgs_gmal_resp_s *gmal_resp;
+	struct fcgs_gmal_entry_s *gmal_entry;
+	u32		num_entries;
+	u8			*rsp_str;
+
+	bfa_trc(port->fcs, req_status);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
+
+		num_entries = bfa_os_ntohl(gmal_resp->ms_len);
+		if (num_entries == 0) {
+			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+			return;
+		}
+		/*
+		* The response could contain multiple Entries.
+		* Entries for SNMP interface, etc.
+		* We look for the entry with a telnet prefix.
+		* First "http://" entry refers to IP addr
+		*/
+
+		gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
+		while (num_entries > 0) {
+			if (strncmp(gmal_entry->prefix,
+				CT_GMAL_RESP_PREFIX_HTTP,
+				sizeof(gmal_entry->prefix)) == 0) {
+
+				/*
+				* if the IP address is terminating with a '/',
+				* remove it.
+				* Byte 0 consists of the length of the string.
+				*/
+				rsp_str = &(gmal_entry->prefix[0]);
+				if (rsp_str[gmal_entry->len-1] == '/')
+					rsp_str[gmal_entry->len-1] = 0;
+
+				/* copy IP Address to fabric */
+				strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
+					gmal_entry->ip_addr,
+					BFA_FCS_FABRIC_IPADDR_SZ);
+				break;
+			} else {
+				--num_entries;
+				++gmal_entry;
+			}
+		}
+
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+}
+
+static void
+bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+					   &ms->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
+			enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
+			ms->port->stats.ms_retries++;
+			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
+				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
+				BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
+			ms->retry_cnt = 0;
+		}
+		break;
+
+	case MSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_fcxp_discard(ms->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
+				enum port_ms_event event)
+{
+	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
+	bfa_trc(ms->port->fcs, event);
+
+	switch (event) {
+	case MSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
+		bfa_fcs_lport_ms_send_gfn(ms, NULL);
+		break;
+
+	case MSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+		bfa_timer_stop(&ms->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ms->port->fcs, event);
+	}
+}
+/**
+ *  ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
+	bfa_fcs_lport_t *port = ms->port;
+	struct fchs_s		fchs;
+	int			len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+					bfa_fcs_lport_ms_send_gfn, ms);
+		return;
+	}
+	ms->fcxp = fcxp;
+
+	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_fcs_lport_get_fcid(port),
+				 bfa_lps_get_peer_nwwn(port->fabric->lps));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ms_gfn_response, (void *)ms,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status, u32 rsp_len,
+			u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
+	bfa_fcs_lport_t *port = ms->port;
+	struct ct_hdr_s	*cthdr = NULL;
+	wwn_t	       *gfn_resp;
+
+	bfa_trc(port->fcs, req_status);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		gfn_resp = (wwn_t *)(cthdr + 1);
+		/* check if it has actually changed */
+		if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
+				gfn_resp, sizeof(wwn_t)) != 0)) {
+			bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
+		}
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ *  ms_pvt MS local functions
+ */
+
+static void
+bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
+	struct bfa_fcs_lport_s *port = ms->port;
+	struct fchs_s	fchs;
+	int	len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ms_plogi_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
+					bfa_fcs_lport_ms_send_plogi, ms);
+		return;
+	}
+	ms->fcxp = fcxp;
+
+	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_os_hton3b(FC_MGMT_SERVER),
+			     bfa_fcs_lport_get_fcid(port), 0,
+			     port->port_cfg.pwwn, port->port_cfg.nwwn,
+				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ms_plogi_response, (void *)ms,
+			  FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	port->stats.ms_plogi_sent++;
+	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status,
+			u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ms->port;
+	struct fc_els_cmd_s *els_cmd;
+	struct fc_ls_rjt_s *ls_rjt;
+
+	bfa_trc(port->fcs, req_status);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		port->stats.ms_plogi_rsp_err++;
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+	switch (els_cmd->els_code) {
+
+	case FC_ELS_ACC:
+		if (rsp_len < sizeof(struct fc_logi_s)) {
+			bfa_trc(port->fcs, rsp_len);
+			port->stats.ms_plogi_acc_err++;
+			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+			break;
+		}
+		port->stats.ms_plogi_accepts++;
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
+		break;
+
+	case FC_ELS_LS_RJT:
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+		bfa_trc(port->fcs, ls_rjt->reason_code);
+		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+		port->stats.ms_rejects++;
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+		break;
+
+	default:
+		port->stats.ms_plogi_unknown_rsp++;
+		bfa_trc(port->fcs, els_cmd->els_code);
+		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
+	}
+}
+
+static void
+bfa_fcs_lport_ms_timeout(void *arg)
+{
+	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
+
+	ms->port->stats.ms_timeouts++;
+	bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
+}
+
+
+void
+bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+	ms->port = port;
+	bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
+
+	/*
+	 * Invoke init routines of sub modules.
+	 */
+	bfa_fcs_lport_fdmi_init(ms);
+}
+
+void
+bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+	ms->port = port;
+	bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
+	bfa_fcs_lport_fdmi_offline(ms);
+}
+
+void
+bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+	ms->port = port;
+	bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
+}
+void
+bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
+
+	/* todo.  Handle this only  when in Online state */
+	if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
+		bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
+}
+
+/**
+ * @page ns_sm_info VPORT NS State Machine
+ *
+ * @section ns_sm_interactions VPORT NS State Machine Interactions
+ *
+ * @section ns_sm VPORT NS State Machine
+ * img ns_sm.jpg
+ */
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
+					   struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
+					     struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
+					    struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_ns_timeout(void *arg);
+static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
+					       struct bfa_fcxp_s *fcxp,
+					       void *cbarg,
+					       bfa_status_t req_status,
+					       u32 rsp_len,
+					       u32 resid_len,
+					       struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
+						 struct bfa_fcxp_s *fcxp,
+						 void *cbarg,
+						 bfa_status_t req_status,
+						 u32 rsp_len,
+						 u32 resid_len,
+						 struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
+						struct bfa_fcxp_s *fcxp,
+						void *cbarg,
+						bfa_status_t req_status,
+						u32 rsp_len,
+						u32 resid_len,
+						struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_ns_process_gidft_pids(
+				struct bfa_fcs_lport_s *port,
+				u32 *pid_buf, u32 n_pids);
+
+static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
+/**
+ *  fcs_ns_sm FCS nameserver interface state machine
+ */
+
+/**
+ * VPort NS State Machine events
+ */
+enum vport_ns_event {
+	NSSM_EVENT_PORT_ONLINE = 1,
+	NSSM_EVENT_PORT_OFFLINE = 2,
+	NSSM_EVENT_PLOGI_SENT = 3,
+	NSSM_EVENT_RSP_OK = 4,
+	NSSM_EVENT_RSP_ERROR = 5,
+	NSSM_EVENT_TIMEOUT = 6,
+	NSSM_EVENT_NS_QUERY = 7,
+	NSSM_EVENT_RSPNID_SENT = 8,
+	NSSM_EVENT_RFTID_SENT = 9,
+	NSSM_EVENT_RFFID_SENT = 10,
+	NSSM_EVENT_GIDFT_SENT = 11,
+};
+
+static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
+					   enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
+						 enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
+					 enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
+					       enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_rspn_id(
+					struct bfa_fcs_lport_ns_s *ns,
+					enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
+					   enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+						 enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_rft_id(
+					struct bfa_fcs_lport_ns_s *ns,
+					enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
+						enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
+					  enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_rff_id(
+					struct bfa_fcs_lport_ns_s *ns,
+					enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
+						enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
+					  enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_sending_gid_ft(
+					struct bfa_fcs_lport_ns_s *ns,
+					enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
+					  enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
+						enum vport_ns_event event);
+static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
+					  enum vport_ns_event event);
+/**
+ *	Start in offline state - awaiting linkup
+ */
+static void
+bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_PORT_ONLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
+		bfa_fcs_lport_ns_send_plogi(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_PLOGI_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
+		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_discard(ns->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
+		bfa_fcs_lport_ns_send_plogi(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
+				   enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSPNID_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
+		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_fcxp_discard(ns->fcxp);
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		/*
+		 * Retry Timer Expired. Re-send
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
+		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
+				  enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RFTID_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_OK:
+		/* Now move to register FC4 Features */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
+		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_discard(ns->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
+		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
+				  enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RFFID_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_OK:
+
+		/*
+		 * If min cfg mode is enabled, we donot initiate rport
+		 * discovery with the fabric. Instead, we will retrieve the
+		 * boot targets from HAL/FW.
+		 */
+		if (__fcs_min_cfg(ns->port->fcs)) {
+			bfa_fcs_lport_ns_boot_target_disc(ns->port);
+			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
+			return;
+		}
+
+		/*
+		 * If the port role is Initiator Mode issue NS query.
+		 * If it is Target Mode, skip this and go to online.
+		 */
+		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+			bfa_sm_set_state(ns,
+				bfa_fcs_lport_ns_sm_sending_gid_ft);
+			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
+		}
+		/*
+		 * kick off mgmt srvr state machine
+		 */
+		bfa_fcs_lport_ms_online(ns->port);
+		break;
+
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_discard(ns->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
+		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+static void
+bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
+				  enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_GIDFT_SENT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+					   &ns->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_RSP_OK:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
+		break;
+
+	case NSSM_EVENT_RSP_ERROR:
+		/*
+		 * TBD: for certain reject codes, we don't need to retry
+		 */
+		/*
+		 * Start timer for a delayed retry
+		 */
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
+		ns->port->stats.ns_retries++;
+		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
+				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_fcxp_discard(ns->fcxp);
+		break;
+
+	case  NSSM_EVENT_NS_QUERY:
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
+				enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
+		bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
+		break;
+
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		bfa_timer_stop(&ns->timer);
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
+			enum vport_ns_event event)
+{
+	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
+	bfa_trc(ns->port->fcs, event);
+
+	switch (event) {
+	case NSSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+		break;
+
+	case NSSM_EVENT_NS_QUERY:
+		/*
+		 * If the port role is Initiator Mode issue NS query.
+		 * If it is Target Mode, skip this and go to online.
+		 */
+		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
+			bfa_sm_set_state(ns,
+				bfa_fcs_lport_ns_sm_sending_gid_ft);
+			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
+		};
+		break;
+
+	default:
+		bfa_sm_fault(ns->port->fcs, event);
+	}
+}
+
+
+
+/**
+ *  ns_pvt Nameserver local functions
+ */
+
+static void
+bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_plogi_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_plogi, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_os_hton3b(FC_NAME_SERVER),
+			     bfa_fcs_lport_get_fcid(port), 0,
+			     port->port_cfg.pwwn, port->port_cfg.nwwn,
+				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_plogi_response, (void *)ns,
+			  FC_MAX_PDUSZ, FC_ELS_TOV);
+	port->stats.ns_plogi_sent++;
+
+	bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status, u32 rsp_len,
+		       u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	/* struct fc_logi_s *plogi_resp; */
+	struct fc_els_cmd_s *els_cmd;
+	struct fc_ls_rjt_s *ls_rjt;
+
+	bfa_trc(port->fcs, req_status);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_plogi_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+	switch (els_cmd->els_code) {
+
+	case FC_ELS_ACC:
+		if (rsp_len < sizeof(struct fc_logi_s)) {
+			bfa_trc(port->fcs, rsp_len);
+			port->stats.ns_plogi_acc_err++;
+			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+			break;
+		}
+		port->stats.ns_plogi_accepts++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		break;
+
+	case FC_ELS_LS_RJT:
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+		bfa_trc(port->fcs, ls_rjt->reason_code);
+		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+		port->stats.ns_rejects++;
+
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		break;
+
+	default:
+		port->stats.ns_plogi_unknown_rsp++;
+		bfa_trc(port->fcs, els_cmd->els_code);
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+	}
+}
+
+/**
+ * Register the symbolic port name.
+ */
+static void
+bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+	u8         symbl[256];
+	u8         *psymbl = &symbl[0];
+
+	bfa_os_memset(symbl, 0, sizeof(symbl));
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_rspnid_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_rspn_id, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	/*
+	 * for V-Port, form a Port Symbolic Name
+	 */
+	if (port->vport) {
+		/**
+		 * For Vports, we append the vport's port symbolic name
+		 * to that of the base port.
+		 */
+
+		strncpy((char *)psymbl,
+			(char *) &
+			(bfa_fcs_lport_get_psym_name
+			 (bfa_fcs_get_base_port(port->fcs))),
+			strlen((char *) &
+			       bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
+							  (port->fcs))));
+
+		/* Ensure we have a null terminating string. */
+		((char *)psymbl)[strlen((char *) &
+			bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
+						(port->fcs)))] = 0;
+		strncat((char *)psymbl,
+			(char *) &(bfa_fcs_lport_get_psym_name(port)),
+		strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
+	} else {
+		psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
+	}
+
+	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			      bfa_fcs_lport_get_fcid(port), 0, psymbl);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	port->stats.ns_rspnid_sent++;
+
+	bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				 void *cbarg, bfa_status_t req_status,
+				 u32 rsp_len, u32 resid_len,
+				 struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_rspnid_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		port->stats.ns_rspnid_accepts++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	port->stats.ns_rspnid_rejects++;
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ * Register FC4-Types
+ */
+static void
+bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_rftid_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_rft_id, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+		     bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_rft_id_response, (void *)ns,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	port->stats.ns_rftid_sent++;
+	bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_rftid_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		port->stats.ns_rftid_accepts++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	port->stats.ns_rftid_rejects++;
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+
+/**
+ * Register FC4-Features : Should be done after RFT_ID
+ */
+static void
+bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+	u8			fc4_ftrs = 0;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_rffid_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_rff_id, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
+		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
+
+	len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			     bfa_fcs_lport_get_fcid(port), 0,
+				 FC_TYPE_FCP, fc4_ftrs);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_rff_id_response, (void *)ns,
+			  FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	port->stats.ns_rffid_sent++;
+	bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct ct_hdr_s *cthdr = NULL;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_rffid_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		port->stats.ns_rffid_accepts++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		return;
+	}
+
+	port->stats.ns_rffid_rejects++;
+	bfa_trc(port->fcs, cthdr->reason_code);
+	bfa_trc(port->fcs, cthdr->exp_code);
+
+	if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
+		/* if this command is not supported, we don't retry */
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+	} else
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+}
+/**
+ * Query Fabric for FC4-Types Devices.
+ *
+* TBD : Need to use a local (FCS private) response buffer, since the response
+ * can be larger than 2K.
+ */
+static void
+bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		port->stats.ns_gidft_alloc_wait++;
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
+					bfa_fcs_lport_ns_send_gid_ft, ns);
+		return;
+	}
+	ns->fcxp = fcxp;
+
+	/*
+	 * This query is only initiated for FCP initiator mode.
+	 */
+	len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			      ns->port->pid, FC_TYPE_FCP);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
+			  bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
+
+	port->stats.ns_gidft_sent++;
+
+	bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
+}
+
+static void
+bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+				void *cbarg, bfa_status_t req_status,
+				u32 rsp_len, u32 resid_len,
+				struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
+	struct bfa_fcs_lport_s *port = ns->port;
+	struct ct_hdr_s *cthdr = NULL;
+	u32        n_pids;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		port->stats.ns_gidft_rsp_err++;
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	if (resid_len != 0) {
+		/*
+		 * TBD : we will need to allocate a larger buffer & retry the
+		 * command
+		 */
+		bfa_trc(port->fcs, rsp_len);
+		bfa_trc(port->fcs, resid_len);
+		return;
+	}
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	switch (cthdr->cmd_rsp_code) {
+
+	case CT_RSP_ACCEPT:
+
+		port->stats.ns_gidft_accepts++;
+		n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
+		bfa_trc(port->fcs, n_pids);
+		bfa_fcs_lport_ns_process_gidft_pids(port,
+						   (u32 *) (cthdr + 1),
+						   n_pids);
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		break;
+
+	case CT_RSP_REJECT:
+
+		/*
+		 * Check the reason code  & explanation.
+		 * There may not have been any FC4 devices in the fabric
+		 */
+		port->stats.ns_gidft_rejects++;
+		bfa_trc(port->fcs, cthdr->reason_code);
+		bfa_trc(port->fcs, cthdr->exp_code);
+
+		if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
+		    && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
+
+			bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
+		} else {
+			/*
+			 * for all other errors, retry
+			 */
+			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+		}
+		break;
+
+	default:
+		port->stats.ns_gidft_unknown_rsp++;
+		bfa_trc(port->fcs, cthdr->cmd_rsp_code);
+		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
+	}
+}
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *	param[in]	port - pointer to bfa_fcs_lport_t.
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+static void
+bfa_fcs_lport_ns_timeout(void *arg)
+{
+	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
+
+	ns->port->stats.ns_timeouts++;
+	bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
+}
+
+/*
+ * Process the PID list in GID_FT response
+ */
+static void
+bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
+				   u32 n_pids)
+{
+	struct fcgs_gidft_resp_s *gidft_entry;
+	struct bfa_fcs_rport_s *rport;
+	u32        ii;
+
+	for (ii = 0; ii < n_pids; ii++) {
+		gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
+
+		if (gidft_entry->pid == port->pid)
+			continue;
+
+		/*
+		 * Check if this rport already exists
+		 */
+		rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
+		if (rport == NULL) {
+			/*
+			 * this is a new device. create rport
+			 */
+			rport = bfa_fcs_rport_create(port, gidft_entry->pid);
+		} else {
+			/*
+			 * this rport already exists
+			 */
+			bfa_fcs_rport_scn(rport);
+		}
+
+		bfa_trc(port->fcs, gidft_entry->pid);
+
+		/*
+		 * if the last entry bit is set, bail out.
+		 */
+		if (gidft_entry->last)
+			return;
+	}
+}
+
+/**
+ *  fcs_ns_public FCS nameserver public interfaces
+ */
+
+/*
+ * Functions called by port/fab.
+ * These will send relevant Events to the ns state machine.
+ */
+void
+bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+	ns->port = port;
+	bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
+}
+
+void
+bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+	ns->port = port;
+	bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+	ns->port = port;
+	bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
+}
+
+void
+bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
+
+	bfa_trc(port->fcs, port->pid);
+	bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
+}
+
+void
+bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
+{
+
+	struct bfa_fcs_rport_s *rport;
+	u8 nwwns;
+	wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
+	int ii;
+
+	bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
+
+	for (ii = 0 ; ii < nwwns; ++ii) {
+		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
+		bfa_assert(rport);
+	}
+}
+
+/**
+ * FCS SCN
+ */
+
+#define FC_QOS_RSCN_EVENT		0x0c
+#define FC_FABRIC_NAME_RSCN_EVENT	0x0d
+
+/*
+ * forward declarations
+ */
+static void     bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
+					  struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_lport_scn_scr_response(void *fcsarg,
+					      struct bfa_fcxp_s *fcxp,
+					      void *cbarg,
+					      bfa_status_t req_status,
+					      u32 rsp_len,
+					      u32 resid_len,
+					      struct fchs_s *rsp_fchs);
+static void     bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
+					     struct fchs_s *rx_fchs);
+static void     bfa_fcs_lport_scn_timeout(void *arg);
+
+/**
+ *  fcs_scm_sm FCS SCN state machine
+ */
+
+/**
+ * VPort SCN State Machine events
+ */
+enum port_scn_event {
+	SCNSM_EVENT_PORT_ONLINE = 1,
+	SCNSM_EVENT_PORT_OFFLINE = 2,
+	SCNSM_EVENT_RSP_OK = 3,
+	SCNSM_EVENT_RSP_ERROR = 4,
+	SCNSM_EVENT_TIMEOUT = 5,
+	SCNSM_EVENT_SCR_SENT = 6,
+};
+
+static void     bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
+					    enum port_scn_event event);
+static void     bfa_fcs_lport_scn_sm_sending_scr(
+					struct bfa_fcs_lport_scn_s *scn,
+					enum port_scn_event event);
+static void     bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
+					enum port_scn_event event);
+static void     bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
+					      enum port_scn_event event);
+static void     bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
+					   enum port_scn_event event);
+
+/**
+ *	Starting state - awaiting link up.
+ */
+static void
+bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
+			enum port_scn_event event)
+{
+	switch (event) {
+	case SCNSM_EVENT_PORT_ONLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
+		bfa_fcs_lport_scn_send_scr(scn, NULL);
+		break;
+
+	case SCNSM_EVENT_PORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(scn->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
+				enum port_scn_event event)
+{
+	switch (event) {
+	case SCNSM_EVENT_SCR_SENT:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
+		break;
+
+	case SCNSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+		bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
+		break;
+
+	default:
+		bfa_sm_fault(scn->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
+			enum port_scn_event event)
+{
+	struct bfa_fcs_lport_s *port = scn->port;
+
+	switch (event) {
+	case SCNSM_EVENT_RSP_OK:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
+		break;
+
+	case SCNSM_EVENT_RSP_ERROR:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
+		bfa_timer_start(port->fcs->bfa, &scn->timer,
+				    bfa_fcs_lport_scn_timeout, scn,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case SCNSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+		bfa_fcxp_discard(scn->fcxp);
+		break;
+
+	default:
+		bfa_sm_fault(port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
+				enum port_scn_event event)
+{
+	switch (event) {
+	case SCNSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
+		bfa_fcs_lport_scn_send_scr(scn, NULL);
+		break;
+
+	case SCNSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+		bfa_timer_stop(&scn->timer);
+		break;
+
+	default:
+		bfa_sm_fault(scn->port->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
+			enum port_scn_event event)
+{
+	switch (event) {
+	case SCNSM_EVENT_PORT_OFFLINE:
+		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+		break;
+
+	default:
+		bfa_sm_fault(scn->port->fcs, event);
+	}
+}
+
+
+
+/**
+ *  fcs_scn_private FCS SCN private functions
+ */
+
+/**
+ * This routine will be called to send a SCR command.
+ */
+static void
+bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
+	struct bfa_fcs_lport_s *port = scn->port;
+	struct fchs_s fchs;
+	int             len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(port->fcs, port->pid);
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
+					bfa_fcs_lport_scn_send_scr, scn);
+		return;
+	}
+	scn->fcxp = fcxp;
+
+	/* Handle VU registrations for Base port only */
+	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
+		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				bfa_lps_is_brcd_fabric(port->fabric->lps),
+							port->pid, 0);
+	} else {
+	    len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				    BFA_FALSE,
+				    port->pid, 0);
+	}
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs,
+			  bfa_fcs_lport_scn_scr_response,
+			  (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
+}
+
+static void
+bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
+			void *cbarg, bfa_status_t req_status, u32 rsp_len,
+			      u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
+	struct bfa_fcs_lport_s *port = scn->port;
+	struct fc_els_cmd_s *els_cmd;
+	struct fc_ls_rjt_s *ls_rjt;
+
+	bfa_trc(port->fcs, port->port_cfg.pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(port->fcs, req_status);
+		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+		return;
+	}
+
+	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+	switch (els_cmd->els_code) {
+
+	case FC_ELS_ACC:
+		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
+		break;
+
+	case FC_ELS_LS_RJT:
+
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+		bfa_trc(port->fcs, ls_rjt->reason_code);
+		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
+
+		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+		break;
+
+	default:
+		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
+	}
+}
+
+/*
+ * Send a LS Accept
+ */
+static void
+bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
+				struct fchs_s *rx_fchs)
+{
+	struct fchs_s fchs;
+	struct bfa_fcxp_s *fcxp;
+	struct bfa_rport_s *bfa_rport = NULL;
+	int             len;
+
+	bfa_trc(port->fcs, rx_fchs->s_id);
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+			      rx_fchs->ox_id);
+
+	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
+			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			  FC_MAX_PDUSZ, 0);
+}
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *	param[in]	vport		- pointer to bfa_fcs_lport_t.
+ *	param[out]	vport_status	- pointer to return vport status in
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+static void
+bfa_fcs_lport_scn_timeout(void *arg)
+{
+	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
+
+	bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
+}
+
+
+
+/**
+ *  fcs_scn_public FCS state change notification public interfaces
+ */
+
+/*
+ * Functions called by port/fab
+ */
+void
+bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+	scn->port = port;
+	bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
+}
+
+void
+bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+	scn->port = port;
+	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
+}
+
+void
+bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
+{
+	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
+
+	scn->port = port;
+	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
+}
+
+static void
+bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	bfa_trc(port->fcs, rpid);
+
+	/**
+	 * If this is an unknown device, then it just came online.
+	 * Otherwise let rport handle the RSCN event.
+	 */
+	rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
+	if (rport == NULL) {
+		/*
+		 * If min cfg mode is enabled, we donot need to
+		 * discover any new rports.
+		 */
+		if (!__fcs_min_cfg(port->fcs))
+			rport = bfa_fcs_rport_create(port, rpid);
+	} else
+		bfa_fcs_rport_scn(rport);
+}
+
+/**
+ * rscn format based PID comparison
+ */
+#define __fc_pid_match(__c0, __c1, __fmt)		\
+	(((__fmt) == FC_RSCN_FORMAT_FABRIC) ||		\
+	 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&		\
+	  ((__c0)[0] == (__c1)[0])) ||				\
+	 (((__fmt) == FC_RSCN_FORMAT_AREA) &&		\
+	  ((__c0)[0] == (__c1)[0]) &&				\
+	  ((__c0)[1] == (__c1)[1])))
+
+static void
+bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
+				enum fc_rscn_format format,
+				u32 rscn_pid)
+{
+	struct bfa_fcs_rport_s *rport;
+	struct list_head        *qe, *qe_next;
+	u8        *c0, *c1;
+
+	bfa_trc(port->fcs, format);
+	bfa_trc(port->fcs, rscn_pid);
+
+	c0 = (u8 *) &rscn_pid;
+
+	list_for_each_safe(qe, qe_next, &port->rport_q) {
+		rport = (struct bfa_fcs_rport_s *) qe;
+		c1 = (u8 *) &rport->pid;
+		if (__fc_pid_match(c0, c1, format))
+			bfa_fcs_rport_scn(rport);
+	}
+}
+
+
+void
+bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
+			struct fchs_s *fchs, u32 len)
+{
+	struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
+	int             num_entries;
+	u32        rscn_pid;
+	bfa_boolean_t   nsquery = BFA_FALSE, found;
+	int             i = 0, j;
+
+	num_entries =
+		(bfa_os_ntohs(rscn->payldlen) -
+		 sizeof(u32)) / sizeof(rscn->event[0]);
+
+	bfa_trc(port->fcs, num_entries);
+
+	port->stats.num_rscn++;
+
+	bfa_fcs_lport_scn_send_ls_acc(port, fchs);
+
+	for (i = 0; i < num_entries; i++) {
+		rscn_pid = rscn->event[i].portid;
+
+		bfa_trc(port->fcs, rscn->event[i].format);
+		bfa_trc(port->fcs, rscn_pid);
+
+		/* check for duplicate entries in the list */
+		found = BFA_FALSE;
+		for (j = 0; j < i; j++) {
+			if (rscn->event[j].portid == rscn_pid) {
+				found = BFA_TRUE;
+				break;
+			}
+		}
+
+		/* if found in down the list, pid has been already processed */
+		if (found) {
+			bfa_trc(port->fcs, rscn_pid);
+			continue;
+		}
+
+		switch (rscn->event[i].format) {
+		case FC_RSCN_FORMAT_PORTID:
+			if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
+				/*
+				 * Ignore this event.
+				 * f/w would have processed it
+				 */
+				bfa_trc(port->fcs, rscn_pid);
+			} else {
+				port->stats.num_portid_rscn++;
+				bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
+			}
+		break;
+
+		case FC_RSCN_FORMAT_FABRIC:
+			if (rscn->event[i].qualifier ==
+					FC_FABRIC_NAME_RSCN_EVENT) {
+				bfa_fcs_lport_ms_fabric_rscn(port);
+				break;
+			}
+			/* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
+
+		case FC_RSCN_FORMAT_AREA:
+		case FC_RSCN_FORMAT_DOMAIN:
+			nsquery = BFA_TRUE;
+			bfa_fcs_lport_scn_multiport_rscn(port,
+							rscn->event[i].format,
+							rscn_pid);
+			break;
+
+
+		default:
+			bfa_assert(0);
+			nsquery = BFA_TRUE;
+		}
+	}
+
+	/**
+	 * If any of area, domain or fabric RSCN is received, do a fresh discovery
+	 * to find new devices.
+	 */
+	if (nsquery)
+		bfa_fcs_lport_ns_query(port);
+}
+
+/**
+ * BFA FCS port
+ */
+/**
+ *  fcs_port_api BFA FCS port API
+ */
+struct bfa_fcs_lport_s *
+bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
+{
+	return &fcs->fabric.bport;
+}
+
+wwn_t
+bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
+		int nrports, bfa_boolean_t bwwn)
+{
+	struct list_head	*qh, *qe;
+	struct bfa_fcs_rport_s *rport = NULL;
+	int	i;
+	struct bfa_fcs_s	*fcs;
+
+	if (port == NULL || nrports == 0)
+		return (wwn_t) 0;
+
+	fcs = port->fcs;
+	bfa_trc(fcs, (u32) nrports);
+
+	i = 0;
+	qh = &port->rport_q;
+	qe = bfa_q_first(qh);
+
+	while ((qe != qh) && (i < nrports)) {
+		rport = (struct bfa_fcs_rport_s *) qe;
+		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+			qe = bfa_q_next(qe);
+			bfa_trc(fcs, (u32) rport->pwwn);
+			bfa_trc(fcs, rport->pid);
+			bfa_trc(fcs, i);
+			continue;
+		}
+
+		if (bwwn) {
+			if (!memcmp(&wwn, &rport->pwwn, 8))
+				break;
+		} else {
+			if (i == index)
+				break;
+		}
+
+		i++;
+		qe = bfa_q_next(qe);
+	}
+
+	bfa_trc(fcs, i);
+	if (rport)
+		return rport->pwwn;
+	else
+		return (wwn_t) 0;
+}
+
+void
+bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
+	 wwn_t rport_wwns[], int *nrports)
+{
+	struct list_head	*qh, *qe;
+	struct bfa_fcs_rport_s *rport = NULL;
+	int	i;
+	struct bfa_fcs_s	*fcs;
+
+	if (port == NULL || rport_wwns == NULL || *nrports == 0)
+		return;
+
+	fcs = port->fcs;
+	bfa_trc(fcs, (u32) *nrports);
+
+	i = 0;
+	qh = &port->rport_q;
+	qe = bfa_q_first(qh);
+
+	while ((qe != qh) && (i < *nrports)) {
+		rport = (struct bfa_fcs_rport_s *) qe;
+		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
+			qe = bfa_q_next(qe);
+			bfa_trc(fcs, (u32) rport->pwwn);
+			bfa_trc(fcs, rport->pid);
+			bfa_trc(fcs, i);
+			continue;
+		}
+
+		rport_wwns[i] = rport->pwwn;
+
+		i++;
+		qe = bfa_q_next(qe);
+	}
+
+	bfa_trc(fcs, i);
+	*nrports = i;
+}
+
+/*
+ * Iterate's through all the rport's in the given port to
+ * determine the maximum operating speed.
+ *
+ * !!!! To be used in TRL Functionality only !!!!
+ */
+bfa_port_speed_t
+bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
+{
+	struct list_head *qh, *qe;
+	struct bfa_fcs_rport_s *rport = NULL;
+	struct bfa_fcs_s	*fcs;
+	bfa_port_speed_t max_speed = 0;
+	struct bfa_port_attr_s port_attr;
+	bfa_port_speed_t port_speed, rport_speed;
+	bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
+
+
+	if (port == NULL)
+		return 0;
+
+	fcs = port->fcs;
+
+	/* Get Physical port's current speed */
+	bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
+	port_speed = port_attr.speed;
+	bfa_trc(fcs, port_speed);
+
+	qh = &port->rport_q;
+	qe = bfa_q_first(qh);
+
+	while (qe != qh) {
+		rport = (struct bfa_fcs_rport_s *) qe;
+		if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) ||
+			(bfa_fcs_rport_get_state(rport) ==
+			  BFA_RPORT_OFFLINE)) {
+			qe = bfa_q_next(qe);
+			continue;
+		}
+
+		rport_speed = rport->rpf.rpsc_speed;
+		if ((trl_enabled) && (rport_speed ==
+			BFA_PORT_SPEED_UNKNOWN)) {
+			/* Use default ratelim speed setting */
+			rport_speed =
+				bfa_fcport_get_ratelim_speed(port->fcs->bfa);
+		}
+
+		if	((rport_speed  == BFA_PORT_SPEED_8GBPS) ||
+			(rport_speed > port_speed)) {
+			max_speed = rport_speed;
+			break;
+		} else if (rport_speed > max_speed) {
+			max_speed = rport_speed;
+		}
+
+		qe = bfa_q_next(qe);
+	}
+
+	bfa_trc(fcs, max_speed);
+	return max_speed;
+}
+
+struct bfa_fcs_lport_s *
+bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
+{
+	struct bfa_fcs_vport_s *vport;
+	bfa_fcs_vf_t   *vf;
+
+	bfa_assert(fcs != NULL);
+
+	vf = bfa_fcs_vf_lookup(fcs, vf_id);
+	if (vf == NULL) {
+		bfa_trc(fcs, vf_id);
+		return NULL;
+	}
+
+	if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
+		return &vf->bport;
+
+	vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
+	if (vport)
+		return &vport->lport;
+
+	return NULL;
+}
+
+/*
+ *  API corresponding to NPIV_VPORT_GETINFO.
+ */
+void
+bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
+	 struct bfa_lport_info_s *port_info)
+{
+
+	bfa_trc(port->fcs, port->fabric->fabric_name);
+
+	if (port->vport == NULL) {
+		/*
+		 * This is a Physical port
+		 */
+		port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
+
+		/*
+		 * @todo : need to fix the state & reason
+		 */
+		port_info->port_state = 0;
+		port_info->offline_reason = 0;
+
+		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
+		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
+
+		port_info->max_vports_supp =
+			bfa_lps_get_max_vport(port->fcs->bfa);
+		port_info->num_vports_inuse =
+			bfa_fcs_fabric_vport_count(port->fabric);
+		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
+		port_info->num_rports_inuse = port->num_rports;
+	} else {
+		/*
+		 * This is a virtual port
+		 */
+		port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
+
+		/*
+		 * @todo : need to fix the state & reason
+		 */
+		port_info->port_state = 0;
+		port_info->offline_reason = 0;
+
+		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
+		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
+	}
+}
+
+void
+bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
+	 struct bfa_lport_stats_s *port_stats)
+{
+	*port_stats = fcs_port->stats;
+}
+
+void
+bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
+{
+	bfa_os_memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
+}
+
+/**
+ * FCS virtual port state machine
+ */
+
+#define __vport_fcs(__vp)       ((__vp)->lport.fcs)
+#define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
+#define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
+#define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
+#define __vport_fcid(__vp)      ((__vp)->lport.pid)
+#define __vport_fabric(__vp)    ((__vp)->lport.fabric)
+#define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
+
+#define BFA_FCS_VPORT_MAX_RETRIES  5
+/*
+ * Forward declarations
+ */
+static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
+static void     bfa_fcs_vport_timeout(void *vport_arg);
+static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
+static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
+
+/**
+ *  fcs_vport_sm FCS virtual port state machine
+ */
+
+/**
+ * VPort State Machine events
+ */
+enum bfa_fcs_vport_event {
+	BFA_FCS_VPORT_SM_CREATE = 1,	/*  vport create event */
+	BFA_FCS_VPORT_SM_DELETE = 2,	/*  vport delete event */
+	BFA_FCS_VPORT_SM_START = 3,	/*  vport start request */
+	BFA_FCS_VPORT_SM_STOP = 4,	/*  stop: unsupported */
+	BFA_FCS_VPORT_SM_ONLINE = 5,	/*  fabric online */
+	BFA_FCS_VPORT_SM_OFFLINE = 6,	/*  fabric offline event */
+	BFA_FCS_VPORT_SM_FRMSENT = 7,	/*  fdisc/logo sent events */
+	BFA_FCS_VPORT_SM_RSP_OK = 8,	/*  good response */
+	BFA_FCS_VPORT_SM_RSP_ERROR = 9,	/*  error/bad response */
+	BFA_FCS_VPORT_SM_TIMEOUT = 10,	/*  delay timer event */
+	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
+	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error*/
+	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
+};
+
+static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
+					enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
+					 enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
+					 enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
+				       enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
+					     enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
+					enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
+					  enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
+					 enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
+				      enum bfa_fcs_vport_event event);
+static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
+				      enum bfa_fcs_vport_event event);
+
+static struct bfa_sm_table_s  vport_sm_table[] = {
+	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
+	{BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
+	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
+	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
+	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
+	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
+	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
+	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
+	{BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
+	{BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
+};
+
+/**
+ * Beginning state.
+ */
+static void
+bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_CREATE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
+		bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Created state - a start event is required to start up the state machine.
+ */
+static void
+bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_START:
+		if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
+		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
+			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+			bfa_fcs_vport_do_fdisc(vport);
+		} else {
+			/**
+			 * Fabric is offline or not NPIV capable, stay in
+			 * offline state.
+			 */
+			vport->vport_stats.fab_no_npiv++;
+			bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		}
+		break;
+
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_ONLINE:
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		/**
+		 * Ignore ONLINE/OFFLINE events from fabric
+		 * till vport is started.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Offline state - awaiting ONLINE event from fabric SM.
+ */
+static void
+bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_ONLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+		vport->fdisc_retries = 0;
+		bfa_fcs_vport_do_fdisc(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		/*
+		 * This can happen if the vport couldn't be initialzied
+		 * due the fact that the npiv was not enabled on the switch.
+		 * In that case we will put the vport in offline state.
+		 * However, the link can go down and cause the this event to
+		 * be sent when we are already offline. Ignore it.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+
+/**
+ * FDISC is sent and awaiting reply from fabric.
+ */
+static void
+bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_lps_discard(vport->lps);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		bfa_lps_discard(vport->lps);
+		break;
+
+	case BFA_FCS_VPORT_SM_RSP_OK:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
+		bfa_fcs_lport_online(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_RSP_ERROR:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
+		bfa_timer_start(__vport_bfa(vport), &vport->timer,
+				    bfa_fcs_vport_timeout, vport,
+				    BFA_FCS_RETRY_TIMEOUT);
+		break;
+
+	case BFA_FCS_VPORT_SM_RSP_FAILED:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		break;
+
+	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * FDISC attempt failed - a timer is active to retry FDISC.
+ */
+static void
+bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
+			     enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_timer_stop(&vport->timer);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		bfa_timer_stop(&vport->timer);
+		break;
+
+	case BFA_FCS_VPORT_SM_TIMEOUT:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
+		vport->vport_stats.fdisc_retries++;
+		vport->fdisc_retries++;
+		bfa_fcs_vport_do_fdisc(vport);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Vport is online (FDISC is complete).
+ */
+static void
+bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
+		bfa_lps_discard(vport->lps);
+		bfa_fcs_lport_offline(&vport->lport);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Vport is being deleted - awaiting lport delete completion to send
+ * LOGO to fabric.
+ */
+static void
+bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		break;
+
+	case BFA_FCS_VPORT_SM_DELCOMP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
+		bfa_fcs_vport_do_logo(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Error State.
+ * This state will be set when the Vport Creation fails due
+ * to errors like Dup WWN. In this state only operation allowed
+ * is a Vport Delete.
+ */
+static void
+bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELETE:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
+		bfa_fcs_lport_delete(&vport->lport);
+		break;
+
+	default:
+		bfa_trc(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * Lport cleanup is in progress since vport is being deleted. Fabric is
+ * offline, so no LOGO is needed to complete vport deletion.
+ */
+static void
+bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_DELCOMP:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+		bfa_fcs_vport_free(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_DELETE:
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+/**
+ * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
+ * is done.
+ */
+static void
+bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
+			enum bfa_fcs_vport_event event)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), event);
+
+	switch (event) {
+	case BFA_FCS_VPORT_SM_OFFLINE:
+		bfa_lps_discard(vport->lps);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case BFA_FCS_VPORT_SM_RSP_OK:
+	case BFA_FCS_VPORT_SM_RSP_ERROR:
+		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+		bfa_fcs_vport_free(vport);
+		break;
+
+	case BFA_FCS_VPORT_SM_DELETE:
+		break;
+
+	default:
+		bfa_sm_fault(__vport_fcs(vport), event);
+	}
+}
+
+
+
+/**
+ *  fcs_vport_private FCS virtual port private functions
+ */
+/**
+ * This routine will be called to send a FDISC command.
+ */
+static void
+bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
+{
+	bfa_lps_fdisc(vport->lps, vport,
+		bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
+		__vport_pwwn(vport), __vport_nwwn(vport));
+	vport->vport_stats.fdisc_sent++;
+}
+
+static void
+bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
+{
+	u8		lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
+	u8		lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
+
+	bfa_trc(__vport_fcs(vport), lsrjt_rsn);
+	bfa_trc(__vport_fcs(vport), lsrjt_expl);
+
+	/* For certain reason codes, we don't want to retry. */
+	switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
+	case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
+	case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
+		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+		else
+			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
+		break;
+
+	case FC_LS_RJT_EXP_INSUFF_RES:
+		/*
+		 * This means max logins per port/switch setting on the
+		 * switch was exceeded.
+		 */
+		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
+			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+		else
+			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
+		break;
+
+	default:
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+	}
+}
+
+/**
+ *	Called to send a logout to the fabric. Used when a V-Port is
+ *	deleted/stopped.
+ */
+static void
+bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
+{
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+
+	vport->vport_stats.logo_sent++;
+	bfa_lps_fdisclogo(vport->lps);
+}
+
+
+/**
+ *     This routine will be called by bfa_timer on timer timeouts.
+ *
+ *	param[in]	vport		- pointer to bfa_fcs_vport_t.
+ *	param[out]	vport_status	- pointer to return vport status in
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+static void
+bfa_fcs_vport_timeout(void *vport_arg)
+{
+	struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
+
+	vport->vport_stats.fdisc_timeouts++;
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
+}
+
+static void
+bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
+{
+	struct bfad_vport_s *vport_drv =
+			(struct bfad_vport_s *)vport->vport_drv;
+
+	bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
+
+	if (vport_drv->comp_del)
+		complete(vport_drv->comp_del);
+
+	bfa_lps_delete(vport->lps);
+}
+
+
+
+/**
+ *  fcs_vport_public FCS virtual port public interfaces
+ */
+
+/**
+ * Online notification from fabric SM.
+ */
+void
+bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
+{
+	vport->vport_stats.fab_online++;
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+}
+
+/**
+ * Offline notification from fabric SM.
+ */
+void
+bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
+{
+	vport->vport_stats.fab_offline++;
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
+}
+
+/**
+ * Cleanup notification from fabric SM on link timer expiry.
+ */
+void
+bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
+{
+	vport->vport_stats.fab_cleanup++;
+}
+/**
+ * delete notification from fabric SM. To be invoked from within FCS.
+ */
+void
+bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
+}
+
+/**
+ * Delete completion callback from associated lport
+ */
+void
+bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
+}
+
+
+
+/**
+ *  fcs_vport_api Virtual port API
+ */
+
+/**
+ *	Use this function to instantiate a new FCS vport object. This
+ *	function will not trigger any HW initialization process (which will be
+ *	done in vport_start() call)
+ *
+ *	param[in] vport	-		pointer to bfa_fcs_vport_t. This space
+ *					needs to be allocated by the driver.
+ *	param[in] fcs		-	FCS instance
+ *	param[in] vport_cfg	-	vport configuration
+ *	param[in] vf_id		-	VF_ID if vport is created within a VF.
+ *					FC_VF_ID_NULL to specify base fabric.
+ *	param[in] vport_drv	-	Opaque handle back to the driver's vport
+ *					structure
+ *
+ *	retval BFA_STATUS_OK - on success.
+ *	retval BFA_STATUS_FAILED - on failure.
+ */
+bfa_status_t
+bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
+		u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
+		struct bfad_vport_s *vport_drv)
+{
+	if (vport_cfg->pwwn == 0)
+		return BFA_STATUS_INVALID_WWN;
+
+	if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
+		return BFA_STATUS_VPORT_WWN_BP;
+
+	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
+		return BFA_STATUS_VPORT_EXISTS;
+
+	if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
+			bfa_lps_get_max_vport(fcs->bfa))
+		return BFA_STATUS_VPORT_MAX;
+
+	vport->lps = bfa_lps_alloc(fcs->bfa);
+	if (!vport->lps)
+		return BFA_STATUS_VPORT_MAX;
+
+	vport->vport_drv = vport_drv;
+	vport_cfg->preboot_vp = BFA_FALSE;
+
+	bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
+	bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
+	bfa_fcs_lport_init(&vport->lport, vport_cfg);
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function to instantiate a new FCS PBC vport object. This
+ *	function will not trigger any HW initialization process (which will be
+ *	done in vport_start() call)
+ *
+ *	param[in] vport	-	pointer to bfa_fcs_vport_t. This space
+ *				needs to be allocated by the driver.
+ *	param[in] fcs	-	FCS instance
+ *	param[in] vport_cfg	-	vport configuration
+ *	param[in] vf_id		-	VF_ID if vport is created within a VF.
+ *					FC_VF_ID_NULL to specify base fabric.
+ *	param[in] vport_drv	-	Opaque handle back to the driver's vport
+ *					structure
+ *
+ *	retval BFA_STATUS_OK - on success.
+ *	retval BFA_STATUS_FAILED - on failure.
+ */
+bfa_status_t
+bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
+			u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
+			struct bfad_vport_s *vport_drv)
+{
+	bfa_status_t rc;
+
+	rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
+	vport->lport.port_cfg.preboot_vp = BFA_TRUE;
+
+	return rc;
+}
+
+/**
+ *	Use this function to findout if this is a pbc vport or not.
+ *
+ * @param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ * @returns None
+ */
+bfa_boolean_t
+bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
+{
+
+	if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
+		return BFA_TRUE;
+	else
+		return BFA_FALSE;
+
+}
+
+/**
+ * Use this function initialize the vport.
+ *
+ * @param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ * @returns None
+ */
+bfa_status_t
+bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function quiese the vport object. This function will return
+ *	immediately, when the vport is actually stopped, the
+ *	bfa_drv_vport_stop_cb() will be called.
+ *
+ *	param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ *	return None
+ */
+bfa_status_t
+bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
+{
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function to delete a vport object. Fabric object should
+ *	be stopped before this function call.
+ *
+ *	!!!!!!! Donot invoke this from within FCS  !!!!!!!
+ *
+ *	param[in] vport - pointer to bfa_fcs_vport_t.
+ *
+ *	return     None
+ */
+bfa_status_t
+bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
+{
+
+	if (vport->lport.port_cfg.preboot_vp)
+		return BFA_STATUS_PBC;
+
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Use this function to get vport's current status info.
+ *
+ *	param[in] vport		pointer to bfa_fcs_vport_t.
+ *	param[out] attr		pointer to return vport attributes
+ *
+ *	return None
+ */
+void
+bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
+			struct bfa_vport_attr_s *attr)
+{
+	if (vport == NULL || attr == NULL)
+		return;
+
+	bfa_os_memset(attr, 0, sizeof(struct bfa_vport_attr_s));
+
+	bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
+	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
+}
+
+/**
+ *	Use this function to get vport's statistics.
+ *
+ *	param[in]	vport	pointer to bfa_fcs_vport_t.
+ *	param[out]	stats	pointer to return vport statistics in
+ *
+ *	return None
+ */
+void
+bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
+			struct bfa_vport_stats_s *stats)
+{
+	*stats = vport->vport_stats;
+}
+
+/**
+ *	Use this function to clear vport's statistics.
+ *
+ *	param[in]	vport	pointer to bfa_fcs_vport_t.
+ *
+ *	return None
+ */
+void
+bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
+{
+	bfa_os_memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
+}
+
+/**
+ *	Lookup a virtual port. Excludes base port from lookup.
+ */
+struct bfa_fcs_vport_s *
+bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
+{
+	struct bfa_fcs_vport_s *vport;
+	struct bfa_fcs_fabric_s *fabric;
+
+	bfa_trc(fcs, vf_id);
+	bfa_trc(fcs, vpwwn);
+
+	fabric = bfa_fcs_vf_lookup(fcs, vf_id);
+	if (!fabric) {
+		bfa_trc(fcs, vf_id);
+		return NULL;
+	}
+
+	vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
+	return vport;
+}
+
+/**
+ * FDISC Response
+ */
+void
+bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
+{
+	struct bfa_fcs_vport_s *vport = uarg;
+
+	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
+	bfa_trc(__vport_fcs(vport), status);
+
+	switch (status) {
+	case BFA_STATUS_OK:
+		/*
+		 * Initialiaze the V-Port fields
+		 */
+		__vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
+		vport->vport_stats.fdisc_accepts++;
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
+		break;
+
+	case BFA_STATUS_INVALID_MAC:
+		/* Only for CNA */
+		vport->vport_stats.fdisc_acc_bad++;
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+
+		break;
+
+	case BFA_STATUS_EPROTOCOL:
+		switch (bfa_lps_get_extstatus(vport->lps)) {
+		case BFA_EPROTO_BAD_ACCEPT:
+			vport->vport_stats.fdisc_acc_bad++;
+			break;
+
+		case BFA_EPROTO_UNKNOWN_RSP:
+			vport->vport_stats.fdisc_unknown_rsp++;
+			break;
+
+		default:
+			break;
+		}
+
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+		break;
+
+	case BFA_STATUS_FABRIC_RJT:
+		vport->vport_stats.fdisc_rejects++;
+		bfa_fcs_vport_fdisc_rejected(vport);
+		break;
+
+	default:
+		vport->vport_stats.fdisc_rsp_err++;
+		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
+	}
+}
+
+/**
+ * LOGO response
+ */
+void
+bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
+{
+	struct bfa_fcs_vport_s *vport = uarg;
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
+}
+
+/**
+ * Received clear virtual link
+ */
+void
+bfa_cb_lps_cvl_event(void *bfad, void *uarg)
+{
+	struct bfa_fcs_vport_s *vport = uarg;
+
+	/* Send an Offline followed by an ONLINE */
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
+	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
+}
diff --git a/drivers/scsi/bfa/bfa_fcs_port.c b/drivers/scsi/bfa/bfa_fcs_port.c
deleted file mode 100644
index 3c27788..0000000
--- a/drivers/scsi/bfa/bfa_fcs_port.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcs_pport.c BFA FCS PPORT ( physical port)
- */
-
-#include <fcs/bfa_fcs.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs_fabric.h>
-#include "fcs_trcmod.h"
-#include "fcs.h"
-#include "fcs_fabric.h"
-#include "fcs_port.h"
-
-BFA_TRC_FILE(FCS, PPORT);
-
-static void
-bfa_fcs_pport_event_handler(void *cbarg, bfa_pport_event_t event)
-{
-	struct bfa_fcs_s      *fcs = cbarg;
-
-	bfa_trc(fcs, event);
-
-	switch (event) {
-	case BFA_PPORT_LINKUP:
-		bfa_fcs_fabric_link_up(&fcs->fabric);
-		break;
-
-	case BFA_PPORT_LINKDOWN:
-		bfa_fcs_fabric_link_down(&fcs->fabric);
-		break;
-
-	case BFA_PPORT_TRUNK_LINKDOWN:
-		bfa_assert(0);
-		break;
-
-	default:
-		bfa_assert(0);
-	}
-}
-
-void
-bfa_fcs_pport_attach(struct bfa_fcs_s *fcs)
-{
-	bfa_fcport_event_register(fcs->bfa, bfa_fcs_pport_event_handler, fcs);
-}
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
new file mode 100644
index 0000000..635f0cd
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -0,0 +1,3126 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+/**
+ *  rport.c Remote port implementation.
+ */
+
+#include "bfa_fcs.h"
+#include "bfa_fcbuild.h"
+#include "bfad_drv.h"
+
+BFA_TRC_FILE(FCS, RPORT);
+
+static u32
+bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
+	 /* In millisecs */
+/*
+ * forward declarations
+ */
+static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(
+		struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
+static void	bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
+static void	bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
+static void	bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
+static void	bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
+static void	bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
+					struct fc_logi_s *plogi);
+static void	bfa_fcs_rport_timeout(void *arg);
+static void	bfa_fcs_rport_send_plogi(void *rport_cbarg,
+					 struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
+					struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_plogi_response(void *fcsarg,
+				struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs);
+static void	bfa_fcs_rport_send_adisc(void *rport_cbarg,
+					 struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_adisc_response(void *fcsarg,
+				struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs);
+static void	bfa_fcs_rport_send_nsdisc(void *rport_cbarg,
+					 struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_gidpn_response(void *fcsarg,
+				struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs);
+static void	bfa_fcs_rport_gpnid_response(void *fcsarg,
+				struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs);
+static void	bfa_fcs_rport_send_logo(void *rport_cbarg,
+					struct bfa_fcxp_s *fcxp_alloced);
+static void	bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
+static void	bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
+					struct fchs_s *rx_fchs, u16 len);
+static void	bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
+				struct fchs_s *rx_fchs, u8 reason_code,
+					  u8 reason_code_expl);
+static void	bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
+				struct fchs_s *rx_fchs, u16 len);
+static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
+/**
+ *  fcs_rport_sm FCS rport state machine events
+ */
+
+enum rport_event {
+	RPSM_EVENT_PLOGI_SEND	= 1,	/*  new rport; start with PLOGI */
+	RPSM_EVENT_PLOGI_RCVD	= 2,	/*  Inbound PLOGI from remote port */
+	RPSM_EVENT_PLOGI_COMP	= 3,	/*  PLOGI completed to rport	*/
+	RPSM_EVENT_LOGO_RCVD	= 4,	/*  LOGO from remote device	*/
+	RPSM_EVENT_LOGO_IMP	= 5,	/*  implicit logo for SLER	*/
+	RPSM_EVENT_FCXP_SENT	= 6,	/*  Frame from has been sent	*/
+	RPSM_EVENT_DELETE	= 7,	/*  RPORT delete request	*/
+	RPSM_EVENT_SCN		= 8,	/*  state change notification	*/
+	RPSM_EVENT_ACCEPTED	= 9,	/*  Good response from remote device */
+	RPSM_EVENT_FAILED	= 10,	/*  Request to rport failed.	*/
+	RPSM_EVENT_TIMEOUT	= 11,	/*  Rport SM timeout event	*/
+	RPSM_EVENT_HCB_ONLINE  = 12,	/*  BFA rport online callback	*/
+	RPSM_EVENT_HCB_OFFLINE = 13,	/*  BFA rport offline callback	*/
+	RPSM_EVENT_FC4_OFFLINE = 14,	/*  FC-4 offline complete	*/
+	RPSM_EVENT_ADDRESS_CHANGE = 15,	/*  Rport's PID has changed	*/
+	RPSM_EVENT_ADDRESS_DISC = 16,	/*  Need to Discover rport's PID */
+	RPSM_EVENT_PRLO_RCVD   = 17,	/*  PRLO from remote device	*/
+	RPSM_EVENT_PLOGI_RETRY = 18,	/*  Retry PLOGI continously */
+};
+
+static void	bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
+					enum rport_event event);
+static void	bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
+						  enum rport_event event);
+static void	bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
+					enum rport_event event);
+static void	bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
+					enum rport_event event);
+static void	bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
+						 enum rport_event event);
+static void	bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
+					 enum rport_event event);
+static void	bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
+					enum rport_event event);
+static void	bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
+					 enum rport_event event);
+static void	bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+static void	bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+						enum rport_event event);
+
+static struct bfa_sm_table_s rport_sm_table[] = {
+	{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
+	{BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
+	{BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
+	{BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
+	{BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
+	{BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
+	{BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
+	{BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
+	{BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
+	{BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
+	{BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
+	{BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
+	{BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
+	{BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
+	{BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
+	{BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
+	{BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
+	{BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
+	{BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
+	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
+	{BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
+	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
+};
+
+/**
+ *		Beginning state.
+ */
+static void
+bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_PLOGI_SEND:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+		rport->plogi_retries = 0;
+		bfa_fcs_rport_send_plogi(rport, NULL);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_ADDRESS_DISC:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is being sent.
+ */
+static void
+bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_SCN:
+		/* query the NS */
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is being sent.
+ */
+static void
+bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_SCN:
+		/**
+		 * Ignore, SCN is possibly online notification.
+		 */
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_HCB_OFFLINE:
+		/**
+		 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is sent.
+ */
+static void
+bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+		bfa_fcs_rport_send_plogi(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_LOGO_RCVD:
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_SCN:
+		bfa_timer_stop(&rport->timer);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_timer_stop(&rport->timer);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is sent.
+ */
+static void
+bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_ACCEPTED:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		rport->plogi_retries = 0;
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+		bfa_fcs_rport_send_logo_acc(rport);
+		/*
+		 * !! fall through !!
+		 */
+	case RPSM_EVENT_PRLO_RCVD:
+		if (rport->prlo == BFA_TRUE)
+			bfa_fcs_rport_send_prlo_acc(rport);
+
+		bfa_fcxp_discard(rport->fcxp);
+		/*
+		 * !! fall through !!
+		 */
+	case RPSM_EVENT_FAILED:
+		if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+			rport->plogi_retries++;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					BFA_FCS_RETRY_TIMEOUT);
+		} else {
+			bfa_stats(rport->port, rport_del_max_plogi_retry);
+			rport->pid = 0;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					bfa_fcs_rport_del_timeout);
+		}
+		break;
+
+	case	RPSM_EVENT_PLOGI_RETRY:
+		rport->plogi_retries = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				(FC_RA_TOV * 1000));
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_SCN:
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		PLOGI is complete. Awaiting BFA rport online callback. FC-4s
+ *		are offline.
+ */
+static void
+bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_HCB_ONLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
+		bfa_fcs_rport_online_action(rport);
+		break;
+
+	case RPSM_EVENT_PRLO_RCVD:
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_rport_offline(rport->bfa_rport);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		/**
+		 * @todo
+		 * Ignore SCN - PLOGI just completed, FC-4 login should detect
+		 * device failures.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is ONLINE. FC-4s active.
+ */
+static void
+bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_SCN:
+		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+			bfa_sm_set_state(rport,
+					 bfa_fcs_rport_sm_nsquery_sending);
+			rport->ns_retries = 0;
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		} else {
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+			bfa_fcs_rport_send_adisc(rport, NULL);
+		}
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_LOGO_IMP:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		An SCN event is received in ONLINE state. NS query is being sent
+ *		prior to ADISC authentication with rport. FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		/**
+		 * ignore SCN, wait for response to query itself
+		 */
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *	An SCN event is received in ONLINE state. NS query is sent to rport.
+ *	FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_ACCEPTED:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
+		bfa_fcs_rport_send_adisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_FAILED:
+		rport->ns_retries++;
+		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+			bfa_sm_set_state(rport,
+					 bfa_fcs_rport_sm_nsquery_sending);
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		} else {
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+			bfa_fcs_rport_offline_action(rport);
+		}
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+	case RPSM_EVENT_PLOGI_RCVD:
+	case RPSM_EVENT_LOGO_IMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *	An SCN event is received in ONLINE state. ADISC is being sent for
+ *	authenticating with rport. FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		An SCN event is received in ONLINE state. ADISC is to rport.
+ *		FC-4s are paused.
+ */
+static void
+bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_ACCEPTED:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		/**
+		 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
+		 * At least go offline when a PLOGI is received.
+		 */
+		bfa_fcxp_discard(rport->fcxp);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case RPSM_EVENT_FAILED:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+		/**
+		 * already processing RSCN
+		 */
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_offline_action(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport has sent LOGO. Awaiting FC-4 offline completion callback.
+ */
+static void
+bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FC4_OFFLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		LOGO needs to be sent to rport. Awaiting FC-4 offline completion
+ *		callback.
+ */
+static void
+bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FC4_OFFLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *	Rport is going offline. Awaiting FC-4 offline completion callback.
+ */
+static void
+bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FC4_OFFLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
+		bfa_rport_offline(rport->bfa_rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_LOGO_IMP:
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		/**
+		 * rport is already going offline.
+		 * SCN - ignore and wait till transitioning to offline state
+		 */
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
+ *		callback.
+ */
+static void
+bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
+				enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_HCB_OFFLINE:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		if (bfa_fcs_lport_is_online(rport->port)) {
+			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
+				bfa_sm_set_state(rport,
+					bfa_fcs_rport_sm_nsdisc_sending);
+				rport->ns_retries = 0;
+				bfa_fcs_rport_send_nsdisc(rport, NULL);
+			} else {
+				bfa_sm_set_state(rport,
+					bfa_fcs_rport_sm_plogi_sending);
+				rport->plogi_retries = 0;
+				bfa_fcs_rport_send_plogi(rport, NULL);
+			}
+		} else {
+			rport->pid = 0;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					bfa_fcs_rport_del_timeout);
+		}
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		/**
+		 * Ignore, already offline.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
+ *		callback to send LOGO accept.
+ */
+static void
+bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_HCB_OFFLINE:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		if (rport->pid && (rport->prlo == BFA_TRUE))
+			bfa_fcs_rport_send_prlo_acc(rport);
+		if (rport->pid && (rport->prlo == BFA_FALSE))
+			bfa_fcs_rport_send_logo_acc(rport);
+		/*
+		 * If the lport is online and if the rport is not a well
+		 * known address port,
+		 * we try to re-discover the r-port.
+		 */
+		if (bfa_fcs_lport_is_online(rport->port) &&
+			(!BFA_FCS_PID_IS_WKA(rport->pid))) {
+			bfa_sm_set_state(rport,
+				bfa_fcs_rport_sm_nsdisc_sending);
+			rport->ns_retries = 0;
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		} else {
+			/*
+			 * if it is not a well known address, reset the
+			 * pid to 0.
+			 */
+			if (!BFA_FCS_PID_IS_WKA(rport->pid))
+				rport->pid = 0;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					bfa_fcs_rport_del_timeout);
+		}
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		/**
+		 * Ignore - already processing a LOGO.
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is being deleted. FC-4s are offline.
+ *  Awaiting BFA rport offline
+ *		callback to send LOGO.
+ */
+static void
+bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
+		 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_HCB_OFFLINE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
+		bfa_fcs_rport_send_logo(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is being deleted. FC-4s are offline. LOGO is being sent.
+ */
+static void
+bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		/* Once LOGO is sent, we donot wait for the response */
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport is offline. FC-4s are offline. BFA rport is offline.
+ *		Timer active to delete stale rport.
+ */
+static void
+bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		bfa_timer_stop(&rport->timer);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_LOGO_IMP:
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_SEND:
+		bfa_timer_stop(&rport->timer);
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+		rport->plogi_retries = 0;
+		bfa_fcs_rport_send_plogi(rport, NULL);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *	Rport address has changed. Nameserver discovery request is being sent.
+ */
+static void
+bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_LOGO_RCVD:
+	case RPSM_EVENT_PRLO_RCVD:
+	case RPSM_EVENT_PLOGI_SEND:
+		break;
+
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		rport->ns_retries = 0; /* reset the retry count */
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Nameserver discovery failed. Waiting for timeout to retry.
+ */
+static void
+bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
+	 enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_TIMEOUT:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_SCN:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
+		bfa_timer_stop(&rport->timer);
+		rport->ns_retries = 0;
+		bfa_fcs_rport_send_nsdisc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_timer_stop(&rport->timer);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+		bfa_fcs_rport_send_logo_acc(rport);
+		break;
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_fcs_rport_send_prlo_acc(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_timer_stop(&rport->timer);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+/**
+ *		Rport address has changed. Nameserver discovery request is sent.
+ */
+static void
+bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
+			enum rport_event event)
+{
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPSM_EVENT_ACCEPTED:
+	case RPSM_EVENT_ADDRESS_CHANGE:
+		if (rport->pid) {
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
+			bfa_fcs_rport_send_plogi(rport, NULL);
+		} else {
+			bfa_sm_set_state(rport,
+				 bfa_fcs_rport_sm_nsdisc_sending);
+			rport->ns_retries = 0;
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		}
+		break;
+
+	case RPSM_EVENT_FAILED:
+		rport->ns_retries++;
+		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
+			bfa_sm_set_state(rport,
+				 bfa_fcs_rport_sm_nsdisc_sending);
+			bfa_fcs_rport_send_nsdisc(rport, NULL);
+		} else {
+			rport->pid = 0;
+			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+			bfa_timer_start(rport->fcs->bfa, &rport->timer,
+					bfa_fcs_rport_timeout, rport,
+					bfa_fcs_rport_del_timeout);
+		};
+		break;
+
+	case RPSM_EVENT_DELETE:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_free(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_RCVD:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_send_plogiacc(rport, NULL);
+		break;
+
+	case RPSM_EVENT_LOGO_IMP:
+		rport->pid = 0;
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_timer_start(rport->fcs->bfa, &rport->timer,
+				bfa_fcs_rport_timeout, rport,
+				bfa_fcs_rport_del_timeout);
+		break;
+
+
+	case RPSM_EVENT_PRLO_RCVD:
+		bfa_fcs_rport_send_prlo_acc(rport);
+		break;
+	case RPSM_EVENT_SCN:
+		/**
+		 * ignore, wait for NS query response
+		 */
+		break;
+
+	case RPSM_EVENT_LOGO_RCVD:
+		/**
+		 * Not logged-in yet. Accept LOGO.
+		 */
+		bfa_fcs_rport_send_logo_acc(rport);
+		break;
+
+	case RPSM_EVENT_PLOGI_COMP:
+		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
+		bfa_fcxp_discard(rport->fcxp);
+		bfa_fcs_rport_hal_online(rport);
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+
+
+/**
+ *  fcs_rport_private FCS RPORT provate functions
+ */
+
+static void
+bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_plogi, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+				bfa_fcs_lport_get_fcid(port), 0,
+				port->port_cfg.pwwn, port->port_cfg.nwwn,
+				bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
+			(void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	rport->stats.plogis++;
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+	struct fc_logi_s	*plogi_rsp;
+	struct fc_ls_rjt_s	*ls_rjt;
+	struct bfa_fcs_rport_s *twin;
+	struct list_head	*qe;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	/*
+	 * Sanity Checks
+	 */
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(rport->fcs, req_status);
+		rport->stats.plogi_failed++;
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		return;
+	}
+
+	plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+	/**
+	 * Check for failure first.
+	 */
+	if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+
+		bfa_trc(rport->fcs, ls_rjt->reason_code);
+		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+
+		if ((ls_rjt->reason_code == FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD) &&
+		 (ls_rjt->reason_code_expl == FC_LS_RJT_EXP_INSUFF_RES)) {
+			rport->stats.rjt_insuff_res++;
+			bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RETRY);
+			return;
+		}
+
+		rport->stats.plogi_rejects++;
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		return;
+	}
+
+	/**
+	 * PLOGI is complete. Make sure this device is not one of the known
+	 * device with a new FC port address.
+	 */
+	list_for_each(qe, &rport->port->rport_q) {
+		twin = (struct bfa_fcs_rport_s *) qe;
+		if (twin == rport)
+			continue;
+		if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
+			bfa_trc(rport->fcs, twin->pid);
+			bfa_trc(rport->fcs, rport->pid);
+
+			/* Update plogi stats in twin */
+			twin->stats.plogis  += rport->stats.plogis;
+			twin->stats.plogi_rejects  +=
+				 rport->stats.plogi_rejects;
+			twin->stats.plogi_timeouts  +=
+				 rport->stats.plogi_timeouts;
+			twin->stats.plogi_failed +=
+				 rport->stats.plogi_failed;
+			twin->stats.plogi_rcvd	  += rport->stats.plogi_rcvd;
+			twin->stats.plogi_accs++;
+
+			bfa_fcs_rport_delete(rport);
+
+			bfa_fcs_rport_update(twin, plogi_rsp);
+			twin->pid = rsp_fchs->s_id;
+			bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
+			return;
+		}
+	}
+
+	/**
+	 * Normal login path -- no evil twins.
+	 */
+	rport->stats.plogi_accs++;
+	bfa_fcs_rport_update(rport, plogi_rsp);
+	bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+}
+
+static void
+bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s		fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->reply_oxid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_plogiacc, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				 rport->pid, bfa_fcs_lport_get_fcid(port),
+				 rport->reply_oxid, port->port_cfg.pwwn,
+				 port->port_cfg.nwwn,
+				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s		fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_adisc, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+				bfa_fcs_lport_get_fcid(port), 0,
+				port->port_cfg.pwwn, port->port_cfg.nwwn);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
+			rport, FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	rport->stats.adisc_sent++;
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+	void		*pld = bfa_fcxp_get_rspbuf(fcxp);
+	struct fc_ls_rjt_s	*ls_rjt;
+
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(rport->fcs, req_status);
+		rport->stats.adisc_failed++;
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		return;
+	}
+
+	if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
+				rport->nwwn)  == FC_PARSE_OK) {
+		rport->stats.adisc_accs++;
+		bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+		return;
+	}
+
+	rport->stats.adisc_rejects++;
+	ls_rjt = pld;
+	bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
+	bfa_trc(rport->fcs, ls_rjt->reason_code);
+	bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+	bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+}
+
+static void
+bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	int		len;
+	bfa_cb_fcxp_send_t cbfn;
+
+	bfa_trc(rport->fcs, rport->pid);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_nsdisc, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	if (rport->pwwn) {
+		len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				bfa_fcs_lport_get_fcid(port), 0, rport->pwwn);
+		cbfn = bfa_fcs_rport_gidpn_response;
+	} else {
+		len = fc_gpnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				bfa_fcs_lport_get_fcid(port), 0, rport->pid);
+		cbfn = bfa_fcs_rport_gpnid_response;
+	}
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, cbfn,
+			(void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
+
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+static void
+bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+	struct ct_hdr_s	*cthdr;
+	struct fcgs_gidpn_resp_s	*gidpn_rsp;
+	struct bfa_fcs_rport_s	*twin;
+	struct list_head	*qe;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		/* Check if the pid is the same as before. */
+		gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
+
+		if (gidpn_rsp->dap == rport->pid) {
+			/* Device is online  */
+			bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+		} else {
+			/*
+			 * Device's PID has changed. We need to cleanup
+			 * and re-login. If there is another device with
+			 * the the newly discovered pid, send an scn notice
+			 * so that its new pid can be discovered.
+			 */
+			list_for_each(qe, &rport->port->rport_q) {
+				twin = (struct bfa_fcs_rport_s *) qe;
+				if (twin == rport)
+					continue;
+				if (gidpn_rsp->dap == twin->pid) {
+					bfa_trc(rport->fcs, twin->pid);
+					bfa_trc(rport->fcs, rport->pid);
+
+					twin->pid = 0;
+					bfa_sm_send_event(twin,
+					 RPSM_EVENT_ADDRESS_CHANGE);
+				}
+			}
+			rport->pid = gidpn_rsp->dap;
+			bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
+		}
+		return;
+	}
+
+	/*
+	 * Reject Response
+	 */
+	switch (cthdr->reason_code) {
+	case CT_RSN_LOGICAL_BUSY:
+		/*
+		 * Need to retry
+		 */
+		bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
+		break;
+
+	case CT_RSN_UNABLE_TO_PERF:
+		/*
+		 * device doesn't exist : Start timer to cleanup this later.
+		 */
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		break;
+
+	default:
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		break;
+	}
+}
+
+static void
+bfa_fcs_rport_gpnid_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+				bfa_status_t req_status, u32 rsp_len,
+				u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+	struct ct_hdr_s	*cthdr;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
+	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
+
+	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
+		bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
+		return;
+	}
+
+	/*
+	 * Reject Response
+	 */
+	switch (cthdr->reason_code) {
+	case CT_RSN_LOGICAL_BUSY:
+		/*
+		 * Need to retry
+		 */
+		bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
+		break;
+
+	case CT_RSN_UNABLE_TO_PERF:
+		/*
+		 * device doesn't exist : Start timer to cleanup this later.
+		 */
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		break;
+
+	default:
+		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
+		break;
+	}
+}
+
+/**
+ *	Called to send a logout to the rport.
+ */
+static void
+bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	u16	len;
+
+	bfa_trc(rport->fcs, rport->pid);
+
+	port = rport->port;
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
+					bfa_fcs_rport_send_logo, rport);
+		return;
+	}
+	rport->fcxp = fcxp;
+
+	len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+				bfa_fcs_lport_get_fcid(port), 0,
+				bfa_fcs_lport_get_pwwn(port));
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL,
+			rport, FC_MAX_PDUSZ, FC_ELS_TOV);
+
+	rport->stats.logos++;
+	bfa_fcxp_discard(rport->fcxp);
+	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
+}
+
+/**
+ *	Send ACC for a LOGO received.
+ */
+static void
+bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
+{
+	struct bfa_fcs_rport_s *rport = rport_cbarg;
+	struct bfa_fcs_lport_s *port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	u16	len;
+
+	bfa_trc(rport->fcs, rport->pid);
+
+	port = rport->port;
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	rport->stats.logo_rcvd++;
+	len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rport->pid, bfa_fcs_lport_get_fcid(port),
+				rport->reply_oxid);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+/**
+ *	brief
+ *	This routine will be called by bfa_timer on timer timeouts.
+ *
+ *	param[in]	rport			- pointer to bfa_fcs_lport_ns_t.
+ *	param[out]	rport_status	- pointer to return vport status in
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+static void
+bfa_fcs_rport_timeout(void *arg)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) arg;
+
+	rport->stats.plogi_timeouts++;
+	bfa_stats(rport->port, rport_plogi_timeouts);
+	bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
+}
+
+static void
+bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
+			struct fchs_s *rx_fchs, u16 len)
+{
+	struct bfa_fcxp_s *fcxp;
+	struct fchs_s	fchs;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fc_prli_s	*prli;
+
+	bfa_trc(port->fcs, rx_fchs->s_id);
+	bfa_trc(port->fcs, rx_fchs->d_id);
+
+	rport->stats.prli_rcvd++;
+
+	/*
+	 * We are in Initiator Mode
+	 */
+	prli = (struct fc_prli_s *) (rx_fchs + 1);
+
+	if (prli->parampage.servparams.target) {
+		/*
+		 * PRLI from a target ?
+		 * Send the Acc.
+		 * PRLI sent by us will be used to transition the IT nexus,
+		 * once the response is received from the target.
+		 */
+		bfa_trc(port->fcs, rx_fchs->s_id);
+		rport->scsi_function = BFA_RPORT_TARGET;
+	} else {
+		bfa_trc(rport->fcs, prli->parampage.type);
+		rport->scsi_function = BFA_RPORT_INITIATOR;
+		bfa_fcs_itnim_is_initiator(rport->itnim);
+	}
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id, port->port_cfg.roles);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+static void
+bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
+			struct fchs_s *rx_fchs, u16 len)
+{
+	struct bfa_fcxp_s *fcxp;
+	struct fchs_s	fchs;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fc_rpsc_speed_info_s speeds;
+	struct bfa_port_attr_s pport_attr;
+
+	bfa_trc(port->fcs, rx_fchs->s_id);
+	bfa_trc(port->fcs, rx_fchs->d_id);
+
+	rport->stats.rpsc_rcvd++;
+	speeds.port_speed_cap =
+		RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
+		RPSC_SPEED_CAP_8G;
+
+	/*
+	 * get curent speed from pport attributes from BFA
+	 */
+	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
+
+	speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id, &speeds);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+static void
+bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
+			struct fchs_s *rx_fchs, u16 len)
+{
+	struct bfa_fcxp_s *fcxp;
+	struct fchs_s	fchs;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fc_adisc_s	*adisc;
+
+	bfa_trc(port->fcs, rx_fchs->s_id);
+	bfa_trc(port->fcs, rx_fchs->d_id);
+
+	rport->stats.adisc_rcvd++;
+
+	adisc = (struct fc_adisc_s *) (rx_fchs + 1);
+
+	/*
+	 * Accept if the itnim for this rport is online.
+	 * Else reject the ADISC.
+	 */
+	if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
+
+		fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+		if (!fcxp)
+			return;
+
+		len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+			 rx_fchs->ox_id, port->port_cfg.pwwn,
+			 port->port_cfg.nwwn);
+
+		bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
+				BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+				FC_MAX_PDUSZ, 0);
+	} else {
+		rport->stats.adisc_rejected++;
+		bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
+					  FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
+					  FC_LS_RJT_EXP_LOGIN_REQUIRED);
+	}
+}
+
+static void
+bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct bfa_rport_info_s rport_info;
+
+	rport_info.pid = rport->pid;
+	rport_info.local_pid = port->pid;
+	rport_info.lp_tag = port->lp_tag;
+	rport_info.vf_id = port->fabric->vf_id;
+	rport_info.vf_en = port->fabric->is_vf;
+	rport_info.fc_class = rport->fc_cos;
+	rport_info.cisc = rport->cisc;
+	rport_info.max_frmsz = rport->maxfrsize;
+	bfa_rport_online(rport->bfa_rport, &rport_info);
+}
+
+static struct bfa_fcs_rport_s *
+bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
+{
+	struct bfa_fcs_s	*fcs = port->fcs;
+	struct bfa_fcs_rport_s *rport;
+	struct bfad_rport_s	*rport_drv;
+
+	/**
+	 * allocate rport
+	 */
+	if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
+		!= BFA_STATUS_OK) {
+		bfa_trc(fcs, rpid);
+		return NULL;
+	}
+
+	/*
+	 * Initialize r-port
+	 */
+	rport->port = port;
+	rport->fcs = fcs;
+	rport->rp_drv = rport_drv;
+	rport->pid = rpid;
+	rport->pwwn = pwwn;
+
+	/**
+	 * allocate BFA rport
+	 */
+	rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
+	if (!rport->bfa_rport) {
+		bfa_trc(fcs, rpid);
+		kfree(rport_drv);
+		return NULL;
+	}
+
+	/**
+	 * allocate FC-4s
+	 */
+	bfa_assert(bfa_fcs_lport_is_initiator(port));
+
+	if (bfa_fcs_lport_is_initiator(port)) {
+		rport->itnim = bfa_fcs_itnim_create(rport);
+		if (!rport->itnim) {
+			bfa_trc(fcs, rpid);
+			bfa_rport_delete(rport->bfa_rport);
+			kfree(rport_drv);
+			return NULL;
+		}
+	}
+
+	bfa_fcs_lport_add_rport(port, rport);
+
+	bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
+
+	/* Initialize the Rport Features(RPF) Sub Module  */
+	if (!BFA_FCS_PID_IS_WKA(rport->pid))
+		bfa_fcs_rpf_init(rport);
+
+	return rport;
+}
+
+
+static void
+bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+
+	/**
+	 * - delete FC-4s
+	 * - delete BFA rport
+	 * - remove from queue of rports
+	 */
+	if (bfa_fcs_lport_is_initiator(port)) {
+		bfa_fcs_itnim_delete(rport->itnim);
+		if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
+			bfa_fcs_rpf_rport_offline(rport);
+	}
+
+	bfa_rport_delete(rport->bfa_rport);
+	bfa_fcs_lport_del_rport(port, rport);
+	kfree(rport->rp_drv);
+}
+
+static void
+bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+	char	rpwwn_buf[BFA_STRING_32];
+
+	rport->stats.onlines++;
+
+	if (bfa_fcs_lport_is_initiator(port)) {
+		bfa_fcs_itnim_rport_online(rport->itnim);
+		if (!BFA_FCS_PID_IS_WKA(rport->pid))
+			bfa_fcs_rpf_rport_online(rport);
+	};
+
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+	wwn2str(rpwwn_buf, rport->pwwn);
+	if (!BFA_FCS_PID_IS_WKA(rport->pid))
+		BFA_LOG(KERN_INFO, bfad, log_level,
+		"Remote port (WWN = %s) online for logical port (WWN = %s)\n",
+		rpwwn_buf, lpwwn_buf);
+}
+
+static void
+bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
+	char	lpwwn_buf[BFA_STRING_32];
+	char	rpwwn_buf[BFA_STRING_32];
+
+	rport->stats.offlines++;
+
+	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
+	wwn2str(rpwwn_buf, rport->pwwn);
+	if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
+		if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE)
+			BFA_LOG(KERN_ERR, bfad, log_level,
+				"Remote port (WWN = %s) connectivity lost for "
+				"logical port (WWN = %s)\n",
+				rpwwn_buf, lpwwn_buf);
+		else
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"Remote port (WWN = %s) offlined by "
+				"logical port (WWN = %s)\n",
+				rpwwn_buf, lpwwn_buf);
+	}
+
+	if (bfa_fcs_lport_is_initiator(port)) {
+		bfa_fcs_itnim_rport_offline(rport->itnim);
+		if (!BFA_FCS_PID_IS_WKA(rport->pid))
+			bfa_fcs_rpf_rport_offline(rport);
+	}
+}
+
+/**
+ * Update rport parameters from PLOGI or PLOGI accept.
+ */
+static void
+bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
+{
+	bfa_fcs_lport_t *port = rport->port;
+
+	/**
+	 * - port name
+	 * - node name
+	 */
+	rport->pwwn = plogi->port_name;
+	rport->nwwn = plogi->node_name;
+
+	/**
+	 * - class of service
+	 */
+	rport->fc_cos = 0;
+	if (plogi->class3.class_valid)
+		rport->fc_cos = FC_CLASS_3;
+
+	if (plogi->class2.class_valid)
+		rport->fc_cos |= FC_CLASS_2;
+
+	/**
+	 * - CISC
+	 * - MAX receive frame size
+	 */
+	rport->cisc = plogi->csp.cisc;
+	rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
+
+	bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
+	bfa_trc(port->fcs, port->fabric->bb_credit);
+	/**
+	 * Direct Attach P2P mode :
+	 * This is to handle a bug (233476) in IBM targets in Direct Attach
+	 *  Mode. Basically, in FLOGI Accept the target would have
+	 * erroneously set the BB Credit to the value used in the FLOGI
+	 * sent by the HBA. It uses the correct value (its own BB credit)
+	 * in PLOGI.
+	 */
+	if ((!bfa_fcs_fabric_is_switched(port->fabric))	 &&
+		(bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
+
+		bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
+		bfa_trc(port->fcs, port->fabric->bb_credit);
+
+		port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
+		bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
+					  port->fabric->bb_credit);
+	}
+
+}
+
+/**
+ *	Called to handle LOGO received from an existing remote port.
+ */
+static void
+bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
+{
+	rport->reply_oxid = fchs->ox_id;
+	bfa_trc(rport->fcs, rport->reply_oxid);
+
+	rport->prlo = BFA_FALSE;
+	rport->stats.logo_rcvd++;
+	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
+}
+
+
+
+/**
+ *  fcs_rport_public FCS rport public interfaces
+ */
+
+/**
+ *	Called by bport/vport to create a remote port instance for a discovered
+ *	remote device.
+ *
+ * @param[in] port	- base port or vport
+ * @param[in] rpid	- remote port ID
+ *
+ * @return None
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 rpid)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	bfa_trc(port->fcs, rpid);
+	rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
+	if (!rport)
+		return NULL;
+
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
+	return rport;
+}
+
+/**
+ * Called to create a rport for which only the wwn is known.
+ *
+ * @param[in] port	- base port
+ * @param[in] rpwwn	- remote port wwn
+ *
+ * @return None
+ */
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_create_by_wwn(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
+{
+	struct bfa_fcs_rport_s *rport;
+	bfa_trc(port->fcs, rpwwn);
+	rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
+	if (!rport)
+		return NULL;
+
+	bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
+	return rport;
+}
+/**
+ * Called by bport in private loop topology to indicate that a
+ * rport has been discovered and plogi has been completed.
+ *
+ * @param[in] port	- base port or vport
+ * @param[in] rpid	- remote port ID
+ */
+void
+bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
+	 struct fc_logi_s *plogi)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
+	if (!rport)
+		return;
+
+	bfa_fcs_rport_update(rport, plogi);
+
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
+}
+
+/**
+ *	Called by bport/vport to handle PLOGI received from a new remote port.
+ *	If an existing rport does a plogi, it will be handled separately.
+ */
+void
+bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
+				struct fc_logi_s *plogi)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
+	if (!rport)
+		return;
+
+	bfa_fcs_rport_update(rport, plogi);
+
+	rport->reply_oxid = fchs->ox_id;
+	bfa_trc(rport->fcs, rport->reply_oxid);
+
+	rport->stats.plogi_rcvd++;
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
+}
+
+static int
+wwn_compare(wwn_t wwn1, wwn_t wwn2)
+{
+	u8		*b1 = (u8 *) &wwn1;
+	u8		*b2 = (u8 *) &wwn2;
+	int		i;
+
+	for (i = 0; i < sizeof(wwn_t); i++) {
+		if (b1[i] < b2[i])
+			return -1;
+		if (b1[i] > b2[i])
+			return 1;
+	}
+	return 0;
+}
+
+/**
+ *	Called by bport/vport to handle PLOGI received from an existing
+ *	 remote port.
+ */
+void
+bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
+			struct fc_logi_s *plogi)
+{
+	/**
+	 * @todo Handle P2P and initiator-initiator.
+	 */
+
+	bfa_fcs_rport_update(rport, plogi);
+
+	rport->reply_oxid = rx_fchs->ox_id;
+	bfa_trc(rport->fcs, rport->reply_oxid);
+
+	/**
+	 * In Switched fabric topology,
+	 * PLOGI to each other. If our pwwn is smaller, ignore it,
+	 * if it is not a well known address.
+	 * If the link topology is N2N,
+	 * this Plogi should be accepted.
+	 */
+	if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) &&
+		(bfa_fcs_fabric_is_switched(rport->port->fabric)) &&
+		(!BFA_FCS_PID_IS_WKA(rport->pid))) {
+		bfa_trc(rport->fcs, rport->pid);
+		return;
+	}
+
+	rport->stats.plogi_rcvd++;
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
+}
+
+/**
+ * Called by bport/vport to delete a remote port instance.
+ *
+ * Rport delete is called under the following conditions:
+ *		- vport is deleted
+ *		- vf is deleted
+ *		- explicit request from OS to delete rport
+ */
+void
+bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
+}
+
+/**
+ * Called by bport/vport to  when a target goes offline.
+ *
+ */
+void
+bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
+}
+
+/**
+ * Called by bport in n2n when a target (attached port) becomes online.
+ *
+ */
+void
+bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
+}
+/**
+ *	Called by bport/vport to notify SCN for the remote port
+ */
+void
+bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
+{
+	rport->stats.rscns++;
+	bfa_sm_send_event(rport, RPSM_EVENT_SCN);
+}
+
+/**
+ *	Called by	fcpim to notify that the ITN cleanup is done.
+ */
+void
+bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
+}
+
+/**
+ *	Called by fcptm to notify that the ITN cleanup is done.
+ */
+void
+bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
+}
+
+/**
+ *	brief
+ *	This routine BFA callback for bfa_rport_online() call.
+ *
+ *	param[in]	cb_arg	-  rport struct.
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+void
+bfa_cb_rport_online(void *cbarg)
+{
+
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
+}
+
+/**
+ *	brief
+ *	This routine BFA callback for bfa_rport_offline() call.
+ *
+ *	param[in]	rport	-
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+void
+bfa_cb_rport_offline(void *cbarg)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
+}
+
+/**
+ *	brief
+ *	This routine is a static BFA callback when there is a QoS flow_id
+ *	change notification
+ *
+ *	param[in]	rport	-
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+void
+bfa_cb_rport_qos_scn_flowid(void *cbarg,
+		struct bfa_rport_qos_attr_s old_qos_attr,
+		struct bfa_rport_qos_attr_s new_qos_attr)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+}
+
+/**
+ *	brief
+ *	This routine is a static BFA callback when there is a QoS priority
+ *	change notification
+ *
+ *	param[in]	rport	-
+ *
+ *	return
+ *		void
+ *
+ *	Special Considerations:
+ *
+ *	note
+ */
+void
+bfa_cb_rport_qos_scn_prio(void *cbarg,
+		struct bfa_rport_qos_attr_s old_qos_attr,
+		struct bfa_rport_qos_attr_s new_qos_attr)
+{
+	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+}
+
+/**
+ *		Called to process any unsolicted frames from this remote port
+ */
+void
+bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
+{
+	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
+}
+
+/**
+ *		Called to process any unsolicted frames from this remote port
+ */
+void
+bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
+			struct fchs_s *fchs, u16 len)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fc_els_cmd_s	*els_cmd;
+
+	bfa_trc(rport->fcs, fchs->s_id);
+	bfa_trc(rport->fcs, fchs->d_id);
+	bfa_trc(rport->fcs, fchs->type);
+
+	if (fchs->type != FC_TYPE_ELS)
+		return;
+
+	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
+
+	bfa_trc(rport->fcs, els_cmd->els_code);
+
+	switch (els_cmd->els_code) {
+	case FC_ELS_LOGO:
+		bfa_stats(port, plogi_rcvd);
+		bfa_fcs_rport_process_logo(rport, fchs);
+		break;
+
+	case FC_ELS_ADISC:
+		bfa_stats(port, adisc_rcvd);
+		bfa_fcs_rport_process_adisc(rport, fchs, len);
+		break;
+
+	case FC_ELS_PRLO:
+		bfa_stats(port, prlo_rcvd);
+		if (bfa_fcs_lport_is_initiator(port))
+			bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
+		break;
+
+	case FC_ELS_PRLI:
+		bfa_stats(port, prli_rcvd);
+		bfa_fcs_rport_process_prli(rport, fchs, len);
+		break;
+
+	case FC_ELS_RPSC:
+		bfa_stats(port, rpsc_rcvd);
+		bfa_fcs_rport_process_rpsc(rport, fchs, len);
+		break;
+
+	default:
+		bfa_stats(port, un_handled_els_rcvd);
+		bfa_fcs_rport_send_ls_rjt(rport, fchs,
+					  FC_LS_RJT_RSN_CMD_NOT_SUPP,
+					  FC_LS_RJT_EXP_NO_ADDL_INFO);
+		break;
+	}
+}
+
+/* send best case  acc to prlo */
+static void
+bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	int		len;
+
+	bfa_trc(rport->fcs, rport->pid);
+
+	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp)
+		return;
+	len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+			rport->pid, bfa_fcs_lport_get_fcid(port),
+			rport->reply_oxid, 0);
+
+	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
+		port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
+		NULL, NULL, FC_MAX_PDUSZ, 0);
+}
+
+/*
+ * Send a LS reject
+ */
+static void
+bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
+			  u8 reason_code, u8 reason_code_expl)
+{
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	struct bfa_fcxp_s *fcxp;
+	int		len;
+
+	bfa_trc(rport->fcs, rx_fchs->s_id);
+
+	fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
+	if (!fcxp)
+		return;
+
+	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
+				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
+				rx_fchs->ox_id, reason_code, reason_code_expl);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
+			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
+			FC_MAX_PDUSZ, 0);
+}
+
+/**
+ * Return state of rport.
+ */
+int
+bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
+{
+	return bfa_sm_to_state(rport_sm_table, rport->sm);
+}
+
+/**
+ *	brief
+ *		 Called by the Driver to set rport delete/ageout timeout
+ *
+ *	param[in]		rport timeout value in seconds.
+ *
+ *	return None
+ */
+void
+bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
+{
+	/* convert to Millisecs */
+	if (rport_tmo > 0)
+		bfa_fcs_rport_del_timeout = rport_tmo * 1000;
+}
+void
+bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id)
+{
+	bfa_trc(rport->fcs, rport->pid);
+
+	rport->prlo = BFA_TRUE;
+	rport->reply_oxid = ox_id;
+	bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
+}
+
+
+
+/**
+ * Remote port implementation.
+ */
+
+/**
+ *  fcs_rport_api FCS rport API.
+ */
+
+/**
+ *	Direct API to add a target by port wwn. This interface is used, for
+ *	example, by bios when target pwwn is known from boot lun configuration.
+ */
+bfa_status_t
+bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
+		struct bfa_fcs_rport_s *rport, struct bfad_rport_s *rport_drv)
+{
+	bfa_trc(port->fcs, *pwwn);
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ *	Direct API to remove a target and its associated resources. This
+ *	interface is used, for example, by driver to remove target
+ *	ports from the target list for a VM.
+ */
+bfa_status_t
+bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
+{
+
+	struct bfa_fcs_rport_s *rport;
+
+	bfa_trc(rport_in->fcs, rport_in->pwwn);
+
+	rport = bfa_fcs_lport_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
+	if (rport == NULL) {
+		/*
+		 * TBD Error handling
+		 */
+		bfa_trc(rport_in->fcs, rport_in->pid);
+		return BFA_STATUS_UNKNOWN_RWWN;
+	}
+
+	/*
+	 * TBD if this remote port is online, send a logo
+	 */
+	return BFA_STATUS_OK;
+
+}
+
+/**
+ *	Remote device status for display/debug.
+ */
+void
+bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
+			struct bfa_rport_attr_s *rport_attr)
+{
+	struct bfa_rport_qos_attr_s qos_attr;
+	bfa_fcs_lport_t *port = rport->port;
+	bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
+
+	bfa_os_memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
+
+	rport_attr->pid = rport->pid;
+	rport_attr->pwwn = rport->pwwn;
+	rport_attr->nwwn = rport->nwwn;
+	rport_attr->cos_supported = rport->fc_cos;
+	rport_attr->df_sz = rport->maxfrsize;
+	rport_attr->state = bfa_fcs_rport_get_state(rport);
+	rport_attr->fc_cos = rport->fc_cos;
+	rport_attr->cisc = rport->cisc;
+	rport_attr->scsi_function = rport->scsi_function;
+	rport_attr->curr_speed  = rport->rpf.rpsc_speed;
+	rport_attr->assigned_speed  = rport->rpf.assigned_speed;
+
+	bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
+	rport_attr->qos_attr = qos_attr;
+
+	rport_attr->trl_enforced = BFA_FALSE;
+	if (bfa_fcport_is_ratelim(port->fcs->bfa)) {
+		if (rport_speed == BFA_PORT_SPEED_UNKNOWN) {
+			/* Use default ratelim speed setting */
+			rport_speed =
+				bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
+		}
+
+		if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
+			rport_attr->trl_enforced = BFA_TRUE;
+	}
+}
+
+/**
+ *	Per remote device statistics.
+ */
+void
+bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
+			struct bfa_rport_stats_s *stats)
+{
+	*stats = rport->stats;
+}
+
+void
+bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
+{
+	bfa_os_memset((char *)&rport->stats, 0,
+			sizeof(struct bfa_rport_stats_s));
+}
+
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	rport = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
+	if (rport == NULL) {
+		/*
+		 * TBD Error handling
+		 */
+	}
+
+	return rport;
+}
+
+struct bfa_fcs_rport_s *
+bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)
+{
+	struct bfa_fcs_rport_s *rport;
+
+	rport = bfa_fcs_lport_get_rport_by_nwwn(port, rnwwn);
+	if (rport == NULL) {
+		/*
+		 * TBD Error handling
+		 */
+	}
+
+	return rport;
+}
+
+/*
+ * This API is to set the Rport's speed. Should be used when RPSC is not
+ * supported by the rport.
+ */
+void
+bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, bfa_port_speed_t speed)
+{
+	rport->rpf.assigned_speed  = speed;
+
+	/* Set this speed in f/w only if the RPSC speed is not available */
+	if (rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
+		bfa_rport_speed(rport->bfa_rport, speed);
+}
+
+
+
+/**
+ * Remote port features (RPF) implementation.
+ */
+
+#define BFA_FCS_RPF_RETRIES	(3)
+#define BFA_FCS_RPF_RETRY_TIMEOUT  (1000) /* 1 sec (In millisecs) */
+
+static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
+				struct bfa_fcxp_s *fcxp_alloced);
+static void     bfa_fcs_rpf_rpsc2_response(void *fcsarg,
+			struct bfa_fcxp_s *fcxp,
+			void *cbarg,
+			bfa_status_t req_status,
+			u32 rsp_len,
+			u32 resid_len,
+			struct fchs_s *rsp_fchs);
+
+static void     bfa_fcs_rpf_timeout(void *arg);
+
+/**
+ *  fcs_rport_ftrs_sm FCS rport state machine events
+ */
+
+enum rpf_event {
+	RPFSM_EVENT_RPORT_OFFLINE  = 1, /* Rport offline		*/
+	RPFSM_EVENT_RPORT_ONLINE   = 2,	/* Rport online			*/
+	RPFSM_EVENT_FCXP_SENT      = 3,	/* Frame from has been sent	*/
+	RPFSM_EVENT_TIMEOUT	   = 4, /* Rport SM timeout event	*/
+	RPFSM_EVENT_RPSC_COMP      = 5,
+	RPFSM_EVENT_RPSC_FAIL      = 6,
+	RPFSM_EVENT_RPSC_ERROR     = 7,
+};
+
+static void	bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
+					enum rpf_event event);
+static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
+				       enum rpf_event event);
+static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
+				       enum rpf_event event);
+static void	bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
+					enum rpf_event event);
+static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
+					enum rpf_event event);
+static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
+					enum rpf_event event);
+
+static void
+bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+	struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_RPORT_ONLINE:
+		/* Send RPSC2 to a Brocade fabric only. */
+		if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
+			((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) ||
+			(bfa_fcs_fabric_get_switch_oui(fabric) ==
+						BFA_FCS_BRCD_SWITCH_OUI))) {
+			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+			rpf->rpsc_retries = 0;
+			bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+		}
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_FCXP_SENT:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
+		rpf->rpsc_retries = 0;
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_RPSC_COMP:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+		/* Update speed info in f/w via BFA */
+		if (rpf->rpsc_speed != BFA_PORT_SPEED_UNKNOWN)
+			bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
+		else if (rpf->assigned_speed != BFA_PORT_SPEED_UNKNOWN)
+			bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
+		break;
+
+	case RPFSM_EVENT_RPSC_FAIL:
+		/* RPSC not supported by rport */
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+		break;
+
+	case RPFSM_EVENT_RPSC_ERROR:
+		/* need to retry...delayed a bit. */
+		if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
+			bfa_timer_start(rport->fcs->bfa, &rpf->timer,
+				    bfa_fcs_rpf_timeout, rpf,
+				    BFA_FCS_RPF_RETRY_TIMEOUT);
+			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
+		} else {
+			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
+		}
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+		bfa_fcxp_discard(rpf->fcxp);
+		rpf->rpsc_retries = 0;
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_TIMEOUT:
+		/* re-send the RPSC */
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		bfa_timer_stop(&rpf->timer);
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+		rpf->rpsc_retries = 0;
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
+		rpf->rpsc_retries = 0;
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+
+static void
+bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
+{
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_trc(rport->fcs, event);
+
+	switch (event) {
+	case RPFSM_EVENT_RPORT_ONLINE:
+		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
+		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
+		break;
+
+	case RPFSM_EVENT_RPORT_OFFLINE:
+		break;
+
+	default:
+		bfa_sm_fault(rport->fcs, event);
+	}
+}
+/**
+ * Called when Rport is created.
+ */
+void
+bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
+{
+	struct bfa_fcs_rpf_s *rpf = &rport->rpf;
+
+	bfa_trc(rport->fcs, rport->pid);
+	rpf->rport = rport;
+
+	bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
+}
+
+/**
+ * Called when Rport becomes online
+ */
+void
+bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
+{
+	bfa_trc(rport->fcs, rport->pid);
+
+	if (__fcs_min_cfg(rport->port->fcs))
+		return;
+
+	if (bfa_fcs_fabric_is_switched(rport->port->fabric))
+		bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
+}
+
+/**
+ * Called when Rport becomes offline
+ */
+void
+bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
+{
+	bfa_trc(rport->fcs, rport->pid);
+
+	if (__fcs_min_cfg(rport->port->fcs))
+		return;
+
+	rport->rpf.rpsc_speed = 0;
+	bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
+}
+
+static void
+bfa_fcs_rpf_timeout(void *arg)
+{
+	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+
+	bfa_trc(rport->fcs, rport->pid);
+	bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
+}
+
+static void
+bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
+{
+	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+	struct bfa_fcs_lport_s *port = rport->port;
+	struct fchs_s	fchs;
+	int		len;
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_trc(rport->fcs, rport->pwwn);
+
+	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
+	if (!fcxp) {
+		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
+					bfa_fcs_rpf_send_rpsc2, rpf);
+		return;
+	}
+	rpf->fcxp = fcxp;
+
+	len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
+			    bfa_fcs_lport_get_fcid(port), &rport->pid, 1);
+
+	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
+			  FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
+			  rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
+	rport->stats.rpsc_sent++;
+	bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
+
+}
+
+static void
+bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
+			    bfa_status_t req_status, u32 rsp_len,
+			    u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
+	struct bfa_fcs_rport_s *rport = rpf->rport;
+	struct fc_ls_rjt_s *ls_rjt;
+	struct fc_rpsc2_acc_s *rpsc2_acc;
+	u16	num_ents;
+
+	bfa_trc(rport->fcs, req_status);
+
+	if (req_status != BFA_STATUS_OK) {
+		bfa_trc(rport->fcs, req_status);
+		if (req_status == BFA_STATUS_ETIMER)
+			rport->stats.rpsc_failed++;
+		bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+		return;
+	}
+
+	rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
+	if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
+		rport->stats.rpsc_accs++;
+		num_ents = bfa_os_ntohs(rpsc2_acc->num_pids);
+		bfa_trc(rport->fcs, num_ents);
+		if (num_ents > 0) {
+			bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
+			bfa_trc(rport->fcs,
+				bfa_os_ntohs(rpsc2_acc->port_info[0].pid));
+			bfa_trc(rport->fcs,
+				bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
+			bfa_trc(rport->fcs,
+				bfa_os_ntohs(rpsc2_acc->port_info[0].index));
+			bfa_trc(rport->fcs,
+				rpsc2_acc->port_info[0].type);
+
+			if (rpsc2_acc->port_info[0].speed == 0) {
+				bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+				return;
+			}
+
+			rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
+				bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
+
+			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
+		}
+	} else {
+		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
+		bfa_trc(rport->fcs, ls_rjt->reason_code);
+		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
+		rport->stats.rpsc_rejects++;
+		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
+			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
+		else
+			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
+	}
+}
diff --git a/drivers/scsi/bfa/bfa_fcs_uf.c b/drivers/scsi/bfa/bfa_fcs_uf.c
deleted file mode 100644
index 3d57d48..0000000
--- a/drivers/scsi/bfa/bfa_fcs_uf.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcs_uf.c BFA FCS UF ( Unsolicited Frames)
- */
-
-#include <fcs/bfa_fcs.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs_fabric.h>
-#include "fcs.h"
-#include "fcs_trcmod.h"
-#include "fcs_fabric.h"
-#include "fcs_uf.h"
-
-BFA_TRC_FILE(FCS, UF);
-
-/**
- * 		BFA callback for unsolicited frame receive handler.
- *
- * @param[in]		cbarg		callback arg for receive handler
- * @param[in]		uf		unsolicited frame descriptor
- *
- * @return None
- */
-static void
-bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
-{
-	struct bfa_fcs_s      *fcs = (struct bfa_fcs_s *) cbarg;
-	struct fchs_s         *fchs = bfa_uf_get_frmbuf(uf);
-	u16        len = bfa_uf_get_frmlen(uf);
-	struct fc_vft_s       *vft;
-	struct bfa_fcs_fabric_s *fabric;
-
-	/**
-	 * check for VFT header
-	 */
-	if (fchs->routing == FC_RTG_EXT_HDR &&
-		fchs->cat_info == FC_CAT_VFT_HDR) {
-		bfa_stats(fcs, uf.tagged);
-		vft = bfa_uf_get_frmbuf(uf);
-		if (fcs->port_vfid == vft->vf_id)
-			fabric = &fcs->fabric;
-		else
-			fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
-
-		/**
-		 * drop frame if vfid is unknown
-		 */
-		if (!fabric) {
-			bfa_assert(0);
-			bfa_stats(fcs, uf.vfid_unknown);
-			bfa_uf_free(uf);
-			return;
-		}
-
-		/**
-		 * skip vft header
-		 */
-		fchs = (struct fchs_s *) (vft + 1);
-		len -= sizeof(struct fc_vft_s);
-
-		bfa_trc(fcs, vft->vf_id);
-	} else {
-		bfa_stats(fcs, uf.untagged);
-		fabric = &fcs->fabric;
-	}
-
-	bfa_trc(fcs, ((u32 *) fchs)[0]);
-	bfa_trc(fcs, ((u32 *) fchs)[1]);
-	bfa_trc(fcs, ((u32 *) fchs)[2]);
-	bfa_trc(fcs, ((u32 *) fchs)[3]);
-	bfa_trc(fcs, ((u32 *) fchs)[4]);
-	bfa_trc(fcs, ((u32 *) fchs)[5]);
-	bfa_trc(fcs, len);
-
-	bfa_fcs_fabric_uf_recv(fabric, fchs, len);
-	bfa_uf_free(uf);
-}
-
-void
-bfa_fcs_uf_attach(struct bfa_fcs_s *fcs)
-{
-	bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
-}
diff --git a/drivers/scsi/bfa/bfa_fcxp.c b/drivers/scsi/bfa/bfa_fcxp.c
deleted file mode 100644
index 8258f88..0000000
--- a/drivers/scsi/bfa/bfa_fcxp.c
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include <bfi/bfi_uf.h>
-#include <cs/bfa_debug.h>
-
-BFA_TRC_FILE(HAL, FCXP);
-BFA_MODULE(fcxp);
-
-/**
- * forward declarations
- */
-static void     __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
-static void     hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
-				 struct bfi_fcxp_send_rsp_s *fcxp_rsp);
-static void     hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
-				 struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
-static void	bfa_fcxp_qresume(void *cbarg);
-static void	bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
-			       struct bfi_fcxp_send_req_s *send_req);
-
-/**
- *  fcxp_pvt BFA FCXP private functions
- */
-
-static void
-claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
-{
-	u8        *dm_kva = NULL;
-	u64        dm_pa;
-	u32        buf_pool_sz;
-
-	dm_kva = bfa_meminfo_dma_virt(mi);
-	dm_pa = bfa_meminfo_dma_phys(mi);
-
-	buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
-
-	/*
-	 * Initialize the fcxp req payload list
-	 */
-	mod->req_pld_list_kva = dm_kva;
-	mod->req_pld_list_pa = dm_pa;
-	dm_kva += buf_pool_sz;
-	dm_pa += buf_pool_sz;
-	bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
-
-	/*
-	 * Initialize the fcxp rsp payload list
-	 */
-	buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
-	mod->rsp_pld_list_kva = dm_kva;
-	mod->rsp_pld_list_pa = dm_pa;
-	dm_kva += buf_pool_sz;
-	dm_pa += buf_pool_sz;
-	bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
-
-	bfa_meminfo_dma_virt(mi) = dm_kva;
-	bfa_meminfo_dma_phys(mi) = dm_pa;
-}
-
-static void
-claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
-{
-	u16        i;
-	struct bfa_fcxp_s *fcxp;
-
-	fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
-	bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
-
-	INIT_LIST_HEAD(&mod->fcxp_free_q);
-	INIT_LIST_HEAD(&mod->fcxp_active_q);
-
-	mod->fcxp_list = fcxp;
-
-	for (i = 0; i < mod->num_fcxps; i++) {
-		fcxp->fcxp_mod = mod;
-		fcxp->fcxp_tag = i;
-
-		list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
-		bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
-		fcxp->reqq_waiting = BFA_FALSE;
-
-		fcxp = fcxp + 1;
-	}
-
-	bfa_meminfo_kva(mi) = (void *)fcxp;
-}
-
-static void
-bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-		u32 *dm_len)
-{
-	u16        num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
-
-	if (num_fcxp_reqs == 0)
-		return;
-
-	/*
-	 * Account for req/rsp payload
-	 */
-	*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
-	if (cfg->drvcfg.min_cfg)
-		*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
-	else
-		*dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
-
-	/*
-	 * Account for fcxp structs
-	 */
-	*ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
-}
-
-static void
-bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		    struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
-	bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
-	mod->bfa = bfa;
-	mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
-
-	/**
-	 * Initialize FCXP request and response payload sizes.
-	 */
-	mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
-	if (!cfg->drvcfg.min_cfg)
-		mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
-
-	INIT_LIST_HEAD(&mod->wait_q);
-
-	claim_fcxp_req_rsp_mem(mod, meminfo);
-	claim_fcxps_mem(mod, meminfo);
-}
-
-static void
-bfa_fcxp_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcxp_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcxp_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_fcxp_iocdisable(struct bfa_s *bfa)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-	struct bfa_fcxp_s *fcxp;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
-		fcxp = (struct bfa_fcxp_s *) qe;
-		if (fcxp->caller == NULL) {
-			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
-					BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
-			bfa_fcxp_free(fcxp);
-		} else {
-			fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
-			bfa_cb_queue(bfa, &fcxp->hcb_qe,
-				      __bfa_fcxp_send_cbfn, fcxp);
-		}
-	}
-}
-
-static struct bfa_fcxp_s *
-bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
-{
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_q_deq(&fm->fcxp_free_q, &fcxp);
-
-	if (fcxp)
-		list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
-
-	return fcxp;
-}
-
-static void
-bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-	struct bfa_fcxp_wqe_s *wqe;
-
-	bfa_q_deq(&mod->wait_q, &wqe);
-	if (wqe) {
-		bfa_trc(mod->bfa, fcxp->fcxp_tag);
-		wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
-		return;
-	}
-
-	bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
-	list_del(&fcxp->qe);
-	list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
-}
-
-static void
-bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
-		       bfa_status_t req_status, u32 rsp_len,
-		       u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	/* discarded fcxp completion */
-}
-
-static void
-__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_fcxp_s *fcxp = cbarg;
-
-	if (complete) {
-		fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
-				fcxp->rsp_status, fcxp->rsp_len,
-				fcxp->residue_len, &fcxp->rsp_fchs);
-	} else {
-		bfa_fcxp_free(fcxp);
-	}
-}
-
-static void
-hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
-{
-	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
-	struct bfa_fcxp_s 	*fcxp;
-	u16		fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
-
-	bfa_trc(bfa, fcxp_tag);
-
-	fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
-
-	/**
-	 * @todo f/w should not set residue to non-0 when everything
-	 *       is received.
-	 */
-	if (fcxp_rsp->req_status == BFA_STATUS_OK)
-		fcxp_rsp->residue_len = 0;
-	else
-		fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
-
-	fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
-
-	bfa_assert(fcxp->send_cbfn != NULL);
-
-	hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
-
-	if (fcxp->send_cbfn != NULL) {
-		if (fcxp->caller == NULL) {
-			bfa_trc(mod->bfa, fcxp->fcxp_tag);
-
-			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
-					fcxp_rsp->req_status, fcxp_rsp->rsp_len,
-					fcxp_rsp->residue_len, &fcxp_rsp->fchs);
-			/*
-			 * fcxp automatically freed on return from the callback
-			 */
-			bfa_fcxp_free(fcxp);
-		} else {
-			bfa_trc(mod->bfa, fcxp->fcxp_tag);
-			fcxp->rsp_status = fcxp_rsp->req_status;
-			fcxp->rsp_len = fcxp_rsp->rsp_len;
-			fcxp->residue_len = fcxp_rsp->residue_len;
-			fcxp->rsp_fchs = fcxp_rsp->fchs;
-
-			bfa_cb_queue(bfa, &fcxp->hcb_qe,
-				      __bfa_fcxp_send_cbfn, fcxp);
-		}
-	} else {
-		bfa_trc(bfa, fcxp_tag);
-	}
-}
-
-static void
-hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
-{
-	union bfi_addr_u      sga_zero = { {0} };
-
-	sge->sg_len = reqlen;
-	sge->flags = BFI_SGE_DATA_LAST;
-	bfa_dma_addr_set(sge[0].sga, req_pa);
-	bfa_sge_to_be(sge);
-	sge++;
-
-	sge->sga = sga_zero;
-	sge->sg_len = reqlen;
-	sge->flags = BFI_SGE_PGDLEN;
-	bfa_sge_to_be(sge);
-}
-
-static void
-hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
-		 struct fchs_s *fchs)
-{
-	/*
-	 * TODO: TX ox_id
-	 */
-	if (reqlen > 0) {
-		if (fcxp->use_ireqbuf) {
-			u32        pld_w0 =
-				*((u32 *) BFA_FCXP_REQ_PLD(fcxp));
-
-			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
-				BFA_PL_EID_TX,
-				reqlen + sizeof(struct fchs_s), fchs, pld_w0);
-		} else {
-			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
-				BFA_PL_EID_TX, reqlen + sizeof(struct fchs_s),
-				fchs);
-		}
-	} else {
-		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
-			       reqlen + sizeof(struct fchs_s), fchs);
-	}
-}
-
-static void
-hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
-		 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
-{
-	if (fcxp_rsp->rsp_len > 0) {
-		if (fcxp->use_irspbuf) {
-			u32        pld_w0 =
-				*((u32 *) BFA_FCXP_RSP_PLD(fcxp));
-
-			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
-					      BFA_PL_EID_RX,
-					      (u16) fcxp_rsp->rsp_len,
-					      &fcxp_rsp->fchs, pld_w0);
-		} else {
-			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
-				       BFA_PL_EID_RX,
-				       (u16) fcxp_rsp->rsp_len,
-				       &fcxp_rsp->fchs);
-		}
-	} else {
-		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
-			       (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
-	}
-}
-
-/**
- * Handler to resume sending fcxp when space in available in cpe queue.
- */
-static void
-bfa_fcxp_qresume(void *cbarg)
-{
-	struct bfa_fcxp_s		*fcxp = cbarg;
-	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
-	struct bfi_fcxp_send_req_s	*send_req;
-
-	fcxp->reqq_waiting = BFA_FALSE;
-	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
-	bfa_fcxp_queue(fcxp, send_req);
-}
-
-/**
- * Queue fcxp send request to foimrware.
- */
-static void
-bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
-{
-	struct bfa_s      		*bfa = fcxp->fcxp_mod->bfa;
-	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
-	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
-	struct bfa_rport_s		*rport = reqi->bfa_rport;
-
-	bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
-			bfa_lpuid(bfa));
-
-	send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
-	if (rport) {
-		send_req->rport_fw_hndl = rport->fw_handle;
-		send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
-		if (send_req->max_frmsz == 0)
-			send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
-	} else {
-		send_req->rport_fw_hndl = 0;
-		send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
-	}
-
-	send_req->vf_id = bfa_os_htons(reqi->vf_id);
-	send_req->lp_tag = reqi->lp_tag;
-	send_req->class = reqi->class;
-	send_req->rsp_timeout = rspi->rsp_timeout;
-	send_req->cts = reqi->cts;
-	send_req->fchs = reqi->fchs;
-
-	send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
-	send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
-
-	/*
-	 * setup req sgles
-	 */
-	if (fcxp->use_ireqbuf == 1) {
-		hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
-					BFA_FCXP_REQ_PLD_PA(fcxp));
-	} else {
-		if (fcxp->nreq_sgles > 0) {
-			bfa_assert(fcxp->nreq_sgles == 1);
-			hal_fcxp_set_local_sges(send_req->req_sge,
-						reqi->req_tot_len,
-						fcxp->req_sga_cbfn(fcxp->caller,
-								   0));
-		} else {
-			bfa_assert(reqi->req_tot_len == 0);
-			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
-		}
-	}
-
-	/*
-	 * setup rsp sgles
-	 */
-	if (fcxp->use_irspbuf == 1) {
-		bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
-
-		hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
-					BFA_FCXP_RSP_PLD_PA(fcxp));
-
-	} else {
-		if (fcxp->nrsp_sgles > 0) {
-			bfa_assert(fcxp->nrsp_sgles == 1);
-			hal_fcxp_set_local_sges(send_req->rsp_sge,
-						rspi->rsp_maxlen,
-						fcxp->rsp_sga_cbfn(fcxp->caller,
-								   0));
-		} else {
-			bfa_assert(rspi->rsp_maxlen == 0);
-			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
-		}
-	}
-
-	hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
-
-	bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
-
-	bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
-	bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
-}
-
-
-/**
- *  hal_fcxp_api BFA FCXP API
- */
-
-/**
- * Allocate an FCXP instance to send a response or to send a request
- * that has a response. Request/response buffers are allocated by caller.
- *
- * @param[in]	bfa		BFA bfa instance
- * @param[in]	nreq_sgles	Number of SG elements required for request
- * 				buffer. 0, if fcxp internal buffers are	used.
- * 				Use bfa_fcxp_get_reqbuf() to get the
- * 				internal req buffer.
- * @param[in]	req_sgles	SG elements describing request buffer. Will be
- * 				copied in by BFA and hence can be freed on
- * 				return from this function.
- * @param[in]	get_req_sga	function ptr to be called to get a request SG
- * 				Address (given the sge index).
- * @param[in]	get_req_sglen	function ptr to be called to get a request SG
- * 				len (given the sge index).
- * @param[in]	get_rsp_sga	function ptr to be called to get a response SG
- * 				Address (given the sge index).
- * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG
- * 				len (given the sge index).
- *
- * @return FCXP instance. NULL on failure.
- */
-struct bfa_fcxp_s *
-bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
-			int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
-			bfa_fcxp_get_sglen_t req_sglen_cbfn,
-			bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
-			bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
-{
-	struct bfa_fcxp_s *fcxp = NULL;
-	u32        nreq_sgpg, nrsp_sgpg;
-
-	bfa_assert(bfa != NULL);
-
-	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
-	if (fcxp == NULL)
-		return NULL;
-
-	bfa_trc(bfa, fcxp->fcxp_tag);
-
-	fcxp->caller = caller;
-
-	if (nreq_sgles == 0) {
-		fcxp->use_ireqbuf = 1;
-	} else {
-		bfa_assert(req_sga_cbfn != NULL);
-		bfa_assert(req_sglen_cbfn != NULL);
-
-		fcxp->use_ireqbuf = 0;
-		fcxp->req_sga_cbfn = req_sga_cbfn;
-		fcxp->req_sglen_cbfn = req_sglen_cbfn;
-
-		fcxp->nreq_sgles = nreq_sgles;
-
-		/*
-		 * alloc required sgpgs
-		 */
-		if (nreq_sgles > BFI_SGE_INLINE) {
-			nreq_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
-
-			if (bfa_sgpg_malloc(bfa, &fcxp->req_sgpg_q, nreq_sgpg)
-			    != BFA_STATUS_OK) {
-				/*
-				 * TODO
-				 */
-			}
-		}
-	}
-
-	if (nrsp_sgles == 0) {
-		fcxp->use_irspbuf = 1;
-	} else {
-		bfa_assert(rsp_sga_cbfn != NULL);
-		bfa_assert(rsp_sglen_cbfn != NULL);
-
-		fcxp->use_irspbuf = 0;
-		fcxp->rsp_sga_cbfn = rsp_sga_cbfn;
-		fcxp->rsp_sglen_cbfn = rsp_sglen_cbfn;
-
-		fcxp->nrsp_sgles = nrsp_sgles;
-		/*
-		 * alloc required sgpgs
-		 */
-		if (nrsp_sgles > BFI_SGE_INLINE) {
-			nrsp_sgpg = BFA_SGPG_NPAGE(nreq_sgles);
-
-			if (bfa_sgpg_malloc
-			    (bfa, &fcxp->rsp_sgpg_q, nrsp_sgpg)
-			    != BFA_STATUS_OK) {
-				/* bfa_sgpg_wait(bfa, &fcxp->rsp_sgpg_wqe,
-				nrsp_sgpg); */
-				/*
-				 * TODO
-				 */
-			}
-		}
-	}
-
-	return fcxp;
-}
-
-/**
- * Get the internal request buffer pointer
- *
- * @param[in]	fcxp	BFA fcxp pointer
- *
- * @return 		pointer to the internal request buffer
- */
-void *
-bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-	void	*reqbuf;
-
-	bfa_assert(fcxp->use_ireqbuf == 1);
-	reqbuf = ((u8 *)mod->req_pld_list_kva) +
-			fcxp->fcxp_tag * mod->req_pld_sz;
-	return reqbuf;
-}
-
-u32
-bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-
-	return mod->req_pld_sz;
-}
-
-/**
- * Get the internal response buffer pointer
- *
- * @param[in]	fcxp	BFA fcxp pointer
- *
- * @return		pointer to the internal request buffer
- */
-void *
-bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-	void	*rspbuf;
-
-	bfa_assert(fcxp->use_irspbuf == 1);
-
-	rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
-			fcxp->fcxp_tag * mod->rsp_pld_sz;
-	return rspbuf;
-}
-
-/**
- * 		Free the BFA FCXP
- *
- * @param[in]	fcxp			BFA fcxp pointer
- *
- * @return 		void
- */
-void
-bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
-{
-	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
-
-	bfa_assert(fcxp != NULL);
-	bfa_trc(mod->bfa, fcxp->fcxp_tag);
-	bfa_fcxp_put(fcxp);
-}
-
-/**
- * Send a FCXP request
- *
- * @param[in]	fcxp	BFA fcxp pointer
- * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports
- * @param[in]	vf_id	virtual Fabric ID
- * @param[in]	lp_tag  lport tag
- * @param[in]	cts	use Continous sequence
- * @param[in]	cos	fc Class of Service
- * @param[in]	reqlen	request length, does not include FCHS length
- * @param[in]	fchs	fc Header Pointer. The header content will be copied
- *			in by BFA.
- *
- * @param[in]	cbfn	call back function to be called on receiving
- * 								the response
- * @param[in]	cbarg	arg for cbfn
- * @param[in]	rsp_timeout
- *			response timeout
- *
- * @return		bfa_status_t
- */
-void
-bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
-		u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
-		u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
-		void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
-{
-	struct bfa_s			*bfa  = fcxp->fcxp_mod->bfa;
-	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
-	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
-	struct bfi_fcxp_send_req_s	*send_req;
-
-	bfa_trc(bfa, fcxp->fcxp_tag);
-
-	/**
-	 * setup request/response info
-	 */
-	reqi->bfa_rport = rport;
-	reqi->vf_id = vf_id;
-	reqi->lp_tag = lp_tag;
-	reqi->class = cos;
-	rspi->rsp_timeout = rsp_timeout;
-	reqi->cts = cts;
-	reqi->fchs = *fchs;
-	reqi->req_tot_len = reqlen;
-	rspi->rsp_maxlen = rsp_maxlen;
-	fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
-	fcxp->send_cbarg = cbarg;
-
-	/**
-	 * If no room in CPE queue, wait for space in request queue
-	 */
-	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
-	if (!send_req) {
-		bfa_trc(bfa, fcxp->fcxp_tag);
-		fcxp->reqq_waiting = BFA_TRUE;
-		bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
-		return;
-	}
-
-	bfa_fcxp_queue(fcxp, send_req);
-}
-
-/**
- * Abort a BFA FCXP
- *
- * @param[in]	fcxp	BFA fcxp pointer
- *
- * @return 		void
- */
-bfa_status_t
-bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
-{
-	bfa_assert(0);
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
-			bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
-	bfa_assert(list_empty(&mod->fcxp_free_q));
-
-	wqe->alloc_cbfn = alloc_cbfn;
-	wqe->alloc_cbarg = alloc_cbarg;
-	list_add_tail(&wqe->qe, &mod->wait_q);
-}
-
-void
-bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
-	bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
-	list_del(&wqe->qe);
-}
-
-void
-bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
-{
-	/**
-	 * If waiting for room in request queue, cancel reqq wait
-	 * and free fcxp.
-	 */
-	if (fcxp->reqq_waiting) {
-		fcxp->reqq_waiting = BFA_FALSE;
-		bfa_reqq_wcancel(&fcxp->reqq_wqe);
-		bfa_fcxp_free(fcxp);
-		return;
-	}
-
-	fcxp->send_cbfn = bfa_fcxp_null_comp;
-}
-
-
-
-/**
- *  hal_fcxp_public BFA FCXP public functions
- */
-
-void
-bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
-{
-	switch (msg->mhdr.msg_id) {
-	case BFI_FCXP_I2H_SEND_RSP:
-		hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
-		break;
-
-	default:
-		bfa_trc(bfa, msg->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-u32
-bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
-{
-	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
-
-	return mod->rsp_pld_sz;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_fcxp_priv.h b/drivers/scsi/bfa/bfa_fcxp_priv.h
deleted file mode 100644
index 4cda493..0000000
--- a/drivers/scsi/bfa/bfa_fcxp_priv.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_FCXP_PRIV_H__
-#define __BFA_FCXP_PRIV_H__
-
-#include <cs/bfa_sm.h>
-#include <protocol/fc.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_fcxp.h>
-
-#define BFA_FCXP_MIN     	(1)
-#define BFA_FCXP_MAX_IBUF_SZ	(2 * 1024 + 256)
-#define BFA_FCXP_MAX_LBUF_SZ	(4 * 1024 + 256)
-
-struct bfa_fcxp_mod_s {
-	struct bfa_s      *bfa;		/*  backpointer to BFA */
-	struct bfa_fcxp_s *fcxp_list;	/*  array of FCXPs */
-	u16        num_fcxps;	/*  max num FCXP requests */
-	struct list_head fcxp_free_q;	/*  free FCXPs */
-	struct list_head fcxp_active_q;	/*  active FCXPs */
-	void	*req_pld_list_kva;	/*  list of FCXP req pld */
-	u64 req_pld_list_pa;	/*  list of FCXP req pld */
-	void *rsp_pld_list_kva;		/*  list of FCXP resp pld */
-	u64 rsp_pld_list_pa;	/*  list of FCXP resp pld */
-	struct list_head  wait_q;		/*  wait queue for free fcxp */
-	u32	req_pld_sz;
-	u32	rsp_pld_sz;
-};
-
-#define BFA_FCXP_MOD(__bfa)		(&(__bfa)->modules.fcxp_mod)
-#define BFA_FCXP_FROM_TAG(__mod, __tag)	(&(__mod)->fcxp_list[__tag])
-
-typedef void    (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
-				   void *cb_arg, bfa_status_t req_status,
-				   u32 rsp_len, u32 resid_len,
-				   struct fchs_s *rsp_fchs);
-
-/**
- * Information needed for a FCXP request
- */
-struct bfa_fcxp_req_info_s {
-	struct bfa_rport_s *bfa_rport;	/*  Pointer to the bfa rport that was
-					 *returned from bfa_rport_create().
-					 *This could be left NULL for WKA or for
-					 *FCXP interactions before the rport
-					 *nexus is established
-					 */
-	struct fchs_s   fchs;	/*  request FC header structure */
-	u8 cts;		/*  continous sequence */
-	u8 class;		/*  FC class for the request/response */
-	u16 max_frmsz;	/*  max send frame size */
-	u16 vf_id;		/*  vsan tag if applicable */
-	u8	lp_tag;		/*  lport tag */
-	u32 req_tot_len;	/*  request payload total length */
-};
-
-struct bfa_fcxp_rsp_info_s {
-	struct fchs_s rsp_fchs;		/*  Response frame's FC header will
-					 * be *sent back in this field */
-	u8         rsp_timeout;	/*  timeout in seconds, 0-no response
-					 */
-	u8         rsvd2[3];
-	u32        rsp_maxlen;	/*  max response length expected */
-};
-
-struct bfa_fcxp_s {
-	struct list_head 	qe;		/*  fcxp queue element */
-	bfa_sm_t        sm;             /*  state machine */
-	void           	*caller;	/*  driver or fcs */
-	struct bfa_fcxp_mod_s *fcxp_mod;
-					/*  back pointer to fcxp mod */
-	u16        fcxp_tag;	/*  internal tag */
-	struct bfa_fcxp_req_info_s req_info;
-					/*  request info */
-	struct bfa_fcxp_rsp_info_s rsp_info;
-					/*  response info */
-	u8 	use_ireqbuf;	/*  use internal req buf */
-	u8         use_irspbuf;	/*  use internal rsp buf */
-	u32        nreq_sgles;	/*  num request SGLEs */
-	u32        nrsp_sgles;	/*  num response SGLEs */
-	struct list_head req_sgpg_q;	/*  SG pages for request buf */
-	struct list_head req_sgpg_wqe;	/*  wait queue for req SG page */
-	struct list_head rsp_sgpg_q;	/*  SG pages for response buf */
-	struct list_head rsp_sgpg_wqe;	/*  wait queue for rsp SG page */
-
-	bfa_fcxp_get_sgaddr_t req_sga_cbfn;
-					/*  SG elem addr user function */
-	bfa_fcxp_get_sglen_t req_sglen_cbfn;
-					/*  SG elem len user function */
-	bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
-					/*  SG elem addr user function */
-	bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
-					/*  SG elem len user function */
-	bfa_cb_fcxp_send_t send_cbfn;   /*  send completion callback */
-	void		*send_cbarg;	/*  callback arg */
-	struct bfa_sge_s   req_sge[BFA_FCXP_MAX_SGES];
-					/*  req SG elems */
-	struct bfa_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];
-					/*  rsp SG elems */
-	u8         rsp_status;	/*  comp: rsp status */
-	u32        rsp_len;	/*  comp: actual response len */
-	u32        residue_len;	/*  comp: residual rsp length */
-	struct fchs_s          rsp_fchs;	/*  comp: response fchs */
-	struct bfa_cb_qe_s    hcb_qe;	/*  comp: callback qelem */
-	struct bfa_reqq_wait_s	reqq_wqe;
-	bfa_boolean_t	reqq_waiting;
-};
-
-#define BFA_FCXP_REQ_PLD(_fcxp) 	(bfa_fcxp_get_reqbuf(_fcxp))
-
-#define BFA_FCXP_RSP_FCHS(_fcxp) 	(&((_fcxp)->rsp_info.fchs))
-#define BFA_FCXP_RSP_PLD(_fcxp) 	(bfa_fcxp_get_rspbuf(_fcxp))
-
-#define BFA_FCXP_REQ_PLD_PA(_fcxp)					\
-	((_fcxp)->fcxp_mod->req_pld_list_pa +				\
-		((_fcxp)->fcxp_mod->req_pld_sz  * (_fcxp)->fcxp_tag))
-
-#define BFA_FCXP_RSP_PLD_PA(_fcxp) 					\
-	((_fcxp)->fcxp_mod->rsp_pld_list_pa +				\
-		((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
-
-void	bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-#endif /* __BFA_FCXP_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_fwimg_priv.h b/drivers/scsi/bfa/bfa_fwimg_priv.h
deleted file mode 100644
index d33e19e..0000000
--- a/drivers/scsi/bfa/bfa_fwimg_priv.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_FWIMG_PRIV_H__
-#define __BFA_FWIMG_PRIV_H__
-
-#define	BFI_FLASH_CHUNK_SZ		256	/*  Flash chunk size */
-#define	BFI_FLASH_CHUNK_SZ_WORDS	(BFI_FLASH_CHUNK_SZ/sizeof(u32))
-
-/**
- * BFI FW image type
- */
-enum {
-	BFI_IMAGE_CB_FC,
-	BFI_IMAGE_CT_FC,
-	BFI_IMAGE_CT_CNA,
-	BFI_IMAGE_MAX,
-};
-
-extern u32 *bfi_image_get_chunk(int type, uint32_t off);
-extern u32 bfi_image_get_size(int type);
-extern u32 bfi_image_ct_fc_size;
-extern u32 bfi_image_ct_cna_size;
-extern u32 bfi_image_cb_fc_size;
-extern u32 *bfi_image_ct_fc;
-extern u32 *bfi_image_ct_cna;
-extern u32 *bfi_image_cb_fc;
-
-
-#endif /* __BFA_FWIMG_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c
index edfd729..c787d3a 100644
--- a/drivers/scsi/bfa/bfa_hw_cb.c
+++ b/drivers/scsi/bfa/bfa_hw_cb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,15 +15,15 @@
  * General Public License for more details.
  */
 
-#include <bfa_priv.h>
-#include <bfi/bfi_cbreg.h>
+#include "bfa_modules.h"
+#include "bfi_cbreg.h"
 
 void
 bfa_hwcb_reginit(struct bfa_s *bfa)
 {
 	struct bfa_iocfc_regs_s	*bfa_regs = &bfa->iocfc.bfa_regs;
 	bfa_os_addr_t		kva = bfa_ioc_bar0(&bfa->ioc);
-	int             	i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+	int			i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
 
 	if (fn == 0) {
 		bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c
index a357fb3..c97ebaf 100644
--- a/drivers/scsi/bfa/bfa_hw_ct.c
+++ b/drivers/scsi/bfa/bfa_hw_ct.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,9 +15,8 @@
  * General Public License for more details.
  */
 
-#include <bfa_priv.h>
-#include <bfi/bfi_ctreg.h>
-#include <bfa_ioc.h>
+#include "bfa_modules.h"
+#include "bfi_ctreg.h"
 
 BFA_TRC_FILE(HAL, IOCFC_CT);
 
@@ -53,7 +52,7 @@
 {
 	struct bfa_iocfc_regs_s	*bfa_regs = &bfa->iocfc.bfa_regs;
 	bfa_os_addr_t		kva = bfa_ioc_bar0(&bfa->ioc);
-	int             	i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
+	int			i, q, fn = bfa_ioc_pcifn(&bfa->ioc);
 
 	if (fn == 0) {
 		bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS);
@@ -87,7 +86,7 @@
 void
 bfa_hwct_reqq_ack(struct bfa_s *bfa, int reqq)
 {
-	u32 r32;
+	u32	r32;
 
 	r32 = bfa_reg_read(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq]);
 	bfa_reg_write(bfa->iocfc.bfa_regs.cpe_q_ctrl[reqq], r32);
diff --git a/drivers/scsi/bfa/bfa_intr.c b/drivers/scsi/bfa/bfa_intr.c
deleted file mode 100644
index 4936788..0000000
--- a/drivers/scsi/bfa/bfa_intr.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#include <bfa.h>
-#include <bfi/bfi_ctreg.h>
-#include <bfa_port_priv.h>
-#include <bfa_intr_priv.h>
-#include <cs/bfa_debug.h>
-
-BFA_TRC_FILE(HAL, INTR);
-
-static void
-bfa_msix_errint(struct bfa_s *bfa, u32 intr)
-{
-	bfa_ioc_error_isr(&bfa->ioc);
-}
-
-static void
-bfa_msix_lpu(struct bfa_s *bfa)
-{
-	bfa_ioc_mbox_isr(&bfa->ioc);
-}
-
-static void
-bfa_reqq_resume(struct bfa_s *bfa, int qid)
-{
-	struct list_head *waitq, *qe, *qen;
-	struct bfa_reqq_wait_s *wqe;
-
-	waitq = bfa_reqq(bfa, qid);
-	list_for_each_safe(qe, qen, waitq) {
-		/**
-		 * Callback only as long as there is room in request queue
-		 */
-		if (bfa_reqq_full(bfa, qid))
-			break;
-
-		list_del(qe);
-		wqe = (struct bfa_reqq_wait_s *) qe;
-		wqe->qresume(wqe->cbarg);
-	}
-}
-
-void
-bfa_msix_all(struct bfa_s *bfa, int vec)
-{
-	bfa_intx(bfa);
-}
-
-/**
- *  hal_intr_api
- */
-bfa_boolean_t
-bfa_intx(struct bfa_s *bfa)
-{
-	u32        intr, qintr;
-	int             queue;
-
-	intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
-	if (!intr)
-		return BFA_FALSE;
-
-	/**
-	 * RME completion queue interrupt
-	 */
-	qintr = intr & __HFN_INT_RME_MASK;
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
-
-	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
-		if (intr & (__HFN_INT_RME_Q0 << queue))
-			bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
-	}
-	intr &= ~qintr;
-	if (!intr)
-		return BFA_TRUE;
-
-	/**
-	 * CPE completion queue interrupt
-	 */
-	qintr = intr & __HFN_INT_CPE_MASK;
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr);
-
-	for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) {
-		if (intr & (__HFN_INT_CPE_Q0 << queue))
-			bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1));
-	}
-	intr &= ~qintr;
-	if (!intr)
-		return BFA_TRUE;
-
-	bfa_msix_lpu_err(bfa, intr);
-
-	return BFA_TRUE;
-}
-
-void
-bfa_isr_enable(struct bfa_s *bfa)
-{
-	u32        intr_unmask;
-	int             pci_func = bfa_ioc_pcifn(&bfa->ioc);
-
-	bfa_trc(bfa, pci_func);
-
-	bfa_msix_install(bfa);
-	intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
-		       __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS |
-		       __HFN_INT_LL_HALT);
-
-	if (pci_func == 0)
-		intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 |
-				__HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 |
-				__HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 |
-				__HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 |
-				__HFN_INT_MBOX_LPU0);
-	else
-		intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 |
-				__HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 |
-				__HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 |
-				__HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 |
-				__HFN_INT_MBOX_LPU1);
-
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask);
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask);
-	bfa->iocfc.intr_mask = ~intr_unmask;
-	bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0);
-}
-
-void
-bfa_isr_disable(struct bfa_s *bfa)
-{
-	bfa_isr_mode_set(bfa, BFA_FALSE);
-	bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L);
-	bfa_msix_uninstall(bfa);
-}
-
-void
-bfa_msix_reqq(struct bfa_s *bfa, int qid)
-{
-	struct list_head *waitq;
-
-	qid &= (BFI_IOC_MAX_CQS - 1);
-
-	bfa->iocfc.hwif.hw_reqq_ack(bfa, qid);
-
-	/**
-	 * Resume any pending requests in the corresponding reqq.
-	 */
-	waitq = bfa_reqq(bfa, qid);
-	if (!list_empty(waitq))
-		bfa_reqq_resume(bfa, qid);
-}
-
-void
-bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	bfa_trc(bfa, m->mhdr.msg_class);
-	bfa_trc(bfa, m->mhdr.msg_id);
-	bfa_trc(bfa, m->mhdr.mtag.i2htok);
-	bfa_assert(0);
-	bfa_trc_stop(bfa->trcmod);
-}
-
-void
-bfa_msix_rspq(struct bfa_s *bfa, int qid)
-{
-	struct bfi_msg_s *m;
-	u32 pi, ci;
-	struct list_head *waitq;
-
-	bfa_trc_fp(bfa, qid);
-
-	qid &= (BFI_IOC_MAX_CQS - 1);
-
-	bfa->iocfc.hwif.hw_rspq_ack(bfa, qid);
-
-	ci = bfa_rspq_ci(bfa, qid);
-	pi = bfa_rspq_pi(bfa, qid);
-
-	bfa_trc_fp(bfa, ci);
-	bfa_trc_fp(bfa, pi);
-
-	if (bfa->rme_process) {
-		while (ci != pi) {
-			m = bfa_rspq_elem(bfa, qid, ci);
-			bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX);
-
-			bfa_isrs[m->mhdr.msg_class] (bfa, m);
-
-			CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems);
-		}
-	}
-
-	/**
-	 * update CI
-	 */
-	bfa_rspq_ci(bfa, qid) = pi;
-	bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[qid], pi);
-	bfa_os_mmiowb();
-
-	/**
-	 * Resume any pending requests in the corresponding reqq.
-	 */
-	waitq = bfa_reqq(bfa, qid);
-	if (!list_empty(waitq))
-		bfa_reqq_resume(bfa, qid);
-}
-
-void
-bfa_msix_lpu_err(struct bfa_s *bfa, int vec)
-{
-	u32 intr, curr_value;
-
-	intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status);
-
-	if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1))
-		bfa_msix_lpu(bfa);
-
-	intr &= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 |
-		__HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS | __HFN_INT_LL_HALT);
-
-	if (intr) {
-		if (intr & __HFN_INT_LL_HALT) {
-			/**
-			 * If LL_HALT bit is set then FW Init Halt LL Port
-			 * Register needs to be cleared as well so Interrupt
-			 * Status Register will be cleared.
-			 */
-			curr_value = bfa_reg_read(bfa->ioc.ioc_regs.ll_halt);
-			curr_value &= ~__FW_INIT_HALT_P;
-			bfa_reg_write(bfa->ioc.ioc_regs.ll_halt, curr_value);
-		}
-
-		if (intr & __HFN_INT_ERR_PSS) {
-			/**
-			 * ERR_PSS bit needs to be cleared as well in case
-			 * interrups are shared so driver's interrupt handler is
-			 * still called eventhough it is already masked out.
-			 */
-			curr_value = bfa_reg_read(
-				bfa->ioc.ioc_regs.pss_err_status_reg);
-			curr_value &= __PSS_ERR_STATUS_SET;
-			bfa_reg_write(bfa->ioc.ioc_regs.pss_err_status_reg,
-				curr_value);
-		}
-
-		bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr);
-		bfa_msix_errint(bfa, intr);
-	}
-}
-
-void
-bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func)
-{
-	bfa_isrs[mc] = isr_func;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_intr_priv.h b/drivers/scsi/bfa/bfa_intr_priv.h
deleted file mode 100644
index 5fc301c..0000000
--- a/drivers/scsi/bfa/bfa_intr_priv.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_INTR_PRIV_H__
-#define __BFA_INTR_PRIV_H__
-
-/**
- * Message handler
- */
-typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
-void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m);
-void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func);
-
-
-#define bfa_reqq_pi(__bfa, __reqq)	((__bfa)->iocfc.req_cq_pi[__reqq])
-#define bfa_reqq_ci(__bfa, __reqq)					\
-	(*(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva))
-
-#define bfa_reqq_full(__bfa, __reqq)				\
-	(((bfa_reqq_pi(__bfa, __reqq) + 1) &			\
-	  ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) ==	\
-	 bfa_reqq_ci(__bfa, __reqq))
-
-#define bfa_reqq_next(__bfa, __reqq)				\
-	(bfa_reqq_full(__bfa, __reqq) ? NULL :			\
-	 ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \
-			  + bfa_reqq_pi((__bfa), (__reqq)))))
-
-#define bfa_reqq_produce(__bfa, __reqq)	do {				\
-	(__bfa)->iocfc.req_cq_pi[__reqq]++;				\
-	(__bfa)->iocfc.req_cq_pi[__reqq] &=				\
-		((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1);      \
-	bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq],		\
-				(__bfa)->iocfc.req_cq_pi[__reqq]);      \
-	bfa_os_mmiowb();      \
-} while (0)
-
-#define bfa_rspq_pi(__bfa, __rspq)					\
-	(*(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva))
-
-#define bfa_rspq_ci(__bfa, __rspq)	((__bfa)->iocfc.rsp_cq_ci[__rspq])
-#define bfa_rspq_elem(__bfa, __rspq, __ci)				\
-	(&((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci])
-
-#define CQ_INCR(__index, __size) do {					\
-			(__index)++;					\
-			(__index) &= ((__size) - 1);      \
-} while (0)
-
-/**
- * Queue element to wait for room in request queue. FIFO order is
- * maintained when fullfilling requests.
- */
-struct bfa_reqq_wait_s {
-	struct list_head 	qe;
-	void		(*qresume) (void *cbarg);
-	void		*cbarg;
-};
-
-/**
- * Circular queue usage assignments
- */
-enum {
-	BFA_REQQ_IOC	= 0,	/*  all low-priority IOC msgs	*/
-	BFA_REQQ_FCXP	= 0,	/*  all FCXP messages		*/
-	BFA_REQQ_LPS	= 0,	/*  all lport service msgs	*/
-	BFA_REQQ_PORT	= 0,	/*  all port messages		*/
-	BFA_REQQ_FLASH	= 0,	/*  for flash module		*/
-	BFA_REQQ_DIAG	= 0,	/*  for diag module		*/
-	BFA_REQQ_RPORT	= 0,	/*  all port messages		*/
-	BFA_REQQ_SBOOT	= 0,	/*  all san boot messages	*/
-	BFA_REQQ_QOS_LO	= 1,	/*  all low priority IO	*/
-	BFA_REQQ_QOS_MD	= 2,	/*  all medium priority IO	*/
-	BFA_REQQ_QOS_HI	= 3,	/*  all high priority IO	*/
-};
-
-static inline void
-bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg),
-			void *cbarg)
-{
-	wqe->qresume = qresume;
-	wqe->cbarg = cbarg;
-}
-
-#define bfa_reqq(__bfa, __reqq)	(&(__bfa)->reqq_waitq[__reqq])
-
-/**
- * static inline void
- * bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe)
- */
-#define bfa_reqq_wait(__bfa, __reqq, __wqe) do {			\
-									\
-		struct list_head *waitq = bfa_reqq(__bfa, __reqq);      \
-									\
-		bfa_assert(((__reqq) < BFI_IOC_MAX_CQS));      \
-		bfa_assert((__wqe)->qresume && (__wqe)->cbarg);      \
-									\
-		list_add_tail(&(__wqe)->qe, waitq);      \
-} while (0)
-
-#define bfa_reqq_wcancel(__wqe)	list_del(&(__wqe)->qe)
-
-#endif /* __BFA_INTR_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 8e78f20..6795b24 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,35 +15,33 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <bfa_ioc.h>
-#include <bfa_fwimg_priv.h>
-#include <cna/bfa_cna_trcmod.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_ctreg.h>
-#include <aen/bfa_aen_ioc.h>
-#include <aen/bfa_aen.h>
-#include <log/bfa_log_hal.h>
-#include <defs/bfa_defs_pci.h>
+#include "bfa_ioc.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
+#include "bfa_defs_svc.h"
+#include "bfad_drv.h"
 
 BFA_TRC_FILE(CNA, IOC);
 
 /**
  * IOC local definitions
  */
-#define BFA_IOC_TOV		2000	/* msecs */
-#define BFA_IOC_HWSEM_TOV       500     /* msecs */
-#define BFA_IOC_HB_TOV          500     /* msecs */
-#define BFA_IOC_HWINIT_MAX      2
-#define BFA_IOC_FWIMG_MINSZ     (16 * 1024)
-#define BFA_IOC_TOV_RECOVER      BFA_IOC_HB_TOV
+#define BFA_IOC_TOV		3000	/* msecs */
+#define BFA_IOC_HWSEM_TOV	500	/* msecs */
+#define BFA_IOC_HB_TOV		500	/* msecs */
+#define BFA_IOC_HWINIT_MAX	2
+#define BFA_IOC_TOV_RECOVER	 BFA_IOC_HB_TOV
 
 #define bfa_ioc_timer_start(__ioc)					\
 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
 			bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
 #define bfa_ioc_timer_stop(__ioc)   bfa_timer_stop(&(__ioc)->ioc_timer)
 
+#define bfa_hb_timer_start(__ioc)					\
+	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->hb_timer,		\
+			bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)
+#define bfa_hb_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->hb_timer)
+
 #define BFA_DBG_FWTRC_ENTS	(BFI_IOC_TRC_ENTS)
 #define BFA_DBG_FWTRC_LEN					\
 	(BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) +	\
@@ -55,100 +53,226 @@
  * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
  */
 
-#define bfa_ioc_firmware_lock(__ioc)                    \
+#define bfa_ioc_firmware_lock(__ioc)			\
 			((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
-#define bfa_ioc_firmware_unlock(__ioc)                  \
+#define bfa_ioc_firmware_unlock(__ioc)			\
 			((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
 #define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
 #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
-#define bfa_ioc_notify_hbfail(__ioc)                    \
+#define bfa_ioc_notify_hbfail(__ioc)			\
 			((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
-#define bfa_ioc_is_optrom(__ioc)        \
-	(bfi_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
 
-bfa_boolean_t   bfa_auto_recover = BFA_TRUE;
+#ifdef BFA_IOC_IS_UEFI
+#define bfa_ioc_is_bios_optrom(__ioc) (0)
+#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI
+#else
+#define bfa_ioc_is_bios_optrom(__ioc)	\
+	(bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
+#define bfa_ioc_is_uefi(__ioc) (0)
+#endif
+
+#define bfa_ioc_mbox_cmd_pending(__ioc)		\
+			(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
+			bfa_reg_read((__ioc)->ioc_regs.hfn_mbox_cmd))
+
+bfa_boolean_t bfa_auto_recover = BFA_TRUE;
 
 /*
  * forward declarations
  */
-static void     bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
-static void     bfa_ioc_timeout(void *ioc);
-static void     bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
-static void     bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_recover(struct bfa_ioc_s *ioc);
-static void	bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
-static void     bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void bfa_ioc_timeout(void *ioc);
+static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
+static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
+static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
+static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
+static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
+static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
+static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
+static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
+static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
+static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
+static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_failed(struct bfa_ioc_s *ioc);
+static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
 
 /**
- *  bfa_ioc_sm
+ *  hal_ioc_sm
  */
 
 /**
- * IOC state machine events
+ * IOC state machine definitions/declarations
  */
 enum ioc_event {
-	IOC_E_ENABLE = 1,	/*  IOC enable request */
-	IOC_E_DISABLE = 2,	/*  IOC disable request */
-	IOC_E_TIMEOUT = 3,	/*  f/w response timeout */
-	IOC_E_FWREADY = 4,	/*  f/w initialization done */
-	IOC_E_FWRSP_GETATTR = 5,	/*  IOC get attribute response */
-	IOC_E_FWRSP_ENABLE = 6,	/*  enable f/w response */
-	IOC_E_FWRSP_DISABLE = 7,	/*  disable f/w response */
-	IOC_E_HBFAIL = 8,	/*  heartbeat failure */
-	IOC_E_HWERROR = 9,	/*  hardware error interrupt */
-	IOC_E_SEMLOCKED = 10,	/*  h/w semaphore is locked */
-	IOC_E_DETACH = 11,	/*  driver detach cleanup */
+	IOC_E_RESET		= 1,	/*  IOC reset request		*/
+	IOC_E_ENABLE		= 2,	/*  IOC enable request		*/
+	IOC_E_DISABLE		= 3,	/*  IOC disable request	*/
+	IOC_E_DETACH		= 4,	/*  driver detach cleanup	*/
+	IOC_E_ENABLED		= 5,	/*  f/w enabled		*/
+	IOC_E_FWRSP_GETATTR	= 6,	/*  IOC get attribute response	*/
+	IOC_E_DISABLED		= 7,	/*  f/w disabled		*/
+	IOC_E_FAILED		= 8,	/*  failure notice by iocpf sm	*/
+	IOC_E_HBFAIL		= 9,	/*  heartbeat failure		*/
+	IOC_E_HWERROR		= 10,	/*  hardware error interrupt	*/
+	IOC_E_TIMEOUT		= 11,	/*  timeout			*/
 };
 
+bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
-bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc_s, enum ioc_event);
+bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
 
 static struct bfa_sm_table_s ioc_sm_table[] = {
+	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
 	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
-	{BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
-	{BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
-	{BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
-	{BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
-	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
+	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
 	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
 	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
 	{BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
-	{BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
+	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
 	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
 	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
 };
 
 /**
+ * IOCPF state machine definitions/declarations
+ */
+
+#define bfa_iocpf_timer_start(__ioc)					\
+	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
+			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
+#define bfa_iocpf_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->ioc_timer)
+
+#define bfa_iocpf_recovery_timer_start(__ioc)				\
+	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
+			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER)
+
+#define bfa_sem_timer_start(__ioc)					\
+	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer,	\
+			bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)
+#define bfa_sem_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->sem_timer)
+
+/*
+ * Forward declareations for iocpf state machine
+ */
+static void bfa_iocpf_enable(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_disable(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_fail(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_initfail(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_stop(struct bfa_ioc_s *ioc);
+static void bfa_iocpf_timeout(void *ioc_arg);
+static void bfa_iocpf_sem_timeout(void *ioc_arg);
+
+/**
+ * IOCPF state machine events
+ */
+enum iocpf_event {
+	IOCPF_E_ENABLE		= 1,	/*  IOCPF enable request	*/
+	IOCPF_E_DISABLE		= 2,	/*  IOCPF disable request	*/
+	IOCPF_E_STOP		= 3,	/*  stop on driver detach	*/
+	IOCPF_E_FWREADY		= 4,	/*  f/w initialization done	*/
+	IOCPF_E_FWRSP_ENABLE	= 5,	/*  enable f/w response	*/
+	IOCPF_E_FWRSP_DISABLE	= 6,	/*  disable f/w response	*/
+	IOCPF_E_FAIL		= 7,	/*  failure notice by ioc sm	*/
+	IOCPF_E_INITFAIL	= 8,	/*  init fail notice by ioc sm	*/
+	IOCPF_E_GETATTRFAIL	= 9,	/*  init fail notice by ioc sm	*/
+	IOCPF_E_SEMLOCKED	= 10,	/*  h/w semaphore is locked	*/
+	IOCPF_E_TIMEOUT		= 11,	/*  f/w response timeout	*/
+};
+
+/**
+ * IOCPF states
+ */
+enum bfa_iocpf_state {
+	BFA_IOCPF_RESET		= 1,	/*  IOC is in reset state */
+	BFA_IOCPF_SEMWAIT	= 2,	/*  Waiting for IOC h/w semaphore */
+	BFA_IOCPF_HWINIT	= 3,	/*  IOC h/w is being initialized */
+	BFA_IOCPF_READY		= 4,	/*  IOCPF is initialized */
+	BFA_IOCPF_INITFAIL	= 5,	/*  IOCPF failed */
+	BFA_IOCPF_FAIL		= 6,	/*  IOCPF failed */
+	BFA_IOCPF_DISABLING	= 7,	/*  IOCPF is being disabled */
+	BFA_IOCPF_DISABLED	= 8,	/*  IOCPF is disabled */
+	BFA_IOCPF_FWMISMATCH	= 9,	/*  IOC f/w different from drivers */
+};
+
+bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
+bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
+
+static struct bfa_sm_table_s iocpf_sm_table[] = {
+	{BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
+	{BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
+	{BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
+	{BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
+	{BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
+	{BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
+	{BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
+	{BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
+	{BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
+	{BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
+	{BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
+};
+
+/**
+ * IOC State Machine
+ */
+
+/**
+ * Beginning state. IOC uninit state.
+ */
+
+static void
+bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)
+{
+}
+
+/**
+ * IOC is in uninit state.
+ */
+static void
+bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)
+{
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOC_E_RESET:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+/**
  * Reset entry actions -- initialize state machine
  */
 static void
 bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
 {
-	ioc->retry_count = 0;
-	ioc->auto_recover = bfa_auto_recover;
+	bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
 }
 
 /**
- * Beginning state. IOC is in reset state.
+ * IOC is in reset state.
  */
 static void
 bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
@@ -157,195 +281,15 @@
 
 	switch (event) {
 	case IOC_E_ENABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_disable_comp(ioc);
-		break;
-
-	case IOC_E_DETACH:
-		break;
-
-	default:
-		bfa_sm_fault(ioc, event);
-	}
-}
-
-/**
- * Semaphore should be acquired for version check.
- */
-static void
-bfa_ioc_sm_fwcheck_entry(struct bfa_ioc_s *ioc)
-{
-	bfa_ioc_hw_sem_get(ioc);
-}
-
-/**
- * Awaiting h/w semaphore to continue with version check.
- */
-static void
-bfa_ioc_sm_fwcheck(struct bfa_ioc_s *ioc, enum ioc_event event)
-{
-	bfa_trc(ioc, event);
-
-	switch (event) {
-	case IOC_E_SEMLOCKED:
-		if (bfa_ioc_firmware_lock(ioc)) {
-			ioc->retry_count = 0;
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
-		} else {
-			bfa_ioc_hw_sem_release(ioc);
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
-		}
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_disable_comp(ioc);
-		/*
-		 * fall through
-		 */
-
-	case IOC_E_DETACH:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
-		break;
-
-	case IOC_E_FWREADY:
-		break;
-
-	default:
-		bfa_sm_fault(ioc, event);
-	}
-}
-
-/**
- * Notify enable completion callback and generate mismatch AEN.
- */
-static void
-bfa_ioc_sm_mismatch_entry(struct bfa_ioc_s *ioc)
-{
-	/**
-	 * Provide enable completion callback and AEN notification only once.
-	 */
-	if (ioc->retry_count == 0) {
-		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-		bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);
-	}
-	ioc->retry_count++;
-	bfa_ioc_timer_start(ioc);
-}
-
-/**
- * Awaiting firmware version match.
- */
-static void
-bfa_ioc_sm_mismatch(struct bfa_ioc_s *ioc, enum ioc_event event)
-{
-	bfa_trc(ioc, event);
-
-	switch (event) {
-	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_disable_comp(ioc);
-		/*
-		 * fall through
-		 */
-
-	case IOC_E_DETACH:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
-		break;
-
-	case IOC_E_FWREADY:
-		break;
-
-	default:
-		bfa_sm_fault(ioc, event);
-	}
-}
-
-/**
- * Request for semaphore.
- */
-static void
-bfa_ioc_sm_semwait_entry(struct bfa_ioc_s *ioc)
-{
-	bfa_ioc_hw_sem_get(ioc);
-}
-
-/**
- * Awaiting semaphore for h/w initialzation.
- */
-static void
-bfa_ioc_sm_semwait(struct bfa_ioc_s *ioc, enum ioc_event event)
-{
-	bfa_trc(ioc, event);
-
-	switch (event) {
-	case IOC_E_SEMLOCKED:
-		ioc->retry_count = 0;
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
-		break;
-
-	case IOC_E_DISABLE:
-		bfa_ioc_hw_sem_get_cancel(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
-		break;
-
-	default:
-		bfa_sm_fault(ioc, event);
-	}
-}
-
-
-static void
-bfa_ioc_sm_hwinit_entry(struct bfa_ioc_s *ioc)
-{
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_reset(ioc, BFA_FALSE);
-}
-
-/**
- * Hardware is being initialized. Interrupts are enabled.
- * Holding hardware semaphore lock.
- */
-static void
-bfa_ioc_sm_hwinit(struct bfa_ioc_s *ioc, enum ioc_event event)
-{
-	bfa_trc(ioc, event);
-
-	switch (event) {
-	case IOC_E_FWREADY:
-		bfa_ioc_timer_stop(ioc);
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
 		break;
 
-	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
-		/*
-		 * fall through
-		 */
-
-	case IOC_E_TIMEOUT:
-		ioc->retry_count++;
-		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
-			bfa_ioc_timer_start(ioc);
-			bfa_ioc_reset(ioc, BFA_TRUE);
-			break;
-		}
-
-		bfa_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+	case IOC_E_DISABLE:
+		bfa_ioc_disable_comp(ioc);
 		break;
 
-	case IOC_E_DISABLE:
-		bfa_ioc_hw_sem_release(ioc);
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
 		break;
 
 	default:
@@ -357,8 +301,7 @@
 static void
 bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
 {
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_send_enable(ioc);
+	bfa_iocpf_enable(ioc);
 }
 
 /**
@@ -371,39 +314,29 @@
 	bfa_trc(ioc, event);
 
 	switch (event) {
-	case IOC_E_FWRSP_ENABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_ioc_hw_sem_release(ioc);
+	case IOC_E_ENABLED:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
 		break;
 
-	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
-		/*
-		 * fall through
-		 */
-
-	case IOC_E_TIMEOUT:
-		ioc->retry_count++;
-		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
-			bfa_reg_write(ioc->ioc_regs.ioc_fwstate,
-				      BFI_IOC_UNINIT);
-			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
-			break;
-		}
-
-		bfa_ioc_hw_sem_release(ioc);
+	case IOC_E_FAILED:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
 		break;
 
-	case IOC_E_DISABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_ioc_hw_sem_release(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+	case IOC_E_HWERROR:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		bfa_iocpf_initfail(ioc);
 		break;
 
-	case IOC_E_FWREADY:
-		bfa_ioc_send_enable(ioc);
+	case IOC_E_DISABLE:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_DETACH:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
+		break;
+
+	case IOC_E_ENABLE:
 		break;
 
 	default:
@@ -434,19 +367,26 @@
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
 		break;
 
+	case IOC_E_FAILED:
+		bfa_ioc_timer_stop(ioc);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		break;
+
 	case IOC_E_HWERROR:
 		bfa_ioc_timer_stop(ioc);
-		/*
-		 * fall through
-		 */
+		/* fall through */
 
 	case IOC_E_TIMEOUT:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
+		bfa_iocpf_getattrfail(ioc);
 		break;
 
 	case IOC_E_DISABLE:
 		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
+		break;
+
+	case IOC_E_ENABLE:
 		break;
 
 	default:
@@ -458,9 +398,11 @@
 static void
 bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
 {
+	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+
 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
 	bfa_ioc_hb_monitor(ioc);
-	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);
+	BFA_LOG(KERN_INFO, bfad, log_level, "IOC enabled\n");
 }
 
 static void
@@ -477,19 +419,18 @@
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
 
-	case IOC_E_HWERROR:
-	case IOC_E_FWREADY:
-		/**
-		 * Hard error or IOC recovery by other function.
-		 * Treat it same as heartbeat failure.
-		 */
+	case IOC_E_FAILED:
 		bfa_ioc_hb_stop(ioc);
-		/*
-		 * !!! fall through !!!
-		 */
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+		break;
+
+	case IOC_E_HWERROR:
+		bfa_ioc_hb_stop(ioc);
+		/* !!! fall through !!! */
 
 	case IOC_E_HBFAIL:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
+		bfa_iocpf_fail(ioc);
 		break;
 
 	default:
@@ -501,9 +442,9 @@
 static void
 bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
 {
-	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);
-	bfa_ioc_timer_start(ioc);
-	bfa_ioc_send_disable(ioc);
+	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+	bfa_iocpf_disable(ioc);
+	BFA_LOG(KERN_INFO, bfad, log_level, "IOC disabled\n");
 }
 
 /**
@@ -515,20 +456,17 @@
 	bfa_trc(ioc, event);
 
 	switch (event) {
-	case IOC_E_FWRSP_DISABLE:
-		bfa_ioc_timer_stop(ioc);
+	case IOC_E_DISABLED:
 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
 		break;
 
 	case IOC_E_HWERROR:
-		bfa_ioc_timer_stop(ioc);
 		/*
-		 * !!! fall through !!!
+		 * No state change.  Will move to disabled state
+		 * after iocpf sm completes failure processing and
+		 * moves to disabled state.
 		 */
-
-	case IOC_E_TIMEOUT:
-		bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		bfa_iocpf_fail(ioc);
 		break;
 
 	default:
@@ -552,19 +490,16 @@
 
 	switch (event) {
 	case IOC_E_ENABLE:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
 		break;
 
 	case IOC_E_DISABLE:
 		ioc->cbfn->disable_cbfn(ioc->bfa);
 		break;
 
-	case IOC_E_FWREADY:
-		break;
-
 	case IOC_E_DETACH:
-		bfa_ioc_firmware_unlock(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
 		break;
 
 	default:
@@ -577,7 +512,6 @@
 bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
 {
 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-	bfa_ioc_timer_start(ioc);
 }
 
 /**
@@ -589,19 +523,24 @@
 	bfa_trc(ioc, event);
 
 	switch (event) {
+	case IOC_E_ENABLED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+		break;
+
+	case IOC_E_FAILED:
+		/**
+		 * Initialization failure during iocpf init retry.
+		 */
+		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+		break;
+
 	case IOC_E_DISABLE:
-		bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
 
 	case IOC_E_DETACH:
-		bfa_ioc_timer_stop(ioc);
-		bfa_ioc_firmware_unlock(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
-		break;
-
-	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+		bfa_iocpf_stop(ioc);
 		break;
 
 	default:
@@ -611,74 +550,50 @@
 
 
 static void
-bfa_ioc_sm_hbfail_entry(struct bfa_ioc_s *ioc)
+bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
 {
-	struct list_head *qe;
-	struct bfa_ioc_hbfail_notify_s *notify;
-
-	/**
-	 * Mark IOC as failed in hardware and stop firmware.
-	 */
-	bfa_ioc_lpu_stop(ioc);
-	bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
-
-	/**
-	 * Notify other functions on HB failure.
-	 */
-	bfa_ioc_notify_hbfail(ioc);
+	struct list_head			*qe;
+	struct bfa_ioc_hbfail_notify_s	*notify;
+	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
 
 	/**
 	 * Notify driver and common modules registered for notification.
 	 */
 	ioc->cbfn->hbfail_cbfn(ioc->bfa);
 	list_for_each(qe, &ioc->hb_notify_q) {
-		notify = (struct bfa_ioc_hbfail_notify_s *)qe;
+		notify = (struct bfa_ioc_hbfail_notify_s *) qe;
 		notify->cbfn(notify->cbarg);
 	}
 
-	/**
-	 * Flush any queued up mailbox requests.
-	 */
-	bfa_ioc_mbox_hbfail(ioc);
-	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL);
-
-	/**
-	 * Trigger auto-recovery after a delay.
-	 */
-	if (ioc->auto_recover) {
-		bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer,
-				bfa_ioc_timeout, ioc, BFA_IOC_TOV_RECOVER);
-	}
+	BFA_LOG(KERN_CRIT, bfad, log_level,
+		"Heart Beat of IOC has failed\n");
 }
 
 /**
- * IOC heartbeat failure.
+ * IOC failure.
  */
 static void
-bfa_ioc_sm_hbfail(struct bfa_ioc_s *ioc, enum ioc_event event)
+bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
 {
 	bfa_trc(ioc, event);
 
 	switch (event) {
 
+	case IOC_E_FAILED:
+		/**
+		 * Initialization failure during iocpf recovery.
+		 * !!! Fall through !!!
+		 */
 	case IOC_E_ENABLE:
 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
 		break;
 
+	case IOC_E_ENABLED:
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
+		break;
+
 	case IOC_E_DISABLE:
-		if (ioc->auto_recover)
-			bfa_ioc_timer_stop(ioc);
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
-		break;
-
-	case IOC_E_TIMEOUT:
-		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
-		break;
-
-	case IOC_E_FWREADY:
-		/**
-		 * Recovery is already initiated by other function.
-		 */
+		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
 		break;
 
 	case IOC_E_HWERROR:
@@ -686,6 +601,498 @@
 		 * HB failure notification, ignore.
 		 */
 		break;
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+
+/**
+ * IOCPF State Machine
+ */
+
+
+/**
+ * Reset entry actions -- initialize state machine
+ */
+static void
+bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
+{
+	iocpf->retry_count = 0;
+	iocpf->auto_recover = bfa_auto_recover;
+}
+
+/**
+ * Beginning state. IOC is in reset state.
+ */
+static void
+bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_ENABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
+		break;
+
+	case IOCPF_E_STOP:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Semaphore should be acquired for version check.
+ */
+static void
+bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/**
+ * Awaiting h/w semaphore to continue with version check.
+ */
+static void
+bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_SEMLOCKED:
+		if (bfa_ioc_firmware_lock(ioc)) {
+			iocpf->retry_count = 0;
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+		} else {
+			bfa_ioc_hw_sem_release(ioc);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
+		}
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		bfa_ioc_pf_disabled(ioc);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Notify enable completion callback.
+ */
+static void
+bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
+{
+	/*
+	 * Call only the first time sm enters fwmismatch state.
+	 */
+	if (iocpf->retry_count == 0)
+		bfa_ioc_pf_fwmismatch(iocpf->ioc);
+
+	iocpf->retry_count++;
+	bfa_iocpf_timer_start(iocpf->ioc);
+}
+
+/**
+ * Awaiting firmware version match.
+ */
+static void
+bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_TIMEOUT:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		bfa_ioc_pf_disabled(ioc);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * Request for semaphore.
+ */
+static void
+bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_hw_sem_get(iocpf->ioc);
+}
+
+/**
+ * Awaiting semaphore for h/w initialzation.
+ */
+static void
+bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_SEMLOCKED:
+		iocpf->retry_count = 0;
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_get_cancel(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_iocpf_timer_start(iocpf->ioc);
+	bfa_ioc_reset(iocpf->ioc, BFA_FALSE);
+}
+
+/**
+ * Hardware is being initialized. Interrupts are enabled.
+ * Holding hardware semaphore lock.
+ */
+static void
+bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_FWREADY:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
+		break;
+
+	case IOCPF_E_INITFAIL:
+		bfa_iocpf_timer_stop(ioc);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOCPF_E_TIMEOUT:
+		iocpf->retry_count++;
+		if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
+			bfa_iocpf_timer_start(ioc);
+			bfa_ioc_reset(ioc, BFA_TRUE);
+			break;
+		}
+
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+
+		if (event == IOCPF_E_TIMEOUT)
+			bfa_ioc_pf_failed(ioc);
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_iocpf_timer_start(iocpf->ioc);
+	bfa_ioc_send_enable(iocpf->ioc);
+}
+
+/**
+ * Host IOC function is being enabled, awaiting response from firmware.
+ * Semaphore is acquired.
+ */
+static void
+bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_FWRSP_ENABLE:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
+		break;
+
+	case IOCPF_E_INITFAIL:
+		bfa_iocpf_timer_stop(ioc);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOCPF_E_TIMEOUT:
+		iocpf->retry_count++;
+		if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
+			bfa_reg_write(ioc->ioc_regs.ioc_fwstate,
+				      BFI_IOC_UNINIT);
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
+			break;
+		}
+
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+
+		if (event == IOCPF_E_TIMEOUT)
+			bfa_ioc_pf_failed(ioc);
+		break;
+
+	case IOCPF_E_DISABLE:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_ioc_hw_sem_release(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
+		break;
+
+	case IOCPF_E_FWREADY:
+		bfa_ioc_send_enable(ioc);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+
+static void
+bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_pf_enabled(iocpf->ioc);
+}
+
+static void
+bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_DISABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
+		break;
+
+	case IOCPF_E_GETATTRFAIL:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+		break;
+
+	case IOCPF_E_FAIL:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		break;
+
+	case IOCPF_E_FWREADY:
+		if (bfa_ioc_is_operational(ioc))
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
+		else
+			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
+
+		bfa_ioc_pf_failed(ioc);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_iocpf_timer_start(iocpf->ioc);
+	bfa_ioc_send_disable(iocpf->ioc);
+}
+
+/**
+ * IOC is being disabled
+ */
+static void
+bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_FWRSP_DISABLE:
+	case IOCPF_E_FWREADY:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	case IOCPF_E_FAIL:
+		bfa_iocpf_timer_stop(ioc);
+		/*
+		 * !!! fall through !!!
+		 */
+
+	case IOCPF_E_TIMEOUT:
+		bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	case IOCPF_E_FWRSP_ENABLE:
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+/**
+ * IOC disable completion entry.
+ */
+static void
+bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_ioc_pf_disabled(iocpf->ioc);
+}
+
+static void
+bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_ENABLE:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
+{
+	bfa_iocpf_timer_start(iocpf->ioc);
+}
+
+/**
+ * Hardware initialization failed.
+ */
+static void
+bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_DISABLE:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	case IOCPF_E_STOP:
+		bfa_iocpf_timer_stop(ioc);
+		bfa_ioc_firmware_unlock(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
+		break;
+
+	case IOCPF_E_TIMEOUT:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+		break;
+
+	default:
+		bfa_sm_fault(ioc, event);
+	}
+}
+
+
+static void
+bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
+{
+	/**
+	 * Mark IOC as failed in hardware and stop firmware.
+	 */
+	bfa_ioc_lpu_stop(iocpf->ioc);
+	bfa_reg_write(iocpf->ioc->ioc_regs.ioc_fwstate, BFI_IOC_FAIL);
+
+	/**
+	 * Notify other functions on HB failure.
+	 */
+	bfa_ioc_notify_hbfail(iocpf->ioc);
+
+	/**
+	 * Flush any queued up mailbox requests.
+	 */
+	bfa_ioc_mbox_hbfail(iocpf->ioc);
+
+	if (iocpf->auto_recover)
+		bfa_iocpf_recovery_timer_start(iocpf->ioc);
+}
+
+/**
+ * IOC is in failed state.
+ */
+static void
+bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
+{
+	struct bfa_ioc_s *ioc = iocpf->ioc;
+
+	bfa_trc(ioc, event);
+
+	switch (event) {
+	case IOCPF_E_DISABLE:
+		if (iocpf->auto_recover)
+			bfa_iocpf_timer_stop(ioc);
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
+		break;
+
+	case IOCPF_E_TIMEOUT:
+		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
+		break;
 
 	default:
 		bfa_sm_fault(ioc, event);
@@ -695,14 +1102,14 @@
 
 
 /**
- *  bfa_ioc_pvt BFA IOC private functions
+ *  hal_ioc_pvt BFA IOC private functions
  */
 
 static void
 bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
 {
-	struct list_head *qe;
-	struct bfa_ioc_hbfail_notify_s *notify;
+	struct list_head			*qe;
+	struct bfa_ioc_hbfail_notify_s	*notify;
 
 	ioc->cbfn->disable_cbfn(ioc->bfa);
 
@@ -710,25 +1117,17 @@
 	 * Notify common modules registered for notification.
 	 */
 	list_for_each(qe, &ioc->hb_notify_q) {
-		notify = (struct bfa_ioc_hbfail_notify_s *)qe;
+		notify = (struct bfa_ioc_hbfail_notify_s *) qe;
 		notify->cbfn(notify->cbarg);
 	}
 }
 
-void
-bfa_ioc_sem_timeout(void *ioc_arg)
-{
-	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
-
-	bfa_ioc_hw_sem_get(ioc);
-}
-
 bfa_boolean_t
 bfa_ioc_sem_get(bfa_os_addr_t sem_reg)
 {
 	u32 r32;
 	int cnt = 0;
-#define BFA_SEM_SPINCNT 3000
+#define BFA_SEM_SPINCNT	3000
 
 	r32 = bfa_reg_read(sem_reg);
 
@@ -754,7 +1153,7 @@
 static void
 bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
 {
-	u32        r32;
+	u32	r32;
 
 	/**
 	 * First read to the semaphore register will return 0, subsequent reads
@@ -762,12 +1161,11 @@
 	 */
 	r32 = bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
 	if (r32 == 0) {
-		bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
 		return;
 	}
 
-	bfa_timer_begin(ioc->timer_mod, &ioc->sem_timer, bfa_ioc_sem_timeout,
-			ioc, BFA_IOC_HWSEM_TOV);
+	bfa_sem_timer_start(ioc);
 }
 
 void
@@ -779,7 +1177,7 @@
 static void
 bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
 {
-	bfa_timer_stop(&ioc->sem_timer);
+	bfa_sem_timer_stop(ioc);
 }
 
 /**
@@ -788,14 +1186,18 @@
 static void
 bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
 {
-	u32        pss_ctl;
-	int             i;
+	u32	pss_ctl;
+	int		i;
 #define PSS_LMEM_INIT_TIME  10000
 
 	pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
 	pss_ctl &= ~__PSS_LMEM_RESET;
 	pss_ctl |= __PSS_LMEM_INIT_EN;
-	pss_ctl |= __PSS_I2C_CLK_DIV(3UL); /* i2c workaround 12.5khz clock */
+
+	/*
+	 * i2c workaround 12.5khz clock
+	 */
+	pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
 	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
 
 	/**
@@ -821,7 +1223,7 @@
 static void
 bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
 {
-	u32        pss_ctl;
+	u32	pss_ctl;
 
 	/**
 	 * Take processor out of reset.
@@ -835,7 +1237,7 @@
 static void
 bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
 {
-	u32        pss_ctl;
+	u32	pss_ctl;
 
 	/**
 	 * Put processors in reset.
@@ -852,10 +1254,10 @@
 void
 bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
 {
-	u32        pgnum, pgoff;
-	u32        loff = 0;
-	int             i;
-	u32       *fwsig = (u32 *) fwhdr;
+	u32	pgnum, pgoff;
+	u32	loff = 0;
+	int		i;
+	u32	*fwsig = (u32 *) fwhdr;
 
 	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
 	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
@@ -863,7 +1265,8 @@
 
 	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
 	     i++) {
-		fwsig[i] = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+		fwsig[i] =
+			bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
 		loff += sizeof(u32);
 	}
 }
@@ -875,10 +1278,10 @@
 bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
 {
 	struct bfi_ioc_image_hdr_s *drv_fwhdr;
-	int             i;
+	int i;
 
 	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
-			bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
+		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
 
 	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
 		if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
@@ -897,21 +1300,20 @@
  * Return true if current running version is valid. Firmware signature and
  * execution context (driver/bios) must match.
  */
-static          bfa_boolean_t
-bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc)
+static bfa_boolean_t
+bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
 {
 	struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
 
 	/**
 	 * If bios/efi boot (flash based) -- return true
 	 */
-	if (bfa_ioc_is_optrom(ioc))
+	if (bfa_ioc_is_bios_optrom(ioc))
 		return BFA_TRUE;
 
 	bfa_ioc_fwver_get(ioc, &fwhdr);
 	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
-			bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
-
+		bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
 
 	if (fwhdr.signature != drv_fwhdr->signature) {
 		bfa_trc(ioc, fwhdr.signature);
@@ -919,9 +1321,9 @@
 		return BFA_FALSE;
 	}
 
-	if (fwhdr.exec != drv_fwhdr->exec) {
-		bfa_trc(ioc, fwhdr.exec);
-		bfa_trc(ioc, drv_fwhdr->exec);
+	if (bfa_os_swap32(fwhdr.param) != boot_env) {
+		bfa_trc(ioc, fwhdr.param);
+		bfa_trc(ioc, boot_env);
 		return BFA_FALSE;
 	}
 
@@ -934,7 +1336,7 @@
 static void
 bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
 {
-	u32        r32;
+	u32	r32;
 
 	r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd);
 	if (r32)
@@ -946,7 +1348,9 @@
 bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
 {
 	enum bfi_ioc_state ioc_fwstate;
-	bfa_boolean_t   fwvalid;
+	bfa_boolean_t fwvalid;
+	u32 boot_type;
+	u32 boot_env;
 
 	ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
 
@@ -955,14 +1359,33 @@
 
 	bfa_trc(ioc, ioc_fwstate);
 
+	boot_type = BFI_BOOT_TYPE_NORMAL;
+	boot_env = BFI_BOOT_LOADER_OS;
+
+	/**
+	 * Flash based firmware boot BIOS env.
+	 */
+	if (bfa_ioc_is_bios_optrom(ioc)) {
+		boot_type = BFI_BOOT_TYPE_FLASH;
+		boot_env = BFI_BOOT_LOADER_BIOS;
+	}
+
+	/**
+	 * Flash based firmware boot UEFI env.
+	 */
+	if (bfa_ioc_is_uefi(ioc)) {
+		boot_type = BFI_BOOT_TYPE_FLASH;
+		boot_env = BFI_BOOT_LOADER_UEFI;
+	}
+
 	/**
 	 * check if firmware is valid
 	 */
 	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
-			BFA_FALSE : bfa_ioc_fwver_valid(ioc);
+		BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
 
 	if (!fwvalid) {
-		bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+		bfa_ioc_boot(ioc, boot_type, boot_env);
 		return;
 	}
 
@@ -971,7 +1394,6 @@
 	 * just wait for an initialization completion interrupt.
 	 */
 	if (ioc_fwstate == BFI_IOC_INITING) {
-		bfa_trc(ioc, ioc_fwstate);
 		ioc->cbfn->reset_cbfn(ioc->bfa);
 		return;
 	}
@@ -985,8 +1407,7 @@
 	 * is loaded.
 	 */
 	if (ioc_fwstate == BFI_IOC_DISABLED ||
-		(!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
-		bfa_trc(ioc, ioc_fwstate);
+	    (!bfa_ioc_is_bios_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
 
 		/**
 		 * When using MSI-X any pending firmware ready event should
@@ -994,20 +1415,20 @@
 		 */
 		bfa_ioc_msgflush(ioc);
 		ioc->cbfn->reset_cbfn(ioc->bfa);
-		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
 		return;
 	}
 
 	/**
 	 * Initialize the h/w for any other states.
 	 */
-	bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+	bfa_ioc_boot(ioc, boot_type, boot_env);
 }
 
 static void
 bfa_ioc_timeout(void *ioc_arg)
 {
-	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
+	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
 
 	bfa_trc(ioc, 0);
 	bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
@@ -1016,8 +1437,8 @@
 void
 bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
 {
-	u32       *msgp = (u32 *) ioc_msg;
-	u32        i;
+	u32 *msgp = (u32 *) ioc_msg;
+	u32 i;
 
 	bfa_trc(ioc, msgp[0]);
 	bfa_trc(ioc, len);
@@ -1038,17 +1459,20 @@
 	 * write 1 to mailbox CMD to trigger LPU event
 	 */
 	bfa_reg_write(ioc->ioc_regs.hfn_mbox_cmd, 1);
-	(void)bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
+	(void) bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
 }
 
 static void
 bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
 {
 	struct bfi_ioc_ctrl_req_s enable_req;
+	struct bfa_timeval_s tv;
 
 	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
 		    bfa_ioc_portid(ioc));
 	enable_req.ioc_class = ioc->ioc_mc;
+	bfa_os_gettimeofday(&tv);
+	enable_req.tv_sec = bfa_os_ntohl(tv.tv_sec);
 	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
 }
 
@@ -1065,7 +1489,7 @@
 static void
 bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
 {
-	struct bfi_ioc_getattr_req_s attr_req;
+	struct bfi_ioc_getattr_req_s	attr_req;
 
 	bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
 		    bfa_ioc_portid(ioc));
@@ -1077,12 +1501,11 @@
 bfa_ioc_hb_check(void *cbarg)
 {
 	struct bfa_ioc_s  *ioc = cbarg;
-	u32     hb_count;
+	u32	hb_count;
 
 	hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
 	if (ioc->hb_count == hb_count) {
-		bfa_log(ioc->logm, BFA_LOG_HAL_HEARTBEAT_FAILURE,
-			hb_count);
+		printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count);
 		bfa_ioc_recover(ioc);
 		return;
 	} else {
@@ -1090,61 +1513,54 @@
 	}
 
 	bfa_ioc_mbox_poll(ioc);
-	bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check,
-			ioc, BFA_IOC_HB_TOV);
+	bfa_hb_timer_start(ioc);
 }
 
 static void
 bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
 {
 	ioc->hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
-	bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc,
-			BFA_IOC_HB_TOV);
+	bfa_hb_timer_start(ioc);
 }
 
 static void
 bfa_ioc_hb_stop(struct bfa_ioc_s *ioc)
 {
-	bfa_timer_stop(&ioc->ioc_timer);
+	bfa_hb_timer_stop(ioc);
 }
 
+
 /**
- *      Initiate a full firmware download.
+ *	Initiate a full firmware download.
  */
 static void
 bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
-		    u32 boot_param)
+		    u32 boot_env)
 {
-	u32       *fwimg;
-	u32        pgnum, pgoff;
-	u32        loff = 0;
-	u32        chunkno = 0;
-	u32        i;
+	u32 *fwimg;
+	u32 pgnum, pgoff;
+	u32 loff = 0;
+	u32 chunkno = 0;
+	u32 i;
 
 	/**
 	 * Initialize LMEM first before code download
 	 */
 	bfa_ioc_lmem_init(ioc);
 
-	/**
-	 * Flash based firmware boot
-	 */
-	bfa_trc(ioc, bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
-	if (bfa_ioc_is_optrom(ioc))
-		boot_type = BFI_BOOT_TYPE_FLASH;
-	fwimg = bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
-
+	bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
+	fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
 
 	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
 	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
 
 	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
 
-	for (i = 0; i < bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
+	for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
 
 		if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
 			chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
-			fwimg = bfi_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
+			fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
 					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
 		}
 
@@ -1162,7 +1578,8 @@
 		loff = PSS_SMEM_PGOFF(loff);
 		if (loff == 0) {
 			pgnum++;
-			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+			bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+				      pgnum);
 		}
 	}
 
@@ -1171,11 +1588,11 @@
 
 	/*
 	 * Set boot type and boot param at the end.
-	 */
+	*/
 	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF,
 			bfa_os_swap32(boot_type));
-	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_PARAM_OFF,
-			bfa_os_swap32(boot_param));
+	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF,
+			bfa_os_swap32(boot_env));
 }
 
 static void
@@ -1190,11 +1607,11 @@
 static void
 bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
 {
-	struct bfi_ioc_attr_s *attr = ioc->attr;
+	struct bfi_ioc_attr_s	*attr = ioc->attr;
 
-	attr->adapter_prop = bfa_os_ntohl(attr->adapter_prop);
+	attr->adapter_prop  = bfa_os_ntohl(attr->adapter_prop);
 	attr->card_type     = bfa_os_ntohl(attr->card_type);
-	attr->maxfrsize = bfa_os_ntohs(attr->maxfrsize);
+	attr->maxfrsize	    = bfa_os_ntohs(attr->maxfrsize);
 
 	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
 }
@@ -1205,8 +1622,8 @@
 static void
 bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	int             mc;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	int	mc;
 
 	INIT_LIST_HEAD(&mod->cmd_q);
 	for (mc = 0; mc < BFI_MC_MAX; mc++) {
@@ -1221,9 +1638,9 @@
 static void
 bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	struct bfa_mbox_cmd_s *cmd;
-	u32        stat;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	struct bfa_mbox_cmd_s		*cmd;
+	u32			stat;
 
 	/**
 	 * If no command pending, do nothing
@@ -1251,25 +1668,194 @@
 static void
 bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	struct bfa_mbox_cmd_s *cmd;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	struct bfa_mbox_cmd_s		*cmd;
 
 	while (!list_empty(&mod->cmd_q))
 		bfa_q_deq(&mod->cmd_q, &cmd);
 }
 
 /**
- *  bfa_ioc_public
+ * Read data from SMEM to host through PCI memmap
+ *
+ * @param[in]	ioc	memory for IOC
+ * @param[in]	tbuf	app memory to store data from smem
+ * @param[in]	soff	smem offset
+ * @param[in]	sz	size of smem in bytes
  */
+static bfa_status_t
+bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
+{
+	u32 pgnum, loff, r32;
+	int i, len;
+	u32 *buf = tbuf;
+
+	pgnum = bfa_ioc_smem_pgnum(ioc, soff);
+	loff = bfa_ioc_smem_pgoff(ioc, soff);
+	bfa_trc(ioc, pgnum);
+	bfa_trc(ioc, loff);
+	bfa_trc(ioc, sz);
+
+	/*
+	 *  Hold semaphore to serialize pll init and fwtrc.
+	 */
+	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
+		bfa_trc(ioc, 0);
+		return BFA_STATUS_FAILED;
+	}
+
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+	len = sz/sizeof(u32);
+	bfa_trc(ioc, len);
+	for (i = 0; i < len; i++) {
+		r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
+		buf[i] = bfa_os_ntohl(r32);
+		loff += sizeof(u32);
+
+		/**
+		 * handle page offset wrap around
+		 */
+		loff = PSS_SMEM_PGOFF(loff);
+		if (loff == 0) {
+			pgnum++;
+			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+		}
+	}
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+		      bfa_ioc_smem_pgnum(ioc, 0));
+	/*
+	 *  release semaphore.
+	 */
+	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+
+	bfa_trc(ioc, pgnum);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Clear SMEM data from host through PCI memmap
+ *
+ * @param[in]	ioc	memory for IOC
+ * @param[in]	soff	smem offset
+ * @param[in]	sz	size of smem in bytes
+ */
+static bfa_status_t
+bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
+{
+	int i, len;
+	u32 pgnum, loff;
+
+	pgnum = bfa_ioc_smem_pgnum(ioc, soff);
+	loff = bfa_ioc_smem_pgoff(ioc, soff);
+	bfa_trc(ioc, pgnum);
+	bfa_trc(ioc, loff);
+	bfa_trc(ioc, sz);
+
+	/*
+	 *  Hold semaphore to serialize pll init and fwtrc.
+	 */
+	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
+		bfa_trc(ioc, 0);
+		return BFA_STATUS_FAILED;
+	}
+
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+
+	len = sz/sizeof(u32); /* len in words */
+	bfa_trc(ioc, len);
+	for (i = 0; i < len; i++) {
+		bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);
+		loff += sizeof(u32);
+
+		/**
+		 * handle page offset wrap around
+		 */
+		loff = PSS_SMEM_PGOFF(loff);
+		if (loff == 0) {
+			pgnum++;
+			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
+		}
+	}
+	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
+		      bfa_ioc_smem_pgnum(ioc, 0));
+
+	/*
+	 *  release semaphore.
+	 */
+	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+	bfa_trc(ioc, pgnum);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * hal iocpf to ioc interface
+ */
+static void
+bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_ENABLED);
+}
+
+static void
+bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_DISABLED);
+}
+
+static void
+bfa_ioc_pf_failed(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(ioc, IOC_E_FAILED);
+}
+
+static void
+bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
+{
+	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
+	/**
+	 * Provide enable completion callback.
+	 */
+	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
+	BFA_LOG(KERN_WARNING, bfad, log_level,
+		"Running firmware version is incompatible "
+		"with the driver version\n");
+}
+
+
+
+/**
+ *  hal_ioc_public
+ */
+
+bfa_status_t
+bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
+{
+
+	/*
+	 *  Hold semaphore so that nobody can access the chip during init.
+	 */
+	bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
+
+	bfa_ioc_pll_init_asic(ioc);
+
+	ioc->pllinit = BFA_TRUE;
+	/*
+	 *  release semaphore.
+	 */
+	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+
+	return BFA_STATUS_OK;
+}
 
 /**
  * Interface used by diag module to do firmware boot with memory test
  * as the entry vector.
  */
 void
-bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param)
+bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
 {
-	bfa_os_addr_t   rb;
+	bfa_os_addr_t	rb;
 
 	bfa_ioc_stats(ioc, ioc_boots);
 
@@ -1280,7 +1866,7 @@
 	 * Initialize IOC state of all functions on a chip reset.
 	 */
 	rb = ioc->pcidev.pci_bar_kva;
-	if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+	if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
 		bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_MEMTEST);
 		bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_MEMTEST);
 	} else {
@@ -1289,7 +1875,7 @@
 	}
 
 	bfa_ioc_msgflush(ioc);
-	bfa_ioc_download_fw(ioc, boot_type, boot_param);
+	bfa_ioc_download_fw(ioc, boot_type, boot_env);
 
 	/**
 	 * Enable interrupts just before starting LPU
@@ -1308,18 +1894,29 @@
 }
 
 
+
 bfa_boolean_t
 bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
 {
 	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
 }
 
+bfa_boolean_t
+bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
+{
+	u32 r32 = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
+
+	return ((r32 != BFI_IOC_UNINIT) &&
+		(r32 != BFI_IOC_INITING) &&
+		(r32 != BFI_IOC_MEMTEST));
+}
+
 void
 bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
 {
-	u32       *msgp = mbmsg;
-	u32        r32;
-	int             i;
+	u32	*msgp = mbmsg;
+	u32	r32;
+	int		i;
 
 	/**
 	 * read the MBOX msg
@@ -1341,9 +1938,10 @@
 void
 bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
 {
-	union bfi_ioc_i2h_msg_u *msg;
+	union bfi_ioc_i2h_msg_u	*msg;
+	struct bfa_iocpf_s *iocpf = &ioc->iocpf;
 
-	msg = (union bfi_ioc_i2h_msg_u *)m;
+	msg = (union bfi_ioc_i2h_msg_u *) m;
 
 	bfa_ioc_stats(ioc, ioc_isrs);
 
@@ -1352,15 +1950,15 @@
 		break;
 
 	case BFI_IOC_I2H_READY_EVENT:
-		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
+		bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
 		break;
 
 	case BFI_IOC_I2H_ENABLE_REPLY:
-		bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
+		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
 		break;
 
 	case BFI_IOC_I2H_DISABLE_REPLY:
-		bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
+		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
 		break;
 
 	case BFI_IOC_I2H_GETATTR_REPLY:
@@ -1378,29 +1976,24 @@
  *
  * @param[in]	ioc	memory for IOC
  * @param[in]	bfa	driver instance structure
- * @param[in]	trcmod	kernel trace module
- * @param[in]	aen	kernel aen event module
- * @param[in]	logm	kernel logging module
  */
 void
 bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
-	       struct bfa_timer_mod_s *timer_mod, struct bfa_trc_mod_s *trcmod,
-	       struct bfa_aen_s *aen, struct bfa_log_mod_s *logm)
+	       struct bfa_timer_mod_s *timer_mod)
 {
-	ioc->bfa = bfa;
-	ioc->cbfn = cbfn;
-	ioc->timer_mod = timer_mod;
-	ioc->trcmod = trcmod;
-	ioc->aen = aen;
-	ioc->logm = logm;
-	ioc->fcmode = BFA_FALSE;
-	ioc->pllinit = BFA_FALSE;
+	ioc->bfa	= bfa;
+	ioc->cbfn	= cbfn;
+	ioc->timer_mod	= timer_mod;
+	ioc->fcmode	= BFA_FALSE;
+	ioc->pllinit	= BFA_FALSE;
 	ioc->dbg_fwsave_once = BFA_TRUE;
+	ioc->iocpf.ioc	= ioc;
 
 	bfa_ioc_mbox_attach(ioc);
 	INIT_LIST_HEAD(&ioc->hb_notify_q);
 
-	bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
+	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
+	bfa_fsm_send_event(ioc, IOC_E_RESET);
 }
 
 /**
@@ -1421,10 +2014,10 @@
 bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
 		 enum bfi_mclass mc)
 {
-	ioc->ioc_mc = mc;
-	ioc->pcidev = *pcidev;
-	ioc->ctdev  = bfa_asic_id_ct(ioc->pcidev.device_id);
-	ioc->cna = ioc->ctdev && !ioc->fcmode;
+	ioc->ioc_mc	= mc;
+	ioc->pcidev	= *pcidev;
+	ioc->ctdev	= bfa_asic_id_ct(ioc->pcidev.device_id);
+	ioc->cna	= ioc->ctdev && !ioc->fcmode;
 
 	/**
 	 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
@@ -1445,14 +2038,14 @@
  * @param[in]	dm_pa	physical address of IOC dma memory
  */
 void
-bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
+bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa)
 {
 	/**
 	 * dma memory for firmware attribute
 	 */
 	ioc->attr_dma.kva = dm_kva;
 	ioc->attr_dma.pa = dm_pa;
-	ioc->attr = (struct bfi_ioc_attr_s *)dm_kva;
+	ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
 }
 
 /**
@@ -1490,7 +2083,7 @@
 int
 bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover)
 {
-return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
+	return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
 }
 
 /**
@@ -1500,8 +2093,8 @@
 void
 bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
 {
-	ioc->dbg_fwsave = dbg_fwsave;
-	ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->auto_recover);
+	ioc->dbg_fwsave	    = dbg_fwsave;
+	ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->iocpf.auto_recover);
 }
 
 u32
@@ -1525,8 +2118,8 @@
 void
 bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	int             mc;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	int				mc;
 
 	for (mc = 0; mc < BFI_MC_MAX; mc++)
 		mod->mbhdlr[mc].cbfn = mcfuncs[mc];
@@ -1539,10 +2132,10 @@
 bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
 		    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
 
-	mod->mbhdlr[mc].cbfn = cbfn;
-	mod->mbhdlr[mc].cbarg = cbarg;
+	mod->mbhdlr[mc].cbfn	= cbfn;
+	mod->mbhdlr[mc].cbarg	= cbarg;
 }
 
 /**
@@ -1555,8 +2148,8 @@
 void
 bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	u32        stat;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	u32			stat;
 
 	/**
 	 * If a previous command is pending, queue new command
@@ -1587,9 +2180,9 @@
 void
 bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
 {
-	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
-	struct bfi_mbmsg_s m;
-	int             mc;
+	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
+	struct bfi_mbmsg_s		m;
+	int				mc;
 
 	bfa_ioc_msgget(ioc, &m);
 
@@ -1621,16 +2214,14 @@
 	ioc->port_id = bfa_ioc_pcifn(ioc);
 }
 
-#ifndef BFA_BIOS_BUILD
-
 /**
  * return true if IOC is disabled
  */
 bfa_boolean_t
 bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
 {
-	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
-		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
+		bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
 }
 
 /**
@@ -1639,9 +2230,9 @@
 bfa_boolean_t
 bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
 {
-	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
-		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck)
-		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch);
+	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
+		bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||
+		bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
 }
 
 #define bfa_ioc_state_disabled(__sm)		\
@@ -1659,8 +2250,8 @@
 bfa_boolean_t
 bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
 {
-	u32        ioc_state;
-	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
+	u32	ioc_state;
+	bfa_os_addr_t	rb = ioc->pcidev.pci_bar_kva;
 
 	if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
 		return BFA_FALSE;
@@ -1669,16 +2260,18 @@
 	if (!bfa_ioc_state_disabled(ioc_state))
 		return BFA_FALSE;
 
-	ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG);
-	if (!bfa_ioc_state_disabled(ioc_state))
-		return BFA_FALSE;
+	if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
+		ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG);
+		if (!bfa_ioc_state_disabled(ioc_state))
+			return BFA_FALSE;
+	}
 
 	return BFA_TRUE;
 }
 
 /**
  * Add to IOC heartbeat failure notification queue. To be used by common
- * modules such as
+ * modules such as cee, port, diag.
  */
 void
 bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
@@ -1692,7 +2285,7 @@
 bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
 			 struct bfa_adapter_attr_s *ad_attr)
 {
-	struct bfi_ioc_attr_s *ioc_attr;
+	struct bfi_ioc_attr_s	*ioc_attr;
 
 	ioc_attr = ioc->attr;
 
@@ -1719,7 +2312,7 @@
 		ad_attr->prototype = 0;
 
 	ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
-	ad_attr->mac = bfa_ioc_get_mac(ioc);
+	ad_attr->mac  = bfa_ioc_get_mac(ioc);
 
 	ad_attr->pcie_gen = ioc_attr->pcie_gen;
 	ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
@@ -1729,6 +2322,7 @@
 	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
 
 	ad_attr->cna_capable = ioc->cna;
+	ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
 }
 
 enum bfa_ioc_type_e
@@ -1782,7 +2376,7 @@
 {
 	bfa_os_memset((void *)optrom_ver, 0, BFA_VERSION_LEN);
 	bfa_os_memcpy(optrom_ver, ioc->attr->optrom_version,
-		BFA_VERSION_LEN);
+		      BFA_VERSION_LEN);
 }
 
 void
@@ -1795,7 +2389,7 @@
 void
 bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
 {
-	struct bfi_ioc_attr_s   *ioc_attr;
+	struct bfi_ioc_attr_s	*ioc_attr;
 
 	bfa_assert(model);
 	bfa_os_memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
@@ -1805,14 +2399,48 @@
 	/**
 	 * model name
 	 */
-	snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
-			BFA_MFG_NAME, ioc_attr->card_type);
+	bfa_os_snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
+		BFA_MFG_NAME, ioc_attr->card_type);
 }
 
 enum bfa_ioc_state
 bfa_ioc_get_state(struct bfa_ioc_s *ioc)
 {
-	return bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+	enum bfa_iocpf_state iocpf_st;
+	enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
+
+	if (ioc_st == BFA_IOC_ENABLING ||
+		ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
+
+		iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
+
+		switch (iocpf_st) {
+		case BFA_IOCPF_SEMWAIT:
+			ioc_st = BFA_IOC_SEMWAIT;
+			break;
+
+		case BFA_IOCPF_HWINIT:
+			ioc_st = BFA_IOC_HWINIT;
+			break;
+
+		case BFA_IOCPF_FWMISMATCH:
+			ioc_st = BFA_IOC_FWMISMATCH;
+			break;
+
+		case BFA_IOCPF_FAIL:
+			ioc_st = BFA_IOC_FAIL;
+			break;
+
+		case BFA_IOCPF_INITFAIL:
+			ioc_st = BFA_IOC_INITFAIL;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	return ioc_st;
 }
 
 void
@@ -1833,7 +2461,7 @@
 }
 
 /**
- *  bfa_wwn_public
+ *  hal_wwn_public
  */
 wwn_t
 bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc)
@@ -1857,10 +2485,10 @@
 bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
 {
 	/*
-	 * Currently mfg mac is used as FCoE enode mac (not configured by PBC)
+	 * Check the IOC type and return the appropriate MAC
 	 */
 	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
-		return bfa_ioc_get_mfg_mac(ioc);
+		return ioc->attr->fcoe_mac;
 	else
 		return ioc->attr->mac;
 }
@@ -1880,12 +2508,16 @@
 mac_t
 bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
 {
-	mac_t   mac;
+	mac_t	m;
 
-	mac = ioc->attr->mfg_mac;
-	mac.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+	m = ioc->attr->mfg_mac;
+	if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
+		m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
+	else
+		bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
+			bfa_ioc_pcifn(ioc));
 
-	return mac;
+	return m;
 }
 
 bfa_boolean_t
@@ -1895,46 +2527,12 @@
 }
 
 /**
- * Send AEN notification
- */
-void
-bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = ioc->logm;
-	s32         inst_num = 0;
-	enum bfa_ioc_type_e ioc_type;
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, event), inst_num);
-
-	memset(&aen_data.ioc.pwwn, 0, sizeof(aen_data.ioc.pwwn));
-	memset(&aen_data.ioc.mac, 0, sizeof(aen_data.ioc.mac));
-	ioc_type = bfa_ioc_get_type(ioc);
-	switch (ioc_type) {
-	case BFA_IOC_TYPE_FC:
-		aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
-		break;
-	case BFA_IOC_TYPE_FCoE:
-		aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
-		aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
-		break;
-	case BFA_IOC_TYPE_LL:
-		aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
-		break;
-	default:
-		bfa_assert(ioc_type == BFA_IOC_TYPE_FC);
-		break;
-	}
-	aen_data.ioc.ioc_type = ioc_type;
-}
-
-/**
  * Retrieve saved firmware trace from a prior IOC failure.
  */
 bfa_status_t
 bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
 {
-	int             tlen;
+	int	tlen;
 
 	if (ioc->dbg_fwsave_len == 0)
 		return BFA_STATUS_ENOFSAVE;
@@ -1963,57 +2561,145 @@
 bfa_status_t
 bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
 {
-	u32        pgnum;
-	u32        loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
-	int             i, tlen;
-	u32       *tbuf = trcdata, r32;
+	u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
+	int tlen;
+	bfa_status_t status;
 
 	bfa_trc(ioc, *trclen);
 
-	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
-	loff = bfa_ioc_smem_pgoff(ioc, loff);
-
-	/*
-	 *  Hold semaphore to serialize pll init and fwtrc.
-	 */
-	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg))
-		return BFA_STATUS_FAILED;
-
-	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
-
 	tlen = *trclen;
 	if (tlen > BFA_DBG_FWTRC_LEN)
 		tlen = BFA_DBG_FWTRC_LEN;
-	tlen /= sizeof(u32);
 
-	bfa_trc(ioc, tlen);
+	status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);
+	*trclen = tlen;
+	return status;
+}
 
-	for (i = 0; i < tlen; i++) {
-		r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
-		tbuf[i] = bfa_os_ntohl(r32);
-		loff += sizeof(u32);
+static void
+bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
+{
+	struct bfa_mbox_cmd_s cmd;
+	struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;
 
-		/**
-		 * handle page offset wrap around
-		 */
-		loff = PSS_SMEM_PGOFF(loff);
-		if (loff == 0) {
-			pgnum++;
-			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
-		}
-	}
-	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
-		      bfa_ioc_smem_pgnum(ioc, 0));
+	bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
+		    bfa_ioc_portid(ioc));
+	req->ioc_class = ioc->ioc_mc;
+	bfa_ioc_mbox_queue(ioc, &cmd);
+}
 
-	/*
-	 *  release semaphore.
+static void
+bfa_ioc_fwsync(struct bfa_ioc_s *ioc)
+{
+	u32 fwsync_iter = 1000;
+
+	bfa_ioc_send_fwsync(ioc);
+
+	/**
+	 * After sending a fw sync mbox command wait for it to
+	 * take effect.  We will not wait for a response because
+	 *    1. fw_sync mbox cmd doesn't have a response.
+	 *    2. Even if we implement that,  interrupts might not
+	 *	 be enabled when we call this function.
+	 * So, just keep checking if any mbox cmd is pending, and
+	 * after waiting for a reasonable amount of time, go ahead.
+	 * It is possible that fw has crashed and the mbox command
+	 * is never acknowledged.
 	 */
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
+	while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)
+		fwsync_iter--;
+}
 
-	bfa_trc(ioc, pgnum);
+/**
+ * Dump firmware smem
+ */
+bfa_status_t
+bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
+				u32 *offset, int *buflen)
+{
+	u32 loff;
+	int dlen;
+	bfa_status_t status;
+	u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);
 
-	*trclen = tlen * sizeof(u32);
-	return BFA_STATUS_OK;
+	if (*offset >= smem_len) {
+		*offset = *buflen = 0;
+		return BFA_STATUS_EINVAL;
+	}
+
+	loff = *offset;
+	dlen = *buflen;
+
+	/**
+	 * First smem read, sync smem before proceeding
+	 * No need to sync before reading every chunk.
+	 */
+	if (loff == 0)
+		bfa_ioc_fwsync(ioc);
+
+	if ((loff + dlen) >= smem_len)
+		dlen = smem_len - loff;
+
+	status = bfa_ioc_smem_read(ioc, buf, loff, dlen);
+
+	if (status != BFA_STATUS_OK) {
+		*offset = *buflen = 0;
+		return status;
+	}
+
+	*offset += dlen;
+
+	if (*offset >= smem_len)
+		*offset = 0;
+
+	*buflen = dlen;
+
+	return status;
+}
+
+/**
+ * Firmware statistics
+ */
+bfa_status_t
+bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)
+{
+	u32 loff = BFI_IOC_FWSTATS_OFF + \
+		BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
+	int tlen;
+	bfa_status_t status;
+
+	if (ioc->stats_busy) {
+		bfa_trc(ioc, ioc->stats_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+	ioc->stats_busy = BFA_TRUE;
+
+	tlen = sizeof(struct bfa_fw_stats_s);
+	status = bfa_ioc_smem_read(ioc, stats, loff, tlen);
+
+	ioc->stats_busy = BFA_FALSE;
+	return status;
+}
+
+bfa_status_t
+bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
+{
+	u32 loff = BFI_IOC_FWSTATS_OFF + \
+		BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
+	int tlen;
+	bfa_status_t status;
+
+	if (ioc->stats_busy) {
+		bfa_trc(ioc, ioc->stats_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+	ioc->stats_busy = BFA_TRUE;
+
+	tlen = sizeof(struct bfa_fw_stats_s);
+	status = bfa_ioc_smem_clr(ioc, loff, tlen);
+
+	ioc->stats_busy = BFA_FALSE;
+	return status;
 }
 
 /**
@@ -2022,7 +2708,7 @@
 static void
 bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
 {
-	int             tlen;
+	int		tlen;
 
 	if (ioc->dbg_fwsave_len) {
 		tlen = ioc->dbg_fwsave_len;
@@ -2050,11 +2736,135 @@
 {
 	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
 		return;
-
-	if (ioc->attr->nwwn == 0)
-		bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_NWWN);
-	if (ioc->attr->pwwn == 0)
-		bfa_ioc_aen_post(ioc, BFA_IOC_AEN_INVALID_PWWN);
 }
 
-#endif
+/**
+ *  hal_iocpf_pvt BFA IOC PF private functions
+ */
+
+static void
+bfa_iocpf_enable(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
+}
+
+static void
+bfa_iocpf_disable(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
+}
+
+static void
+bfa_iocpf_fail(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
+}
+
+static void
+bfa_iocpf_initfail(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
+}
+
+static void
+bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
+}
+
+static void
+bfa_iocpf_stop(struct bfa_ioc_s *ioc)
+{
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
+}
+
+static void
+bfa_iocpf_timeout(void *ioc_arg)
+{
+	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
+
+	bfa_trc(ioc, 0);
+	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
+}
+
+static void
+bfa_iocpf_sem_timeout(void *ioc_arg)
+{
+	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
+
+	bfa_ioc_hw_sem_get(ioc);
+}
+
+/**
+ *  bfa timer function
+ */
+void
+bfa_timer_init(struct bfa_timer_mod_s *mod)
+{
+	INIT_LIST_HEAD(&mod->timer_q);
+}
+
+void
+bfa_timer_beat(struct bfa_timer_mod_s *mod)
+{
+	struct list_head *qh = &mod->timer_q;
+	struct list_head *qe, *qe_next;
+	struct bfa_timer_s *elem;
+	struct list_head timedout_q;
+
+	INIT_LIST_HEAD(&timedout_q);
+
+	qe = bfa_q_next(qh);
+
+	while (qe != qh) {
+		qe_next = bfa_q_next(qe);
+
+		elem = (struct bfa_timer_s *) qe;
+		if (elem->timeout <= BFA_TIMER_FREQ) {
+			elem->timeout = 0;
+			list_del(&elem->qe);
+			list_add_tail(&elem->qe, &timedout_q);
+		} else {
+			elem->timeout -= BFA_TIMER_FREQ;
+		}
+
+		qe = qe_next;	/* go to next elem */
+	}
+
+	/*
+	 * Pop all the timeout entries
+	 */
+	while (!list_empty(&timedout_q)) {
+		bfa_q_deq(&timedout_q, &elem);
+		elem->timercb(elem->arg);
+	}
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+		    void (*timercb) (void *), void *arg, unsigned int timeout)
+{
+
+	bfa_assert(timercb != NULL);
+	bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
+
+	timer->timeout = timeout;
+	timer->timercb = timercb;
+	timer->arg = arg;
+
+	list_add_tail(&timer->qe, &mod->timer_q);
+}
+
+/**
+ * Should be called with lock protection
+ */
+void
+bfa_timer_stop(struct bfa_timer_s *timer)
+{
+	bfa_assert(!list_empty(&timer->qe));
+
+	list_del(&timer->qe);
+}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index cae05b2..288c580 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -18,18 +18,74 @@
 #ifndef __BFA_IOC_H__
 #define __BFA_IOC_H__
 
-#include <cs/bfa_sm.h>
-#include <bfi/bfi.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_boot.h>
-#include <bfa_timer.h>
+#include "bfa_os_inc.h"
+#include "bfa_cs.h"
+#include "bfi.h"
+
+/**
+ * BFA timer declarations
+ */
+typedef void (*bfa_timer_cbfn_t)(void *);
+
+/**
+ * BFA timer data structure
+ */
+struct bfa_timer_s {
+	struct list_head	qe;
+	bfa_timer_cbfn_t timercb;
+	void		*arg;
+	int		timeout;	/**< in millisecs. */
+};
+
+/**
+ * Timer module structure
+ */
+struct bfa_timer_mod_s {
+	struct list_head timer_q;
+};
+
+#define BFA_TIMER_FREQ 200 /**< specified in millisecs */
+
+void bfa_timer_beat(struct bfa_timer_mod_s *mod);
+void bfa_timer_init(struct bfa_timer_mod_s *mod);
+void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
+			bfa_timer_cbfn_t timercb, void *arg,
+			unsigned int timeout);
+void bfa_timer_stop(struct bfa_timer_s *timer);
+
+/**
+ * Generic Scatter Gather Element used by driver
+ */
+struct bfa_sge_s {
+	u32	sg_len;
+	void		*sg_addr;
+};
+
+#define bfa_sge_word_swap(__sge) do {					     \
+	((u32 *)(__sge))[0] = bfa_os_swap32(((u32 *)(__sge))[0]);      \
+	((u32 *)(__sge))[1] = bfa_os_swap32(((u32 *)(__sge))[1]);      \
+	((u32 *)(__sge))[2] = bfa_os_swap32(((u32 *)(__sge))[2]);      \
+} while (0)
+
+#define bfa_swap_words(_x)  (	\
+	((_x) << 32) | ((_x) >> 32))
+
+#ifdef __BIGENDIAN
+#define bfa_sge_to_be(_x)
+#define bfa_sge_to_le(_x)	bfa_sge_word_swap(_x)
+#define bfa_sgaddr_le(_x)	bfa_swap_words(_x)
+#else
+#define	bfa_sge_to_be(_x)	bfa_sge_word_swap(_x)
+#define bfa_sge_to_le(_x)
+#define bfa_sgaddr_le(_x)	(_x)
+#endif
 
 /**
  * PCI device information required by IOC
  */
 struct bfa_pcidev_s {
-	int             pci_slot;
-	u8         pci_func;
+	int		pci_slot;
+	u8		pci_func;
 	u16	device_id;
 	bfa_os_addr_t   pci_bar_kva;
 };
@@ -39,13 +95,18 @@
  * Address
  */
 struct bfa_dma_s {
-	void		*kva;	/*! Kernel virtual address	*/
-	u64	pa;	/*! Physical address		*/
+	void		*kva;	/* ! Kernel virtual address	*/
+	u64	pa;	/* ! Physical address		*/
 };
 
 #define BFA_DMA_ALIGN_SZ	256
 #define BFA_ROUNDUP(_l, _s)	(((_l) + ((_s) - 1)) & ~((_s) - 1))
 
+/**
+ * smem size for Crossbow and Catapult
+ */
+#define BFI_SMEM_CB_SIZE	0x200000U	/* ! 2MB for crossbow	*/
+#define BFI_SMEM_CT_SIZE	0x280000U	/* ! 2.5MB for catapult	*/
 
 
 #define bfa_dma_addr_set(dma_addr, pa)	\
@@ -101,7 +162,7 @@
  * IOC Mailbox structures
  */
 struct bfa_mbox_cmd_s {
-	struct list_head		qe;
+	struct list_head	qe;
 	u32	msg[BFI_IOC_MSGSZ];
 };
 
@@ -110,8 +171,8 @@
  */
 typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg_s *m);
 struct bfa_ioc_mbox_mod_s {
-	struct list_head	cmd_q;		/*  pending mbox queue	*/
-	int		nmclass;	/*  number of handlers */
+	struct list_head		cmd_q;	/*  pending mbox queue	*/
+	int			nmclass;	/*  number of handlers */
 	struct {
 		bfa_ioc_mbox_mcfunc_t	cbfn;	/*  message handlers	*/
 		void			*cbarg;
@@ -149,49 +210,54 @@
 	(__notify)->cbarg = (__cbarg);      \
 } while (0)
 
+struct bfa_iocpf_s {
+	bfa_fsm_t		fsm;
+	struct bfa_ioc_s	*ioc;
+	u32		retry_count;
+	bfa_boolean_t		auto_recover;
+};
+
 struct bfa_ioc_s {
 	bfa_fsm_t		fsm;
 	struct bfa_s		*bfa;
 	struct bfa_pcidev_s	pcidev;
-	struct bfa_timer_mod_s 	*timer_mod;
-	struct bfa_timer_s 	ioc_timer;
-	struct bfa_timer_s 	sem_timer;
+	struct bfa_timer_mod_s	*timer_mod;
+	struct bfa_timer_s	ioc_timer;
+	struct bfa_timer_s	sem_timer;
+	struct bfa_timer_s	hb_timer;
 	u32		hb_count;
-	u32		retry_count;
 	struct list_head		hb_notify_q;
 	void			*dbg_fwsave;
 	int			dbg_fwsave_len;
 	bfa_boolean_t		dbg_fwsave_once;
 	enum bfi_mclass		ioc_mc;
-	struct bfa_ioc_regs_s 	ioc_regs;
+	struct bfa_ioc_regs_s	ioc_regs;
 	struct bfa_trc_mod_s	*trcmod;
-	struct bfa_aen_s	*aen;
-	struct bfa_log_mod_s	*logm;
 	struct bfa_ioc_drv_stats_s	stats;
-	bfa_boolean_t		auto_recover;
 	bfa_boolean_t		fcmode;
 	bfa_boolean_t		ctdev;
 	bfa_boolean_t		cna;
 	bfa_boolean_t		pllinit;
+	bfa_boolean_t		stats_busy;	/*  outstanding stats */
 	u8			port_id;
-
 	struct bfa_dma_s	attr_dma;
 	struct bfi_ioc_attr_s	*attr;
 	struct bfa_ioc_cbfn_s	*cbfn;
 	struct bfa_ioc_mbox_mod_s mbox_mod;
-	struct bfa_ioc_hwif_s   *ioc_hwif;
+	struct bfa_ioc_hwif_s	*ioc_hwif;
+	struct bfa_iocpf_s	iocpf;
 };
 
 struct bfa_ioc_hwif_s {
-	bfa_status_t    (*ioc_pll_init) (struct bfa_ioc_s *ioc);
-	bfa_boolean_t   (*ioc_firmware_lock)    (struct bfa_ioc_s *ioc);
-	void            (*ioc_firmware_unlock)  (struct bfa_ioc_s *ioc);
-	void		(*ioc_reg_init) (struct bfa_ioc_s *ioc);
-	void		(*ioc_map_port) (struct bfa_ioc_s *ioc);
-	void		(*ioc_isr_mode_set)     (struct bfa_ioc_s *ioc,
-						bfa_boolean_t msix);
-	void            (*ioc_notify_hbfail)    (struct bfa_ioc_s *ioc);
-	void            (*ioc_ownership_reset)  (struct bfa_ioc_s *ioc);
+	bfa_status_t (*ioc_pll_init) (bfa_os_addr_t rb, bfa_boolean_t fcmode);
+	bfa_boolean_t	(*ioc_firmware_lock)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_firmware_unlock)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_reg_init)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_map_port)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_isr_mode_set)	(struct bfa_ioc_s *ioc,
+					bfa_boolean_t msix);
+	void		(*ioc_notify_hbfail)	(struct bfa_ioc_s *ioc);
+	void		(*ioc_ownership_reset)	(struct bfa_ioc_s *ioc);
 };
 
 #define bfa_ioc_pcifn(__ioc)		((__ioc)->pcidev.pci_func)
@@ -206,18 +272,19 @@
 #define bfa_ioc_rx_bbcredit(__ioc)	((__ioc)->attr->rx_bbcredit)
 #define bfa_ioc_speed_sup(__ioc)	\
 	BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop)
-#define bfa_ioc_get_nports(__ioc)       \
+#define bfa_ioc_get_nports(__ioc)	\
 	BFI_ADAPTER_GETP(NPORTS, (__ioc)->attr->adapter_prop)
 
-#define bfa_ioc_stats(_ioc, _stats)     ((_ioc)->stats._stats++)
-#define BFA_IOC_FWIMG_MINSZ     (16 * 1024)
-#define BFA_IOC_FWIMG_TYPE(__ioc)                                       \
-	(((__ioc)->ctdev) ?                                             \
-	 (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :     \
+#define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)
+#define BFA_IOC_FWIMG_MINSZ	(16 * 1024)
+#define BFA_IOC_FWIMG_TYPE(__ioc)					\
+	(((__ioc)->ctdev) ?						\
+	 (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) :	\
 	 BFI_IMAGE_CB_FC)
-
-#define BFA_IOC_FLASH_CHUNK_NO(off)             (off / BFI_FLASH_CHUNK_SZ_WORDS)
-#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off)      (off % BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FW_SMEM_SIZE(__ioc)					\
+	(((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE)
+#define BFA_IOC_FLASH_CHUNK_NO(off)		(off / BFI_FLASH_CHUNK_SZ_WORDS)
+#define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off)	(off % BFI_FLASH_CHUNK_SZ_WORDS)
 #define BFA_IOC_FLASH_CHUNK_ADDR(chunkno)  (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
 
 /**
@@ -235,18 +302,28 @@
 /**
  * IOC interfaces
  */
-#define bfa_ioc_pll_init(__ioc) ((__ioc)->ioc_hwif->ioc_pll_init(__ioc))
-#define bfa_ioc_isr_mode_set(__ioc, __msix)                     \
+
+#define bfa_ioc_pll_init_asic(__ioc) \
+	((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \
+			   (__ioc)->fcmode))
+
+bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc);
+bfa_status_t bfa_ioc_cb_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode);
+bfa_boolean_t bfa_ioc_ct_pll_init_complete(bfa_os_addr_t rb);
+bfa_status_t bfa_ioc_ct_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode);
+
+#define	bfa_ioc_isr_mode_set(__ioc, __msix)			\
 			((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix))
-#define bfa_ioc_ownership_reset(__ioc)                          \
+#define	bfa_ioc_ownership_reset(__ioc)				\
 			((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc))
 
+
 void bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc);
 void bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc);
+
 void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa,
-		struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod,
-		struct bfa_trc_mod_s *trcmod,
-		struct bfa_aen_s *aen, struct bfa_log_mod_s *logm);
+		struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod);
+void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
 void bfa_ioc_detach(struct bfa_ioc_s *ioc);
 void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
 		enum bfi_mclass mc);
@@ -256,21 +333,22 @@
 void bfa_ioc_disable(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
 
-void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param);
+void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type,
+		u32 boot_param);
 void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
 void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc);
+bfa_boolean_t bfa_ioc_is_initialized(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc);
 bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc);
-void bfa_ioc_cfg_complete(struct bfa_ioc_s *ioc);
 enum bfa_ioc_type_e bfa_ioc_get_type(struct bfa_ioc_s *ioc);
 void bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num);
 void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver);
 void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver);
 void bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model);
 void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc,
-	char *manufacturer);
+		char *manufacturer);
 void bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev);
 enum bfa_ioc_state bfa_ioc_get_state(struct bfa_ioc_s *ioc);
 
@@ -284,6 +362,8 @@
 void bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc);
 bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
 				 int *trclen);
+bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
+	u32 *offset, int *buflen);
 u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr);
 u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr);
 void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc);
@@ -297,7 +377,8 @@
 			struct bfi_ioc_image_hdr_s *fwhdr);
 bfa_boolean_t bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,
 			struct bfi_ioc_image_hdr_s *fwhdr);
-void bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event);
+bfa_status_t bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats);
+bfa_status_t bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc);
 
 /*
  * bfa mfg wwn API functions
@@ -310,5 +391,68 @@
 mac_t bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc);
 u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc);
 
-#endif /* __BFA_IOC_H__ */
+/*
+ * F/W Image Size & Chunk
+ */
+extern u32 bfi_image_ct_fc_size;
+extern u32 bfi_image_ct_cna_size;
+extern u32 bfi_image_cb_fc_size;
+extern u32 *bfi_image_ct_fc;
+extern u32 *bfi_image_ct_cna;
+extern u32 *bfi_image_cb_fc;
 
+static inline u32 *
+bfi_image_ct_fc_get_chunk(u32 off)
+{	return (u32 *)(bfi_image_ct_fc + off); }
+
+static inline u32 *
+bfi_image_ct_cna_get_chunk(u32 off)
+{	return (u32 *)(bfi_image_ct_cna + off); }
+
+static inline u32 *
+bfi_image_cb_fc_get_chunk(u32 off)
+{	return (u32 *)(bfi_image_cb_fc + off); }
+
+static inline u32*
+bfa_cb_image_get_chunk(int type, u32 off)
+{
+	switch (type) {
+	case BFI_IMAGE_CT_FC:
+		return bfi_image_ct_fc_get_chunk(off);	break;
+	case BFI_IMAGE_CT_CNA:
+		return bfi_image_ct_cna_get_chunk(off);	break;
+	case BFI_IMAGE_CB_FC:
+		return bfi_image_cb_fc_get_chunk(off);	break;
+	default: return 0;
+	}
+}
+
+static inline u32
+bfa_cb_image_get_size(int type)
+{
+	switch (type) {
+	case BFI_IMAGE_CT_FC:
+		return bfi_image_ct_fc_size;	break;
+	case BFI_IMAGE_CT_CNA:
+		return bfi_image_ct_cna_size;	break;
+	case BFI_IMAGE_CB_FC:
+		return bfi_image_cb_fc_size;	break;
+	default: return 0;
+	}
+}
+
+/**
+ * CNA TRCMOD declaration
+ */
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+	BFA_TRC_CNA_PORT	= 1,
+	BFA_TRC_CNA_IOC		= 2,
+	BFA_TRC_CNA_IOC_CB	= 3,
+	BFA_TRC_CNA_IOC_CT	= 4,
+};
+
+#endif /* __BFA_IOC_H__ */
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index 324bdde..d7ac864 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,22 +15,15 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <bfa_ioc.h>
-#include <bfa_fwimg_priv.h>
-#include <cna/bfa_cna_trcmod.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_cbreg.h>
-#include <log/bfa_log_hal.h>
-#include <defs/bfa_defs_pci.h>
+#include "bfa_ioc.h"
+#include "bfi_cbreg.h"
+#include "bfa_defs.h"
 
 BFA_TRC_FILE(CNA, IOC_CB);
 
 /*
  * forward declarations
  */
-static bfa_status_t bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc);
 static bfa_boolean_t bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc);
 static void bfa_ioc_cb_firmware_unlock(struct bfa_ioc_s *ioc);
 static void bfa_ioc_cb_reg_init(struct bfa_ioc_s *ioc);
@@ -95,6 +88,7 @@
  * Host <-> LPU mailbox command/status registers
  */
 static struct { u32 hfn, lpu; } iocreg_mbcmd[] = {
+
 	{ HOSTFN0_LPU0_CMD_STAT, LPU0_HOSTFN0_CMD_STAT },
 	{ HOSTFN1_LPU1_CMD_STAT, LPU1_HOSTFN1_CMD_STAT }
 };
@@ -154,6 +148,7 @@
 /**
  * Initialize IOC to port mapping.
  */
+
 static void
 bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc)
 {
@@ -161,6 +156,7 @@
 	 * For crossbow, port id is same as pci function.
 	 */
 	ioc->port_id = bfa_ioc_pcifn(ioc);
+
 	bfa_trc(ioc, ioc->port_id);
 }
 
@@ -172,75 +168,6 @@
 {
 }
 
-static bfa_status_t
-bfa_ioc_cb_pll_init(struct bfa_ioc_s *ioc)
-{
-	bfa_os_addr_t	rb = ioc->pcidev.pci_bar_kva;
-	u32	pll_sclk, pll_fclk;
-
-	/*
-	 *  Hold semaphore so that nobody can access the chip during init.
-	 */
-	bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
-
-	pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN |
-			__APP_PLL_212_P0_1(3U) |
-			__APP_PLL_212_JITLMT0_1(3U) |
-			__APP_PLL_212_CNTLMT0_1(3U);
-	pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN |
-			__APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) |
-			__APP_PLL_400_JITLMT0_1(3U) |
-			__APP_PLL_400_CNTLMT0_1(3U);
-
-	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
-	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
-
-	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
-			__APP_PLL_212_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
-			__APP_PLL_212_BYPASS |
-			__APP_PLL_212_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
-			__APP_PLL_400_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
-			__APP_PLL_400_BYPASS |
-			__APP_PLL_400_LOGIC_SOFT_RESET);
-	bfa_os_udelay(2);
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
-			__APP_PLL_212_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
-			__APP_PLL_400_LOGIC_SOFT_RESET);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
-			pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
-			pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET);
-
-	/**
-	 * Wait for PLLs to lock.
-	 */
-	bfa_os_udelay(2000);
-	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk);
-
-	/*
-	 *  release semaphore.
-	 */
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
-
-	return BFA_STATUS_OK;
-}
-
 /**
  * Cleanup hw semaphore and usecnt registers
  */
@@ -256,3 +183,54 @@
 	bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
 	bfa_ioc_hw_sem_release(ioc);
 }
+
+
+
+bfa_status_t
+bfa_ioc_cb_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode)
+{
+	u32	pll_sclk, pll_fclk;
+
+	pll_sclk = __APP_PLL_212_ENABLE | __APP_PLL_212_LRESETN |
+		__APP_PLL_212_P0_1(3U) |
+		__APP_PLL_212_JITLMT0_1(3U) |
+		__APP_PLL_212_CNTLMT0_1(3U);
+	pll_fclk = __APP_PLL_400_ENABLE | __APP_PLL_400_LRESETN |
+		__APP_PLL_400_RSEL200500 | __APP_PLL_400_P0_1(3U) |
+		__APP_PLL_400_JITLMT0_1(3U) |
+		__APP_PLL_400_CNTLMT0_1(3U);
+	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
+	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+	bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+			  __APP_PLL_212_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+			  __APP_PLL_212_BYPASS |
+			  __APP_PLL_212_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+			  __APP_PLL_400_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+			  __APP_PLL_400_BYPASS |
+			  __APP_PLL_400_LOGIC_SOFT_RESET);
+	bfa_os_udelay(2);
+	bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+			  __APP_PLL_212_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+			  __APP_PLL_400_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_212_CTL_REG,
+			  pll_sclk | __APP_PLL_212_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_400_CTL_REG,
+			  pll_fclk | __APP_PLL_400_LOGIC_SOFT_RESET);
+	bfa_os_udelay(2000);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + APP_PLL_212_CTL_REG), pll_sclk);
+	bfa_reg_write((rb + APP_PLL_400_CTL_REG), pll_fclk);
+
+	return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 68f027d..f21b82c 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,22 +15,15 @@
  * General Public License for more details.
  */
 
-#include <bfa.h>
-#include <bfa_ioc.h>
-#include <bfa_fwimg_priv.h>
-#include <cna/bfa_cna_trcmod.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_ioc.h>
-#include <bfi/bfi_ctreg.h>
-#include <log/bfa_log_hal.h>
-#include <defs/bfa_defs_pci.h>
+#include "bfa_ioc.h"
+#include "bfi_ctreg.h"
+#include "bfa_defs.h"
 
 BFA_TRC_FILE(CNA, IOC_CT);
 
 /*
  * forward declarations
  */
-static bfa_status_t bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc);
 static bfa_boolean_t bfa_ioc_ct_firmware_lock(struct bfa_ioc_s *ioc);
 static void bfa_ioc_ct_firmware_unlock(struct bfa_ioc_s *ioc);
 static void bfa_ioc_ct_reg_init(struct bfa_ioc_s *ioc);
@@ -78,7 +71,8 @@
 	/**
 	 * If bios boot (flash based) -- do not increment usage count
 	 */
-	if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ)
+	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+						BFA_IOC_FWIMG_MINSZ)
 		return BFA_TRUE;
 
 	bfa_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg);
@@ -136,7 +130,8 @@
 	/**
 	 * If bios boot (flash based) -- do not decrement usage count
 	 */
-	if (bfi_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < BFA_IOC_FWIMG_MINSZ)
+	if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) <
+						BFA_IOC_FWIMG_MINSZ)
 		return;
 
 	/**
@@ -308,111 +303,6 @@
 	bfa_reg_write(rb + FNC_PERS_REG, r32);
 }
 
-static bfa_status_t
-bfa_ioc_ct_pll_init(struct bfa_ioc_s *ioc)
-{
-	bfa_os_addr_t	rb = ioc->pcidev.pci_bar_kva;
-	u32	pll_sclk, pll_fclk, r32;
-
-	/*
-	 *  Hold semaphore so that nobody can access the chip during init.
-	 */
-	bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
-
-	pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
-		__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
-		__APP_PLL_312_JITLMT0_1(3U) |
-		__APP_PLL_312_CNTLMT0_1(1U);
-	pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
-		__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
-		__APP_PLL_425_JITLMT0_1(3U) |
-		__APP_PLL_425_CNTLMT0_1(1U);
-
-	/**
-	 *	For catapult, choose operational mode FC/FCoE
-	 */
-	if (ioc->fcmode) {
-		bfa_reg_write((rb + OP_MODE), 0);
-		bfa_reg_write((rb + ETH_MAC_SER_REG),
-				__APP_EMS_CMLCKSEL |
-				__APP_EMS_REFCKBUFEN2 |
-				__APP_EMS_CHANNEL_SEL);
-	} else {
-		ioc->pllinit = BFA_TRUE;
-		bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE);
-		bfa_reg_write((rb + ETH_MAC_SER_REG),
-				 __APP_EMS_REFCKBUFEN1);
-	}
-
-	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
-	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
-
-	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk |
-		__APP_PLL_312_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk |
-		__APP_PLL_425_LOGIC_SOFT_RESET);
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk |
-		__APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk |
-		__APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE);
-
-	/**
-	 * Wait for PLLs to lock.
-	 */
-	bfa_reg_read(rb + HOSTFN0_INT_MSK);
-	bfa_os_udelay(2000);
-	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
-	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
-
-	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk |
-		__APP_PLL_312_ENABLE);
-	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk |
-		__APP_PLL_425_ENABLE);
-
-	/**
-	 * PSS memory reset is asserted at power-on-reset. Need to clear
-	 * this before running EDRAM BISTR
-	 */
-	if (ioc->cna) {
-		bfa_reg_write((rb + PMM_1T_RESET_REG_P0), __PMM_1T_RESET_P);
-		bfa_reg_write((rb + PMM_1T_RESET_REG_P1), __PMM_1T_RESET_P);
-	}
-
-	r32 = bfa_reg_read((rb + PSS_CTL_REG));
-	r32 &= ~__PSS_LMEM_RESET;
-	bfa_reg_write((rb + PSS_CTL_REG), r32);
-	bfa_os_udelay(1000);
-
-	if (ioc->cna) {
-		bfa_reg_write((rb + PMM_1T_RESET_REG_P0), 0);
-		bfa_reg_write((rb + PMM_1T_RESET_REG_P1), 0);
-	}
-
-	bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START);
-	bfa_os_udelay(1000);
-	r32 = bfa_reg_read((rb + MBIST_STAT_REG));
-	bfa_trc(ioc, r32);
-
-	/**
-	 * Clear BISTR
-	 */
-	bfa_reg_write((rb + MBIST_CTL_REG), 0);
-
-	/*
-	 *  release semaphore.
-	 */
-	bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
-
-	return BFA_STATUS_OK;
-}
-
 /**
  * Cleanup hw semaphore and usecnt registers
  */
@@ -434,3 +324,86 @@
 	bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
 	bfa_ioc_hw_sem_release(ioc);
 }
+
+
+
+/*
+ * Check the firmware state to know if pll_init has been completed already
+ */
+bfa_boolean_t
+bfa_ioc_ct_pll_init_complete(bfa_os_addr_t rb)
+{
+	if ((bfa_reg_read(rb + BFA_IOC0_STATE_REG) == BFI_IOC_OP) ||
+	  (bfa_reg_read(rb + BFA_IOC1_STATE_REG) == BFI_IOC_OP))
+		return BFA_TRUE;
+
+	return BFA_FALSE;
+}
+
+bfa_status_t
+bfa_ioc_ct_pll_init(bfa_os_addr_t rb, bfa_boolean_t fcmode)
+{
+	u32	pll_sclk, pll_fclk, r32;
+
+	pll_sclk = __APP_PLL_312_LRESETN | __APP_PLL_312_ENARST |
+		__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(3U) |
+		__APP_PLL_312_JITLMT0_1(3U) |
+		__APP_PLL_312_CNTLMT0_1(1U);
+	pll_fclk = __APP_PLL_425_LRESETN | __APP_PLL_425_ENARST |
+		__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
+		__APP_PLL_425_JITLMT0_1(3U) |
+		__APP_PLL_425_CNTLMT0_1(1U);
+	if (fcmode) {
+		bfa_reg_write((rb + OP_MODE), 0);
+		bfa_reg_write((rb + ETH_MAC_SER_REG),
+				__APP_EMS_CMLCKSEL |
+				__APP_EMS_REFCKBUFEN2 |
+				__APP_EMS_CHANNEL_SEL);
+	} else {
+		bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE);
+		bfa_reg_write((rb + ETH_MAC_SER_REG),
+				__APP_EMS_REFCKBUFEN1);
+	}
+	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
+	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
+	bfa_reg_write(rb + APP_PLL_312_CTL_REG, pll_sclk |
+		__APP_PLL_312_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_425_CTL_REG, pll_fclk |
+		__APP_PLL_425_LOGIC_SOFT_RESET);
+	bfa_reg_write(rb + APP_PLL_312_CTL_REG, pll_sclk |
+		__APP_PLL_312_LOGIC_SOFT_RESET | __APP_PLL_312_ENABLE);
+	bfa_reg_write(rb + APP_PLL_425_CTL_REG, pll_fclk |
+		__APP_PLL_425_LOGIC_SOFT_RESET | __APP_PLL_425_ENABLE);
+	bfa_reg_read(rb + HOSTFN0_INT_MSK);
+	bfa_os_udelay(2000);
+	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
+	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
+	bfa_reg_write(rb + APP_PLL_312_CTL_REG, pll_sclk |
+		__APP_PLL_312_ENABLE);
+	bfa_reg_write(rb + APP_PLL_425_CTL_REG, pll_fclk |
+		__APP_PLL_425_ENABLE);
+	if (!fcmode) {
+		bfa_reg_write((rb + PMM_1T_RESET_REG_P0), __PMM_1T_RESET_P);
+		bfa_reg_write((rb + PMM_1T_RESET_REG_P1), __PMM_1T_RESET_P);
+	}
+	r32 = bfa_reg_read((rb + PSS_CTL_REG));
+	r32 &= ~__PSS_LMEM_RESET;
+	bfa_reg_write((rb + PSS_CTL_REG), r32);
+	bfa_os_udelay(1000);
+	if (!fcmode) {
+		bfa_reg_write((rb + PMM_1T_RESET_REG_P0), 0);
+		bfa_reg_write((rb + PMM_1T_RESET_REG_P1), 0);
+	}
+
+	bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START);
+	bfa_os_udelay(1000);
+	r32 = bfa_reg_read((rb + MBIST_STAT_REG));
+	bfa_reg_write((rb + MBIST_CTL_REG), 0);
+	return BFA_STATUS_OK;
+}
diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c
deleted file mode 100644
index 90820be..0000000
--- a/drivers/scsi/bfa/bfa_iocfc.c
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <cs/bfa_debug.h>
-#include <bfa_priv.h>
-#include <log/bfa_log_hal.h>
-#include <bfi/bfi_boot.h>
-#include <bfi/bfi_cbreg.h>
-#include <aen/bfa_aen_ioc.h>
-#include <defs/bfa_defs_iocfc.h>
-#include <defs/bfa_defs_pci.h>
-#include "bfa_callback_priv.h"
-#include "bfad_drv.h"
-
-BFA_TRC_FILE(HAL, IOCFC);
-
-/**
- * IOC local definitions
- */
-#define BFA_IOCFC_TOV		5000	/* msecs */
-
-enum {
-	BFA_IOCFC_ACT_NONE	= 0,
-	BFA_IOCFC_ACT_INIT	= 1,
-	BFA_IOCFC_ACT_STOP	= 2,
-	BFA_IOCFC_ACT_DISABLE	= 3,
-};
-
-/*
- * forward declarations
- */
-static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status);
-static void bfa_iocfc_disable_cbfn(void *bfa_arg);
-static void bfa_iocfc_hbfail_cbfn(void *bfa_arg);
-static void bfa_iocfc_reset_cbfn(void *bfa_arg);
-static void bfa_iocfc_stats_clear(void *bfa_arg);
-static void bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d,
-			struct bfa_fw_stats_s *s);
-static void bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete);
-static void bfa_iocfc_stats_clr_timeout(void *bfa_arg);
-static void bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete);
-static void bfa_iocfc_stats_timeout(void *bfa_arg);
-
-static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn;
-
-/**
- *  bfa_ioc_pvt BFA IOC private functions
- */
-
-static void
-bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
-	int             i, per_reqq_sz, per_rspq_sz;
-
-	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
-							BFA_DMA_ALIGN_SZ);
-	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
-							BFA_DMA_ALIGN_SZ);
-
-	/*
-	 * Calculate CQ size
-	 */
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		*dm_len = *dm_len + per_reqq_sz;
-		*dm_len = *dm_len + per_rspq_sz;
-	}
-
-	/*
-	 * Calculate Shadow CI/PI size
-	 */
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++)
-		*dm_len += (2 * BFA_CACHELINE_SZ);
-}
-
-static void
-bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len)
-{
-	*dm_len +=
-		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
-	*dm_len +=
-		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-			    BFA_CACHELINE_SZ);
-	*dm_len += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
-}
-
-/**
- * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ
- */
-static void
-bfa_iocfc_send_cfg(void *bfa_arg)
-{
-	struct bfa_s *bfa = bfa_arg;
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfg_req_s cfg_req;
-	struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo;
-	struct bfa_iocfc_cfg_s  *cfg = &iocfc->cfg;
-	int             i;
-
-	bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS);
-	bfa_trc(bfa, cfg->fwcfg.num_cqs);
-
-	bfa_iocfc_reset_queues(bfa);
-
-	/**
-	 * initialize IOC configuration info
-	 */
-	cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG;
-	cfg_info->num_cqs = cfg->fwcfg.num_cqs;
-
-	bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa);
-	bfa_dma_be_addr_set(cfg_info->stats_addr, iocfc->stats_pa);
-
-	/**
-	 * dma map REQ and RSP circular queues and shadow pointers
-	 */
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		bfa_dma_be_addr_set(cfg_info->req_cq_ba[i],
-				       iocfc->req_cq_ba[i].pa);
-		bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i],
-				       iocfc->req_cq_shadow_ci[i].pa);
-		cfg_info->req_cq_elems[i] =
-			bfa_os_htons(cfg->drvcfg.num_reqq_elems);
-
-		bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i],
-				       iocfc->rsp_cq_ba[i].pa);
-		bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i],
-				       iocfc->rsp_cq_shadow_pi[i].pa);
-		cfg_info->rsp_cq_elems[i] =
-			bfa_os_htons(cfg->drvcfg.num_rspq_elems);
-	}
-
-	/**
-	 * Enable interrupt coalescing if it is driver init path
-	 * and not ioc disable/enable path.
-	 */
-	if (!iocfc->cfgdone)
-		cfg_info->intr_attr.coalesce = BFA_TRUE;
-
-	iocfc->cfgdone = BFA_FALSE;
-
-	/**
-	 * dma map IOC configuration itself
-	 */
-	bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ,
-			bfa_lpuid(bfa));
-	bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa);
-
-	bfa_ioc_mbox_send(&bfa->ioc, &cfg_req,
-			sizeof(struct bfi_iocfc_cfg_req_s));
-}
-
-static void
-bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		    struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	bfa->bfad = bfad;
-	iocfc->bfa = bfa;
-	iocfc->action = BFA_IOCFC_ACT_NONE;
-
-	bfa_os_assign(iocfc->cfg, *cfg);
-
-	/**
-	 * Initialize chip specific handlers.
-	 */
-	if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) {
-		iocfc->hwif.hw_reginit = bfa_hwct_reginit;
-		iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack;
-		iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack;
-		iocfc->hwif.hw_msix_init = bfa_hwct_msix_init;
-		iocfc->hwif.hw_msix_install = bfa_hwct_msix_install;
-		iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall;
-		iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set;
-		iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs;
-		iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range;
-	} else {
-		iocfc->hwif.hw_reginit = bfa_hwcb_reginit;
-		iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack;
-		iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack;
-		iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init;
-		iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install;
-		iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall;
-		iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set;
-		iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs;
-		iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range;
-	}
-
-	iocfc->hwif.hw_reginit(bfa);
-	bfa->msix.nvecs = 0;
-}
-
-static void
-bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg,
-		      struct bfa_meminfo_s *meminfo)
-{
-	u8        *dm_kva;
-	u64        dm_pa;
-	int             i, per_reqq_sz, per_rspq_sz;
-	struct bfa_iocfc_s  *iocfc = &bfa->iocfc;
-	int		dbgsz;
-
-	dm_kva = bfa_meminfo_dma_virt(meminfo);
-	dm_pa = bfa_meminfo_dma_phys(meminfo);
-
-	/*
-	 * First allocate dma memory for IOC.
-	 */
-	bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa);
-	dm_kva += bfa_ioc_meminfo();
-	dm_pa  += bfa_ioc_meminfo();
-
-	/*
-	 * Claim DMA-able memory for the request/response queues and for shadow
-	 * ci/pi registers
-	 */
-	per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ),
-							BFA_DMA_ALIGN_SZ);
-	per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ),
-							BFA_DMA_ALIGN_SZ);
-
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		iocfc->req_cq_ba[i].kva = dm_kva;
-		iocfc->req_cq_ba[i].pa = dm_pa;
-		bfa_os_memset(dm_kva, 0, per_reqq_sz);
-		dm_kva += per_reqq_sz;
-		dm_pa += per_reqq_sz;
-
-		iocfc->rsp_cq_ba[i].kva = dm_kva;
-		iocfc->rsp_cq_ba[i].pa = dm_pa;
-		bfa_os_memset(dm_kva, 0, per_rspq_sz);
-		dm_kva += per_rspq_sz;
-		dm_pa += per_rspq_sz;
-	}
-
-	for (i = 0; i < cfg->fwcfg.num_cqs; i++) {
-		iocfc->req_cq_shadow_ci[i].kva = dm_kva;
-		iocfc->req_cq_shadow_ci[i].pa = dm_pa;
-		dm_kva += BFA_CACHELINE_SZ;
-		dm_pa += BFA_CACHELINE_SZ;
-
-		iocfc->rsp_cq_shadow_pi[i].kva = dm_kva;
-		iocfc->rsp_cq_shadow_pi[i].pa = dm_pa;
-		dm_kva += BFA_CACHELINE_SZ;
-		dm_pa += BFA_CACHELINE_SZ;
-	}
-
-	/*
-	 * Claim DMA-able memory for the config info page
-	 */
-	bfa->iocfc.cfg_info.kva = dm_kva;
-	bfa->iocfc.cfg_info.pa = dm_pa;
-	bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva;
-	dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
-	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ);
-
-	/*
-	 * Claim DMA-able memory for the config response
-	 */
-	bfa->iocfc.cfgrsp_dma.kva = dm_kva;
-	bfa->iocfc.cfgrsp_dma.pa = dm_pa;
-	bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva;
-
-	dm_kva +=
-		BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-			    BFA_CACHELINE_SZ);
-	dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s),
-			     BFA_CACHELINE_SZ);
-
-	/*
-	 * Claim DMA-able memory for iocfc stats
-	 */
-	bfa->iocfc.stats_kva = dm_kva;
-	bfa->iocfc.stats_pa = dm_pa;
-	bfa->iocfc.fw_stats = (struct bfa_fw_stats_s *) dm_kva;
-	dm_kva += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
-	dm_pa += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ);
-
-	bfa_meminfo_dma_virt(meminfo) = dm_kva;
-	bfa_meminfo_dma_phys(meminfo) = dm_pa;
-
-	dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover);
-	if (dbgsz > 0) {
-		bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo));
-		bfa_meminfo_kva(meminfo) += dbgsz;
-	}
-}
-
-/**
- * Start BFA submodules.
- */
-static void
-bfa_iocfc_start_submod(struct bfa_s *bfa)
-{
-	int             i;
-
-	bfa->rme_process = BFA_TRUE;
-
-	for (i = 0; hal_mods[i]; i++)
-		hal_mods[i]->start(bfa);
-}
-
-/**
- * Disable BFA submodules.
- */
-static void
-bfa_iocfc_disable_submod(struct bfa_s *bfa)
-{
-	int             i;
-
-	for (i = 0; hal_mods[i]; i++)
-		hal_mods[i]->iocdisable(bfa);
-}
-
-static void
-bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	if (complete) {
-		if (bfa->iocfc.cfgdone)
-			bfa_cb_init(bfa->bfad, BFA_STATUS_OK);
-		else
-			bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED);
-	} else {
-		if (bfa->iocfc.cfgdone)
-			bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
-	}
-}
-
-static void
-bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl)
-{
-	struct bfa_s  *bfa = bfa_arg;
-	struct bfad_s *bfad = bfa->bfad;
-
-	if (compl)
-		complete(&bfad->comp);
-
-	else
-		bfa->iocfc.action = BFA_IOCFC_ACT_NONE;
-}
-
-static void
-bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl)
-{
-	struct bfa_s  *bfa = bfa_arg;
-	struct bfad_s *bfad = bfa->bfad;
-
-	if (compl)
-		complete(&bfad->disable_comp);
-}
-
-/**
- * Update BFA configuration from firmware configuration.
- */
-static void
-bfa_iocfc_cfgrsp(struct bfa_s *bfa)
-{
-	struct bfa_iocfc_s		*iocfc	 = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s	*cfgrsp  = iocfc->cfgrsp;
-	struct bfa_iocfc_fwcfg_s	*fwcfg   = &cfgrsp->fwcfg;
-
-	fwcfg->num_cqs        = fwcfg->num_cqs;
-	fwcfg->num_ioim_reqs  = bfa_os_ntohs(fwcfg->num_ioim_reqs);
-	fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs);
-	fwcfg->num_fcxp_reqs  = bfa_os_ntohs(fwcfg->num_fcxp_reqs);
-	fwcfg->num_uf_bufs    = bfa_os_ntohs(fwcfg->num_uf_bufs);
-	fwcfg->num_rports     = bfa_os_ntohs(fwcfg->num_rports);
-
-	iocfc->cfgdone = BFA_TRUE;
-
-	/**
-	 * Configuration is complete - initialize/start submodules
-	 */
-	bfa_fcport_init(bfa);
-
-	if (iocfc->action == BFA_IOCFC_ACT_INIT)
-		bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa);
-	else
-		bfa_iocfc_start_submod(bfa);
-}
-
-static void
-bfa_iocfc_stats_clear(void *bfa_arg)
-{
-	struct bfa_s		*bfa = bfa_arg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-	struct bfi_iocfc_stats_req_s stats_req;
-
-	bfa_timer_start(bfa, &iocfc->stats_timer,
-			    bfa_iocfc_stats_clr_timeout, bfa,
-			    BFA_IOCFC_TOV);
-
-	bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CLEAR_STATS_REQ,
-		bfa_lpuid(bfa));
-	bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
-		sizeof(struct bfi_iocfc_stats_req_s));
-}
-
-static void
-bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d, struct bfa_fw_stats_s *s)
-{
-	u32       *dip = (u32 *) d;
-	u32       *sip = (u32 *) s;
-	int             i;
-
-	for (i = 0; i < (sizeof(struct bfa_fw_stats_s) / sizeof(u32)); i++)
-		dip[i] = bfa_os_ntohl(sip[i]);
-}
-
-static void
-bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete)
-{
-	struct bfa_s *bfa = bfa_arg;
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-
-	if (complete) {
-		bfa_ioc_clr_stats(&bfa->ioc);
-		iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
-	} else {
-		iocfc->stats_busy = BFA_FALSE;
-		iocfc->stats_status = BFA_STATUS_OK;
-	}
-}
-
-static void
-bfa_iocfc_stats_clr_timeout(void *bfa_arg)
-{
-	struct bfa_s		*bfa = bfa_arg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	bfa_trc(bfa, 0);
-
-	iocfc->stats_status = BFA_STATUS_ETIMER;
-	bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_clr_cb, bfa);
-}
-
-static void
-bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete)
-{
-	struct bfa_s		*bfa = bfa_arg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	if (complete) {
-		if (iocfc->stats_status == BFA_STATUS_OK) {
-			bfa_os_memset(iocfc->stats_ret, 0,
-				sizeof(*iocfc->stats_ret));
-			bfa_iocfc_stats_swap(&iocfc->stats_ret->fw_stats,
-				iocfc->fw_stats);
-		}
-		iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status);
-	} else {
-		iocfc->stats_busy = BFA_FALSE;
-		iocfc->stats_status = BFA_STATUS_OK;
-	}
-}
-
-static void
-bfa_iocfc_stats_timeout(void *bfa_arg)
-{
-	struct bfa_s		*bfa = bfa_arg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	bfa_trc(bfa, 0);
-
-	iocfc->stats_status = BFA_STATUS_ETIMER;
-	bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb, bfa);
-}
-
-static void
-bfa_iocfc_stats_query(struct bfa_s *bfa)
-{
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-	struct bfi_iocfc_stats_req_s stats_req;
-
-	bfa_timer_start(bfa, &iocfc->stats_timer,
-			    bfa_iocfc_stats_timeout, bfa, BFA_IOCFC_TOV);
-
-	bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_GET_STATS_REQ,
-			bfa_lpuid(bfa));
-	bfa_ioc_mbox_send(&bfa->ioc, &stats_req,
-		sizeof(struct bfi_iocfc_stats_req_s));
-}
-
-void
-bfa_iocfc_reset_queues(struct bfa_s *bfa)
-{
-	int             q;
-
-	for (q = 0; q < BFI_IOC_MAX_CQS; q++) {
-		bfa_reqq_ci(bfa, q) = 0;
-		bfa_reqq_pi(bfa, q) = 0;
-		bfa_rspq_ci(bfa, q) = 0;
-		bfa_rspq_pi(bfa, q) = 0;
-	}
-}
-
-/**
- * IOC enable request is complete
- */
-static void
-bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	if (status != BFA_STATUS_OK) {
-		bfa_isr_disable(bfa);
-		if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
-			bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe,
-				     bfa_iocfc_init_cb, bfa);
-		return;
-	}
-
-	bfa_iocfc_send_cfg(bfa);
-}
-
-/**
- * IOC disable request is complete
- */
-static void
-bfa_iocfc_disable_cbfn(void *bfa_arg)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	bfa_isr_disable(bfa);
-	bfa_iocfc_disable_submod(bfa);
-
-	if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP)
-		bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb,
-			     bfa);
-	else {
-		bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE);
-		bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb,
-			     bfa);
-	}
-}
-
-/**
- * Notify sub-modules of hardware failure.
- */
-static void
-bfa_iocfc_hbfail_cbfn(void *bfa_arg)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	bfa->rme_process = BFA_FALSE;
-
-	bfa_isr_disable(bfa);
-	bfa_iocfc_disable_submod(bfa);
-
-	if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT)
-		bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb,
-			     bfa);
-}
-
-/**
- * Actions on chip-reset completion.
- */
-static void
-bfa_iocfc_reset_cbfn(void *bfa_arg)
-{
-	struct bfa_s	*bfa = bfa_arg;
-
-	bfa_iocfc_reset_queues(bfa);
-	bfa_isr_enable(bfa);
-}
-
-
-
-/**
- *  bfa_ioc_public
- */
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
-{
-	/* dma memory for IOC */
-	*dm_len += bfa_ioc_meminfo();
-
-	bfa_iocfc_fw_cfg_sz(cfg, dm_len);
-	bfa_iocfc_cqs_sz(cfg, dm_len);
-	*km_len += bfa_ioc_debug_trcsz(bfa_auto_recover);
-}
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		   struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	int             i;
-
-	bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn;
-	bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn;
-	bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn;
-	bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn;
-
-	bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod,
-		bfa->trcmod, bfa->aen, bfa->logm);
-
-	/**
-	 * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC.
-	 */
-	if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC)
-		bfa_ioc_set_fcmode(&bfa->ioc);
-
-	bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC);
-	bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs);
-
-	bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev);
-	bfa_iocfc_mem_claim(bfa, cfg, meminfo);
-	bfa_timer_init(&bfa->timer_mod);
-
-	INIT_LIST_HEAD(&bfa->comp_q);
-	for (i = 0; i < BFI_IOC_MAX_CQS; i++)
-		INIT_LIST_HEAD(&bfa->reqq_waitq[i]);
-}
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_detach(struct bfa_s *bfa)
-{
-	bfa_ioc_detach(&bfa->ioc);
-}
-
-/**
- * Query IOC memory requirement information.
- */
-void
-bfa_iocfc_init(struct bfa_s *bfa)
-{
-	bfa->iocfc.action = BFA_IOCFC_ACT_INIT;
-	bfa_ioc_enable(&bfa->ioc);
-}
-
-/**
- * IOC start called from bfa_start(). Called to start IOC operations
- * at driver instantiation for this instance.
- */
-void
-bfa_iocfc_start(struct bfa_s *bfa)
-{
-	if (bfa->iocfc.cfgdone)
-		bfa_iocfc_start_submod(bfa);
-}
-
-/**
- * IOC stop called from bfa_stop(). Called only when driver is unloaded
- * for this instance.
- */
-void
-bfa_iocfc_stop(struct bfa_s *bfa)
-{
-	bfa->iocfc.action = BFA_IOCFC_ACT_STOP;
-
-	bfa->rme_process = BFA_FALSE;
-	bfa_ioc_disable(&bfa->ioc);
-}
-
-void
-bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m)
-{
-	struct bfa_s		*bfa = bfaarg;
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-	union bfi_iocfc_i2h_msg_u	*msg;
-
-	msg = (union bfi_iocfc_i2h_msg_u *) m;
-	bfa_trc(bfa, msg->mh.msg_id);
-
-	switch (msg->mh.msg_id) {
-	case BFI_IOCFC_I2H_CFG_REPLY:
-		iocfc->cfg_reply = &msg->cfg_reply;
-		bfa_iocfc_cfgrsp(bfa);
-		break;
-
-	case BFI_IOCFC_I2H_GET_STATS_RSP:
-		if (iocfc->stats_busy == BFA_FALSE
-		    || iocfc->stats_status == BFA_STATUS_ETIMER)
-			break;
-
-		bfa_timer_stop(&iocfc->stats_timer);
-		iocfc->stats_status = BFA_STATUS_OK;
-		bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb,
-			      bfa);
-		break;
-	case BFI_IOCFC_I2H_CLEAR_STATS_RSP:
-		/*
-		 * check for timer pop before processing the rsp
-		 */
-		if (iocfc->stats_busy == BFA_FALSE
-		    || iocfc->stats_status == BFA_STATUS_ETIMER)
-			break;
-
-		bfa_timer_stop(&iocfc->stats_timer);
-		iocfc->stats_status = BFA_STATUS_OK;
-		bfa_cb_queue(bfa, &iocfc->stats_hcb_qe,
-			      bfa_iocfc_stats_clr_cb, bfa);
-		break;
-	case BFI_IOCFC_I2H_UPDATEQ_RSP:
-		iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK);
-		break;
-	default:
-		bfa_assert(0);
-	}
-}
-
-#ifndef BFA_BIOS_BUILD
-void
-bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr)
-{
-	bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr);
-}
-
-u64
-bfa_adapter_get_id(struct bfa_s *bfa)
-{
-	return bfa_ioc_get_adid(&bfa->ioc);
-}
-
-void
-bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr)
-{
-	struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
-
-	attr->intr_attr.coalesce = iocfc->cfginfo->intr_attr.coalesce;
-
-	attr->intr_attr.delay = iocfc->cfginfo->intr_attr.delay ?
-			bfa_os_ntohs(iocfc->cfginfo->intr_attr.delay) :
-			bfa_os_ntohs(iocfc->cfgrsp->intr_attr.delay);
-
-	attr->intr_attr.latency = iocfc->cfginfo->intr_attr.latency ?
-			bfa_os_ntohs(iocfc->cfginfo->intr_attr.latency) :
-			bfa_os_ntohs(iocfc->cfgrsp->intr_attr.latency);
-
-	attr->config    = iocfc->cfg;
-
-}
-
-bfa_status_t
-bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr)
-{
-	struct bfa_iocfc_s		*iocfc = &bfa->iocfc;
-	struct bfi_iocfc_set_intr_req_s *m;
-
-	iocfc->cfginfo->intr_attr.coalesce = attr->coalesce;
-	iocfc->cfginfo->intr_attr.delay = bfa_os_htons(attr->delay);
-	iocfc->cfginfo->intr_attr.latency = bfa_os_htons(attr->latency);
-
-	if (!bfa_iocfc_is_operational(bfa))
-		return BFA_STATUS_OK;
-
-	m = bfa_reqq_next(bfa, BFA_REQQ_IOC);
-	if (!m)
-		return BFA_STATUS_DEVBUSY;
-
-	bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ,
-			bfa_lpuid(bfa));
-	m->coalesce = iocfc->cfginfo->intr_attr.coalesce;
-	m->delay    = iocfc->cfginfo->intr_attr.delay;
-	m->latency  = iocfc->cfginfo->intr_attr.latency;
-
-
-	bfa_trc(bfa, attr->delay);
-	bfa_trc(bfa, attr->latency);
-
-	bfa_reqq_produce(bfa, BFA_REQQ_IOC);
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa)
-{
-	struct bfa_iocfc_s      *iocfc = &bfa->iocfc;
-
-	iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1);
-	bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa);
-}
-
-bfa_status_t
-bfa_iocfc_get_stats(struct bfa_s *bfa, struct bfa_iocfc_stats_s *stats,
-		      bfa_cb_ioc_t cbfn, void *cbarg)
-{
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	if (iocfc->stats_busy) {
-		bfa_trc(bfa, iocfc->stats_busy);
-		return BFA_STATUS_DEVBUSY;
-	}
-
-	if (!bfa_iocfc_is_operational(bfa)) {
-		bfa_trc(bfa, 0);
-		return BFA_STATUS_IOC_NON_OP;
-	}
-
-	iocfc->stats_busy = BFA_TRUE;
-	iocfc->stats_ret = stats;
-	iocfc->stats_cbfn = cbfn;
-	iocfc->stats_cbarg = cbarg;
-
-	bfa_iocfc_stats_query(bfa);
-
-	return BFA_STATUS_OK;
-}
-
-bfa_status_t
-bfa_iocfc_clear_stats(struct bfa_s *bfa, bfa_cb_ioc_t cbfn, void *cbarg)
-{
-	struct bfa_iocfc_s	*iocfc = &bfa->iocfc;
-
-	if (iocfc->stats_busy) {
-		bfa_trc(bfa, iocfc->stats_busy);
-		return BFA_STATUS_DEVBUSY;
-	}
-
-	if (!bfa_iocfc_is_operational(bfa)) {
-		bfa_trc(bfa, 0);
-		return BFA_STATUS_IOC_NON_OP;
-	}
-
-	iocfc->stats_busy = BFA_TRUE;
-	iocfc->stats_cbfn = cbfn;
-	iocfc->stats_cbarg = cbarg;
-
-	bfa_iocfc_stats_clear(bfa);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Enable IOC after it is disabled.
- */
-void
-bfa_iocfc_enable(struct bfa_s *bfa)
-{
-	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
-		     "IOC Enable");
-	bfa_ioc_enable(&bfa->ioc);
-}
-
-void
-bfa_iocfc_disable(struct bfa_s *bfa)
-{
-	bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0,
-		     "IOC Disable");
-	bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE;
-
-	bfa->rme_process = BFA_FALSE;
-	bfa_ioc_disable(&bfa->ioc);
-}
-
-
-bfa_boolean_t
-bfa_iocfc_is_operational(struct bfa_s *bfa)
-{
-	return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone;
-}
-
-/**
- * Return boot target port wwns -- read from boot information in flash.
- */
-void
-bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns)
-{
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-	int i;
-
-	if (cfgrsp->pbc_cfg.boot_enabled && cfgrsp->pbc_cfg.nbluns) {
-		bfa_trc(bfa, cfgrsp->pbc_cfg.nbluns);
-		*nwwns = cfgrsp->pbc_cfg.nbluns;
-		for (i = 0; i < cfgrsp->pbc_cfg.nbluns; i++)
-			wwns[i] = cfgrsp->pbc_cfg.blun[i].tgt_pwwn;
-
-		return;
-	}
-
-	*nwwns = cfgrsp->bootwwns.nwwns;
-	memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn));
-}
-
-void
-bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg)
-{
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled;
-	pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns;
-	pbcfg->speed = cfgrsp->pbc_cfg.port_speed;
-	memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun));
-}
-
-int
-bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport)
-{
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
-
-	memcpy(pbc_vport, cfgrsp->pbc_cfg.vport, sizeof(cfgrsp->pbc_cfg.vport));
-	return cfgrsp->pbc_cfg.nvports;
-}
-
-
-#endif
-
-
diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h
deleted file mode 100644
index 74a6a04..0000000
--- a/drivers/scsi/bfa/bfa_iocfc.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_IOCFC_H__
-#define __BFA_IOCFC_H__
-
-#include <bfa_ioc.h>
-#include <bfa.h>
-#include <bfi/bfi_iocfc.h>
-#include <bfi/bfi_pbc.h>
-#include <bfa_callback_priv.h>
-
-#define BFA_REQQ_NELEMS_MIN	(4)
-#define BFA_RSPQ_NELEMS_MIN	(4)
-
-struct bfa_iocfc_regs_s {
-	bfa_os_addr_t   intr_status;
-	bfa_os_addr_t   intr_mask;
-	bfa_os_addr_t   cpe_q_pi[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   cpe_q_ci[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   cpe_q_depth[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   cpe_q_ctrl[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   rme_q_ci[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   rme_q_pi[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   rme_q_depth[BFI_IOC_MAX_CQS];
-	bfa_os_addr_t   rme_q_ctrl[BFI_IOC_MAX_CQS];
-};
-
-/**
- * MSIX vector handlers
- */
-#define BFA_MSIX_MAX_VECTORS	22
-typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec);
-struct bfa_msix_s {
-	int	nvecs;
-	bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS];
-};
-
-/**
- * Chip specific interfaces
- */
-struct bfa_hwif_s {
-	void (*hw_reginit)(struct bfa_s *bfa);
-	void (*hw_reqq_ack)(struct bfa_s *bfa, int reqq);
-	void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq);
-	void (*hw_msix_init)(struct bfa_s *bfa, int nvecs);
-	void (*hw_msix_install)(struct bfa_s *bfa);
-	void (*hw_msix_uninstall)(struct bfa_s *bfa);
-	void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix);
-	void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap,
-			u32 *nvecs, u32 *maxvec);
-	void (*hw_msix_get_rme_range) (struct bfa_s *bfa, u32 *start,
-			u32 *end);
-};
-typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status);
-
-struct bfa_iocfc_s {
-	struct bfa_s 		*bfa;
-	struct bfa_iocfc_cfg_s 	cfg;
-	int			action;
-
-	u32        	req_cq_pi[BFI_IOC_MAX_CQS];
-	u32        	rsp_cq_ci[BFI_IOC_MAX_CQS];
-
-	struct bfa_cb_qe_s	init_hcb_qe;
-	struct bfa_cb_qe_s	stop_hcb_qe;
-	struct bfa_cb_qe_s	dis_hcb_qe;
-	struct bfa_cb_qe_s	stats_hcb_qe;
-	bfa_boolean_t		cfgdone;
-
-	struct bfa_dma_s	cfg_info;
-	struct bfi_iocfc_cfg_s *cfginfo;
-	struct bfa_dma_s	cfgrsp_dma;
-	struct bfi_iocfc_cfgrsp_s *cfgrsp;
-	struct bfi_iocfc_cfg_reply_s *cfg_reply;
-
-	u8			*stats_kva;
-	u64		stats_pa;
-	struct bfa_fw_stats_s 	*fw_stats;
-	struct bfa_timer_s 	stats_timer;	/*  timer */
-	struct bfa_iocfc_stats_s *stats_ret;	/*  driver stats location */
-	bfa_status_t		stats_status;	/*  stats/statsclr status */
-	bfa_boolean_t   	stats_busy;	/*  outstanding stats */
-	bfa_cb_ioc_t		stats_cbfn;	/*  driver callback function */
-	void           		*stats_cbarg;	/*  user callback arg */
-
-	struct bfa_dma_s   	req_cq_ba[BFI_IOC_MAX_CQS];
-	struct bfa_dma_s   	req_cq_shadow_ci[BFI_IOC_MAX_CQS];
-	struct bfa_dma_s   	rsp_cq_ba[BFI_IOC_MAX_CQS];
-	struct bfa_dma_s   	rsp_cq_shadow_pi[BFI_IOC_MAX_CQS];
-	struct bfa_iocfc_regs_s	bfa_regs;	/*  BFA device registers */
-	struct bfa_hwif_s	hwif;
-
-	bfa_cb_iocfc_t		updateq_cbfn; /*  bios callback function */
-	void			*updateq_cbarg;	/*  bios callback arg */
-	u32			intr_mask;
-};
-
-#define bfa_lpuid(__bfa)		bfa_ioc_portid(&(__bfa)->ioc)
-#define bfa_msix_init(__bfa, __nvecs)	\
-	((__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs))
-#define bfa_msix_install(__bfa)	\
-	((__bfa)->iocfc.hwif.hw_msix_install(__bfa))
-#define bfa_msix_uninstall(__bfa)	\
-	((__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa))
-#define bfa_isr_mode_set(__bfa, __msix)	\
-	((__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix))
-#define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec)	\
-	((__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap,	\
-		 __nvecs, __maxvec))
-#define bfa_msix_get_rme_range(__bfa, __start, __end)   \
-	((__bfa)->iocfc.hwif.hw_msix_get_rme_range(__bfa, __start, __end))
-
-/*
- * FC specific IOC functions.
- */
-void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len);
-void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad,
-		struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
-		struct bfa_pcidev_s *pcidev);
-void bfa_iocfc_detach(struct bfa_s *bfa);
-void bfa_iocfc_init(struct bfa_s *bfa);
-void bfa_iocfc_start(struct bfa_s *bfa);
-void bfa_iocfc_stop(struct bfa_s *bfa);
-void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg);
-void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa);
-bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa);
-void bfa_iocfc_reset_queues(struct bfa_s *bfa);
-void bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
-			u32 reqq_sci, u32 rspq_spi,
-			bfa_cb_iocfc_t cbfn, void *cbarg);
-
-void bfa_msix_all(struct bfa_s *bfa, int vec);
-void bfa_msix_reqq(struct bfa_s *bfa, int vec);
-void bfa_msix_rspq(struct bfa_s *bfa, int vec);
-void bfa_msix_lpu_err(struct bfa_s *bfa, int vec);
-
-void bfa_hwcb_reginit(struct bfa_s *bfa);
-void bfa_hwcb_reqq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwcb_msix_install(struct bfa_s *bfa);
-void bfa_hwcb_msix_uninstall(struct bfa_s *bfa);
-void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
-void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
-			u32 *nvecs, u32 *maxvec);
-void bfa_hwcb_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end);
-void bfa_hwct_reginit(struct bfa_s *bfa);
-void bfa_hwct_reqq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq);
-void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs);
-void bfa_hwct_msix_install(struct bfa_s *bfa);
-void bfa_hwct_msix_uninstall(struct bfa_s *bfa);
-void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix);
-void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap,
-			u32 *nvecs, u32 *maxvec);
-void bfa_hwct_msix_get_rme_range(struct bfa_s *bfa, u32 *start, u32 *end);
-
-void bfa_com_meminfo(bfa_boolean_t mincfg, u32 *dm_len);
-void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi,
-		bfa_boolean_t mincfg);
-void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns);
-void bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa,
-		struct bfa_boot_pbc_s *pbcfg);
-int bfa_iocfc_get_pbc_vports(struct bfa_s *bfa,
-		struct bfi_pbc_vport_s *pbc_vport);
-
-#endif /* __BFA_IOCFC_H__ */
-
diff --git a/drivers/scsi/bfa/bfa_iocfc_q.c b/drivers/scsi/bfa/bfa_iocfc_q.c
deleted file mode 100644
index 500a17d..0000000
--- a/drivers/scsi/bfa/bfa_iocfc_q.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include "bfa_intr_priv.h"
-
-BFA_TRC_FILE(HAL, IOCFC_Q);
-
-void
-bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba,
-				u32 reqq_sci, u32 rspq_spi, bfa_cb_iocfc_t cbfn,
-				void *cbarg)
-{
-	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
-	struct bfi_iocfc_updateq_req_s updateq_req;
-
-	iocfc->updateq_cbfn = cbfn;
-	iocfc->updateq_cbarg = cbarg;
-
-	bfi_h2i_set(updateq_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_UPDATEQ_REQ,
-			bfa_lpuid(bfa));
-
-	updateq_req.reqq_ba = bfa_os_htonl(reqq_ba);
-	updateq_req.rspq_ba = bfa_os_htonl(rspq_ba);
-	updateq_req.reqq_sci = bfa_os_htonl(reqq_sci);
-	updateq_req.rspq_spi = bfa_os_htonl(rspq_spi);
-
-	bfa_ioc_mbox_send(&bfa->ioc, &updateq_req,
-			sizeof(struct bfi_iocfc_updateq_req_s));
-}
diff --git a/drivers/scsi/bfa/bfa_ioim.c b/drivers/scsi/bfa/bfa_ioim.c
deleted file mode 100644
index bdfdc19..0000000
--- a/drivers/scsi/bfa/bfa_ioim.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include <cs/bfa_debug.h>
-#include <bfa_cb_ioim_macros.h>
-
-BFA_TRC_FILE(HAL, IOIM);
-
-/*
- * forward declarations.
- */
-static bfa_boolean_t	bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim);
-static bfa_boolean_t	bfa_ioim_sge_setup(struct bfa_ioim_s *ioim);
-static void		bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim);
-static bfa_boolean_t	bfa_ioim_send_abort(struct bfa_ioim_s *ioim);
-static void		bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim);
-static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
-
-/**
- *  bfa_ioim_sm
- */
-
-/**
- * IO state machine events
- */
-enum bfa_ioim_event {
-	BFA_IOIM_SM_START = 1,		/*  io start request from host */
-	BFA_IOIM_SM_COMP_GOOD = 2,	/*  io good comp, resource free */
-	BFA_IOIM_SM_COMP = 3,		/*  io comp, resource is free */
-	BFA_IOIM_SM_COMP_UTAG = 4,	/*  io comp, resource is free */
-	BFA_IOIM_SM_DONE = 5,		/*  io comp, resource not free */
-	BFA_IOIM_SM_FREE = 6,		/*  io resource is freed */
-	BFA_IOIM_SM_ABORT = 7,		/*  abort request from scsi stack */
-	BFA_IOIM_SM_ABORT_COMP = 8,	/*  abort from f/w */
-	BFA_IOIM_SM_ABORT_DONE = 9,	/*  abort completion from f/w */
-	BFA_IOIM_SM_QRESUME = 10,	/*  CQ space available to queue IO */
-	BFA_IOIM_SM_SGALLOCED = 11,	/*  SG page allocation successful */
-	BFA_IOIM_SM_SQRETRY = 12,	/*  sequence recovery retry */
-	BFA_IOIM_SM_HCB	= 13,		/*  bfa callback complete */
-	BFA_IOIM_SM_CLEANUP = 14,	/*  IO cleanup from itnim */
-	BFA_IOIM_SM_TMSTART = 15,	/*  IO cleanup from tskim */
-	BFA_IOIM_SM_TMDONE = 16,	/*  IO cleanup from tskim */
-	BFA_IOIM_SM_HWFAIL = 17,	/*  IOC h/w failure event */
-	BFA_IOIM_SM_IOTOV = 18,		/*  ITN offline TOV       */
-};
-
-/*
- * forward declaration of IO state machine
- */
-static void     bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim,
-				       enum bfa_ioim_event event);
-static void     bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim,
-					enum bfa_ioim_event event);
-static void     bfa_ioim_sm_active(struct bfa_ioim_s *ioim,
-				       enum bfa_ioim_event event);
-static void     bfa_ioim_sm_abort(struct bfa_ioim_s *ioim,
-				      enum bfa_ioim_event event);
-static void     bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim,
-					enum bfa_ioim_event event);
-static void     bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim,
-				      enum bfa_ioim_event event);
-static void     bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim,
-					    enum bfa_ioim_event event);
-static void     bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim,
-					      enum bfa_ioim_event event);
-static void     bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim,
-				    enum bfa_ioim_event event);
-static void     bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim,
-					 enum bfa_ioim_event event);
-static void     bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim,
-					enum bfa_ioim_event event);
-
-/**
- * 		IO is not started (unallocated).
- */
-static void
-bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_START:
-		if (!bfa_itnim_is_online(ioim->itnim)) {
-			if (!bfa_itnim_hold_io(ioim->itnim)) {
-				bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-				list_del(&ioim->qe);
-				list_add_tail(&ioim->qe,
-						&ioim->fcpim->ioim_comp_q);
-				bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-						__bfa_cb_ioim_pathtov, ioim);
-			} else {
-				list_del(&ioim->qe);
-				list_add_tail(&ioim->qe,
-						&ioim->itnim->pending_q);
-			}
-			break;
-		}
-
-		if (ioim->nsges > BFI_SGE_INLINE) {
-			if (!bfa_ioim_sge_setup(ioim)) {
-				bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc);
-				return;
-			}
-		}
-
-		if (!bfa_ioim_send_ioreq(ioim)) {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
-			break;
-		}
-
-		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
-		break;
-
-	case BFA_IOIM_SM_IOTOV:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-				__bfa_cb_ioim_pathtov, ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		/**
-		 * IO in pending queue can get abort requests. Complete abort
-		 * requests immediately.
-		 */
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim));
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-				ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		IO is waiting for SG pages.
- */
-static void
-bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_SGALLOCED:
-		if (!bfa_ioim_send_ioreq(ioim)) {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_qfull);
-			break;
-		}
-		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		IO is active.
- */
-static void
-bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_COMP_GOOD:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
-			      __bfa_cb_ioim_good_comp, ioim);
-		break;
-
-	case BFA_IOIM_SM_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		ioim->iosp->abort_explicit = BFA_TRUE;
-		ioim->io_cbfn = __bfa_cb_ioim_abort;
-
-		if (bfa_ioim_send_abort(ioim))
-			bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
-		else {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull);
-			bfa_reqq_wait(ioim->bfa, ioim->reqq,
-					&ioim->iosp->reqq_wait);
-		}
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		ioim->iosp->abort_explicit = BFA_FALSE;
-		ioim->io_cbfn = __bfa_cb_ioim_failed;
-
-		if (bfa_ioim_send_abort(ioim))
-			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
-		else {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
-			bfa_reqq_wait(ioim->bfa, ioim->reqq,
-					&ioim->iosp->reqq_wait);
-		}
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		IO is being aborted, waiting for completion from firmware.
- */
-static void
-bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_COMP_GOOD:
-	case BFA_IOIM_SM_COMP:
-	case BFA_IOIM_SM_DONE:
-	case BFA_IOIM_SM_FREE:
-		break;
-
-	case BFA_IOIM_SM_ABORT_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_COMP_UTAG:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
-		ioim->iosp->abort_explicit = BFA_FALSE;
-
-		if (bfa_ioim_send_abort(ioim))
-			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
-		else {
-			bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
-			bfa_reqq_wait(ioim->bfa, ioim->reqq,
-					  &ioim->iosp->reqq_wait);
-		}
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * IO is being cleaned up (implicit abort), waiting for completion from
- * firmware.
- */
-static void
-bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_COMP_GOOD:
-	case BFA_IOIM_SM_COMP:
-	case BFA_IOIM_SM_DONE:
-	case BFA_IOIM_SM_FREE:
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		/**
-		 * IO is already being aborted implicitly
-		 */
-		ioim->io_cbfn = __bfa_cb_ioim_abort;
-		break;
-
-	case BFA_IOIM_SM_ABORT_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_COMP_UTAG:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		/**
-		 * IO can be in cleanup state already due to TM command. 2nd cleanup
-		 * request comes from ITN offline event.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		IO is waiting for room in request CQ
- */
-static void
-bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_QRESUME:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_active);
-		bfa_ioim_send_ioreq(ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		Active IO is being aborted, waiting for room in request CQ.
- */
-static void
-bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_QRESUME:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_abort);
-		bfa_ioim_send_abort(ioim);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE);
-		ioim->iosp->abort_explicit = BFA_FALSE;
-		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull);
-		break;
-
-	case BFA_IOIM_SM_COMP_GOOD:
-	case BFA_IOIM_SM_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort,
-			      ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * 		Active IO is being cleaned up, waiting for room in request CQ.
- */
-static void
-bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_QRESUME:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup);
-		bfa_ioim_send_abort(ioim);
-		break;
-
-	case BFA_IOIM_SM_ABORT:
-		/**
-		 * IO is already being cleaned up implicitly
-		 */
-		ioim->io_cbfn = __bfa_cb_ioim_abort;
-		break;
-
-	case BFA_IOIM_SM_COMP_GOOD:
-	case BFA_IOIM_SM_COMP:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_DONE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		bfa_reqq_wcancel(&ioim->iosp->reqq_wait);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed,
-			      ioim);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * IO bfa callback is pending.
- */
-static void
-bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_trc_fp(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_HCB:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-		bfa_ioim_free(ioim);
-		bfa_cb_ioim_resfree(ioim->bfa->bfad);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * IO bfa callback is pending. IO resource cannot be freed.
- */
-static void
-bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_HCB:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_resfree);
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q);
-		break;
-
-	case BFA_IOIM_SM_FREE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-/**
- * IO is completed, waiting resource free from firmware.
- */
-static void
-bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, event);
-
-	switch (event) {
-	case BFA_IOIM_SM_FREE:
-		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-		bfa_ioim_free(ioim);
-		bfa_cb_ioim_resfree(ioim->bfa->bfad);
-		break;
-
-	case BFA_IOIM_SM_CLEANUP:
-		bfa_ioim_notify_cleanup(ioim);
-		break;
-
-	case BFA_IOIM_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_sm_fault(ioim->bfa, event);
-	}
-}
-
-
-
-/**
- *  bfa_ioim_private
- */
-
-static void
-__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio);
-}
-
-static void
-__bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s	*ioim = cbarg;
-	struct bfi_ioim_rsp_s *m;
-	u8		*snsinfo = NULL;
-	u8         sns_len = 0;
-	s32         residue = 0;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
-	if (m->io_status == BFI_IOIM_STS_OK) {
-		/**
-		 * setup sense information, if present
-		 */
-		if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION
-					&& m->sns_len) {
-			sns_len = m->sns_len;
-			snsinfo = ioim->iosp->snsinfo;
-		}
-
-		/**
-		 * setup residue value correctly for normal completions
-		 */
-		if (m->resid_flags == FCP_RESID_UNDER)
-			residue = bfa_os_ntohl(m->residue);
-		if (m->resid_flags == FCP_RESID_OVER) {
-			residue = bfa_os_ntohl(m->residue);
-			residue = -residue;
-		}
-	}
-
-	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status,
-			  m->scsi_status, sns_len, snsinfo, residue);
-}
-
-static void
-__bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
-			  0, 0, NULL, 0);
-}
-
-static void
-__bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
-			  0, 0, NULL, 0);
-}
-
-static void
-__bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
-		return;
-	}
-
-	bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
-}
-
-static void
-bfa_ioim_sgpg_alloced(void *cbarg)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
-	list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q);
-	bfa_ioim_sgpg_setup(ioim);
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED);
-}
-
-/**
- * Send I/O request to firmware.
- */
-static          bfa_boolean_t
-bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim)
-{
-	struct bfa_itnim_s *itnim = ioim->itnim;
-	struct bfi_ioim_req_s *m;
-	static struct fcp_cmnd_s cmnd_z0 = { 0 };
-	struct bfi_sge_s      *sge;
-	u32        pgdlen = 0;
-	u64 addr;
-	struct scatterlist *sg;
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
-	if (!m) {
-		bfa_reqq_wait(ioim->bfa, ioim->reqq,
-				  &ioim->iosp->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	/**
-	 * build i/o request message next
-	 */
-	m->io_tag = bfa_os_htons(ioim->iotag);
-	m->rport_hdl = ioim->itnim->rport->fw_handle;
-	m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio);
-
-	/**
-	 * build inline IO SG element here
-	 */
-	sge = &m->sges[0];
-	if (ioim->nsges) {
-		sg = (struct scatterlist *)scsi_sglist(cmnd);
-		addr = bfa_os_sgaddr(sg_dma_address(sg));
-		sge->sga = *(union bfi_addr_u *) &addr;
-		pgdlen = sg_dma_len(sg);
-		sge->sg_len = pgdlen;
-		sge->flags = (ioim->nsges > BFI_SGE_INLINE) ?
-					BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST;
-		bfa_sge_to_be(sge);
-		sge++;
-	}
-
-	if (ioim->nsges > BFI_SGE_INLINE) {
-		sge->sga = ioim->sgpg->sgpg_pa;
-	} else {
-		sge->sga.a32.addr_lo = 0;
-		sge->sga.a32.addr_hi = 0;
-	}
-	sge->sg_len = pgdlen;
-	sge->flags = BFI_SGE_PGDLEN;
-	bfa_sge_to_be(sge);
-
-	/**
-	 * set up I/O command parameters
-	 */
-	bfa_os_assign(m->cmnd, cmnd_z0);
-	m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio);
-	m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio);
-	bfa_os_assign(m->cmnd.cdb,
-			*(struct scsi_cdb_s *)bfa_cb_ioim_get_cdb(ioim->dio));
-	m->cmnd.fcp_dl = bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
-
-	/**
-	 * set up I/O message header
-	 */
-	switch (m->cmnd.iodir) {
-	case FCP_IODIR_READ:
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa));
-		bfa_stats(itnim, input_reqs);
-		break;
-	case FCP_IODIR_WRITE:
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa));
-		bfa_stats(itnim, output_reqs);
-		break;
-	case FCP_IODIR_RW:
-		bfa_stats(itnim, input_reqs);
-		bfa_stats(itnim, output_reqs);
-	default:
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
-	}
-	if (itnim->seq_rec ||
-	    (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1)))
-		bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa));
-
-#ifdef IOIM_ADVANCED
-	m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio);
-	m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio);
-	m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio);
-
-	/**
-	 * Handle large CDB (>16 bytes).
-	 */
-	m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) -
-					FCP_CMND_CDB_LEN) / sizeof(u32);
-	if (m->cmnd.addl_cdb_len) {
-		bfa_os_memcpy(&m->cmnd.cdb + 1, (struct scsi_cdb_s *)
-				bfa_cb_ioim_get_cdb(ioim->dio) + 1,
-				m->cmnd.addl_cdb_len * sizeof(u32));
-		fcp_cmnd_fcpdl(&m->cmnd) =
-				bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio));
-	}
-#endif
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(ioim->bfa, ioim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- * Setup any additional SG pages needed.Inline SG element is setup
- * at queuing time.
- */
-static bfa_boolean_t
-bfa_ioim_sge_setup(struct bfa_ioim_s *ioim)
-{
-	u16        nsgpgs;
-
-	bfa_assert(ioim->nsges > BFI_SGE_INLINE);
-
-	/**
-	 * allocate SG pages needed
-	 */
-	nsgpgs = BFA_SGPG_NPAGE(ioim->nsges);
-	if (!nsgpgs)
-		return BFA_TRUE;
-
-	if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs)
-	    != BFA_STATUS_OK) {
-		bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs);
-		return BFA_FALSE;
-	}
-
-	ioim->nsgpgs = nsgpgs;
-	bfa_ioim_sgpg_setup(ioim);
-
-	return BFA_TRUE;
-}
-
-static void
-bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim)
-{
-	int             sgeid, nsges, i;
-	struct bfi_sge_s      *sge;
-	struct bfa_sgpg_s *sgpg;
-	u32        pgcumsz;
-	u64        addr;
-	struct scatterlist *sg;
-	struct scsi_cmnd *cmnd = (struct scsi_cmnd *) ioim->dio;
-
-	sgeid = BFI_SGE_INLINE;
-	ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q);
-
-	sg = scsi_sglist(cmnd);
-	sg = sg_next(sg);
-
-	do {
-		sge = sgpg->sgpg->sges;
-		nsges = ioim->nsges - sgeid;
-		if (nsges > BFI_SGPG_DATA_SGES)
-			nsges = BFI_SGPG_DATA_SGES;
-
-		pgcumsz = 0;
-		for (i = 0; i < nsges; i++, sge++, sgeid++, sg = sg_next(sg)) {
-			addr = bfa_os_sgaddr(sg_dma_address(sg));
-			sge->sga = *(union bfi_addr_u *) &addr;
-			sge->sg_len = sg_dma_len(sg);
-			pgcumsz += sge->sg_len;
-
-			/**
-			 * set flags
-			 */
-			if (i < (nsges - 1))
-				sge->flags = BFI_SGE_DATA;
-			else if (sgeid < (ioim->nsges - 1))
-				sge->flags = BFI_SGE_DATA_CPL;
-			else
-				sge->flags = BFI_SGE_DATA_LAST;
-		}
-
-		sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg);
-
-		/**
-		 * set the link element of each page
-		 */
-		if (sgeid == ioim->nsges) {
-			sge->flags = BFI_SGE_PGDLEN;
-			sge->sga.a32.addr_lo = 0;
-			sge->sga.a32.addr_hi = 0;
-		} else {
-			sge->flags = BFI_SGE_LINK;
-			sge->sga = sgpg->sgpg_pa;
-		}
-		sge->sg_len = pgcumsz;
-	} while (sgeid < ioim->nsges);
-}
-
-/**
- * Send I/O abort request to firmware.
- */
-static          bfa_boolean_t
-bfa_ioim_send_abort(struct bfa_ioim_s *ioim)
-{
-	struct bfi_ioim_abort_req_s *m;
-	enum bfi_ioim_h2i       msgop;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(ioim->bfa, ioim->reqq);
-	if (!m)
-		return BFA_FALSE;
-
-	/**
-	 * build i/o request message next
-	 */
-	if (ioim->iosp->abort_explicit)
-		msgop = BFI_IOIM_H2I_IOABORT_REQ;
-	else
-		msgop = BFI_IOIM_H2I_IOCLEANUP_REQ;
-
-	bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa));
-	m->io_tag    = bfa_os_htons(ioim->iotag);
-	m->abort_tag = ++ioim->abort_tag;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(ioim->bfa, ioim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- * Call to resume any I/O requests waiting for room in request queue.
- */
-static void
-bfa_ioim_qresume(void *cbarg)
-{
-	struct bfa_ioim_s *ioim = cbarg;
-
-	bfa_fcpim_stats(ioim->fcpim, qresumes);
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME);
-}
-
-
-static void
-bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim)
-{
-	/**
-	 * Move IO from itnim queue to fcpim global queue since itnim will be
-	 * freed.
-	 */
-	list_del(&ioim->qe);
-	list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-
-	if (!ioim->iosp->tskim) {
-		if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) {
-			bfa_cb_dequeue(&ioim->hcb_qe);
-			list_del(&ioim->qe);
-			list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q);
-		}
-		bfa_itnim_iodone(ioim->itnim);
-	} else
-		bfa_tskim_iodone(ioim->iosp->tskim);
-}
-
-/**
- * 		  or after the link comes back.
- */
-void
-bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov)
-{
-	/**
-	 * If path tov timer expired, failback with PATHTOV status - these
-	 * IO requests are not normally retried by IO stack.
-	 *
-	 * Otherwise device cameback online and fail it with normal failed
-	 * status so that IO stack retries these failed IO requests.
-	 */
-	if (iotov)
-		ioim->io_cbfn = __bfa_cb_ioim_pathtov;
-	else
-		ioim->io_cbfn = __bfa_cb_ioim_failed;
-
-	bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim);
-
-    /**
-     * Move IO to fcpim global queue since itnim will be
-     * freed.
-     */
-    list_del(&ioim->qe);
-    list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-}
-
-
-
-/**
- *  bfa_ioim_friend
- */
-
-/**
- * Memory allocation and initialization.
- */
-void
-bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
-{
-	struct bfa_ioim_s		*ioim;
-	struct bfa_ioim_sp_s	*iosp;
-	u16		i;
-	u8			*snsinfo;
-	u32		snsbufsz;
-
-	/**
-	 * claim memory first
-	 */
-	ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo);
-	fcpim->ioim_arr = ioim;
-	bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs);
-
-	iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo);
-	fcpim->ioim_sp_arr = iosp;
-	bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs);
-
-	/**
-	 * Claim DMA memory for per IO sense data.
-	 */
-	snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN;
-	fcpim->snsbase.pa  = bfa_meminfo_dma_phys(minfo);
-	bfa_meminfo_dma_phys(minfo) += snsbufsz;
-
-	fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo);
-	bfa_meminfo_dma_virt(minfo) += snsbufsz;
-	snsinfo = fcpim->snsbase.kva;
-	bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa);
-
-	/**
-	 * Initialize ioim free queues
-	 */
-	INIT_LIST_HEAD(&fcpim->ioim_free_q);
-	INIT_LIST_HEAD(&fcpim->ioim_resfree_q);
-	INIT_LIST_HEAD(&fcpim->ioim_comp_q);
-
-	for (i = 0; i < fcpim->num_ioim_reqs;
-	     i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) {
-		/*
-		 * initialize IOIM
-		 */
-		bfa_os_memset(ioim, 0, sizeof(struct bfa_ioim_s));
-		ioim->iotag   = i;
-		ioim->bfa     = fcpim->bfa;
-		ioim->fcpim   = fcpim;
-		ioim->iosp    = iosp;
-		iosp->snsinfo = snsinfo;
-		INIT_LIST_HEAD(&ioim->sgpg_q);
-		bfa_reqq_winit(&ioim->iosp->reqq_wait,
-				   bfa_ioim_qresume, ioim);
-		bfa_sgpg_winit(&ioim->iosp->sgpg_wqe,
-				   bfa_ioim_sgpg_alloced, ioim);
-		bfa_sm_set_state(ioim, bfa_ioim_sm_uninit);
-
-		list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
-	}
-}
-
-/**
- * Driver detach time call.
- */
-void
-bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
-}
-
-void
-bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
-	struct bfa_ioim_s *ioim;
-	u16        iotag;
-	enum bfa_ioim_event evt = BFA_IOIM_SM_COMP;
-
-	iotag = bfa_os_ntohs(rsp->io_tag);
-
-	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
-	bfa_assert(ioim->iotag == iotag);
-
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_trc(ioim->bfa, rsp->io_status);
-	bfa_trc(ioim->bfa, rsp->reuse_io_tag);
-
-	if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active))
-		bfa_os_assign(ioim->iosp->comp_rspmsg, *m);
-
-	switch (rsp->io_status) {
-	case BFI_IOIM_STS_OK:
-		bfa_fcpim_stats(fcpim, iocomp_ok);
-		if (rsp->reuse_io_tag == 0)
-			evt = BFA_IOIM_SM_DONE;
-		else
-			evt = BFA_IOIM_SM_COMP;
-		break;
-
-	case BFI_IOIM_STS_TIMEDOUT:
-	case BFI_IOIM_STS_ABORTED:
-		rsp->io_status = BFI_IOIM_STS_ABORTED;
-		bfa_fcpim_stats(fcpim, iocomp_aborted);
-		if (rsp->reuse_io_tag == 0)
-			evt = BFA_IOIM_SM_DONE;
-		else
-			evt = BFA_IOIM_SM_COMP;
-		break;
-
-	case BFI_IOIM_STS_PROTO_ERR:
-		bfa_fcpim_stats(fcpim, iocom_proto_err);
-		bfa_assert(rsp->reuse_io_tag);
-		evt = BFA_IOIM_SM_COMP;
-		break;
-
-	case BFI_IOIM_STS_SQER_NEEDED:
-		bfa_fcpim_stats(fcpim, iocom_sqer_needed);
-		bfa_assert(rsp->reuse_io_tag == 0);
-		evt = BFA_IOIM_SM_SQRETRY;
-		break;
-
-	case BFI_IOIM_STS_RES_FREE:
-		bfa_fcpim_stats(fcpim, iocom_res_free);
-		evt = BFA_IOIM_SM_FREE;
-		break;
-
-	case BFI_IOIM_STS_HOST_ABORTED:
-		bfa_fcpim_stats(fcpim, iocom_hostabrts);
-		if (rsp->abort_tag != ioim->abort_tag) {
-			bfa_trc(ioim->bfa, rsp->abort_tag);
-			bfa_trc(ioim->bfa, ioim->abort_tag);
-			return;
-		}
-
-		if (rsp->reuse_io_tag)
-			evt = BFA_IOIM_SM_ABORT_COMP;
-		else
-			evt = BFA_IOIM_SM_ABORT_DONE;
-		break;
-
-	case BFI_IOIM_STS_UTAG:
-		bfa_fcpim_stats(fcpim, iocom_utags);
-		evt = BFA_IOIM_SM_COMP_UTAG;
-		break;
-
-	default:
-		bfa_assert(0);
-	}
-
-	bfa_sm_send_event(ioim, evt);
-}
-
-void
-bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m;
-	struct bfa_ioim_s *ioim;
-	u16        iotag;
-
-	iotag = bfa_os_ntohs(rsp->io_tag);
-
-	ioim = BFA_IOIM_FROM_TAG(fcpim, iotag);
-	bfa_assert(ioim->iotag == iotag);
-
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
-}
-
-/**
- * Called by itnim to clean up IO while going offline.
- */
-void
-bfa_ioim_cleanup(struct bfa_ioim_s *ioim)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_fcpim_stats(ioim->fcpim, io_cleanups);
-
-	ioim->iosp->tskim = NULL;
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
-}
-
-void
-bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_fcpim_stats(ioim->fcpim, io_tmaborts);
-
-	ioim->iosp->tskim = tskim;
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP);
-}
-
-/**
- * IOC failure handling.
- */
-void
-bfa_ioim_iocdisable(struct bfa_ioim_s *ioim)
-{
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL);
-}
-
-/**
- * IO offline TOV popped. Fail the pending IO.
- */
-void
-bfa_ioim_tov(struct bfa_ioim_s *ioim)
-{
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV);
-}
-
-
-
-/**
- *  bfa_ioim_api
- */
-
-/**
- * Allocate IOIM resource for initiator mode I/O request.
- */
-struct bfa_ioim_s *
-bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio,
-		struct bfa_itnim_s *itnim, u16 nsges)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfa_ioim_s *ioim;
-
-	/**
-	 * alocate IOIM resource
-	 */
-	bfa_q_deq(&fcpim->ioim_free_q, &ioim);
-	if (!ioim) {
-		bfa_fcpim_stats(fcpim, no_iotags);
-		return NULL;
-	}
-
-	ioim->dio = dio;
-	ioim->itnim = itnim;
-	ioim->nsges = nsges;
-	ioim->nsgpgs = 0;
-
-	bfa_stats(fcpim, total_ios);
-	bfa_stats(itnim, ios);
-	fcpim->ios_active++;
-
-	list_add_tail(&ioim->qe, &itnim->io_q);
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-
-	return ioim;
-}
-
-void
-bfa_ioim_free(struct bfa_ioim_s *ioim)
-{
-	struct bfa_fcpim_mod_s *fcpim = ioim->fcpim;
-
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-	bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit));
-
-	bfa_assert_fp(list_empty(&ioim->sgpg_q)
-		   || (ioim->nsges > BFI_SGE_INLINE));
-
-	if (ioim->nsgpgs > 0)
-		bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs);
-
-	bfa_stats(ioim->itnim, io_comps);
-	fcpim->ios_active--;
-
-	list_del(&ioim->qe);
-	list_add_tail(&ioim->qe, &fcpim->ioim_free_q);
-}
-
-void
-bfa_ioim_start(struct bfa_ioim_s *ioim)
-{
-	bfa_trc_fp(ioim->bfa, ioim->iotag);
-
-	/**
-	 * Obtain the queue over which this request has to be issued
-	 */
-	ioim->reqq = bfa_fcpim_ioredirect_enabled(ioim->bfa) ?
-			bfa_cb_ioim_get_reqq(ioim->dio) :
-			bfa_itnim_get_reqq(ioim);
-
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_START);
-}
-
-/**
- * Driver I/O abort request.
- */
-void
-bfa_ioim_abort(struct bfa_ioim_s *ioim)
-{
-	bfa_trc(ioim->bfa, ioim->iotag);
-	bfa_fcpim_stats(ioim->fcpim, io_aborts);
-	bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT);
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_itnim.c b/drivers/scsi/bfa/bfa_itnim.c
deleted file mode 100644
index a914ff2..0000000
--- a/drivers/scsi/bfa/bfa_itnim.c
+++ /dev/null
@@ -1,1088 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include <bfa_fcpim.h>
-#include "bfa_fcpim_priv.h"
-
-BFA_TRC_FILE(HAL, ITNIM);
-
-#define BFA_ITNIM_FROM_TAG(_fcpim, _tag)				\
-	((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))
-
-#define bfa_fcpim_additn(__itnim)					\
-	list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
-#define bfa_fcpim_delitn(__itnim)	do {				\
-	bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim));      \
-	list_del(&(__itnim)->qe);      \
-	bfa_assert(list_empty(&(__itnim)->io_q));      \
-	bfa_assert(list_empty(&(__itnim)->io_cleanup_q));      \
-	bfa_assert(list_empty(&(__itnim)->pending_q));      \
-} while (0)
-
-#define bfa_itnim_online_cb(__itnim) do {				\
-	if ((__itnim)->bfa->fcs)					\
-		bfa_cb_itnim_online((__itnim)->ditn);      \
-	else {								\
-		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
-		__bfa_cb_itnim_online, (__itnim));      \
-	}								\
-} while (0)
-
-#define bfa_itnim_offline_cb(__itnim) do {				\
-	if ((__itnim)->bfa->fcs)					\
-		bfa_cb_itnim_offline((__itnim)->ditn);      \
-	else {								\
-		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
-		__bfa_cb_itnim_offline, (__itnim));      \
-	}								\
-} while (0)
-
-#define bfa_itnim_sler_cb(__itnim) do {					\
-	if ((__itnim)->bfa->fcs)					\
-		bfa_cb_itnim_sler((__itnim)->ditn);      \
-	else {								\
-		bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe,	\
-		__bfa_cb_itnim_sler, (__itnim));      \
-	}								\
-} while (0)
-
-/*
- * forward declarations
- */
-static void     bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
-static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
-static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_cleanp_comp(void *itnim_cbarg);
-static void     bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
-static void     __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
-static void     __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
-static void     __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
-static void     bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_iotov(void *itnim_arg);
-static void     bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
-static void     bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
-
-/**
- *  bfa_itnim_sm BFA itnim state machine
- */
-
-
-enum bfa_itnim_event {
-	BFA_ITNIM_SM_CREATE = 1,	/*  itnim is created */
-	BFA_ITNIM_SM_ONLINE = 2,	/*  itnim is online */
-	BFA_ITNIM_SM_OFFLINE = 3,	/*  itnim is offline */
-	BFA_ITNIM_SM_FWRSP = 4,		/*  firmware response */
-	BFA_ITNIM_SM_DELETE = 5,	/*  deleting an existing itnim */
-	BFA_ITNIM_SM_CLEANUP = 6,	/*  IO cleanup completion */
-	BFA_ITNIM_SM_SLER = 7,		/*  second level error recovery */
-	BFA_ITNIM_SM_HWFAIL = 8,	/*  IOC h/w failure event */
-	BFA_ITNIM_SM_QRESUME = 9,	/*  queue space available */
-};
-
-static void     bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
-					enum bfa_itnim_event event);
-static void     bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
-					 enum bfa_itnim_event event);
-static void     bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void	bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
-				enum bfa_itnim_event event);
-static void     bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
-					enum bfa_itnim_event event);
-static void     bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
-				      enum bfa_itnim_event event);
-static void     bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
-						 enum bfa_itnim_event event);
-static void     bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
-						enum bfa_itnim_event event);
-static void     bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void     bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
-					 enum bfa_itnim_event event);
-static void     bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
-					    enum bfa_itnim_event event);
-static void     bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void     bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void     bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-static void     bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
-					  enum bfa_itnim_event event);
-
-/**
- * 		Beginning/unallocated state - no events expected.
- */
-static void
-bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_CREATE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_created);
-		itnim->is_online = BFA_FALSE;
-		bfa_fcpim_additn(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Beginning state, only online event expected.
- */
-static void
-bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_ONLINE:
-		if (bfa_itnim_send_fwcreate(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Waiting for itnim create response from firmware.
- */
-static void
-bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_FWRSP:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_online);
-		itnim->is_online = BFA_TRUE;
-		bfa_itnim_iotov_online(itnim);
-		bfa_itnim_online_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending);
-		break;
-
-	case BFA_ITNIM_SM_OFFLINE:
-		if (bfa_itnim_send_fwdelete(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-static void
-bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
-			enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_QRESUME:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
-		bfa_itnim_send_fwcreate(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	case BFA_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 	Waiting for itnim create response from firmware, a delete is pending.
- */
-static void
-bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
-				enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_FWRSP:
-		if (bfa_itnim_send_fwdelete(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Online state - normal parking state.
- */
-static void
-bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
-		itnim->is_online = BFA_FALSE;
-		bfa_itnim_iotov_start(itnim);
-		bfa_itnim_cleanup(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
-		itnim->is_online = BFA_FALSE;
-		bfa_itnim_cleanup(itnim);
-		break;
-
-	case BFA_ITNIM_SM_SLER:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_sler);
-		itnim->is_online = BFA_FALSE;
-		bfa_itnim_iotov_start(itnim);
-		bfa_itnim_sler_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		itnim->is_online = BFA_FALSE;
-		bfa_itnim_iotov_start(itnim);
-		bfa_itnim_iocdisable_cleanup(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Second level error recovery need.
- */
-static void
-bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_OFFLINE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline);
-		bfa_itnim_cleanup(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
-		bfa_itnim_cleanup(itnim);
-		bfa_itnim_iotov_delete(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_itnim_iocdisable_cleanup(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Going offline. Waiting for active IO cleanup.
- */
-static void
-bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
-				 enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_CLEANUP:
-		if (bfa_itnim_send_fwdelete(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete);
-		bfa_itnim_iotov_delete(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_itnim_iocdisable_cleanup(itnim);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_SLER:
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Deleting itnim. Waiting for active IO cleanup.
- */
-static void
-bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
-				enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_CLEANUP:
-		if (bfa_itnim_send_fwdelete(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_itnim_iocdisable_cleanup(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * Rport offline. Fimrware itnim is being deleted - awaiting f/w response.
- */
-static void
-bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_FWRSP:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_offline);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-static void
-bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
-			enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_QRESUME:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete);
-		bfa_itnim_send_fwdelete(itnim);
-		break;
-
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Offline state.
- */
-static void
-bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_itnim_iotov_delete(itnim);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	case BFA_ITNIM_SM_ONLINE:
-		if (bfa_itnim_send_fwcreate(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		IOC h/w failed state.
- */
-static void
-bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
-			    enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_DELETE:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_itnim_iotov_delete(itnim);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	case BFA_ITNIM_SM_OFFLINE:
-		bfa_itnim_offline_cb(itnim);
-		break;
-
-	case BFA_ITNIM_SM_ONLINE:
-		if (bfa_itnim_send_fwcreate(itnim))
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate);
-		else
-			bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-/**
- * 		Itnim is deleted, waiting for firmware response to delete.
- */
-static void
-bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_FWRSP:
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-static void
-bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim,
-			enum bfa_itnim_event event)
-{
-	bfa_trc(itnim->bfa, itnim->rport->rport_tag);
-	bfa_trc(itnim->bfa, event);
-
-	switch (event) {
-	case BFA_ITNIM_SM_QRESUME:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_deleting);
-		bfa_itnim_send_fwdelete(itnim);
-		break;
-
-	case BFA_ITNIM_SM_HWFAIL:
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-		bfa_reqq_wcancel(&itnim->reqq_wait);
-		bfa_fcpim_delitn(itnim);
-		break;
-
-	default:
-		bfa_sm_fault(itnim->bfa, event);
-	}
-}
-
-
-
-/**
- *  bfa_itnim_private
- */
-
-/**
- * 		Initiate cleanup of all IOs on an IOC failure.
- */
-static void
-bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim)
-{
-	struct bfa_tskim_s *tskim;
-	struct bfa_ioim_s *ioim;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &itnim->tsk_q) {
-		tskim = (struct bfa_tskim_s *) qe;
-		bfa_tskim_iocdisable(tskim);
-	}
-
-	list_for_each_safe(qe, qen, &itnim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_ioim_iocdisable(ioim);
-	}
-
-	/**
-	 * For IO request in pending queue, we pretend an early timeout.
-	 */
-	list_for_each_safe(qe, qen, &itnim->pending_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_ioim_tov(ioim);
-	}
-
-	list_for_each_safe(qe, qen, &itnim->io_cleanup_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_ioim_iocdisable(ioim);
-	}
-}
-
-/**
- * 		IO cleanup completion
- */
-static void
-bfa_itnim_cleanp_comp(void *itnim_cbarg)
-{
-	struct bfa_itnim_s *itnim = itnim_cbarg;
-
-	bfa_stats(itnim, cleanup_comps);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP);
-}
-
-/**
- * 		Initiate cleanup of all IOs.
- */
-static void
-bfa_itnim_cleanup(struct bfa_itnim_s *itnim)
-{
-	struct bfa_ioim_s  *ioim;
-	struct bfa_tskim_s *tskim;
-	struct list_head         *qe, *qen;
-
-	bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim);
-
-	list_for_each_safe(qe, qen, &itnim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-
-		/**
-		 * Move IO to a cleanup queue from active queue so that a later
-		 * TM will not pickup this IO.
-		 */
-		list_del(&ioim->qe);
-		list_add_tail(&ioim->qe, &itnim->io_cleanup_q);
-
-		bfa_wc_up(&itnim->wc);
-		bfa_ioim_cleanup(ioim);
-	}
-
-	list_for_each_safe(qe, qen, &itnim->tsk_q) {
-		tskim = (struct bfa_tskim_s *) qe;
-		bfa_wc_up(&itnim->wc);
-		bfa_tskim_cleanup(tskim);
-	}
-
-	bfa_wc_wait(&itnim->wc);
-}
-
-static void
-__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_itnim_s *itnim = cbarg;
-
-	if (complete)
-		bfa_cb_itnim_online(itnim->ditn);
-}
-
-static void
-__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_itnim_s *itnim = cbarg;
-
-	if (complete)
-		bfa_cb_itnim_offline(itnim->ditn);
-}
-
-static void
-__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_itnim_s *itnim = cbarg;
-
-	if (complete)
-		bfa_cb_itnim_sler(itnim->ditn);
-}
-
-/**
- * Call to resume any I/O requests waiting for room in request queue.
- */
-static void
-bfa_itnim_qresume(void *cbarg)
-{
-	struct bfa_itnim_s *itnim = cbarg;
-
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME);
-}
-
-
-
-
-/**
- *  bfa_itnim_public
- */
-
-void
-bfa_itnim_iodone(struct bfa_itnim_s *itnim)
-{
-	bfa_wc_down(&itnim->wc);
-}
-
-void
-bfa_itnim_tskdone(struct bfa_itnim_s *itnim)
-{
-	bfa_wc_down(&itnim->wc);
-}
-
-void
-bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
-{
-	/**
-	 * ITN memory
-	 */
-	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s);
-}
-
-void
-bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
-{
-	struct bfa_s      *bfa = fcpim->bfa;
-	struct bfa_itnim_s *itnim;
-	int             i;
-
-	INIT_LIST_HEAD(&fcpim->itnim_q);
-
-	itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo);
-	fcpim->itnim_arr = itnim;
-
-	for (i = 0; i < fcpim->num_itnims; i++, itnim++) {
-		bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s));
-		itnim->bfa = bfa;
-		itnim->fcpim = fcpim;
-		itnim->reqq = BFA_REQQ_QOS_LO;
-		itnim->rport = BFA_RPORT_FROM_TAG(bfa, i);
-		itnim->iotov_active = BFA_FALSE;
-		bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim);
-
-		INIT_LIST_HEAD(&itnim->io_q);
-		INIT_LIST_HEAD(&itnim->io_cleanup_q);
-		INIT_LIST_HEAD(&itnim->pending_q);
-		INIT_LIST_HEAD(&itnim->tsk_q);
-		INIT_LIST_HEAD(&itnim->delay_comp_q);
-		bfa_sm_set_state(itnim, bfa_itnim_sm_uninit);
-	}
-
-	bfa_meminfo_kva(minfo) = (u8 *) itnim;
-}
-
-void
-bfa_itnim_iocdisable(struct bfa_itnim_s *itnim)
-{
-	bfa_stats(itnim, ioc_disabled);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL);
-}
-
-static bfa_boolean_t
-bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim)
-{
-	struct bfi_itnim_create_req_s *m;
-
-	itnim->msg_no++;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
-	if (!m) {
-		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ,
-			bfa_lpuid(itnim->bfa));
-	m->fw_handle = itnim->rport->fw_handle;
-	m->class = FC_CLASS_3;
-	m->seq_rec = itnim->seq_rec;
-	m->msg_no = itnim->msg_no;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(itnim->bfa, itnim->reqq);
-	return BFA_TRUE;
-}
-
-static bfa_boolean_t
-bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim)
-{
-	struct bfi_itnim_delete_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(itnim->bfa, itnim->reqq);
-	if (!m) {
-		bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ,
-			bfa_lpuid(itnim->bfa));
-	m->fw_handle = itnim->rport->fw_handle;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(itnim->bfa, itnim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- * Cleanup all pending failed inflight requests.
- */
-static void
-bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov)
-{
-	struct bfa_ioim_s *ioim;
-	struct list_head *qe, *qen;
-
-	list_for_each_safe(qe, qen, &itnim->delay_comp_q) {
-		ioim = (struct bfa_ioim_s *)qe;
-		bfa_ioim_delayed_comp(ioim, iotov);
-	}
-}
-
-/**
- * Start all pending IO requests.
- */
-static void
-bfa_itnim_iotov_online(struct bfa_itnim_s *itnim)
-{
-	struct bfa_ioim_s *ioim;
-
-	bfa_itnim_iotov_stop(itnim);
-
-	/**
-	 * Abort all inflight IO requests in the queue
-	 */
-	bfa_itnim_delayed_comp(itnim, BFA_FALSE);
-
-	/**
-	 * Start all pending IO requests.
-	 */
-	while (!list_empty(&itnim->pending_q)) {
-		bfa_q_deq(&itnim->pending_q, &ioim);
-		list_add_tail(&ioim->qe, &itnim->io_q);
-		bfa_ioim_start(ioim);
-	}
-}
-
-/**
- * Fail all pending IO requests
- */
-static void
-bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim)
-{
-	struct bfa_ioim_s *ioim;
-
-	/**
-	 * Fail all inflight IO requests in the queue
-	 */
-	bfa_itnim_delayed_comp(itnim, BFA_TRUE);
-
-	/**
-	 * Fail any pending IO requests.
-	 */
-	while (!list_empty(&itnim->pending_q)) {
-		bfa_q_deq(&itnim->pending_q, &ioim);
-		list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-		bfa_ioim_tov(ioim);
-	}
-}
-
-/**
- * IO TOV timer callback. Fail any pending IO requests.
- */
-static void
-bfa_itnim_iotov(void *itnim_arg)
-{
-	struct bfa_itnim_s *itnim = itnim_arg;
-
-	itnim->iotov_active = BFA_FALSE;
-
-	bfa_cb_itnim_tov_begin(itnim->ditn);
-	bfa_itnim_iotov_cleanup(itnim);
-	bfa_cb_itnim_tov(itnim->ditn);
-}
-
-/**
- * Start IO TOV timer for failing back pending IO requests in offline state.
- */
-static void
-bfa_itnim_iotov_start(struct bfa_itnim_s *itnim)
-{
-	if (itnim->fcpim->path_tov > 0) {
-
-		itnim->iotov_active = BFA_TRUE;
-		bfa_assert(bfa_itnim_hold_io(itnim));
-		bfa_timer_start(itnim->bfa, &itnim->timer,
-			bfa_itnim_iotov, itnim, itnim->fcpim->path_tov);
-	}
-}
-
-/**
- * Stop IO TOV timer.
- */
-static void
-bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim)
-{
-	if (itnim->iotov_active) {
-		itnim->iotov_active = BFA_FALSE;
-		bfa_timer_stop(&itnim->timer);
-	}
-}
-
-/**
- * Stop IO TOV timer.
- */
-static void
-bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim)
-{
-    bfa_boolean_t pathtov_active = BFA_FALSE;
-
-    if (itnim->iotov_active)
-		pathtov_active = BFA_TRUE;
-
-	bfa_itnim_iotov_stop(itnim);
-	if (pathtov_active)
-		bfa_cb_itnim_tov_begin(itnim->ditn);
-	bfa_itnim_iotov_cleanup(itnim);
-	if (pathtov_active)
-		bfa_cb_itnim_tov(itnim->ditn);
-}
-
-
-
-/**
- *  bfa_itnim_public
- */
-
-/**
- * 		Itnim interrupt processing.
- */
-void
-bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	union bfi_itnim_i2h_msg_u msg;
-	struct bfa_itnim_s *itnim;
-
-	bfa_trc(bfa, m->mhdr.msg_id);
-
-	msg.msg = m;
-
-	switch (m->mhdr.msg_id) {
-	case BFI_ITNIM_I2H_CREATE_RSP:
-		itnim = BFA_ITNIM_FROM_TAG(fcpim,
-					       msg.create_rsp->bfa_handle);
-		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
-		bfa_stats(itnim, create_comps);
-		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
-		break;
-
-	case BFI_ITNIM_I2H_DELETE_RSP:
-		itnim = BFA_ITNIM_FROM_TAG(fcpim,
-					       msg.delete_rsp->bfa_handle);
-		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
-		bfa_stats(itnim, delete_comps);
-		bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP);
-		break;
-
-	case BFI_ITNIM_I2H_SLER_EVENT:
-		itnim = BFA_ITNIM_FROM_TAG(fcpim,
-					       msg.sler_event->bfa_handle);
-		bfa_stats(itnim, sler_events);
-		bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER);
-		break;
-
-	default:
-		bfa_trc(bfa, m->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-
-
-/**
- *  bfa_itnim_api
- */
-
-struct bfa_itnim_s *
-bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfa_itnim_s *itnim;
-
-	itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag);
-	bfa_assert(itnim->rport == rport);
-
-	itnim->ditn = ditn;
-
-	bfa_stats(itnim, creates);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE);
-
-	return itnim;
-}
-
-void
-bfa_itnim_delete(struct bfa_itnim_s *itnim)
-{
-	bfa_stats(itnim, deletes);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE);
-}
-
-void
-bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec)
-{
-	itnim->seq_rec = seq_rec;
-	bfa_stats(itnim, onlines);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE);
-}
-
-void
-bfa_itnim_offline(struct bfa_itnim_s *itnim)
-{
-	bfa_stats(itnim, offlines);
-	bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE);
-}
-
-/**
- * Return true if itnim is considered offline for holding off IO request.
- * IO is not held if itnim is being deleted.
- */
-bfa_boolean_t
-bfa_itnim_hold_io(struct bfa_itnim_s *itnim)
-{
-	return
-		itnim->fcpim->path_tov && itnim->iotov_active &&
-		(bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) ||
-		 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable))
-	;
-}
-
-void
-bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
-	struct bfa_itnim_hal_stats_s *stats)
-{
-	*stats = itnim->stats;
-}
-
-void
-bfa_itnim_clear_stats(struct bfa_itnim_s *itnim)
-{
-	bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats));
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_log.c b/drivers/scsi/bfa/bfa_log.c
deleted file mode 100644
index e751401..0000000
--- a/drivers/scsi/bfa/bfa_log.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_log.c BFA log library
- */
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_log.h>
-
-/*
- * global log info structure
- */
-struct bfa_log_info_s {
-	u32        start_idx;	/*  start index for a module */
-	u32        total_count;	/*  total count for a module */
-	enum bfa_log_severity level;	/*  global log level */
-	bfa_log_cb_t	cbfn;		/*  callback function */
-};
-
-static struct bfa_log_info_s bfa_log_info[BFA_LOG_MODULE_ID_MAX + 1];
-static u32 bfa_log_msg_total_count;
-static int      bfa_log_initialized;
-
-static char    *bfa_log_severity[] =
-	{ "[none]", "[critical]", "[error]", "[warn]", "[info]", "" };
-
-/**
- * BFA log library initialization
- *
- * The log library initialization includes the following,
- *    - set log instance name and callback function
- *    - read the message array generated from xml files
- *    - calculate start index for each module
- *    - calculate message count for each module
- *    - perform error checking
- *
- * @param[in] log_mod - log module info
- * @param[in] instance_name - instance name
- * @param[in] cbfn - callback function
- *
- * It return 0 on success, or -1 on failure
- */
-int
-bfa_log_init(struct bfa_log_mod_s *log_mod, char *instance_name,
-			bfa_log_cb_t cbfn)
-{
-	struct bfa_log_msgdef_s *msg;
-	u32        pre_mod_id = 0;
-	u32        cur_mod_id = 0;
-	u32        i, pre_idx, idx, msg_id;
-
-	/*
-	 * set instance name
-	 */
-	if (log_mod) {
-		strncpy(log_mod->instance_info, instance_name,
-			sizeof(log_mod->instance_info));
-		log_mod->cbfn = cbfn;
-		for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++)
-			log_mod->log_level[i] = BFA_LOG_WARNING;
-	}
-
-	if (bfa_log_initialized)
-		return 0;
-
-	for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++) {
-		bfa_log_info[i].start_idx = 0;
-		bfa_log_info[i].total_count = 0;
-		bfa_log_info[i].level = BFA_LOG_WARNING;
-		bfa_log_info[i].cbfn = cbfn;
-	}
-
-	pre_idx = 0;
-	idx = 0;
-	msg = bfa_log_msg_array;
-	msg_id = BFA_LOG_GET_MSG_ID(msg);
-	pre_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
-	while (msg_id != 0) {
-		cur_mod_id = BFA_LOG_GET_MOD_ID(msg_id);
-
-		if (cur_mod_id > BFA_LOG_MODULE_ID_MAX) {
-			cbfn(log_mod, msg_id,
-				"%s%s log: module id %u out of range\n",
-				BFA_LOG_CAT_NAME,
-				bfa_log_severity[BFA_LOG_ERROR],
-				cur_mod_id);
-			return -1;
-		}
-
-		if (pre_mod_id > BFA_LOG_MODULE_ID_MAX) {
-			cbfn(log_mod, msg_id,
-				"%s%s log: module id %u out of range\n",
-				BFA_LOG_CAT_NAME,
-				bfa_log_severity[BFA_LOG_ERROR],
-				pre_mod_id);
-			return -1;
-		}
-
-		if (cur_mod_id != pre_mod_id) {
-			bfa_log_info[pre_mod_id].start_idx = pre_idx;
-			bfa_log_info[pre_mod_id].total_count = idx - pre_idx;
-			pre_mod_id = cur_mod_id;
-			pre_idx = idx;
-		}
-
-		idx++;
-		msg++;
-		msg_id = BFA_LOG_GET_MSG_ID(msg);
-	}
-
-	bfa_log_info[cur_mod_id].start_idx = pre_idx;
-	bfa_log_info[cur_mod_id].total_count = idx - pre_idx;
-	bfa_log_msg_total_count = idx;
-
-	cbfn(log_mod, msg_id, "%s%s log: init OK, msg total count %u\n",
-		BFA_LOG_CAT_NAME,
-		bfa_log_severity[BFA_LOG_INFO], bfa_log_msg_total_count);
-
-	bfa_log_initialized = 1;
-
-	return 0;
-}
-
-/**
- * BFA log set log level for a module
- *
- * @param[in] log_mod - log module info
- * @param[in] mod_id - module id
- * @param[in] log_level - log severity level
- *
- * It return BFA_STATUS_OK on success, or > 0 on failure
- */
-bfa_status_t
-bfa_log_set_level(struct bfa_log_mod_s *log_mod, int mod_id,
-		  enum bfa_log_severity log_level)
-{
-	if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
-		return BFA_STATUS_EINVAL;
-
-	if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
-		return BFA_STATUS_EINVAL;
-
-	if (log_mod)
-		log_mod->log_level[mod_id] = log_level;
-	else
-		bfa_log_info[mod_id].level = log_level;
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * BFA log set log level for all modules
- *
- * @param[in] log_mod - log module info
- * @param[in] log_level - log severity level
- *
- * It return BFA_STATUS_OK on success, or > 0 on failure
- */
-bfa_status_t
-bfa_log_set_level_all(struct bfa_log_mod_s *log_mod,
-		  enum bfa_log_severity log_level)
-{
-	int mod_id = BFA_LOG_UNUSED_ID + 1;
-
-	if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX)
-		return BFA_STATUS_EINVAL;
-
-	if (log_mod) {
-		for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
-			log_mod->log_level[mod_id] = log_level;
-	} else {
-		for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++)
-			bfa_log_info[mod_id].level = log_level;
-	}
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * BFA log set log level for all aen sub-modules
- *
- * @param[in] log_mod - log module info
- * @param[in] log_level - log severity level
- *
- * It return BFA_STATUS_OK on success, or > 0 on failure
- */
-bfa_status_t
-bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod,
-		  enum bfa_log_severity log_level)
-{
-	int mod_id = BFA_LOG_AEN_MIN + 1;
-
-	if (log_mod) {
-		for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
-			log_mod->log_level[mod_id] = log_level;
-	} else {
-		for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++)
-			bfa_log_info[mod_id].level = log_level;
-	}
-
-	return BFA_STATUS_OK;
-}
-
-/**
- * BFA log get log level for a module
- *
- * @param[in] log_mod - log module info
- * @param[in] mod_id - module id
- *
- * It returns log level or -1 on error
- */
-enum bfa_log_severity
-bfa_log_get_level(struct bfa_log_mod_s *log_mod, int mod_id)
-{
-	if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX)
-		return BFA_LOG_INVALID;
-
-	if (log_mod)
-		return log_mod->log_level[mod_id];
-	else
-		return bfa_log_info[mod_id].level;
-}
-
-enum bfa_log_severity
-bfa_log_get_msg_level(struct bfa_log_mod_s *log_mod, u32 msg_id)
-{
-	struct bfa_log_msgdef_s *msg;
-	u32        mod = BFA_LOG_GET_MOD_ID(msg_id);
-	u32        idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
-
-	if (!bfa_log_initialized)
-		return BFA_LOG_INVALID;
-
-	if (mod > BFA_LOG_MODULE_ID_MAX)
-		return BFA_LOG_INVALID;
-
-	if (idx >= bfa_log_info[mod].total_count) {
-		bfa_log_info[mod].cbfn(log_mod, msg_id,
-			"%s%s log: inconsistent idx %u vs. total count %u\n",
-			BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
-			bfa_log_info[mod].total_count);
-		return BFA_LOG_INVALID;
-	}
-
-	msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
-	if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
-		bfa_log_info[mod].cbfn(log_mod, msg_id,
-			"%s%s log: inconsistent msg id %u array msg id %u\n",
-			BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
-			msg_id, BFA_LOG_GET_MSG_ID(msg));
-		return BFA_LOG_INVALID;
-	}
-
-	return BFA_LOG_GET_SEVERITY(msg);
-}
-
-/**
- * BFA log message handling
- *
- * BFA log message handling finds the message based on message id and prints
- * out the message based on its format and arguments. It also does prefix
- * the severity etc.
- *
- * @param[in] log_mod - log module info
- * @param[in] msg_id - message id
- * @param[in] ... - message arguments
- *
- * It return 0 on success, or -1 on errors
- */
-int
-bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...)
-{
-	va_list         ap;
-	char            buf[256];
-	struct bfa_log_msgdef_s *msg;
-	int             log_level;
-	u32        mod = BFA_LOG_GET_MOD_ID(msg_id);
-	u32        idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1;
-
-	if (!bfa_log_initialized)
-		return -1;
-
-	if (mod > BFA_LOG_MODULE_ID_MAX)
-		return -1;
-
-	if (idx >= bfa_log_info[mod].total_count) {
-		bfa_log_info[mod].
-			cbfn
-			(log_mod, msg_id,
-			"%s%s log: inconsistent idx %u vs. total count %u\n",
-			BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx,
-			bfa_log_info[mod].total_count);
-		return -1;
-	}
-
-	msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx;
-	if (msg_id != BFA_LOG_GET_MSG_ID(msg)) {
-		bfa_log_info[mod].
-			cbfn
-			(log_mod, msg_id,
-			"%s%s log: inconsistent msg id %u array msg id %u\n",
-			BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR],
-			msg_id, BFA_LOG_GET_MSG_ID(msg));
-		return -1;
-	}
-
-	log_level = log_mod ? log_mod->log_level[mod] : bfa_log_info[mod].level;
-	if ((BFA_LOG_GET_SEVERITY(msg) > log_level) &&
-			(msg->attributes != BFA_LOG_ATTR_NONE))
-		return 0;
-
-	va_start(ap, msg_id);
-	bfa_os_vsprintf(buf, BFA_LOG_GET_MSG_FMT_STRING(msg), ap);
-	va_end(ap);
-
-	if (log_mod)
-		log_mod->cbfn(log_mod, msg_id, "%s[%s]%s%s %s: %s\n",
-				BFA_LOG_CAT_NAME, log_mod->instance_info,
-				bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
-				(msg->attributes & BFA_LOG_ATTR_AUDIT)
-				? " (audit) " : "", msg->msg_value, buf);
-	else
-		bfa_log_info[mod].cbfn(log_mod, msg_id, "%s%s%s %s: %s\n",
-				BFA_LOG_CAT_NAME,
-				bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)],
-				(msg->attributes & BFA_LOG_ATTR_AUDIT) ?
-				" (audit) " : "", msg->msg_value, buf);
-
-	return 0;
-}
-
diff --git a/drivers/scsi/bfa/bfa_log_module.c b/drivers/scsi/bfa/bfa_log_module.c
deleted file mode 100644
index cf577ef..0000000
--- a/drivers/scsi/bfa/bfa_log_module.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <cs/bfa_log.h>
-#include <aen/bfa_aen_adapter.h>
-#include <aen/bfa_aen_audit.h>
-#include <aen/bfa_aen_ethport.h>
-#include <aen/bfa_aen_ioc.h>
-#include <aen/bfa_aen_itnim.h>
-#include <aen/bfa_aen_lport.h>
-#include <aen/bfa_aen_port.h>
-#include <aen/bfa_aen_rport.h>
-#include <log/bfa_log_fcs.h>
-#include <log/bfa_log_hal.h>
-#include <log/bfa_log_linux.h>
-#include <log/bfa_log_wdrv.h>
-
-struct bfa_log_msgdef_s bfa_log_msg_array[] = {
-
-
-/* messages define for BFA_AEN_CAT_ADAPTER Module */
-{BFA_AEN_ADAPTER_ADD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ADAPTER_ADD",
- "New adapter found: SN = %s, base port WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_ADAPTER_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_ADAPTER_REMOVE",
- "Adapter removed: SN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_AUDIT Module */
-{BFA_AEN_AUDIT_AUTH_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_ENABLE",
- "Authentication enabled for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_AUDIT_AUTH_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_DISABLE",
- "Authentication disabled for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_ETHPORT Module */
-{BFA_AEN_ETHPORT_LINKUP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_LINKUP",
- "Base port ethernet linkup: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_ETHPORT_LINKDOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_LINKDOWN",
- "Base port ethernet linkdown: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_ETHPORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_ENABLE",
- "Base port ethernet interface enabled: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_ETHPORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ETHPORT_DISABLE",
- "Base port ethernet interface disabled: mac = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_IOC Module */
-{BFA_AEN_IOC_HBGOOD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_IOC_HBGOOD",
- "Heart Beat of IOC %d is good.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_HBFAIL, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_CRITICAL,
- "BFA_AEN_IOC_HBFAIL",
- "Heart Beat of IOC %d has failed.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_IOC_ENABLE",
- "IOC %d is enabled.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_IOC_DISABLE",
- "IOC %d is disabled.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_FWMISMATCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWMISMATCH",
- "Running firmware version is incompatible with the driver version.",
- (0), 0},
-
-{BFA_AEN_IOC_FWCFG_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWCFG_ERROR",
- "Link initialization failed due to firmware configuration read error:"
- " WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_INVALID_VENDOR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_VENDOR",
- "Unsupported switch vendor. Link initialization failed: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_IOC_INVALID_NWWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_NWWN",
- "Invalid NWWN. Link initialization failed: NWWN = 00:00:00:00:00:00:00:00.",
- (0), 0},
-
-{BFA_AEN_IOC_INVALID_PWWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_IOC_INVALID_PWWN",
- "Invalid PWWN. Link initialization failed: PWWN = 00:00:00:00:00:00:00:00.",
- (0), 0},
-
-
-
-
-/* messages define for BFA_AEN_CAT_ITNIM Module */
-{BFA_AEN_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ITNIM_ONLINE",
- "Target (WWN = %s) is online for initiator (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_ITNIM_OFFLINE",
- "Target (WWN = %s) offlined by initiator (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_ITNIM_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_ITNIM_DISCONNECT",
- "Target (WWN = %s) connectivity lost for initiator (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-
-
-
-/* messages define for BFA_AEN_CAT_LPORT Module */
-{BFA_AEN_LPORT_NEW, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_NEW",
- "New logical port created: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DELETE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_DELETE",
- "Logical port deleted: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_ONLINE",
- "Logical port online: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_OFFLINE",
- "Logical port taken offline: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_LPORT_DISCONNECT",
- "Logical port lost fabric connectivity: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_NEW_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_LPORT_NEW_PROP",
- "New virtual port created using proprietary interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DELETE_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_PROP",
- "Virtual port deleted using proprietary interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_NEW_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_LPORT_NEW_STANDARD",
- "New virtual port created using standard interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_DELETE_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_STANDARD",
- "Virtual port deleted using standard interface: WWN = %s, Role = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_LPORT_NPIV_DUP_WWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_DUP_WWN",
- "Virtual port login failed. Duplicate WWN = %s reported by fabric.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_LPORT_NPIV_FABRIC_MAX, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_FABRIC_MAX",
- "Virtual port (WWN = %s) login failed. Max NPIV ports already exist in"
- " fabric/fport.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_LPORT_NPIV_UNKNOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_UNKNOWN",
- "Virtual port (WWN = %s) login failed.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_PORT Module */
-{BFA_AEN_PORT_ONLINE, BFA_LOG_ATTR_NONE, BFA_LOG_INFO, "BFA_AEN_PORT_ONLINE",
- "Base port online: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
- "BFA_AEN_PORT_OFFLINE",
- "Base port offline: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_RLIR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_RLIR",
- "RLIR event not supported.",
- (0), 0},
-
-{BFA_AEN_PORT_SFP_INSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_SFP_INSERT",
- "New SFP found: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_SFP_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_REMOVE",
- "SFP removed: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_SFP_POM, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
- "BFA_AEN_PORT_SFP_POM",
- "SFP POM level to %s: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_PORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_ENABLE",
- "Base port enabled: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_DISABLE",
- "Base port disabled: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_AUTH_ON, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_PORT_AUTH_ON",
- "Authentication successful for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_AUTH_OFF, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "BFA_AEN_PORT_AUTH_OFF",
- "Authentication unsuccessful for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "BFA_AEN_PORT_DISCONNECT",
- "Base port (WWN = %s) lost fabric connectivity.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_QOS_NEG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING,
- "BFA_AEN_PORT_QOS_NEG",
- "QOS negotiation failed for base port: WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_FABRIC_NAME_CHANGE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_FABRIC_NAME_CHANGE",
- "Base port WWN = %s, Fabric WWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_PORT_SFP_ACCESS_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_ACCESS_ERROR",
- "SFP access error: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_AEN_PORT_SFP_UNSUPPORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_UNSUPPORT",
- "Unsupported SFP found: WWN/MAC = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for BFA_AEN_CAT_RPORT Module */
-{BFA_AEN_RPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_ONLINE",
- "Remote port (WWN = %s) online for logical port (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_RPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_OFFLINE",
- "Remote port (WWN = %s) offlined by logical port (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_RPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "BFA_AEN_RPORT_DISCONNECT",
- "Remote port (WWN = %s) connectivity lost for logical port (WWN = %s).",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2},
-
-{BFA_AEN_RPORT_QOS_PRIO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_QOS_PRIO",
- "QOS priority changed to %s: RPWWN = %s and LPWWN = %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_AEN_RPORT_QOS_FLOWID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "BFA_AEN_RPORT_QOS_FLOWID",
- "QOS flow ID changed to %d: RPWWN = %s and LPWWN = %s.",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-
-
-
-/* messages define for FCS Module */
-{BFA_LOG_FCS_FABRIC_NOSWITCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "FCS_FABRIC_NOSWITCH",
- "No switched fabric presence is detected.",
- (0), 0},
-
-{BFA_LOG_FCS_FABRIC_ISOLATED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "FCS_FABRIC_ISOLATED",
- "Port is isolated due to VF_ID mismatch. PWWN: %s, Port VF_ID: %04x and"
- " switch port VF_ID: %04x.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_X << BFA_LOG_ARG1) |
-  (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
-
-
-
-
-/* messages define for HAL Module */
-{BFA_LOG_HAL_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "HAL_ASSERT",
- "Assertion failure: %s:%d: %s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_HAL_HEARTBEAT_FAILURE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_CRITICAL, "HAL_HEARTBEAT_FAILURE",
- "Firmware heartbeat failure at %d",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_HAL_FCPIM_PARM_INVALID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "HAL_FCPIM_PARM_INVALID",
- "Driver configuration %s value %d is invalid. Value should be within"
- " %d and %d.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_D << BFA_LOG_ARG2) | (BFA_LOG_D << BFA_LOG_ARG3) | 0), 4},
-
-{BFA_LOG_HAL_SM_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR,
- "HAL_SM_ASSERT",
- "SM Assertion failure: %s:%d: event = %d",
- ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_D << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_HAL_DRIVER_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "HAL_DRIVER_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_HAL_DRIVER_CONFIG_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "HAL_DRIVER_CONFIG_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_HAL_MBOX_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "HAL_MBOX_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for LINUX Module */
-{BFA_LOG_LINUX_DEVICE_CLAIMED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DEVICE_CLAIMED",
- "bfa device at %s claimed.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_HASH_INIT_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_HASH_INIT_FAILED",
- "Hash table initialization failure for the port %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_SYSFS_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_SYSFS_FAILED",
- "sysfs file creation failure for the port %s.",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_MEM_ALLOC_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_MEM_ALLOC_FAILED",
- "Memory allocation failed: %s.  ",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_DRIVER_REGISTRATION_FAILED",
- "%s.  ",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_ITNIM_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_ITNIM_FREE",
- "scsi%d: FCID: %s WWPN: %s",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_LINUX_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_ITNIM_ONLINE",
- "Target: %d:0:%d FCID: %s WWPN: %s",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
-
-{BFA_LOG_LINUX_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_ITNIM_OFFLINE",
- "Target: %d:0:%d FCID: %s WWPN: %s",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) |
-  (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4},
-
-{BFA_LOG_LINUX_SCSI_HOST_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_SCSI_HOST_FREE",
- "Free scsi%d",
- ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_SCSI_ABORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_SCSI_ABORT",
- "scsi%d: abort cmnd %p, iotag %x",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
-  (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_LINUX_SCSI_ABORT_COMP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_SCSI_ABORT_COMP",
- "scsi%d: complete abort 0x%p, iotag 0x%x",
- ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) |
-  (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3},
-
-{BFA_LOG_LINUX_DRIVER_CONFIG_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_DRIVER_CONFIG_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_BNA_STATE_MACHINE,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_BNA_STATE_MACHINE",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_IOC_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_IOC_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_RESOURCE_ALLOC_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_RESOURCE_ALLOC_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_RING_BUFFER_ERROR,
- BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO,
- "LINUX_RING_BUFFER_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_ERROR, "LINUX_DRIVER_ERROR",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_INFO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DRIVER_INFO",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_DIAG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DRIVER_DIAG",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-{BFA_LOG_LINUX_DRIVER_AEN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "LINUX_DRIVER_AEN",
- "%s",
- ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1},
-
-
-
-
-/* messages define for WDRV Module */
-{BFA_LOG_WDRV_IOC_INIT_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_INIT_ERROR",
- "IOC initialization has failed.",
- (0), 0},
-
-{BFA_LOG_WDRV_IOC_INTERNAL_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_INTERNAL_ERROR",
- "IOC internal error.  ",
- (0), 0},
-
-{BFA_LOG_WDRV_IOC_START_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_START_ERROR",
- "IOC could not be started.  ",
- (0), 0},
-
-{BFA_LOG_WDRV_IOC_STOP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_IOC_STOP_ERROR",
- "IOC could not be stopped.  ",
- (0), 0},
-
-{BFA_LOG_WDRV_INSUFFICIENT_RESOURCES, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_INSUFFICIENT_RESOURCES",
- "Insufficient memory.  ",
- (0), 0},
-
-{BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG,
- BFA_LOG_INFO, "WDRV_BASE_ADDRESS_MAP_ERROR",
- "Unable to map the IOC onto the system address space.  ",
- (0), 0},
-
-
-{0, 0, 0, "", "", 0, 0},
-};
diff --git a/drivers/scsi/bfa/bfa_lps.c b/drivers/scsi/bfa/bfa_lps.c
deleted file mode 100644
index acabb44..0000000
--- a/drivers/scsi/bfa/bfa_lps.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include <bfi/bfi_lps.h>
-#include <cs/bfa_debug.h>
-#include <defs/bfa_defs_pci.h>
-
-BFA_TRC_FILE(HAL, LPS);
-BFA_MODULE(lps);
-
-#define BFA_LPS_MIN_LPORTS	(1)
-#define BFA_LPS_MAX_LPORTS	(256)
-
-/*
- * Maximum Vports supported per physical port or vf.
- */
-#define BFA_LPS_MAX_VPORTS_SUPP_CB  255
-#define BFA_LPS_MAX_VPORTS_SUPP_CT  190
-
-/**
- * forward declarations
- */
-static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
-			    u32 *dm_len);
-static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
-			   struct bfa_iocfc_cfg_s *cfg,
-			   struct bfa_meminfo_s *meminfo,
-			   struct bfa_pcidev_s *pcidev);
-static void bfa_lps_detach(struct bfa_s *bfa);
-static void bfa_lps_start(struct bfa_s *bfa);
-static void bfa_lps_stop(struct bfa_s *bfa);
-static void bfa_lps_iocdisable(struct bfa_s *bfa);
-static void bfa_lps_login_rsp(struct bfa_s *bfa,
-			      struct bfi_lps_login_rsp_s *rsp);
-static void bfa_lps_logout_rsp(struct bfa_s *bfa,
-			       struct bfi_lps_logout_rsp_s *rsp);
-static void bfa_lps_reqq_resume(void *lps_arg);
-static void bfa_lps_free(struct bfa_lps_s *lps);
-static void bfa_lps_send_login(struct bfa_lps_s *lps);
-static void bfa_lps_send_logout(struct bfa_lps_s *lps);
-static void bfa_lps_login_comp(struct bfa_lps_s *lps);
-static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
-static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
-
-/**
- *  lps_pvt BFA LPS private functions
- */
-
-enum bfa_lps_event {
-	BFA_LPS_SM_LOGIN	= 1,	/* login request from user	*/
-	BFA_LPS_SM_LOGOUT	= 2,	/* logout request from user	*/
-	BFA_LPS_SM_FWRSP	= 3,	/* f/w response to login/logout	*/
-	BFA_LPS_SM_RESUME	= 4,	/* space present in reqq queue	*/
-	BFA_LPS_SM_DELETE	= 5,	/* lps delete from user		*/
-	BFA_LPS_SM_OFFLINE	= 6,	/* Link is offline		*/
-	BFA_LPS_SM_RX_CVL       = 7,	/* Rx clear virtual link        */
-};
-
-static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps,
-			enum bfa_lps_event event);
-static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
-static void bfa_lps_sm_logowait(struct bfa_lps_s *lps,
-			enum bfa_lps_event event);
-
-/**
- * Init state -- no login
- */
-static void
-bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_LOGIN:
-		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
-			bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
-			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
-		} else {
-			bfa_sm_set_state(lps, bfa_lps_sm_login);
-			bfa_lps_send_login(lps);
-		}
-		if (lps->fdisc)
-			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-			BFA_PL_EID_LOGIN, 0, "FDISC Request");
-		else
-			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-			BFA_PL_EID_LOGIN, 0, "FLOGI Request");
-		break;
-
-	case BFA_LPS_SM_LOGOUT:
-		bfa_lps_logout_comp(lps);
-		break;
-
-	case BFA_LPS_SM_DELETE:
-		bfa_lps_free(lps);
-		break;
-
-	case BFA_LPS_SM_RX_CVL:
-	case BFA_LPS_SM_OFFLINE:
-		break;
-
-	case BFA_LPS_SM_FWRSP:
-		/* Could happen when fabric detects loopback and discards
-		 * the lps request. Fw will eventually sent out the timeout
-		 * Just ignore
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * login is in progress -- awaiting response from firmware
- */
-static void
-bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_FWRSP:
-		if (lps->status == BFA_STATUS_OK) {
-			bfa_sm_set_state(lps, bfa_lps_sm_online);
-			if (lps->fdisc)
-				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-				BFA_PL_EID_LOGIN, 0, "FDISC Accept");
-			else
-				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-				BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
-		} else {
-			bfa_sm_set_state(lps, bfa_lps_sm_init);
-			if (lps->fdisc)
-				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-				BFA_PL_EID_LOGIN, 0,
-				"FDISC Fail (RJT or timeout)");
-			else
-				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-				BFA_PL_EID_LOGIN, 0,
-				"FLOGI Fail (RJT or timeout)");
-		}
-		bfa_lps_login_comp(lps);
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * login pending - awaiting space in request queue
- */
-static void
-bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_RESUME:
-		bfa_sm_set_state(lps, bfa_lps_sm_login);
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		bfa_reqq_wcancel(&lps->wqe);
-		break;
-
-	case BFA_LPS_SM_RX_CVL:
-		/*
-		 * Login was not even sent out; so when getting out
-		 * of this state, it will appear like a login retry
-		 * after Clear virtual link
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * login complete
- */
-static void
-bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_LOGOUT:
-		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
-			bfa_sm_set_state(lps, bfa_lps_sm_logowait);
-			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
-		} else {
-			bfa_sm_set_state(lps, bfa_lps_sm_logout);
-			bfa_lps_send_logout(lps);
-		}
-		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-			BFA_PL_EID_LOGO, 0, "Logout");
-		break;
-
-	case BFA_LPS_SM_RX_CVL:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-
-		/* Let the vport module know about this event */
-		bfa_lps_cvl_event(lps);
-		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
-			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-	case BFA_LPS_SM_DELETE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * logout in progress - awaiting firmware response
- */
-static void
-bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_FWRSP:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		bfa_lps_logout_comp(lps);
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-/**
- * logout pending -- awaiting space in request queue
- */
-static void
-bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
-{
-	bfa_trc(lps->bfa, lps->lp_tag);
-	bfa_trc(lps->bfa, event);
-
-	switch (event) {
-	case BFA_LPS_SM_RESUME:
-		bfa_sm_set_state(lps, bfa_lps_sm_logout);
-		bfa_lps_send_logout(lps);
-		break;
-
-	case BFA_LPS_SM_OFFLINE:
-		bfa_sm_set_state(lps, bfa_lps_sm_init);
-		bfa_reqq_wcancel(&lps->wqe);
-		break;
-
-	default:
-		bfa_sm_fault(lps->bfa, event);
-	}
-}
-
-
-
-/**
- *  lps_pvt BFA LPS private functions
- */
-
-/**
- * return memory requirement
- */
-static void
-bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
-{
-	if (cfg->drvcfg.min_cfg)
-		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
-	else
-		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
-}
-
-/**
- * bfa module attach at initialization time
- */
-static void
-bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-	int			i;
-
-	bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s));
-	mod->num_lps = BFA_LPS_MAX_LPORTS;
-	if (cfg->drvcfg.min_cfg)
-		mod->num_lps = BFA_LPS_MIN_LPORTS;
-	else
-		mod->num_lps = BFA_LPS_MAX_LPORTS;
-	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
-
-	bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
-
-	INIT_LIST_HEAD(&mod->lps_free_q);
-	INIT_LIST_HEAD(&mod->lps_active_q);
-
-	for (i = 0; i < mod->num_lps; i++, lps++) {
-		lps->bfa	= bfa;
-		lps->lp_tag	= (u8) i;
-		lps->reqq	= BFA_REQQ_LPS;
-		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
-		list_add_tail(&lps->qe, &mod->lps_free_q);
-	}
-}
-
-static void
-bfa_lps_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_lps_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_lps_stop(struct bfa_s *bfa)
-{
-}
-
-/**
- * IOC in disabled state -- consider all lps offline
- */
-static void
-bfa_lps_iocdisable(struct bfa_s *bfa)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-	struct list_head		*qe, *qen;
-
-	list_for_each_safe(qe, qen, &mod->lps_active_q) {
-		lps = (struct bfa_lps_s *) qe;
-		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
-	}
-}
-
-/**
- * Firmware login response
- */
-static void
-bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-
-	bfa_assert(rsp->lp_tag < mod->num_lps);
-	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
-
-	lps->status = rsp->status;
-	switch (rsp->status) {
-	case BFA_STATUS_OK:
-		lps->fport	= rsp->f_port;
-		lps->npiv_en	= rsp->npiv_en;
-		lps->lp_pid	= rsp->lp_pid;
-		lps->pr_bbcred	= bfa_os_ntohs(rsp->bb_credit);
-		lps->pr_pwwn	= rsp->port_name;
-		lps->pr_nwwn	= rsp->node_name;
-		lps->auth_req	= rsp->auth_req;
-		lps->lp_mac	= rsp->lp_mac;
-		lps->brcd_switch = rsp->brcd_switch;
-		lps->fcf_mac	= rsp->fcf_mac;
-
-		break;
-
-	case BFA_STATUS_FABRIC_RJT:
-		lps->lsrjt_rsn = rsp->lsrjt_rsn;
-		lps->lsrjt_expl = rsp->lsrjt_expl;
-
-		break;
-
-	case BFA_STATUS_EPROTOCOL:
-		lps->ext_status = rsp->ext_status;
-
-		break;
-
-	default:
-		/* Nothing to do with other status */
-		break;
-	}
-
-	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
-}
-
-/**
- * Firmware logout response
- */
-static void
-bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-
-	bfa_assert(rsp->lp_tag < mod->num_lps);
-	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
-
-	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
-}
-
-/**
- * Firmware received a Clear virtual link request (for FCoE)
- */
-static void
-bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
-{
-	struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s        *lps;
-
-	lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
-
-	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
-}
-
-/**
- * Space is available in request queue, resume queueing request to firmware.
- */
-static void
-bfa_lps_reqq_resume(void *lps_arg)
-{
-	struct bfa_lps_s	*lps = lps_arg;
-
-	bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
-}
-
-/**
- * lps is freed -- triggered by vport delete
- */
-static void
-bfa_lps_free(struct bfa_lps_s *lps)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
-
-	list_del(&lps->qe);
-	list_add_tail(&lps->qe, &mod->lps_free_q);
-}
-
-/**
- * send login request to firmware
- */
-static void
-bfa_lps_send_login(struct bfa_lps_s *lps)
-{
-	struct bfi_lps_login_req_s	*m;
-
-	m = bfa_reqq_next(lps->bfa, lps->reqq);
-	bfa_assert(m);
-
-	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
-			bfa_lpuid(lps->bfa));
-
-	m->lp_tag	= lps->lp_tag;
-	m->alpa		= lps->alpa;
-	m->pdu_size	= bfa_os_htons(lps->pdusz);
-	m->pwwn		= lps->pwwn;
-	m->nwwn		= lps->nwwn;
-	m->fdisc	= lps->fdisc;
-	m->auth_en	= lps->auth_en;
-
-	bfa_reqq_produce(lps->bfa, lps->reqq);
-}
-
-/**
- * send logout request to firmware
- */
-static void
-bfa_lps_send_logout(struct bfa_lps_s *lps)
-{
-	struct bfi_lps_logout_req_s *m;
-
-	m = bfa_reqq_next(lps->bfa, lps->reqq);
-	bfa_assert(m);
-
-	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
-			bfa_lpuid(lps->bfa));
-
-	m->lp_tag    = lps->lp_tag;
-	m->port_name = lps->pwwn;
-	bfa_reqq_produce(lps->bfa, lps->reqq);
-}
-
-/**
- * Indirect login completion handler for non-fcs
- */
-static void
-bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
-{
-	struct bfa_lps_s *lps	= arg;
-
-	if (!complete)
-		return;
-
-	if (lps->fdisc)
-		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
-	else
-		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
-}
-
-/**
- * Login completion handler -- direct call for fcs, queue for others
- */
-static void
-bfa_lps_login_comp(struct bfa_lps_s *lps)
-{
-	if (!lps->bfa->fcs) {
-		bfa_cb_queue(lps->bfa, &lps->hcb_qe,
-				bfa_lps_login_comp_cb, lps);
-		return;
-	}
-
-	if (lps->fdisc)
-		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
-	else
-		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
-}
-
-/**
- * Indirect logout completion handler for non-fcs
- */
-static void
-bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
-{
-	struct bfa_lps_s *lps	= arg;
-
-	if (!complete)
-		return;
-
-	if (lps->fdisc)
-		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
-	else
-		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
-}
-
-/**
- * Logout completion handler -- direct call for fcs, queue for others
- */
-static void
-bfa_lps_logout_comp(struct bfa_lps_s *lps)
-{
-	if (!lps->bfa->fcs) {
-		bfa_cb_queue(lps->bfa, &lps->hcb_qe,
-				bfa_lps_logout_comp_cb, lps);
-		return;
-	}
-	if (lps->fdisc)
-		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
-	else
-		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
-}
-
-/**
- * Clear virtual link completion handler for non-fcs
- */
-static void
-bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
-{
-	struct bfa_lps_s *lps   = arg;
-
-	if (!complete)
-		return;
-
-	/* Clear virtual link to base port will result in link down */
-	if (lps->fdisc)
-		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
-}
-
-/**
- * Received Clear virtual link event --direct call for fcs,
- * queue for others
- */
-static void
-bfa_lps_cvl_event(struct bfa_lps_s *lps)
-{
-	if (!lps->bfa->fcs) {
-		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
-				lps);
-		return;
-	}
-
-	/* Clear virtual link to base port will result in link down */
-	if (lps->fdisc)
-		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
-}
-
-u32
-bfa_lps_get_max_vport(struct bfa_s *bfa)
-{
-	if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
-		return BFA_LPS_MAX_VPORTS_SUPP_CT;
-	else
-		return BFA_LPS_MAX_VPORTS_SUPP_CB;
-}
-
-/**
- *  lps_public BFA LPS public functions
- */
-
-/**
- * Allocate a lport srvice tag.
- */
-struct bfa_lps_s  *
-bfa_lps_alloc(struct bfa_s *bfa)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps = NULL;
-
-	bfa_q_deq(&mod->lps_free_q, &lps);
-
-	if (lps == NULL)
-		return NULL;
-
-	list_add_tail(&lps->qe, &mod->lps_active_q);
-
-	bfa_sm_set_state(lps, bfa_lps_sm_init);
-	return lps;
-}
-
-/**
- * Free lport service tag. This can be called anytime after an alloc.
- * No need to wait for any pending login/logout completions.
- */
-void
-bfa_lps_delete(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
-}
-
-/**
- * Initiate a lport login.
- */
-void
-bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
-	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
-{
-	lps->uarg	= uarg;
-	lps->alpa	= alpa;
-	lps->pdusz	= pdusz;
-	lps->pwwn	= pwwn;
-	lps->nwwn	= nwwn;
-	lps->fdisc	= BFA_FALSE;
-	lps->auth_en	= auth_en;
-	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
-}
-
-/**
- * Initiate a lport fdisc login.
- */
-void
-bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
-	wwn_t nwwn)
-{
-	lps->uarg	= uarg;
-	lps->alpa	= 0;
-	lps->pdusz	= pdusz;
-	lps->pwwn	= pwwn;
-	lps->nwwn	= nwwn;
-	lps->fdisc	= BFA_TRUE;
-	lps->auth_en	= BFA_FALSE;
-	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
-}
-
-/**
- * Initiate a lport logout (flogi).
- */
-void
-bfa_lps_flogo(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
-}
-
-/**
- * Initiate a lport FDSIC logout.
- */
-void
-bfa_lps_fdisclogo(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
-}
-
-/**
- * Discard a pending login request -- should be called only for
- * link down handling.
- */
-void
-bfa_lps_discard(struct bfa_lps_s *lps)
-{
-	bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
-}
-
-/**
- * Return lport services tag
- */
-u8
-bfa_lps_get_tag(struct bfa_lps_s *lps)
-{
-	return lps->lp_tag;
-}
-
-/**
- * Return lport services tag given the pid
- */
-u8
-bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
-{
-	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
-	struct bfa_lps_s	*lps;
-	int			i;
-
-	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
-		if (lps->lp_pid == pid)
-			return lps->lp_tag;
-	}
-
-	/* Return base port tag anyway */
-	return 0;
-}
-
-/**
- * return if fabric login indicates support for NPIV
- */
-bfa_boolean_t
-bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
-{
-	return lps->npiv_en;
-}
-
-/**
- * Return TRUE if attached to F-Port, else return FALSE
- */
-bfa_boolean_t
-bfa_lps_is_fport(struct bfa_lps_s *lps)
-{
-	return lps->fport;
-}
-
-/**
- * Return TRUE if attached to a Brocade Fabric
- */
-bfa_boolean_t
-bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
-{
-	return lps->brcd_switch;
-}
-/**
- * return TRUE if authentication is required
- */
-bfa_boolean_t
-bfa_lps_is_authreq(struct bfa_lps_s *lps)
-{
-	return lps->auth_req;
-}
-
-bfa_eproto_status_t
-bfa_lps_get_extstatus(struct bfa_lps_s *lps)
-{
-	return lps->ext_status;
-}
-
-/**
- * return port id assigned to the lport
- */
-u32
-bfa_lps_get_pid(struct bfa_lps_s *lps)
-{
-	return lps->lp_pid;
-}
-
-/**
- * Return bb_credit assigned in FLOGI response
- */
-u16
-bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
-{
-	return lps->pr_bbcred;
-}
-
-/**
- * Return peer port name
- */
-wwn_t
-bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
-{
-	return lps->pr_pwwn;
-}
-
-/**
- * Return peer node name
- */
-wwn_t
-bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
-{
-	return lps->pr_nwwn;
-}
-
-/**
- * return reason code if login request is rejected
- */
-u8
-bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
-{
-	return lps->lsrjt_rsn;
-}
-
-/**
- * return explanation code if login request is rejected
- */
-u8
-bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
-{
-	return lps->lsrjt_expl;
-}
-
-/**
- * Return fpma/spma MAC for lport
- */
-struct mac_s
-bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
-{
-	return lps->lp_mac;
-}
-
-/**
- * LPS firmware message class handler.
- */
-void
-bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	union bfi_lps_i2h_msg_u	msg;
-
-	bfa_trc(bfa, m->mhdr.msg_id);
-	msg.msg = m;
-
-	switch (m->mhdr.msg_id) {
-	case BFI_LPS_H2I_LOGIN_RSP:
-		bfa_lps_login_rsp(bfa, msg.login_rsp);
-		break;
-
-	case BFI_LPS_H2I_LOGOUT_RSP:
-		bfa_lps_logout_rsp(bfa, msg.logout_rsp);
-		break;
-
-	case BFI_LPS_H2I_CVL_EVENT:
-		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
-		break;
-
-	default:
-		bfa_trc(bfa, m->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_lps_priv.h b/drivers/scsi/bfa/bfa_lps_priv.h
deleted file mode 100644
index d16c6ce..0000000
--- a/drivers/scsi/bfa/bfa_lps_priv.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_LPS_PRIV_H__
-#define __BFA_LPS_PRIV_H__
-
-#include <bfa_svc.h>
-
-struct bfa_lps_mod_s {
-	struct list_head		lps_free_q;
-	struct list_head		lps_active_q;
-	struct bfa_lps_s	*lps_arr;
-	int			num_lps;
-};
-
-#define BFA_LPS_MOD(__bfa)		(&(__bfa)->modules.lps_mod)
-#define BFA_LPS_FROM_TAG(__mod, __tag)	(&(__mod)->lps_arr[__tag])
-
-/*
- * external functions
- */
-void	bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#endif /* __BFA_LPS_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_priv.h b/drivers/scsi/bfa/bfa_modules.h
similarity index 69%
rename from drivers/scsi/bfa/bfa_priv.h
rename to drivers/scsi/bfa/bfa_modules.h
index bf4939b..2cd5273 100644
--- a/drivers/scsi/bfa/bfa_priv.h
+++ b/drivers/scsi/bfa/bfa_modules.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,26 +15,52 @@
  * General Public License for more details.
  */
 
-#ifndef __BFA_PRIV_H__
-#define __BFA_PRIV_H__
+/**
+ *  bfa_modules.h BFA modules
+ */
 
-#include "bfa_iocfc.h"
-#include "bfa_intr_priv.h"
-#include "bfa_trcmod_priv.h"
-#include "bfa_modules_priv.h"
-#include "bfa_fwimg_priv.h"
-#include <cs/bfa_log.h>
-#include <bfa_timer.h>
+#ifndef __BFA_MODULES_H__
+#define __BFA_MODULES_H__
+
+#include "bfa_cs.h"
+#include "bfa.h"
+#include "bfa_svc.h"
+#include "bfa_fcpim.h"
+#include "bfa_port.h"
+
+struct bfa_modules_s {
+	struct bfa_fcport_s	fcport;		/*  fc port module	      */
+	struct bfa_fcxp_mod_s	fcxp_mod;	/*  fcxp module	      */
+	struct bfa_lps_mod_s	lps_mod;	/*  fcxp module	      */
+	struct bfa_uf_mod_s	uf_mod;		/*  unsolicited frame module */
+	struct bfa_rport_mod_s	rport_mod;	/*  remote port module	      */
+	struct bfa_fcpim_mod_s	fcpim_mod;	/*  FCP initiator module     */
+	struct bfa_sgpg_mod_s	sgpg_mod;	/*  SG page module	      */
+	struct bfa_port_s	port;		/*  Physical port module     */
+};
+
+/*
+ * !!! Only append to the enums defined here to avoid any versioning
+ * !!! needed between trace utility and driver version
+ */
+enum {
+	BFA_TRC_HAL_CORE	= 1,
+	BFA_TRC_HAL_FCXP	= 2,
+	BFA_TRC_HAL_FCPIM	= 3,
+	BFA_TRC_HAL_IOCFC_CT	= 4,
+	BFA_TRC_HAL_IOCFC_CB	= 5,
+};
+
 
 /**
  * Macro to define a new BFA module
  */
-#define BFA_MODULE(__mod) 						\
+#define BFA_MODULE(__mod)						\
 	static void bfa_ ## __mod ## _meminfo(				\
 			struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,	\
 			u32 *dm_len);      \
 	static void bfa_ ## __mod ## _attach(struct bfa_s *bfa,		\
-			void *bfad, struct bfa_iocfc_cfg_s *cfg, 	\
+			void *bfad, struct bfa_iocfc_cfg_s *cfg,	\
 			struct bfa_meminfo_s *meminfo,			\
 			struct bfa_pcidev_s *pcidev);      \
 	static void bfa_ ## __mod ## _detach(struct bfa_s *bfa);      \
@@ -77,17 +103,15 @@
 
 struct bfa_s {
 	void			*bfad;		/*  BFA driver instance    */
-	struct bfa_aen_s	*aen;		/*  AEN module		    */
 	struct bfa_plog_s	*plog;		/*  portlog buffer	    */
-	struct bfa_log_mod_s	*logm;		/*  driver logging modulen */
 	struct bfa_trc_mod_s	*trcmod;	/*  driver tracing	    */
 	struct bfa_ioc_s	ioc;		/*  IOC module		    */
 	struct bfa_iocfc_s	iocfc;		/*  IOCFC module	    */
 	struct bfa_timer_mod_s	timer_mod;	/*  timer module	    */
 	struct bfa_modules_s	modules;	/*  BFA modules	    */
-	struct list_head	comp_q;		/*  pending completions    */
-	bfa_boolean_t		rme_process;	/*  RME processing enabled */
-	struct list_head		reqq_waitq[BFI_IOC_MAX_CQS];
+	struct list_head	comp_q;		/*  pending completions     */
+	bfa_boolean_t		rme_process;	/*  RME processing enabled  */
+	struct list_head	reqq_waitq[BFI_IOC_MAX_CQS];
 	bfa_boolean_t		fcs;		/*  FCS is attached to BFA */
 	struct bfa_msix_s	msix;
 };
@@ -95,8 +119,6 @@
 extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX];
 extern bfa_ioc_mbox_mcfunc_t  bfa_mbox_isrs[];
 extern bfa_boolean_t bfa_auto_recover;
-extern struct bfa_module_s hal_mod_flash;
-extern struct bfa_module_s hal_mod_fcdiag;
 extern struct bfa_module_s hal_mod_sgpg;
 extern struct bfa_module_s hal_mod_fcport;
 extern struct bfa_module_s hal_mod_fcxp;
@@ -104,7 +126,5 @@
 extern struct bfa_module_s hal_mod_uf;
 extern struct bfa_module_s hal_mod_rport;
 extern struct bfa_module_s hal_mod_fcpim;
-extern struct bfa_module_s hal_mod_pbind;
 
-#endif /* __BFA_PRIV_H__ */
-
+#endif /* __BFA_MODULES_H__ */
diff --git a/drivers/scsi/bfa/bfa_modules_priv.h b/drivers/scsi/bfa/bfa_modules_priv.h
deleted file mode 100644
index f554c2f..0000000
--- a/drivers/scsi/bfa/bfa_modules_priv.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_MODULES_PRIV_H__
-#define __BFA_MODULES_PRIV_H__
-
-#include "bfa_uf_priv.h"
-#include "bfa_port_priv.h"
-#include "bfa_rport_priv.h"
-#include "bfa_fcxp_priv.h"
-#include "bfa_lps_priv.h"
-#include "bfa_fcpim_priv.h"
-#include <cee/bfa_cee.h>
-#include <port/bfa_port.h>
-
-
-struct bfa_modules_s {
-	struct bfa_fcport_s	fcport;	/*  fc port module	*/
-	struct bfa_fcxp_mod_s fcxp_mod; /*  fcxp module		*/
-	struct bfa_lps_mod_s lps_mod;   /*  fcxp module		*/
-	struct bfa_uf_mod_s uf_mod;	/*  unsolicited frame module	*/
-	struct bfa_rport_mod_s rport_mod; /*  remote port module	*/
-	struct bfa_fcpim_mod_s fcpim_mod; /*  FCP initiator module	*/
-	struct bfa_sgpg_mod_s sgpg_mod; /*  SG page module		*/
-	struct bfa_cee_s cee;   	/*  CEE Module                 */
-	struct bfa_port_s port;		/*  Physical port module	*/
-};
-
-#endif /* __BFA_MODULES_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_os_inc.h b/drivers/scsi/bfa/bfa_os_inc.h
index bd1cd3e..788a250 100644
--- a/drivers/scsi/bfa/bfa_os_inc.h
+++ b/drivers/scsi/bfa/bfa_os_inc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -22,30 +22,20 @@
 #ifndef __BFA_OS_INC_H__
 #define __BFA_OS_INC_H__
 
-#ifndef __KERNEL__
-#include <stdint.h>
-#else
 #include <linux/types.h>
-
 #include <linux/version.h>
 #include <linux/pci.h>
-
 #include <linux/dma-mapping.h>
-#define SET_MODULE_VERSION(VER)
-
 #include <linux/idr.h>
-
 #include <linux/interrupt.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
-
 #include <linux/workqueue.h>
-
+#include <linux/bitops.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
-
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport_fc.h>
 #include <scsi/scsi_transport.h>
@@ -54,97 +44,75 @@
 #define __BIGENDIAN
 #endif
 
-#define BFA_ERR			KERN_ERR
-#define BFA_WARNING		KERN_WARNING
-#define BFA_NOTICE		KERN_NOTICE
-#define BFA_INFO		KERN_INFO
-#define BFA_DEBUG		KERN_DEBUG
+static inline u64 bfa_os_get_clock(void)
+{
+	return jiffies;
+}
 
-#define LOG_BFAD_INIT		0x00000001
-#define LOG_FCP_IO		0x00000002
+static inline u64 bfa_os_get_log_time(void)
+{
+	u64 system_time = 0;
+	struct timeval tv;
+	do_gettimeofday(&tv);
 
-#ifdef DEBUG
-#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...)			\
-		BFA_LOG(bfad, level, mask, fmt, ## arg)
-#define BFA_DEV_TRACE(bfad, level, fmt, arg...)				\
-		BFA_DEV_PRINTF(bfad, level, fmt, ## arg)
-#define BFA_TRACE(level, fmt, arg...)					\
-		BFA_PRINTF(level, fmt, ## arg)
-#else
-#define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...)
-#define BFA_DEV_TRACE(bfad, level, fmt, arg...)
-#define BFA_TRACE(level, fmt, arg...)
-#endif
+	/* We are interested in seconds only. */
+	system_time = tv.tv_sec;
+	return system_time;
+}
+
+#define bfa_io_lat_clock_res_div HZ
+#define bfa_io_lat_clock_res_mul 1000
 
 #define BFA_ASSERT(p) do {						\
 	if (!(p)) {      \
 		printk(KERN_ERR "assert(%s) failed at %s:%d\n",		\
 		#p, __FILE__, __LINE__);      \
-		BUG();      \
 	}								\
 } while (0)
 
-
-#define BFA_LOG(bfad, level, mask, fmt, arg...)				\
-do { 									\
-	if (((mask) & (((struct bfad_s *)(bfad))->			\
-		cfg_data[cfg_log_mask])) || (level[1] <= '3'))		\
-		dev_printk(level, &(((struct bfad_s *)			\
-			(bfad))->pcidev->dev), fmt, ##arg);      \
+#define BFA_LOG(level, bfad, mask, fmt, arg...)				\
+do {									\
+	if (((mask) == 4) || (level[1] <= '4'))				\
+		dev_printk(level, &((bfad)->pcidev)->dev, fmt, ##arg);	\
 } while (0)
 
-#ifndef BFA_DEV_PRINTF
-#define BFA_DEV_PRINTF(bfad, level, fmt, arg...)			\
-		dev_printk(level, &(((struct bfad_s *)			\
-			(bfad))->pcidev->dev), fmt, ##arg);
-#endif
-
-#define BFA_PRINTF(level, fmt, arg...)					\
-		printk(level fmt, ##arg);
-
-int bfa_os_MWB(void *);
-
-#define bfa_os_mmiowb()		mmiowb()
-
 #define bfa_swap_3b(_x)				\
 	((((_x) & 0xff) << 16) |		\
 	((_x) & 0x00ff00) |			\
 	(((_x) & 0xff0000) >> 16))
 
-#define bfa_swap_8b(_x) 				\
-     ((((_x) & 0xff00000000000000ull) >> 56)		\
-      | (((_x) & 0x00ff000000000000ull) >> 40)		\
-      | (((_x) & 0x0000ff0000000000ull) >> 24)		\
-      | (((_x) & 0x000000ff00000000ull) >> 8)		\
-      | (((_x) & 0x00000000ff000000ull) << 8)		\
-      | (((_x) & 0x0000000000ff0000ull) << 24)		\
-      | (((_x) & 0x000000000000ff00ull) << 40)		\
-      | (((_x) & 0x00000000000000ffull) << 56))
+#define bfa_swap_8b(_x)					\
+	((((_x) & 0xff00000000000000ull) >> 56)		\
+	 | (((_x) & 0x00ff000000000000ull) >> 40)	\
+	 | (((_x) & 0x0000ff0000000000ull) >> 24)	\
+	 | (((_x) & 0x000000ff00000000ull) >> 8)	\
+	 | (((_x) & 0x00000000ff000000ull) << 8)	\
+	 | (((_x) & 0x0000000000ff0000ull) << 24)	\
+	 | (((_x) & 0x000000000000ff00ull) << 40)	\
+	 | (((_x) & 0x00000000000000ffull) << 56))
 
-#define bfa_os_swap32(_x) 			\
-	((((_x) & 0xff) << 24) 		|	\
+#define bfa_os_swap32(_x)			\
+	((((_x) & 0xff) << 24)		|	\
 	(((_x) & 0x0000ff00) << 8)	|	\
 	(((_x) & 0x00ff0000) >> 8)	|	\
 	(((_x) & 0xff000000) >> 24))
 
-#define bfa_os_swap_sgaddr(_x)	((u64)(					\
-	(((u64)(_x) & (u64)0x00000000000000ffull) << 32)	|	\
-	(((u64)(_x) & (u64)0x000000000000ff00ull) << 32)	|	\
-	(((u64)(_x) & (u64)0x0000000000ff0000ull) << 32)	|	\
-	(((u64)(_x) & (u64)0x00000000ff000000ull) << 32)	|	\
-	(((u64)(_x) & (u64)0x000000ff00000000ull) >> 32)	|	\
-	(((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32)	|	\
-	(((u64)(_x) & (u64)0x00ff000000000000ull) >> 32)	|	\
+#define bfa_os_swap_sgaddr(_x)  ((u64)(                                 \
+	(((u64)(_x) & (u64)0x00000000000000ffull) << 32)        |       \
+	(((u64)(_x) & (u64)0x000000000000ff00ull) << 32)        |       \
+	(((u64)(_x) & (u64)0x0000000000ff0000ull) << 32)        |       \
+	(((u64)(_x) & (u64)0x00000000ff000000ull) << 32)        |       \
+	(((u64)(_x) & (u64)0x000000ff00000000ull) >> 32)        |       \
+	(((u64)(_x) & (u64)0x0000ff0000000000ull) >> 32)        |       \
+	(((u64)(_x) & (u64)0x00ff000000000000ull) >> 32)        |       \
 	(((u64)(_x) & (u64)0xff00000000000000ull) >> 32)))
 
 #ifndef __BIGENDIAN
 #define bfa_os_htons(_x) ((u16)((((_x) & 0xff00) >> 8) | \
 				 (((_x) & 0x00ff) << 8)))
-
 #define bfa_os_htonl(_x)	bfa_os_swap32(_x)
 #define bfa_os_htonll(_x)	bfa_swap_8b(_x)
 #define bfa_os_hton3b(_x)	bfa_swap_3b(_x)
-
 #define bfa_os_wtole(_x)   (_x)
 #define bfa_os_sgaddr(_x)  (_x)
 
@@ -170,17 +138,16 @@
 #define bfa_os_memcpy	memcpy
 #define bfa_os_udelay	udelay
 #define bfa_os_vsprintf vsprintf
+#define bfa_os_snprintf snprintf
 
 #define bfa_os_assign(__t, __s) __t = __s
-
-#define bfa_os_addr_t char __iomem *
-#define bfa_os_panic()
+#define bfa_os_addr_t void __iomem *
 
 #define bfa_os_reg_read(_raddr) readl(_raddr)
 #define bfa_os_reg_write(_raddr, _val) writel((_val), (_raddr))
-#define bfa_os_mem_read(_raddr, _off)                                   \
+#define bfa_os_mem_read(_raddr, _off)					\
 	bfa_os_swap32(readl(((_raddr) + (_off))))
-#define bfa_os_mem_write(_raddr, _off, _val)                            \
+#define bfa_os_mem_write(_raddr, _off, _val)				\
 	writel(bfa_os_swap32((_val)), ((_raddr) + (_off)))
 
 #define BFA_TRC_TS(_trcm)						\
@@ -191,11 +158,6 @@
 				(tv.tv_sec*1000000+tv.tv_usec);      \
 			 })
 
-struct bfa_log_mod_s;
-void bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
-			const char *fmt, ...);
-#endif
-
 #define boolean_t int
 
 /**
@@ -206,7 +168,15 @@
 	u32	tv_usec;	/*  microseconds   */
 };
 
-void bfa_os_gettimeofday(struct bfa_timeval_s *tv);
+static inline void
+bfa_os_gettimeofday(struct bfa_timeval_s *tv)
+{
+	struct timeval  tmp_tv;
+
+	do_gettimeofday(&tmp_tv);
+	tv->tv_sec = (u32) tmp_tv.tv_sec;
+	tv->tv_usec = (u32) tmp_tv.tv_usec;
+}
 
 static inline void
 wwn2str(char *wwn_str, u64 wwn)
diff --git a/drivers/scsi/bfa/bfa_plog.h b/drivers/scsi/bfa/bfa_plog.h
new file mode 100644
index 0000000..501f0ed
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_plog.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+#ifndef __BFA_PORTLOG_H__
+#define __BFA_PORTLOG_H__
+
+#include "bfa_fc.h"
+#include "bfa_defs.h"
+
+#define BFA_PL_NLOG_ENTS 256
+#define BFA_PL_LOG_REC_INCR(_x) ((_x)++, (_x) %= BFA_PL_NLOG_ENTS)
+
+#define BFA_PL_STRING_LOG_SZ   32   /* number of chars in string log */
+#define BFA_PL_INT_LOG_SZ      8    /* number of integers in the integer log */
+
+enum bfa_plog_log_type {
+	BFA_PL_LOG_TYPE_INVALID	= 0,
+	BFA_PL_LOG_TYPE_INT	= 1,
+	BFA_PL_LOG_TYPE_STRING	= 2,
+};
+
+/*
+ * the (fixed size) record format for each entry in the portlog
+ */
+struct bfa_plog_rec_s {
+	u64	tv;	/* timestamp */
+	u8	 port;	/* Source port that logged this entry */
+	u8	 mid;	/* module id */
+	u8	 eid;	/* indicates Rx, Tx, IOCTL, etc.  bfa_plog_eid */
+	u8	 log_type; /* string/integer log, bfa_plog_log_type_t */
+	u8	 log_num_ints;
+	/*
+	 * interpreted only if log_type is INT_LOG. indicates number of
+	 * integers in the int_log[] (0-PL_INT_LOG_SZ).
+	 */
+	u8	 rsvd;
+	u16	misc;	/* can be used to indicate fc frame length */
+	union {
+		char	    string_log[BFA_PL_STRING_LOG_SZ];
+		u32	int_log[BFA_PL_INT_LOG_SZ];
+	} log_entry;
+
+};
+
+/*
+ * the following #defines will be used by the logging entities to indicate
+ * their module id. BFAL will convert the integer value to string format
+ *
+* process to be used while changing the following #defines:
+ *  - Always add new entries at the end
+ *  - define corresponding string in BFAL
+ *  - Do not remove any entry or rearrange the order.
+ */
+enum bfa_plog_mid {
+	BFA_PL_MID_INVALID	= 0,
+	BFA_PL_MID_DEBUG	= 1,
+	BFA_PL_MID_DRVR		= 2,
+	BFA_PL_MID_HAL		= 3,
+	BFA_PL_MID_HAL_FCXP	= 4,
+	BFA_PL_MID_HAL_UF	= 5,
+	BFA_PL_MID_FCS		= 6,
+	BFA_PL_MID_LPS		= 7,
+	BFA_PL_MID_MAX		= 8
+};
+
+#define BFA_PL_MID_STRLEN    8
+struct bfa_plog_mid_strings_s {
+	char	    m_str[BFA_PL_MID_STRLEN];
+};
+
+/*
+ * the following #defines will be used by the logging entities to indicate
+ * their event type. BFAL will convert the integer value to string format
+ *
+* process to be used while changing the following #defines:
+ *  - Always add new entries at the end
+ *  - define corresponding string in BFAL
+ *  - Do not remove any entry or rearrange the order.
+ */
+enum bfa_plog_eid {
+	BFA_PL_EID_INVALID		= 0,
+	BFA_PL_EID_IOC_DISABLE		= 1,
+	BFA_PL_EID_IOC_ENABLE		= 2,
+	BFA_PL_EID_PORT_DISABLE		= 3,
+	BFA_PL_EID_PORT_ENABLE		= 4,
+	BFA_PL_EID_PORT_ST_CHANGE	= 5,
+	BFA_PL_EID_TX			= 6,
+	BFA_PL_EID_TX_ACK1		= 7,
+	BFA_PL_EID_TX_RJT		= 8,
+	BFA_PL_EID_TX_BSY		= 9,
+	BFA_PL_EID_RX			= 10,
+	BFA_PL_EID_RX_ACK1		= 11,
+	BFA_PL_EID_RX_RJT		= 12,
+	BFA_PL_EID_RX_BSY		= 13,
+	BFA_PL_EID_CT_IN		= 14,
+	BFA_PL_EID_CT_OUT		= 15,
+	BFA_PL_EID_DRIVER_START		= 16,
+	BFA_PL_EID_RSCN			= 17,
+	BFA_PL_EID_DEBUG		= 18,
+	BFA_PL_EID_MISC			= 19,
+	BFA_PL_EID_FIP_FCF_DISC		= 20,
+	BFA_PL_EID_FIP_FCF_CVL		= 21,
+	BFA_PL_EID_LOGIN		= 22,
+	BFA_PL_EID_LOGO			= 23,
+	BFA_PL_EID_TRUNK_SCN		= 24,
+	BFA_PL_EID_MAX
+};
+
+#define BFA_PL_ENAME_STRLEN	8
+struct bfa_plog_eid_strings_s {
+	char	    e_str[BFA_PL_ENAME_STRLEN];
+};
+
+#define BFA_PL_SIG_LEN	8
+#define BFA_PL_SIG_STR  "12pl123"
+
+/*
+ * per port circular log buffer
+ */
+struct bfa_plog_s {
+	char	    plog_sig[BFA_PL_SIG_LEN];	/* Start signature */
+	u8	 plog_enabled;
+	u8	 rsvd[7];
+	u32	ticks;
+	u16	head;
+	u16	tail;
+	struct bfa_plog_rec_s  plog_recs[BFA_PL_NLOG_ENTS];
+};
+
+void bfa_plog_init(struct bfa_plog_s *plog);
+void bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+			enum bfa_plog_eid event, u16 misc, char *log_str);
+void bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+			enum bfa_plog_eid event, u16 misc,
+			u32 *intarr, u32 num_ints);
+void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+		enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr);
+void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+			enum bfa_plog_eid event, u16 misc,
+			struct fchs_s *fchdr, u32 pld_w0);
+void bfa_plog_clear(struct bfa_plog_s *plog);
+void bfa_plog_enable(struct bfa_plog_s *plog);
+void bfa_plog_disable(struct bfa_plog_s *plog);
+bfa_boolean_t	bfa_plog_get_setting(struct bfa_plog_s *plog);
+
+#endif /* __BFA_PORTLOG_H__ */
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index c7e69f1..b6d170a 100644
--- a/drivers/scsi/bfa/bfa_port.c
+++ b/drivers/scsi/bfa/bfa_port.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -15,30 +15,25 @@
  * General Public License for more details.
  */
 
-#include <defs/bfa_defs_port.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-#include <cs/bfa_debug.h>
-#include <port/bfa_port.h>
-#include <bfi/bfi.h>
-#include <bfi/bfi_port.h>
-#include <bfa_ioc.h>
-#include <cna/bfa_cna_trcmod.h>
+#include "bfa_defs_svc.h"
+#include "bfa_port.h"
+#include "bfi.h"
+#include "bfa_ioc.h"
+
 
 BFA_TRC_FILE(CNA, PORT);
 
 #define bfa_ioc_portid(__ioc) ((__ioc)->port_id)
-#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc)
 
 static void
-bfa_port_stats_swap(struct bfa_port_s *port, union bfa_pport_stats_u *stats)
+bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats)
 {
-	u32       *dip = (u32 *) stats;
-	u32        t0, t1;
-	int             i;
+	u32    *dip = (u32 *) stats;
+	u32    t0, t1;
+	int	    i;
 
-	for (i = 0; i < sizeof(union bfa_pport_stats_u) / sizeof(u32);
-	     i += 2) {
+	for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32);
+		i += 2) {
 		t0 = dip[i];
 		t1 = dip[i + 1];
 #ifdef __BIGENDIAN
@@ -49,11 +44,6 @@
 		dip[i + 1] = bfa_os_ntohl(t0);
 #endif
 	}
-
-    /** todo
-     * QoS stats r also swapped as 64bit; that structure also
-     * has to use 64 bit counters
-     */
 }
 
 /**
@@ -68,7 +58,9 @@
 static void
 bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status)
 {
-	bfa_assert(0);
+	bfa_trc(port, status);
+	port->endis_pending = BFA_FALSE;
+	port->endis_cbfn(port->endis_cbarg, status);
 }
 
 /**
@@ -83,7 +75,9 @@
 static void
 bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status)
 {
-	bfa_assert(0);
+	bfa_trc(port, status);
+	port->endis_pending = BFA_FALSE;
+	port->endis_cbfn(port->endis_cbarg, status);
 }
 
 /**
@@ -105,7 +99,7 @@
 		struct bfa_timeval_s tv;
 
 		memcpy(port->stats, port->stats_dma.kva,
-		       sizeof(union bfa_pport_stats_u));
+		       sizeof(union bfa_port_stats_u));
 		bfa_port_stats_swap(port, port->stats);
 
 		bfa_os_gettimeofday(&tv);
@@ -133,11 +127,11 @@
 	struct bfa_timeval_s tv;
 
 	port->stats_status = status;
-	port->stats_busy = BFA_FALSE;
+	port->stats_busy   = BFA_FALSE;
 
 	/**
-	 * re-initialize time stamp for stats reset
-	 */
+	* re-initialize time stamp for stats reset
+	*/
 	bfa_os_gettimeofday(&tv);
 	port->stats_reset_time = tv.tv_sec;
 
@@ -158,10 +152,10 @@
 static void
 bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m)
 {
-	struct bfa_port_s *port = (struct bfa_port_s *)cbarg;
+	struct bfa_port_s *port = (struct bfa_port_s *) cbarg;
 	union bfi_port_i2h_msg_u *i2hmsg;
 
-	i2hmsg = (union bfi_port_i2h_msg_u *)m;
+	i2hmsg = (union bfi_port_i2h_msg_u *) m;
 	bfa_trc(port, m->mh.msg_id);
 
 	switch (m->mh.msg_id) {
@@ -178,9 +172,7 @@
 		break;
 
 	case BFI_PORT_I2H_GET_STATS_RSP:
-		/*
-		 * Stats busy flag is still set? (may be cmd timed out)
-		 */
+		/* Stats busy flag is still set? (may be cmd timed out) */
 		if (port->stats_busy == BFA_FALSE)
 			break;
 		bfa_port_get_stats_isr(port, i2hmsg->getstats_rsp.status);
@@ -208,7 +200,7 @@
 u32
 bfa_port_meminfo(void)
 {
-	return BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), BFA_DMA_ALIGN_SZ);
+	return BFA_ROUNDUP(sizeof(union bfa_port_stats_u), BFA_DMA_ALIGN_SZ);
 }
 
 /**
@@ -216,8 +208,8 @@
  *
  *
  * @param[in] port Port module pointer
- * 	      dma_kva Kernel Virtual Address of Port DMA Memory
- * 	      dma_pa  Physical Address of Port DMA Memory
+ *	      dma_kva Kernel Virtual Address of Port DMA Memory
+ *	      dma_pa  Physical Address of Port DMA Memory
  *
  * @return void
  */
@@ -225,7 +217,7 @@
 bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa)
 {
 	port->stats_dma.kva = dma_kva;
-	port->stats_dma.pa = dma_pa;
+	port->stats_dma.pa  = dma_pa;
 }
 
 /**
@@ -239,12 +231,14 @@
  */
 bfa_status_t
 bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
-		void *cbarg)
+		 void *cbarg)
 {
 	struct bfi_port_generic_req_s *m;
 
-	/** todo Not implemented */
-	bfa_assert(0);
+	if (bfa_ioc_is_disabled(port->ioc)) {
+		bfa_trc(port, BFA_STATUS_IOC_DISABLED);
+		return BFA_STATUS_IOC_DISABLED;
+	}
 
 	if (!bfa_ioc_is_operational(port->ioc)) {
 		bfa_trc(port, BFA_STATUS_IOC_FAILURE);
@@ -256,11 +250,11 @@
 		return BFA_STATUS_DEVBUSY;
 	}
 
-	m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
+	m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
 
 	port->msgtag++;
-	port->endis_cbfn = cbfn;
-	port->endis_cbarg = cbarg;
+	port->endis_cbfn    = cbfn;
+	port->endis_cbarg   = cbarg;
 	port->endis_pending = BFA_TRUE;
 
 	bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ,
@@ -281,12 +275,14 @@
  */
 bfa_status_t
 bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn,
-		 void *cbarg)
+		  void *cbarg)
 {
 	struct bfi_port_generic_req_s *m;
 
-	/** todo Not implemented */
-	bfa_assert(0);
+	if (bfa_ioc_is_disabled(port->ioc)) {
+		bfa_trc(port, BFA_STATUS_IOC_DISABLED);
+		return BFA_STATUS_IOC_DISABLED;
+	}
 
 	if (!bfa_ioc_is_operational(port->ioc)) {
 		bfa_trc(port, BFA_STATUS_IOC_FAILURE);
@@ -298,11 +294,11 @@
 		return BFA_STATUS_DEVBUSY;
 	}
 
-	m = (struct bfi_port_generic_req_s *)port->endis_mb.msg;
+	m = (struct bfi_port_generic_req_s *) port->endis_mb.msg;
 
 	port->msgtag++;
-	port->endis_cbfn = cbfn;
-	port->endis_cbarg = cbarg;
+	port->endis_cbfn    = cbfn;
+	port->endis_cbarg   = cbarg;
 	port->endis_pending = BFA_TRUE;
 
 	bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ,
@@ -322,8 +318,8 @@
  * @return Status
  */
 bfa_status_t
-bfa_port_get_stats(struct bfa_port_s *port, union bfa_pport_stats_u *stats,
-		   bfa_port_stats_cbfn_t cbfn, void *cbarg)
+bfa_port_get_stats(struct bfa_port_s *port, union bfa_port_stats_u *stats,
+		    bfa_port_stats_cbfn_t cbfn, void *cbarg)
 {
 	struct bfi_port_get_stats_req_s *m;
 
@@ -337,12 +333,12 @@
 		return BFA_STATUS_DEVBUSY;
 	}
 
-	m = (struct bfi_port_get_stats_req_s *)port->stats_mb.msg;
+	m = (struct bfi_port_get_stats_req_s *) port->stats_mb.msg;
 
-	port->stats = stats;
-	port->stats_cbfn = cbfn;
+	port->stats	  = stats;
+	port->stats_cbfn  = cbfn;
 	port->stats_cbarg = cbarg;
-	port->stats_busy = BFA_TRUE;
+	port->stats_busy  = BFA_TRUE;
 	bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa);
 
 	bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ,
@@ -362,7 +358,7 @@
  */
 bfa_status_t
 bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn,
-		     void *cbarg)
+		      void *cbarg)
 {
 	struct bfi_port_generic_req_s *m;
 
@@ -376,11 +372,11 @@
 		return BFA_STATUS_DEVBUSY;
 	}
 
-	m = (struct bfi_port_generic_req_s *)port->stats_mb.msg;
+	m = (struct bfi_port_generic_req_s *) port->stats_mb.msg;
 
-	port->stats_cbfn = cbfn;
+	port->stats_cbfn  = cbfn;
 	port->stats_cbarg = cbarg;
-	port->stats_busy = BFA_TRUE;
+	port->stats_busy  = BFA_TRUE;
 
 	bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ,
 		    bfa_ioc_portid(port->ioc));
@@ -400,11 +396,9 @@
 void
 bfa_port_hbfail(void *arg)
 {
-	struct bfa_port_s *port = (struct bfa_port_s *)arg;
+	struct bfa_port_s *port = (struct bfa_port_s *) arg;
 
-	/*
-	 * Fail any pending get_stats/clear_stats requests
-	 */
+	/* Fail any pending get_stats/clear_stats requests */
 	if (port->stats_busy) {
 		if (port->stats_cbfn)
 			port->stats_cbfn(port->stats_cbarg, BFA_STATUS_FAILED);
@@ -412,9 +406,7 @@
 		port->stats_busy = BFA_FALSE;
 	}
 
-	/*
-	 * Clear any enable/disable is pending
-	 */
+	/* Clear any enable/disable is pending */
 	if (port->endis_pending) {
 		if (port->endis_cbfn)
 			port->endis_cbfn(port->endis_cbarg, BFA_STATUS_FAILED);
@@ -433,22 +425,20 @@
  *                   The device driver specific mbox ISR functions have
  *                   this pointer as one of the parameters.
  *            trcmod -
- *            logmod -
  *
  * @return void
  */
 void
-bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev,
-		struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod)
+bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
+		 void *dev, struct bfa_trc_mod_s *trcmod)
 {
 	struct bfa_timeval_s tv;
 
 	bfa_assert(port);
 
-	port->dev = dev;
-	port->ioc = ioc;
+	port->dev    = dev;
+	port->ioc    = ioc;
 	port->trcmod = trcmod;
-	port->logmod = logmod;
 
 	port->stats_busy = BFA_FALSE;
 	port->endis_pending = BFA_FALSE;
diff --git a/drivers/scsi/bfa/bfa_port.h b/drivers/scsi/bfa/bfa_port.h
new file mode 100644
index 0000000..dbce9df
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_port.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFA_PORT_H__
+#define __BFA_PORT_H__
+
+#include "bfa_defs_svc.h"
+#include "bfa_ioc.h"
+#include "bfa_cs.h"
+
+typedef void (*bfa_port_stats_cbfn_t) (void *dev, bfa_status_t status);
+typedef void (*bfa_port_endis_cbfn_t) (void *dev, bfa_status_t status);
+
+struct bfa_port_s {
+	void				*dev;
+	struct bfa_ioc_s		*ioc;
+	struct bfa_trc_mod_s		*trcmod;
+	u32			msgtag;
+	bfa_boolean_t			stats_busy;
+	struct bfa_mbox_cmd_s		stats_mb;
+	bfa_port_stats_cbfn_t		stats_cbfn;
+	void				*stats_cbarg;
+	bfa_status_t			stats_status;
+	u32			stats_reset_time;
+	union bfa_port_stats_u		*stats;
+	struct bfa_dma_s		stats_dma;
+	bfa_boolean_t			endis_pending;
+	struct bfa_mbox_cmd_s		endis_mb;
+	bfa_port_endis_cbfn_t		endis_cbfn;
+	void				*endis_cbarg;
+	bfa_status_t			endis_status;
+	struct bfa_ioc_hbfail_notify_s	hbfail;
+};
+
+void	     bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
+				void *dev, struct bfa_trc_mod_s *trcmod);
+void	     bfa_port_detach(struct bfa_port_s *port);
+void	     bfa_port_hbfail(void *arg);
+
+bfa_status_t bfa_port_get_stats(struct bfa_port_s *port,
+				 union bfa_port_stats_u *stats,
+				 bfa_port_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_port_clear_stats(struct bfa_port_s *port,
+				   bfa_port_stats_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_port_enable(struct bfa_port_s *port,
+			      bfa_port_endis_cbfn_t cbfn, void *cbarg);
+bfa_status_t bfa_port_disable(struct bfa_port_s *port,
+			       bfa_port_endis_cbfn_t cbfn, void *cbarg);
+u32     bfa_port_meminfo(void);
+void	     bfa_port_mem_claim(struct bfa_port_s *port,
+				 u8 *dma_kva, u64 dma_pa);
+#endif	/* __BFA_PORT_H__ */
diff --git a/drivers/scsi/bfa/bfa_port_priv.h b/drivers/scsi/bfa/bfa_port_priv.h
deleted file mode 100644
index c9ebe04..0000000
--- a/drivers/scsi/bfa/bfa_port_priv.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_PORT_PRIV_H__
-#define __BFA_PORT_PRIV_H__
-
-#include <defs/bfa_defs_pport.h>
-#include <bfi/bfi_pport.h>
-#include "bfa_intr_priv.h"
-
-/**
- * Link notification data structure
- */
-struct bfa_fcport_ln_s {
-	struct bfa_fcport_s     *fcport;
-	bfa_sm_t                sm;
-	struct bfa_cb_qe_s      ln_qe;  /*  BFA callback queue elem for ln */
-	enum bfa_pport_linkstate ln_event; /*  ln event for callback */
-};
-
-/**
- * BFA FC port data structure
- */
-struct bfa_fcport_s {
-	struct bfa_s 		*bfa;	/*  parent BFA instance */
-	bfa_sm_t		sm;	/*  port state machine */
-	wwn_t			nwwn;	/*  node wwn of physical port */
-	wwn_t			pwwn;	/*  port wwn of physical oprt */
-	enum bfa_pport_speed speed_sup;
-					/*  supported speeds */
-	enum bfa_pport_speed speed;	/*  current speed */
-	enum bfa_pport_topology topology;	/*  current topology */
-	u8			myalpa;	/*  my ALPA in LOOP topology */
-	u8			rsvd[3];
-	u32             mypid:24;
-	u32             rsvd_b:8;
-	struct bfa_pport_cfg_s	cfg;	/*  current port configuration */
-	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
-	struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
-	struct bfa_reqq_wait_s	reqq_wait;
-					/*  to wait for room in reqq */
-	struct bfa_reqq_wait_s	svcreq_wait;
-					/*  to wait for room in reqq */
-	struct bfa_reqq_wait_s	stats_reqq_wait;
-					/*  to wait for room in reqq (stats) */
-	void			*event_cbarg;
-	void			(*event_cbfn) (void *cbarg,
-						bfa_pport_event_t event);
-	union {
-		union bfi_fcport_i2h_msg_u i2hmsg;
-	} event_arg;
-	void			*bfad;	/*  BFA driver handle */
-	struct bfa_fcport_ln_s   ln; /* Link Notification */
-	struct bfa_cb_qe_s		hcb_qe;	/*  BFA callback queue elem */
-	struct bfa_timer_s      timer;  /*  timer */
-	u32		msgtag;	/*  fimrware msg tag for reply */
-	u8			*stats_kva;
-	u64		stats_pa;
-	union bfa_fcport_stats_u *stats;
-	union bfa_fcport_stats_u *stats_ret; /*  driver stats location */
-	bfa_status_t            stats_status; /*  stats/statsclr status */
-	bfa_boolean_t           stats_busy; /*  outstanding stats/statsclr */
-	bfa_boolean_t           stats_qfull;
-	u32                	stats_reset_time; /* stats reset time stamp */
-	bfa_cb_pport_t          stats_cbfn; /*  driver callback function */
-	void                    *stats_cbarg; /* user callback arg */
-	bfa_boolean_t           diag_busy; /*  diag busy status */
-	bfa_boolean_t           beacon; /*  port beacon status */
-	bfa_boolean_t           link_e2e_beacon; /*  link beacon status */
-};
-
-#define BFA_FCPORT_MOD(__bfa)	(&(__bfa)->modules.fcport)
-
-/*
- * public functions
- */
-void bfa_fcport_init(struct bfa_s *bfa);
-void bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#endif /* __BFA_PORT_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_rport.c b/drivers/scsi/bfa/bfa_rport.c
deleted file mode 100644
index ccd0680..0000000
--- a/drivers/scsi/bfa/bfa_rport.c
+++ /dev/null
@@ -1,906 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <cs/bfa_debug.h>
-#include <bfi/bfi_rport.h>
-#include "bfa_intr_priv.h"
-
-BFA_TRC_FILE(HAL, RPORT);
-BFA_MODULE(rport);
-
-#define bfa_rport_offline_cb(__rp) do {				\
-	if ((__rp)->bfa->fcs)						\
-		bfa_cb_rport_offline((__rp)->rport_drv);      \
-	else {								\
-		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
-				__bfa_cb_rport_offline, (__rp));      \
-	}								\
-} while (0)
-
-#define bfa_rport_online_cb(__rp) do {				\
-	if ((__rp)->bfa->fcs)						\
-		bfa_cb_rport_online((__rp)->rport_drv);      \
-	else {								\
-		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
-				  __bfa_cb_rport_online, (__rp));      \
-		}							\
-} while (0)
-
-/*
- * forward declarations
- */
-static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
-static void bfa_rport_free(struct bfa_rport_s *rport);
-static bfa_boolean_t bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
-static bfa_boolean_t bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
-static bfa_boolean_t bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
-static void __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete);
-
-/**
- *  bfa_rport_sm BFA rport state machine
- */
-
-
-enum bfa_rport_event {
-	BFA_RPORT_SM_CREATE	= 1,	/*  rport create event		*/
-	BFA_RPORT_SM_DELETE	= 2,	/*  deleting an existing rport */
-	BFA_RPORT_SM_ONLINE	= 3,	/*  rport is online		*/
-	BFA_RPORT_SM_OFFLINE	= 4,	/*  rport is offline		*/
-	BFA_RPORT_SM_FWRSP	= 5,	/*  firmware response		*/
-	BFA_RPORT_SM_HWFAIL	= 6,	/*  IOC h/w failure		*/
-	BFA_RPORT_SM_QOS_SCN	= 7,	/*  QoS SCN from firmware	*/
-	BFA_RPORT_SM_SET_SPEED	= 8,	/*  Set Rport Speed 		*/
-	BFA_RPORT_SM_QRESUME	= 9,	/*  space in requeue queue	*/
-};
-
-static void	bfa_rport_sm_uninit(struct bfa_rport_s *rp,
-					enum bfa_rport_event event);
-static void	bfa_rport_sm_created(struct bfa_rport_s *rp,
-					 enum bfa_rport_event event);
-static void	bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_online(struct bfa_rport_s *rp,
-					enum bfa_rport_event event);
-static void	bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_offline(struct bfa_rport_s *rp,
-					 enum bfa_rport_event event);
-static void	bfa_rport_sm_deleting(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
-					    enum bfa_rport_event event);
-static void	bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-static void	bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
-					  enum bfa_rport_event event);
-
-/**
- * Beginning state, only online event expected.
- */
-static void
-bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_CREATE:
-		bfa_stats(rp, sm_un_cr);
-		bfa_sm_set_state(rp, bfa_rport_sm_created);
-		break;
-
-	default:
-		bfa_stats(rp, sm_un_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-static void
-bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_ONLINE:
-		bfa_stats(rp, sm_cr_on);
-		if (bfa_rport_send_fwcreate(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_cr_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_cr_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	default:
-		bfa_stats(rp, sm_cr_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Waiting for rport create response from firmware.
- */
-static void
-bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_fwc_rsp);
-		bfa_sm_set_state(rp, bfa_rport_sm_online);
-		bfa_rport_online_cb(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_fwc_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
-		break;
-
-	case BFA_RPORT_SM_OFFLINE:
-		bfa_stats(rp, sm_fwc_off);
-		bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_fwc_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	default:
-		bfa_stats(rp, sm_fwc_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Request queue is full, awaiting queue resume to send create request.
- */
-static void
-bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_QRESUME:
-		bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
-		bfa_rport_send_fwcreate(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_fwc_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_OFFLINE:
-		bfa_stats(rp, sm_fwc_off);
-		bfa_sm_set_state(rp, bfa_rport_sm_offline);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_fwc_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		break;
-
-	default:
-		bfa_stats(rp, sm_fwc_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Online state - normal parking state.
- */
-static void
-bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	struct bfi_rport_qos_scn_s *qos_scn;
-
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_OFFLINE:
-		bfa_stats(rp, sm_on_off);
-		if (bfa_rport_send_fwdelete(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_on_del);
-		if (bfa_rport_send_fwdelete(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_on_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	case BFA_RPORT_SM_SET_SPEED:
-		bfa_rport_send_fwspeed(rp);
-		break;
-
-	case BFA_RPORT_SM_QOS_SCN:
-		qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
-		rp->qos_attr = qos_scn->new_qos_attr;
-		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
-		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
-		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
-		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
-
-		qos_scn->old_qos_attr.qos_flow_id  =
-			bfa_os_ntohl(qos_scn->old_qos_attr.qos_flow_id);
-		qos_scn->new_qos_attr.qos_flow_id  =
-			bfa_os_ntohl(qos_scn->new_qos_attr.qos_flow_id);
-		qos_scn->old_qos_attr.qos_priority =
-			bfa_os_ntohl(qos_scn->old_qos_attr.qos_priority);
-		qos_scn->new_qos_attr.qos_priority =
-			bfa_os_ntohl(qos_scn->new_qos_attr.qos_priority);
-
-		if (qos_scn->old_qos_attr.qos_flow_id !=
-			qos_scn->new_qos_attr.qos_flow_id)
-			bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
-						    qos_scn->old_qos_attr,
-						    qos_scn->new_qos_attr);
-		if (qos_scn->old_qos_attr.qos_priority !=
-			qos_scn->new_qos_attr.qos_priority)
-			bfa_cb_rport_qos_scn_prio(rp->rport_drv,
-						  qos_scn->old_qos_attr,
-						  qos_scn->new_qos_attr);
-		break;
-
-	default:
-		bfa_stats(rp, sm_on_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Firmware rport is being deleted - awaiting f/w response.
- */
-static void
-bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_fwd_rsp);
-		bfa_sm_set_state(rp, bfa_rport_sm_offline);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_fwd_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_fwd_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	default:
-		bfa_stats(rp, sm_fwd_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-static void
-bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_QRESUME:
-		bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
-		bfa_rport_send_fwdelete(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_fwd_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_fwd_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	default:
-		bfa_stats(rp, sm_fwd_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Offline state.
- */
-static void
-bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_off_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_ONLINE:
-		bfa_stats(rp, sm_off_on);
-		if (bfa_rport_send_fwcreate(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_off_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	default:
-		bfa_stats(rp, sm_off_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Rport is deleted, waiting for firmware response to delete.
- */
-static void
-bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_del_fwrsp);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_del_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	default:
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-static void
-bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_QRESUME:
-		bfa_stats(rp, sm_del_fwrsp);
-		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
-		bfa_rport_send_fwdelete(rp);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_del_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_reqq_wcancel(&rp->reqq_wait);
-		bfa_rport_free(rp);
-		break;
-
-	default:
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Waiting for rport create response from firmware. A delete is pending.
- */
-static void
-bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
-				enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_delp_fwrsp);
-		if (bfa_rport_send_fwdelete(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_delp_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	default:
-		bfa_stats(rp, sm_delp_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * Waiting for rport create response from firmware. Rport offline is pending.
- */
-static void
-bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
-				 enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_FWRSP:
-		bfa_stats(rp, sm_offp_fwrsp);
-		if (bfa_rport_send_fwdelete(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_offp_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		bfa_stats(rp, sm_offp_hwf);
-		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
-		break;
-
-	default:
-		bfa_stats(rp, sm_offp_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-/**
- * IOC h/w failed.
- */
-static void
-bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
-{
-	bfa_trc(rp->bfa, rp->rport_tag);
-	bfa_trc(rp->bfa, event);
-
-	switch (event) {
-	case BFA_RPORT_SM_OFFLINE:
-		bfa_stats(rp, sm_iocd_off);
-		bfa_rport_offline_cb(rp);
-		break;
-
-	case BFA_RPORT_SM_DELETE:
-		bfa_stats(rp, sm_iocd_del);
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-		bfa_rport_free(rp);
-		break;
-
-	case BFA_RPORT_SM_ONLINE:
-		bfa_stats(rp, sm_iocd_on);
-		if (bfa_rport_send_fwcreate(rp))
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
-		else
-			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
-		break;
-
-	case BFA_RPORT_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_stats(rp, sm_iocd_unexp);
-		bfa_sm_fault(rp->bfa, event);
-	}
-}
-
-
-
-/**
- *  bfa_rport_private BFA rport private functions
- */
-
-static void
-__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_rport_s *rp = cbarg;
-
-	if (complete)
-		bfa_cb_rport_online(rp->rport_drv);
-}
-
-static void
-__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_rport_s *rp = cbarg;
-
-	if (complete)
-		bfa_cb_rport_offline(rp->rport_drv);
-}
-
-static void
-bfa_rport_qresume(void *cbarg)
-{
-	struct bfa_rport_s	*rp = cbarg;
-
-	bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
-}
-
-static void
-bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
-{
-	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
-		cfg->fwcfg.num_rports = BFA_RPORT_MIN;
-
-	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
-}
-
-static void
-bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		     struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
-	struct bfa_rport_s *rp;
-	u16        i;
-
-	INIT_LIST_HEAD(&mod->rp_free_q);
-	INIT_LIST_HEAD(&mod->rp_active_q);
-
-	rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
-	mod->rps_list = rp;
-	mod->num_rports = cfg->fwcfg.num_rports;
-
-	bfa_assert(mod->num_rports
-		   && !(mod->num_rports & (mod->num_rports - 1)));
-
-	for (i = 0; i < mod->num_rports; i++, rp++) {
-		bfa_os_memset(rp, 0, sizeof(struct bfa_rport_s));
-		rp->bfa = bfa;
-		rp->rport_tag = i;
-		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
-
-		/**
-		 *  - is unused
-		 */
-		if (i)
-			list_add_tail(&rp->qe, &mod->rp_free_q);
-
-		bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
-	}
-
-	/**
-	 * consume memory
-	 */
-	bfa_meminfo_kva(meminfo) = (u8 *) rp;
-}
-
-static void
-bfa_rport_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_rport_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_rport_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_rport_iocdisable(struct bfa_s *bfa)
-{
-	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
-	struct bfa_rport_s *rport;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &mod->rp_active_q) {
-		rport = (struct bfa_rport_s *) qe;
-		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
-	}
-}
-
-static struct bfa_rport_s *
-bfa_rport_alloc(struct bfa_rport_mod_s *mod)
-{
-	struct bfa_rport_s *rport;
-
-	bfa_q_deq(&mod->rp_free_q, &rport);
-	if (rport)
-		list_add_tail(&rport->qe, &mod->rp_active_q);
-
-	return rport;
-}
-
-static void
-bfa_rport_free(struct bfa_rport_s *rport)
-{
-	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
-
-	bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
-	list_del(&rport->qe);
-	list_add_tail(&rport->qe, &mod->rp_free_q);
-}
-
-static bfa_boolean_t
-bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
-{
-	struct bfi_rport_create_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
-	if (!m) {
-		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
-			bfa_lpuid(rp->bfa));
-	m->bfa_handle = rp->rport_tag;
-	m->max_frmsz = bfa_os_htons(rp->rport_info.max_frmsz);
-	m->pid = rp->rport_info.pid;
-	m->lp_tag = rp->rport_info.lp_tag;
-	m->local_pid = rp->rport_info.local_pid;
-	m->fc_class = rp->rport_info.fc_class;
-	m->vf_en = rp->rport_info.vf_en;
-	m->vf_id = rp->rport_info.vf_id;
-	m->cisc = rp->rport_info.cisc;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
-	return BFA_TRUE;
-}
-
-static bfa_boolean_t
-bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
-{
-	struct bfi_rport_delete_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
-	if (!m) {
-		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
-			bfa_lpuid(rp->bfa));
-	m->fw_handle = rp->fw_handle;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
-	return BFA_TRUE;
-}
-
-static bfa_boolean_t
-bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
-{
-	struct bfa_rport_speed_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
-	if (!m) {
-		bfa_trc(rp->bfa, rp->rport_info.speed);
-		return BFA_FALSE;
-	}
-
-	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
-			bfa_lpuid(rp->bfa));
-	m->fw_handle = rp->fw_handle;
-	m->speed = (u8)rp->rport_info.speed;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
-	return BFA_TRUE;
-}
-
-
-
-/**
- *  bfa_rport_public
- */
-
-/**
- * 		Rport interrupt processing.
- */
-void
-bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	union bfi_rport_i2h_msg_u msg;
-	struct bfa_rport_s *rp;
-
-	bfa_trc(bfa, m->mhdr.msg_id);
-
-	msg.msg = m;
-
-	switch (m->mhdr.msg_id) {
-	case BFI_RPORT_I2H_CREATE_RSP:
-		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
-		rp->fw_handle = msg.create_rsp->fw_handle;
-		rp->qos_attr = msg.create_rsp->qos_attr;
-		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
-		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
-		break;
-
-	case BFI_RPORT_I2H_DELETE_RSP:
-		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
-		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
-		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
-		break;
-
-	case BFI_RPORT_I2H_QOS_SCN:
-		rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
-		rp->event_arg.fw_msg = msg.qos_scn_evt;
-		bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
-		break;
-
-	default:
-		bfa_trc(bfa, m->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-
-
-/**
- *  bfa_rport_api
- */
-
-struct bfa_rport_s *
-bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
-{
-	struct bfa_rport_s *rp;
-
-	rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
-
-	if (rp == NULL)
-		return NULL;
-
-	rp->bfa = bfa;
-	rp->rport_drv = rport_drv;
-	bfa_rport_clear_stats(rp);
-
-	bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
-	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
-
-	return rp;
-}
-
-void
-bfa_rport_delete(struct bfa_rport_s *rport)
-{
-	bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
-}
-
-void
-bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
-{
-	bfa_assert(rport_info->max_frmsz != 0);
-
-	/**
-	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI
-	 * responses. Default to minimum size.
-	 */
-	if (rport_info->max_frmsz == 0) {
-		bfa_trc(rport->bfa, rport->rport_tag);
-		rport_info->max_frmsz = FC_MIN_PDUSZ;
-	}
-
-	bfa_os_assign(rport->rport_info, *rport_info);
-	bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
-}
-
-void
-bfa_rport_offline(struct bfa_rport_s *rport)
-{
-	bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
-}
-
-void
-bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed)
-{
-	bfa_assert(speed != 0);
-	bfa_assert(speed != BFA_PPORT_SPEED_AUTO);
-
-	rport->rport_info.speed = speed;
-	bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
-}
-
-void
-bfa_rport_get_stats(struct bfa_rport_s *rport,
-	struct bfa_rport_hal_stats_s *stats)
-{
-	*stats = rport->stats;
-}
-
-void
-bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
-					struct bfa_rport_qos_attr_s *qos_attr)
-{
-	qos_attr->qos_priority  = bfa_os_ntohl(rport->qos_attr.qos_priority);
-	qos_attr->qos_flow_id  = bfa_os_ntohl(rport->qos_attr.qos_flow_id);
-
-}
-
-void
-bfa_rport_clear_stats(struct bfa_rport_s *rport)
-{
-	bfa_os_memset(&rport->stats, 0, sizeof(rport->stats));
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_rport_priv.h b/drivers/scsi/bfa/bfa_rport_priv.h
deleted file mode 100644
index 6490ce2..0000000
--- a/drivers/scsi/bfa/bfa_rport_priv.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_RPORT_PRIV_H__
-#define __BFA_RPORT_PRIV_H__
-
-#include <bfa_svc.h>
-
-#define BFA_RPORT_MIN	4
-
-struct bfa_rport_mod_s {
-	struct bfa_rport_s *rps_list;	/*  list of rports	*/
-	struct list_head 	rp_free_q;	/*  free bfa_rports	*/
-	struct list_head 	rp_active_q;	/*  free bfa_rports 	*/
-	u16	num_rports;	/*  number of rports	*/
-};
-
-#define BFA_RPORT_MOD(__bfa)	(&(__bfa)->modules.rport_mod)
-
-/**
- * Convert rport tag to RPORT
- */
-#define BFA_RPORT_FROM_TAG(__bfa, _tag)				\
-	(BFA_RPORT_MOD(__bfa)->rps_list +				\
-	 ((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1)))
-
-/*
- * external functions
- */
-void	bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-#endif /* __BFA_RPORT_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_sgpg.c b/drivers/scsi/bfa/bfa_sgpg.c
deleted file mode 100644
index ae452c4..0000000
--- a/drivers/scsi/bfa/bfa_sgpg.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-
-BFA_TRC_FILE(HAL, SGPG);
-BFA_MODULE(sgpg);
-
-/**
- *  bfa_sgpg_mod BFA SGPG Mode module
- */
-
-/**
- * Compute and return memory needed by FCP(im) module.
- */
-static void
-bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
-		u32 *dm_len)
-{
-	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
-		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
-
-	*km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
-	*dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
-}
-
-
-static void
-bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		    struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_sgpg_mod_s	*mod = BFA_SGPG_MOD(bfa);
-	int				i;
-	struct bfa_sgpg_s		*hsgpg;
-	struct bfi_sgpg_s 	*sgpg;
-	u64		align_len;
-
-	union {
-		u64        pa;
-		union bfi_addr_u      addr;
-	} sgpg_pa;
-
-	INIT_LIST_HEAD(&mod->sgpg_q);
-	INIT_LIST_HEAD(&mod->sgpg_wait_q);
-
-	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
-
-	mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
-	mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
-	align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
-	mod->sgpg_arr_pa += align_len;
-	mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
-						align_len);
-	mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
-						align_len);
-
-	hsgpg = mod->hsgpg_arr;
-	sgpg = mod->sgpg_arr;
-	sgpg_pa.pa = mod->sgpg_arr_pa;
-	mod->free_sgpgs = mod->num_sgpgs;
-
-	bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
-
-	for (i = 0; i < mod->num_sgpgs; i++) {
-		bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
-		bfa_os_memset(sgpg, 0, sizeof(*sgpg));
-
-		hsgpg->sgpg = sgpg;
-		hsgpg->sgpg_pa = sgpg_pa.addr;
-		list_add_tail(&hsgpg->qe, &mod->sgpg_q);
-
-		hsgpg++;
-		sgpg++;
-		sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
-	}
-
-	bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
-	bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
-	bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
-}
-
-static void
-bfa_sgpg_detach(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_sgpg_start(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_sgpg_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_sgpg_iocdisable(struct bfa_s *bfa)
-{
-}
-
-
-
-/**
- *  bfa_sgpg_public BFA SGPG public functions
- */
-
-bfa_status_t
-bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
-{
-	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-	struct bfa_sgpg_s *hsgpg;
-	int             i;
-
-	bfa_trc_fp(bfa, nsgpgs);
-
-	if (mod->free_sgpgs < nsgpgs)
-		return BFA_STATUS_ENOMEM;
-
-	for (i = 0; i < nsgpgs; i++) {
-		bfa_q_deq(&mod->sgpg_q, &hsgpg);
-		bfa_assert(hsgpg);
-		list_add_tail(&hsgpg->qe, sgpg_q);
-	}
-
-	mod->free_sgpgs -= nsgpgs;
-	return BFA_STATUS_OK;
-}
-
-void
-bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
-{
-	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-	struct bfa_sgpg_wqe_s *wqe;
-
-	bfa_trc_fp(bfa, nsgpg);
-
-	mod->free_sgpgs += nsgpg;
-	bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
-
-	list_splice_tail_init(sgpg_q, &mod->sgpg_q);
-
-	if (list_empty(&mod->sgpg_wait_q))
-		return;
-
-	/**
-	 * satisfy as many waiting requests as possible
-	 */
-	do {
-		wqe = bfa_q_first(&mod->sgpg_wait_q);
-		if (mod->free_sgpgs < wqe->nsgpg)
-			nsgpg = mod->free_sgpgs;
-		else
-			nsgpg = wqe->nsgpg;
-		bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
-		wqe->nsgpg -= nsgpg;
-		if (wqe->nsgpg == 0) {
-			list_del(&wqe->qe);
-			wqe->cbfn(wqe->cbarg);
-		}
-	} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
-}
-
-void
-bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
-{
-	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-
-	bfa_assert(nsgpg > 0);
-	bfa_assert(nsgpg > mod->free_sgpgs);
-
-	wqe->nsgpg_total = wqe->nsgpg = nsgpg;
-
-	/**
-	 * allocate any left to this one first
-	 */
-	if (mod->free_sgpgs) {
-		/**
-		 * no one else is waiting for SGPG
-		 */
-		bfa_assert(list_empty(&mod->sgpg_wait_q));
-		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
-		wqe->nsgpg -= mod->free_sgpgs;
-		mod->free_sgpgs = 0;
-	}
-
-	list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
-}
-
-void
-bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
-{
-	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
-
-	bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
-	list_del(&wqe->qe);
-
-	if (wqe->nsgpg_total != wqe->nsgpg)
-		bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
-				   wqe->nsgpg_total - wqe->nsgpg);
-}
-
-void
-bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
-		   void *cbarg)
-{
-	INIT_LIST_HEAD(&wqe->sgpg_q);
-	wqe->cbfn = cbfn;
-	wqe->cbarg = cbarg;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_sgpg_priv.h b/drivers/scsi/bfa/bfa_sgpg_priv.h
deleted file mode 100644
index 9c2a8cb..0000000
--- a/drivers/scsi/bfa/bfa_sgpg_priv.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  hal_sgpg.h BFA SG page module
- */
-
-#ifndef __BFA_SGPG_PRIV_H__
-#define __BFA_SGPG_PRIV_H__
-
-#include <cs/bfa_q.h>
-
-#define BFA_SGPG_MIN	(16)
-
-/**
- * Alignment macro for SG page allocation
- */
-#define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1)) \
-			& ~(sizeof(struct bfi_sgpg_s) - 1))
-
-struct bfa_sgpg_wqe_s {
-	struct list_head qe;	/*  queue sg page element	*/
-	int	nsgpg;		/*  pages to be allocated	*/
-	int	nsgpg_total;	/*  total pages required	*/
-	void	(*cbfn) (void *cbarg);
-				/*  callback function		*/
-	void	*cbarg;		/*  callback arg		*/
-	struct list_head sgpg_q;	/*  queue of alloced sgpgs	*/
-};
-
-struct bfa_sgpg_s {
-	struct list_head 	qe;	/*  queue sg page element	*/
-	struct bfi_sgpg_s *sgpg; /*  va of SG page		*/
-	union bfi_addr_u sgpg_pa;/*  pa of SG page		*/
-};
-
-/**
- * Given number of SG elements, BFA_SGPG_NPAGE() returns the number of
- * SG pages required.
- */
-#define BFA_SGPG_NPAGE(_nsges)  (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
-
-struct bfa_sgpg_mod_s {
-	struct bfa_s *bfa;
-	int		num_sgpgs;	/*  number of SG pages		*/
-	int		free_sgpgs;	/*  number of free SG pages	*/
-	struct bfa_sgpg_s *hsgpg_arr;	/*  BFA SG page array	*/
-	struct bfi_sgpg_s *sgpg_arr;	/*  actual SG page array	*/
-	u64	sgpg_arr_pa;	/*  SG page array DMA addr	*/
-	struct list_head sgpg_q;	/*  queue of free SG pages	*/
-	struct list_head sgpg_wait_q; /*  wait queue for SG pages	*/
-};
-#define BFA_SGPG_MOD(__bfa)	(&(__bfa)->modules.sgpg_mod)
-
-bfa_status_t	bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
-								int nsgpgs);
-void		bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q,
-								int nsgpgs);
-void		bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe,
-				   void (*cbfn) (void *cbarg), void *cbarg);
-void		bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe,
-								int nsgpgs);
-void		bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
-
-#endif /* __BFA_SGPG_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_sm.c b/drivers/scsi/bfa/bfa_sm.c
deleted file mode 100644
index 5420f4f..0000000
--- a/drivers/scsi/bfa/bfa_sm.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfasm.c BFA State machine utility functions
- */
-
-#include <cs/bfa_sm.h>
-
-/**
- *  cs_sm_api
- */
-
-int
-bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm)
-{
-	int             i = 0;
-
-	while (smt[i].sm && smt[i].sm != sm)
-		i++;
-	return smt[i].state;
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
new file mode 100644
index 0000000..aa1dc74
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -0,0 +1,5423 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#include "bfa_os_inc.h"
+#include "bfa_plog.h"
+#include "bfa_cs.h"
+#include "bfa_modules.h"
+#include "bfad_drv.h"
+
+BFA_TRC_FILE(HAL, FCXP);
+BFA_MODULE(fcxp);
+BFA_MODULE(sgpg);
+BFA_MODULE(lps);
+BFA_MODULE(fcport);
+BFA_MODULE(rport);
+BFA_MODULE(uf);
+
+/**
+ * LPS related definitions
+ */
+#define BFA_LPS_MIN_LPORTS      (1)
+#define BFA_LPS_MAX_LPORTS      (256)
+
+/*
+ * Maximum Vports supported per physical port or vf.
+ */
+#define BFA_LPS_MAX_VPORTS_SUPP_CB  255
+#define BFA_LPS_MAX_VPORTS_SUPP_CT  190
+
+/**
+ *  lps_pvt BFA LPS private functions
+ */
+
+enum bfa_lps_event {
+	BFA_LPS_SM_LOGIN	= 1,	/* login request from user	*/
+	BFA_LPS_SM_LOGOUT	= 2,	/* logout request from user	*/
+	BFA_LPS_SM_FWRSP	= 3,	/* f/w response to login/logout	*/
+	BFA_LPS_SM_RESUME	= 4,	/* space present in reqq queue	*/
+	BFA_LPS_SM_DELETE	= 5,	/* lps delete from user		*/
+	BFA_LPS_SM_OFFLINE	= 6,	/* Link is offline		*/
+	BFA_LPS_SM_RX_CVL	= 7,	/* Rx clear virtual link	*/
+};
+
+/**
+ * FC PORT related definitions
+ */
+/*
+ * The port is considered disabled if corresponding physical port or IOC are
+ * disabled explicitly
+ */
+#define BFA_PORT_IS_DISABLED(bfa) \
+	((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
+	(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
+
+
+/**
+ * BFA port state machine events
+ */
+enum bfa_fcport_sm_event {
+	BFA_FCPORT_SM_START	= 1,	/*  start port state machine	*/
+	BFA_FCPORT_SM_STOP	= 2,	/*  stop port state machine	*/
+	BFA_FCPORT_SM_ENABLE	= 3,	/*  enable port		*/
+	BFA_FCPORT_SM_DISABLE	= 4,	/*  disable port state machine */
+	BFA_FCPORT_SM_FWRSP	= 5,	/*  firmware enable/disable rsp */
+	BFA_FCPORT_SM_LINKUP	= 6,	/*  firmware linkup event	*/
+	BFA_FCPORT_SM_LINKDOWN	= 7,	/*  firmware linkup down	*/
+	BFA_FCPORT_SM_QRESUME	= 8,	/*  CQ space available	*/
+	BFA_FCPORT_SM_HWFAIL	= 9,	/*  IOC h/w failure		*/
+};
+
+/**
+ * BFA port link notification state machine events
+ */
+
+enum bfa_fcport_ln_sm_event {
+	BFA_FCPORT_LN_SM_LINKUP		= 1,	/*  linkup event	*/
+	BFA_FCPORT_LN_SM_LINKDOWN	= 2,	/*  linkdown event	*/
+	BFA_FCPORT_LN_SM_NOTIFICATION	= 3	/*  done notification	*/
+};
+
+/**
+ * RPORT related definitions
+ */
+#define bfa_rport_offline_cb(__rp) do {					\
+	if ((__rp)->bfa->fcs)						\
+		bfa_cb_rport_offline((__rp)->rport_drv);      \
+	else {								\
+		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
+				__bfa_cb_rport_offline, (__rp));      \
+	}								\
+} while (0)
+
+#define bfa_rport_online_cb(__rp) do {					\
+	if ((__rp)->bfa->fcs)						\
+		bfa_cb_rport_online((__rp)->rport_drv);      \
+	else {								\
+		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
+				  __bfa_cb_rport_online, (__rp));      \
+		}							\
+} while (0)
+
+
+enum bfa_rport_event {
+	BFA_RPORT_SM_CREATE	= 1,	/*  rport create event		*/
+	BFA_RPORT_SM_DELETE	= 2,	/*  deleting an existing rport	*/
+	BFA_RPORT_SM_ONLINE	= 3,	/*  rport is online		*/
+	BFA_RPORT_SM_OFFLINE	= 4,	/*  rport is offline		*/
+	BFA_RPORT_SM_FWRSP	= 5,	/*  firmware response		*/
+	BFA_RPORT_SM_HWFAIL	= 6,	/*  IOC h/w failure		*/
+	BFA_RPORT_SM_QOS_SCN	= 7,	/*  QoS SCN from firmware	*/
+	BFA_RPORT_SM_SET_SPEED	= 8,	/*  Set Rport Speed		*/
+	BFA_RPORT_SM_QRESUME	= 9,	/*  space in requeue queue	*/
+};
+
+/**
+ * forward declarations FCXP related functions
+ */
+static void	__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
+static void	hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
+				struct bfi_fcxp_send_rsp_s *fcxp_rsp);
+static void	hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
+				struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
+static void	bfa_fcxp_qresume(void *cbarg);
+static void	bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
+				struct bfi_fcxp_send_req_s *send_req);
+
+/**
+ * forward declarations for LPS functions
+ */
+static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+				u32 *dm_len);
+static void bfa_lps_attach(struct bfa_s *bfa, void *bfad,
+				struct bfa_iocfc_cfg_s *cfg,
+				struct bfa_meminfo_s *meminfo,
+				struct bfa_pcidev_s *pcidev);
+static void bfa_lps_detach(struct bfa_s *bfa);
+static void bfa_lps_start(struct bfa_s *bfa);
+static void bfa_lps_stop(struct bfa_s *bfa);
+static void bfa_lps_iocdisable(struct bfa_s *bfa);
+static void bfa_lps_login_rsp(struct bfa_s *bfa,
+				struct bfi_lps_login_rsp_s *rsp);
+static void bfa_lps_logout_rsp(struct bfa_s *bfa,
+				struct bfi_lps_logout_rsp_s *rsp);
+static void bfa_lps_reqq_resume(void *lps_arg);
+static void bfa_lps_free(struct bfa_lps_s *lps);
+static void bfa_lps_send_login(struct bfa_lps_s *lps);
+static void bfa_lps_send_logout(struct bfa_lps_s *lps);
+static void bfa_lps_login_comp(struct bfa_lps_s *lps);
+static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
+static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
+
+/**
+ * forward declaration for LPS state machine
+ */
+static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
+					event);
+static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
+static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
+					event);
+
+/**
+ * forward declaration for FC Port functions
+ */
+static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
+static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
+static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
+static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
+static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
+static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
+static void bfa_fcport_scn(struct bfa_fcport_s *fcport,
+			enum bfa_port_linkstate event, bfa_boolean_t trunk);
+static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
+				enum bfa_port_linkstate event);
+static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
+static void bfa_fcport_stats_get_timeout(void *cbarg);
+static void bfa_fcport_stats_clr_timeout(void *cbarg);
+static void bfa_trunk_iocdisable(struct bfa_s *bfa);
+
+/**
+ * forward declaration for FC PORT state machine
+ */
+static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
+					enum bfa_fcport_sm_event event);
+
+static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
+					enum bfa_fcport_ln_sm_event event);
+
+static struct bfa_sm_table_s hal_port_sm_table[] = {
+	{BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},
+	{BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},
+	{BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},
+	{BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},
+	{BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},
+	{BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},
+	{BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},
+	{BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},
+	{BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},
+	{BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
+	{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
+	{BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
+};
+
+
+/**
+ * forward declaration for RPORT related functions
+ */
+static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
+static void		bfa_rport_free(struct bfa_rport_s *rport);
+static bfa_boolean_t	bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
+static bfa_boolean_t	bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
+static bfa_boolean_t	bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
+static void		__bfa_cb_rport_online(void *cbarg,
+						bfa_boolean_t complete);
+static void		__bfa_cb_rport_offline(void *cbarg,
+						bfa_boolean_t complete);
+
+/**
+ * forward declaration for RPORT state machine
+ */
+static void     bfa_rport_sm_uninit(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_created(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_online(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_offline(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_deleting(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+static void     bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
+					enum bfa_rport_event event);
+
+/**
+ * PLOG related definitions
+ */
+static int
+plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
+{
+	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
+		(pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
+		return 1;
+
+	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
+		(pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
+		return 1;
+
+	return 0;
+}
+
+static void
+bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
+{
+	u16 tail;
+	struct bfa_plog_rec_s *pl_recp;
+
+	if (plog->plog_enabled == 0)
+		return;
+
+	if (plkd_validate_logrec(pl_rec)) {
+		bfa_assert(0);
+		return;
+	}
+
+	tail = plog->tail;
+
+	pl_recp = &(plog->plog_recs[tail]);
+
+	bfa_os_memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
+
+	pl_recp->tv = bfa_os_get_log_time();
+	BFA_PL_LOG_REC_INCR(plog->tail);
+
+	if (plog->head == plog->tail)
+		BFA_PL_LOG_REC_INCR(plog->head);
+}
+
+void
+bfa_plog_init(struct bfa_plog_s *plog)
+{
+	bfa_os_memset((char *)plog, 0, sizeof(struct bfa_plog_s));
+
+	bfa_os_memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
+	plog->head = plog->tail = 0;
+	plog->plog_enabled = 1;
+}
+
+void
+bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+		enum bfa_plog_eid event,
+		u16 misc, char *log_str)
+{
+	struct bfa_plog_rec_s  lp;
+
+	if (plog->plog_enabled) {
+		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+		lp.mid = mid;
+		lp.eid = event;
+		lp.log_type = BFA_PL_LOG_TYPE_STRING;
+		lp.misc = misc;
+		strncpy(lp.log_entry.string_log, log_str,
+			BFA_PL_STRING_LOG_SZ - 1);
+		lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
+		bfa_plog_add(plog, &lp);
+	}
+}
+
+void
+bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+		enum bfa_plog_eid event,
+		u16 misc, u32 *intarr, u32 num_ints)
+{
+	struct bfa_plog_rec_s  lp;
+	u32 i;
+
+	if (num_ints > BFA_PL_INT_LOG_SZ)
+		num_ints = BFA_PL_INT_LOG_SZ;
+
+	if (plog->plog_enabled) {
+		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+		lp.mid = mid;
+		lp.eid = event;
+		lp.log_type = BFA_PL_LOG_TYPE_INT;
+		lp.misc = misc;
+
+		for (i = 0; i < num_ints; i++)
+			bfa_os_assign(lp.log_entry.int_log[i],
+					intarr[i]);
+
+		lp.log_num_ints = (u8) num_ints;
+
+		bfa_plog_add(plog, &lp);
+	}
+}
+
+void
+bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+			enum bfa_plog_eid event,
+			u16 misc, struct fchs_s *fchdr)
+{
+	struct bfa_plog_rec_s  lp;
+	u32	*tmp_int = (u32 *) fchdr;
+	u32	ints[BFA_PL_INT_LOG_SZ];
+
+	if (plog->plog_enabled) {
+		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+
+		ints[0] = tmp_int[0];
+		ints[1] = tmp_int[1];
+		ints[2] = tmp_int[4];
+
+		bfa_plog_intarr(plog, mid, event, misc, ints, 3);
+	}
+}
+
+void
+bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
+		      enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
+		      u32 pld_w0)
+{
+	struct bfa_plog_rec_s  lp;
+	u32	*tmp_int = (u32 *) fchdr;
+	u32	ints[BFA_PL_INT_LOG_SZ];
+
+	if (plog->plog_enabled) {
+		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
+
+		ints[0] = tmp_int[0];
+		ints[1] = tmp_int[1];
+		ints[2] = tmp_int[4];
+		ints[3] = pld_w0;
+
+		bfa_plog_intarr(plog, mid, event, misc, ints, 4);
+	}
+}
+
+void
+bfa_plog_clear(struct bfa_plog_s *plog)
+{
+	plog->head = plog->tail = 0;
+}
+
+void
+bfa_plog_enable(struct bfa_plog_s *plog)
+{
+	plog->plog_enabled = 1;
+}
+
+void
+bfa_plog_disable(struct bfa_plog_s *plog)
+{
+	plog->plog_enabled = 0;
+}
+
+bfa_boolean_t
+bfa_plog_get_setting(struct bfa_plog_s *plog)
+{
+	return (bfa_boolean_t)plog->plog_enabled;
+}
+
+/**
+ *  fcxp_pvt BFA FCXP private functions
+ */
+
+static void
+claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+{
+	u8	       *dm_kva = NULL;
+	u64	dm_pa;
+	u32	buf_pool_sz;
+
+	dm_kva = bfa_meminfo_dma_virt(mi);
+	dm_pa = bfa_meminfo_dma_phys(mi);
+
+	buf_pool_sz = mod->req_pld_sz * mod->num_fcxps;
+
+	/*
+	 * Initialize the fcxp req payload list
+	 */
+	mod->req_pld_list_kva = dm_kva;
+	mod->req_pld_list_pa = dm_pa;
+	dm_kva += buf_pool_sz;
+	dm_pa += buf_pool_sz;
+	bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz);
+
+	/*
+	 * Initialize the fcxp rsp payload list
+	 */
+	buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps;
+	mod->rsp_pld_list_kva = dm_kva;
+	mod->rsp_pld_list_pa = dm_pa;
+	dm_kva += buf_pool_sz;
+	dm_pa += buf_pool_sz;
+	bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz);
+
+	bfa_meminfo_dma_virt(mi) = dm_kva;
+	bfa_meminfo_dma_phys(mi) = dm_pa;
+}
+
+static void
+claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi)
+{
+	u16	i;
+	struct bfa_fcxp_s *fcxp;
+
+	fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi);
+	bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
+
+	INIT_LIST_HEAD(&mod->fcxp_free_q);
+	INIT_LIST_HEAD(&mod->fcxp_active_q);
+
+	mod->fcxp_list = fcxp;
+
+	for (i = 0; i < mod->num_fcxps; i++) {
+		fcxp->fcxp_mod = mod;
+		fcxp->fcxp_tag = i;
+
+		list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+		bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
+		fcxp->reqq_waiting = BFA_FALSE;
+
+		fcxp = fcxp + 1;
+	}
+
+	bfa_meminfo_kva(mi) = (void *)fcxp;
+}
+
+static void
+bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+		 u32 *dm_len)
+{
+	u16	num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs;
+
+	if (num_fcxp_reqs == 0)
+		return;
+
+	/*
+	 * Account for req/rsp payload
+	 */
+	*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+	if (cfg->drvcfg.min_cfg)
+		*dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs;
+	else
+		*dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs;
+
+	/*
+	 * Account for fcxp structs
+	 */
+	*ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs;
+}
+
+static void
+bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+	bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s));
+	mod->bfa = bfa;
+	mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
+
+	/**
+	 * Initialize FCXP request and response payload sizes.
+	 */
+	mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
+	if (!cfg->drvcfg.min_cfg)
+		mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
+
+	INIT_LIST_HEAD(&mod->wait_q);
+
+	claim_fcxp_req_rsp_mem(mod, meminfo);
+	claim_fcxps_mem(mod, meminfo);
+}
+
+static void
+bfa_fcxp_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_fcxp_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+	struct bfa_fcxp_s *fcxp;
+	struct list_head	      *qe, *qen;
+
+	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
+		fcxp = (struct bfa_fcxp_s *) qe;
+		if (fcxp->caller == NULL) {
+			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+					BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
+			bfa_fcxp_free(fcxp);
+		} else {
+			fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
+			bfa_cb_queue(bfa, &fcxp->hcb_qe,
+				     __bfa_fcxp_send_cbfn, fcxp);
+		}
+	}
+}
+
+static struct bfa_fcxp_s *
+bfa_fcxp_get(struct bfa_fcxp_mod_s *fm)
+{
+	struct bfa_fcxp_s *fcxp;
+
+	bfa_q_deq(&fm->fcxp_free_q, &fcxp);
+
+	if (fcxp)
+		list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
+
+	return fcxp;
+}
+
+static void
+bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
+	       struct bfa_s *bfa,
+	       u8 *use_ibuf,
+	       u32 *nr_sgles,
+	       bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
+	       bfa_fcxp_get_sglen_t *r_sglen_cbfn,
+	       struct list_head *r_sgpg_q,
+	       int n_sgles,
+	       bfa_fcxp_get_sgaddr_t sga_cbfn,
+	       bfa_fcxp_get_sglen_t sglen_cbfn)
+{
+
+	bfa_assert(bfa != NULL);
+
+	bfa_trc(bfa, fcxp->fcxp_tag);
+
+	if (n_sgles == 0) {
+		*use_ibuf = 1;
+	} else {
+		bfa_assert(*sga_cbfn != NULL);
+		bfa_assert(*sglen_cbfn != NULL);
+
+		*use_ibuf = 0;
+		*r_sga_cbfn = sga_cbfn;
+		*r_sglen_cbfn = sglen_cbfn;
+
+		*nr_sgles = n_sgles;
+
+		/*
+		 * alloc required sgpgs
+		 */
+		if (n_sgles > BFI_SGE_INLINE)
+			bfa_assert(0);
+	}
+
+}
+
+static void
+bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
+	       void *caller, struct bfa_s *bfa, int nreq_sgles,
+	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
+	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+
+	bfa_assert(bfa != NULL);
+
+	bfa_trc(bfa, fcxp->fcxp_tag);
+
+	fcxp->caller = caller;
+
+	bfa_fcxp_init_reqrsp(fcxp, bfa,
+		&fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
+		&fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
+		nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
+
+	bfa_fcxp_init_reqrsp(fcxp, bfa,
+		&fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
+		&fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
+		nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
+
+}
+
+static void
+bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+	struct bfa_fcxp_wqe_s *wqe;
+
+	bfa_q_deq(&mod->wait_q, &wqe);
+	if (wqe) {
+		bfa_trc(mod->bfa, fcxp->fcxp_tag);
+
+		bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
+			wqe->nrsp_sgles, wqe->req_sga_cbfn,
+			wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
+			wqe->rsp_sglen_cbfn);
+
+		wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
+		return;
+	}
+
+	bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
+	list_del(&fcxp->qe);
+	list_add_tail(&fcxp->qe, &mod->fcxp_free_q);
+}
+
+static void
+bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
+		   bfa_status_t req_status, u32 rsp_len,
+		   u32 resid_len, struct fchs_s *rsp_fchs)
+{
+	/* discarded fcxp completion */
+}
+
+static void
+__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_fcxp_s *fcxp = cbarg;
+
+	if (complete) {
+		fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+				fcxp->rsp_status, fcxp->rsp_len,
+				fcxp->residue_len, &fcxp->rsp_fchs);
+	} else {
+		bfa_fcxp_free(fcxp);
+	}
+}
+
+static void
+hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
+{
+	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
+	struct bfa_fcxp_s	*fcxp;
+	u16		fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag);
+
+	bfa_trc(bfa, fcxp_tag);
+
+	fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len);
+
+	/**
+	 * @todo f/w should not set residue to non-0 when everything
+	 *	 is received.
+	 */
+	if (fcxp_rsp->req_status == BFA_STATUS_OK)
+		fcxp_rsp->residue_len = 0;
+	else
+		fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len);
+
+	fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
+
+	bfa_assert(fcxp->send_cbfn != NULL);
+
+	hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
+
+	if (fcxp->send_cbfn != NULL) {
+		bfa_trc(mod->bfa, (NULL == fcxp->caller));
+		if (fcxp->caller == NULL) {
+			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
+					fcxp_rsp->req_status, fcxp_rsp->rsp_len,
+					fcxp_rsp->residue_len, &fcxp_rsp->fchs);
+			/*
+			 * fcxp automatically freed on return from the callback
+			 */
+			bfa_fcxp_free(fcxp);
+		} else {
+			fcxp->rsp_status = fcxp_rsp->req_status;
+			fcxp->rsp_len = fcxp_rsp->rsp_len;
+			fcxp->residue_len = fcxp_rsp->residue_len;
+			fcxp->rsp_fchs = fcxp_rsp->fchs;
+
+			bfa_cb_queue(bfa, &fcxp->hcb_qe,
+					__bfa_fcxp_send_cbfn, fcxp);
+		}
+	} else {
+		bfa_trc(bfa, (NULL == fcxp->send_cbfn));
+	}
+}
+
+static void
+hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa)
+{
+	union bfi_addr_u      sga_zero = { {0} };
+
+	sge->sg_len = reqlen;
+	sge->flags = BFI_SGE_DATA_LAST;
+	bfa_dma_addr_set(sge[0].sga, req_pa);
+	bfa_sge_to_be(sge);
+	sge++;
+
+	sge->sga = sga_zero;
+	sge->sg_len = reqlen;
+	sge->flags = BFI_SGE_PGDLEN;
+	bfa_sge_to_be(sge);
+}
+
+static void
+hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
+		 struct fchs_s *fchs)
+{
+	/*
+	 * TODO: TX ox_id
+	 */
+	if (reqlen > 0) {
+		if (fcxp->use_ireqbuf) {
+			u32	pld_w0 =
+				*((u32 *) BFA_FCXP_REQ_PLD(fcxp));
+
+			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
+					BFA_PL_EID_TX,
+					reqlen + sizeof(struct fchs_s), fchs,
+					pld_w0);
+		} else {
+			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
+					BFA_PL_EID_TX,
+					reqlen + sizeof(struct fchs_s),
+					fchs);
+		}
+	} else {
+		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
+			       reqlen + sizeof(struct fchs_s), fchs);
+	}
+}
+
+static void
+hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
+		 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
+{
+	if (fcxp_rsp->rsp_len > 0) {
+		if (fcxp->use_irspbuf) {
+			u32	pld_w0 =
+				*((u32 *) BFA_FCXP_RSP_PLD(fcxp));
+
+			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
+					      BFA_PL_EID_RX,
+					      (u16) fcxp_rsp->rsp_len,
+					      &fcxp_rsp->fchs, pld_w0);
+		} else {
+			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
+				       BFA_PL_EID_RX,
+				       (u16) fcxp_rsp->rsp_len,
+				       &fcxp_rsp->fchs);
+		}
+	} else {
+		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
+			       (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
+	}
+}
+
+/**
+ * Handler to resume sending fcxp when space in available in cpe queue.
+ */
+static void
+bfa_fcxp_qresume(void *cbarg)
+{
+	struct bfa_fcxp_s		*fcxp = cbarg;
+	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
+	struct bfi_fcxp_send_req_s	*send_req;
+
+	fcxp->reqq_waiting = BFA_FALSE;
+	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
+	bfa_fcxp_queue(fcxp, send_req);
+}
+
+/**
+ * Queue fcxp send request to foimrware.
+ */
+static void
+bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
+{
+	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
+	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
+	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
+	struct bfa_rport_s		*rport = reqi->bfa_rport;
+
+	bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
+		    bfa_lpuid(bfa));
+
+	send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag);
+	if (rport) {
+		send_req->rport_fw_hndl = rport->fw_handle;
+		send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz);
+		if (send_req->max_frmsz == 0)
+			send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
+	} else {
+		send_req->rport_fw_hndl = 0;
+		send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ);
+	}
+
+	send_req->vf_id = bfa_os_htons(reqi->vf_id);
+	send_req->lp_tag = reqi->lp_tag;
+	send_req->class = reqi->class;
+	send_req->rsp_timeout = rspi->rsp_timeout;
+	send_req->cts = reqi->cts;
+	send_req->fchs = reqi->fchs;
+
+	send_req->req_len = bfa_os_htonl(reqi->req_tot_len);
+	send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen);
+
+	/*
+	 * setup req sgles
+	 */
+	if (fcxp->use_ireqbuf == 1) {
+		hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len,
+					BFA_FCXP_REQ_PLD_PA(fcxp));
+	} else {
+		if (fcxp->nreq_sgles > 0) {
+			bfa_assert(fcxp->nreq_sgles == 1);
+			hal_fcxp_set_local_sges(send_req->req_sge,
+						reqi->req_tot_len,
+						fcxp->req_sga_cbfn(fcxp->caller,
+								   0));
+		} else {
+			bfa_assert(reqi->req_tot_len == 0);
+			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+		}
+	}
+
+	/*
+	 * setup rsp sgles
+	 */
+	if (fcxp->use_irspbuf == 1) {
+		bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ);
+
+		hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen,
+					BFA_FCXP_RSP_PLD_PA(fcxp));
+
+	} else {
+		if (fcxp->nrsp_sgles > 0) {
+			bfa_assert(fcxp->nrsp_sgles == 1);
+			hal_fcxp_set_local_sges(send_req->rsp_sge,
+						rspi->rsp_maxlen,
+						fcxp->rsp_sga_cbfn(fcxp->caller,
+								   0));
+		} else {
+			bfa_assert(rspi->rsp_maxlen == 0);
+			hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0);
+		}
+	}
+
+	hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
+
+	bfa_reqq_produce(bfa, BFA_REQQ_FCXP);
+
+	bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
+	bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
+}
+
+/**
+ *  hal_fcxp_api BFA FCXP API
+ */
+
+/**
+ * Allocate an FCXP instance to send a response or to send a request
+ * that has a response. Request/response buffers are allocated by caller.
+ *
+ * @param[in]	bfa		BFA bfa instance
+ * @param[in]	nreq_sgles	Number of SG elements required for request
+ *				buffer. 0, if fcxp internal buffers are	used.
+ *				Use bfa_fcxp_get_reqbuf() to get the
+ *				internal req buffer.
+ * @param[in]	req_sgles	SG elements describing request buffer. Will be
+ *				copied in by BFA and hence can be freed on
+ *				return from this function.
+ * @param[in]	get_req_sga	function ptr to be called to get a request SG
+ *				Address (given the sge index).
+ * @param[in]	get_req_sglen	function ptr to be called to get a request SG
+ *				len (given the sge index).
+ * @param[in]	get_rsp_sga	function ptr to be called to get a response SG
+ *				Address (given the sge index).
+ * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG
+ *				len (given the sge index).
+ *
+ * @return FCXP instance. NULL on failure.
+ */
+struct bfa_fcxp_s *
+bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
+	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
+	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+	struct bfa_fcxp_s *fcxp = NULL;
+
+	bfa_assert(bfa != NULL);
+
+	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa));
+	if (fcxp == NULL)
+		return NULL;
+
+	bfa_trc(bfa, fcxp->fcxp_tag);
+
+	bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
+			req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
+
+	return fcxp;
+}
+
+/**
+ * Get the internal request buffer pointer
+ *
+ * @param[in]	fcxp	BFA fcxp pointer
+ *
+ * @return		pointer to the internal request buffer
+ */
+void *
+bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+	void	*reqbuf;
+
+	bfa_assert(fcxp->use_ireqbuf == 1);
+	reqbuf = ((u8 *)mod->req_pld_list_kva) +
+		fcxp->fcxp_tag * mod->req_pld_sz;
+	return reqbuf;
+}
+
+u32
+bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+
+	return mod->req_pld_sz;
+}
+
+/**
+ * Get the internal response buffer pointer
+ *
+ * @param[in]	fcxp	BFA fcxp pointer
+ *
+ * @return		pointer to the internal request buffer
+ */
+void *
+bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+	void	*rspbuf;
+
+	bfa_assert(fcxp->use_irspbuf == 1);
+
+	rspbuf = ((u8 *)mod->rsp_pld_list_kva) +
+		fcxp->fcxp_tag * mod->rsp_pld_sz;
+	return rspbuf;
+}
+
+/**
+ *		Free the BFA FCXP
+ *
+ * @param[in]	fcxp			BFA fcxp pointer
+ *
+ * @return		void
+ */
+void
+bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
+{
+	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
+
+	bfa_assert(fcxp != NULL);
+	bfa_trc(mod->bfa, fcxp->fcxp_tag);
+	bfa_fcxp_put(fcxp);
+}
+
+/**
+ * Send a FCXP request
+ *
+ * @param[in]	fcxp	BFA fcxp pointer
+ * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports
+ * @param[in]	vf_id	virtual Fabric ID
+ * @param[in]	lp_tag	lport tag
+ * @param[in]	cts	use Continous sequence
+ * @param[in]	cos	fc Class of Service
+ * @param[in]	reqlen	request length, does not include FCHS length
+ * @param[in]	fchs	fc Header Pointer. The header content will be copied
+ *			in by BFA.
+ *
+ * @param[in]	cbfn	call back function to be called on receiving
+ *								the response
+ * @param[in]	cbarg	arg for cbfn
+ * @param[in]	rsp_timeout
+ *			response timeout
+ *
+ * @return		bfa_status_t
+ */
+void
+bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
+	      u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
+	      u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
+	      void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
+{
+	struct bfa_s			*bfa  = fcxp->fcxp_mod->bfa;
+	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
+	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
+	struct bfi_fcxp_send_req_s	*send_req;
+
+	bfa_trc(bfa, fcxp->fcxp_tag);
+
+	/**
+	 * setup request/response info
+	 */
+	reqi->bfa_rport = rport;
+	reqi->vf_id = vf_id;
+	reqi->lp_tag = lp_tag;
+	reqi->class = cos;
+	rspi->rsp_timeout = rsp_timeout;
+	reqi->cts = cts;
+	reqi->fchs = *fchs;
+	reqi->req_tot_len = reqlen;
+	rspi->rsp_maxlen = rsp_maxlen;
+	fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
+	fcxp->send_cbarg = cbarg;
+
+	/**
+	 * If no room in CPE queue, wait for space in request queue
+	 */
+	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
+	if (!send_req) {
+		bfa_trc(bfa, fcxp->fcxp_tag);
+		fcxp->reqq_waiting = BFA_TRUE;
+		bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
+		return;
+	}
+
+	bfa_fcxp_queue(fcxp, send_req);
+}
+
+/**
+ * Abort a BFA FCXP
+ *
+ * @param[in]	fcxp	BFA fcxp pointer
+ *
+ * @return		void
+ */
+bfa_status_t
+bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
+{
+	bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
+	bfa_assert(0);
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+	       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
+	       void *caller, int nreq_sgles,
+	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
+	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
+	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
+	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+	bfa_assert(list_empty(&mod->fcxp_free_q));
+
+	wqe->alloc_cbfn = alloc_cbfn;
+	wqe->alloc_cbarg = alloc_cbarg;
+	wqe->caller = caller;
+	wqe->bfa = bfa;
+	wqe->nreq_sgles = nreq_sgles;
+	wqe->nrsp_sgles = nrsp_sgles;
+	wqe->req_sga_cbfn = req_sga_cbfn;
+	wqe->req_sglen_cbfn = req_sglen_cbfn;
+	wqe->rsp_sga_cbfn = rsp_sga_cbfn;
+	wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
+
+	list_add_tail(&wqe->qe, &mod->wait_q);
+}
+
+void
+bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+	bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe));
+	list_del(&wqe->qe);
+}
+
+void
+bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
+{
+	/**
+	 * If waiting for room in request queue, cancel reqq wait
+	 * and free fcxp.
+	 */
+	if (fcxp->reqq_waiting) {
+		fcxp->reqq_waiting = BFA_FALSE;
+		bfa_reqq_wcancel(&fcxp->reqq_wqe);
+		bfa_fcxp_free(fcxp);
+		return;
+	}
+
+	fcxp->send_cbfn = bfa_fcxp_null_comp;
+}
+
+
+
+/**
+ *  hal_fcxp_public BFA FCXP public functions
+ */
+
+void
+bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+	switch (msg->mhdr.msg_id) {
+	case BFI_FCXP_I2H_SEND_RSP:
+		hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
+		break;
+
+	default:
+		bfa_trc(bfa, msg->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+u32
+bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
+{
+	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
+
+	return mod->rsp_pld_sz;
+}
+
+
+/**
+ *  BFA LPS state machine functions
+ */
+
+/**
+ * Init state -- no login
+ */
+static void
+bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_LOGIN:
+		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+			bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
+			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+		} else {
+			bfa_sm_set_state(lps, bfa_lps_sm_login);
+			bfa_lps_send_login(lps);
+		}
+
+		if (lps->fdisc)
+			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+				BFA_PL_EID_LOGIN, 0, "FDISC Request");
+		else
+			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+				BFA_PL_EID_LOGIN, 0, "FLOGI Request");
+		break;
+
+	case BFA_LPS_SM_LOGOUT:
+		bfa_lps_logout_comp(lps);
+		break;
+
+	case BFA_LPS_SM_DELETE:
+		bfa_lps_free(lps);
+		break;
+
+	case BFA_LPS_SM_RX_CVL:
+	case BFA_LPS_SM_OFFLINE:
+		break;
+
+	case BFA_LPS_SM_FWRSP:
+		/*
+		 * Could happen when fabric detects loopback and discards
+		 * the lps request. Fw will eventually sent out the timeout
+		 * Just ignore
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * login is in progress -- awaiting response from firmware
+ */
+static void
+bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_FWRSP:
+		if (lps->status == BFA_STATUS_OK) {
+			bfa_sm_set_state(lps, bfa_lps_sm_online);
+			if (lps->fdisc)
+				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+					BFA_PL_EID_LOGIN, 0, "FDISC Accept");
+			else
+				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+					BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
+		} else {
+			bfa_sm_set_state(lps, bfa_lps_sm_init);
+			if (lps->fdisc)
+				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+					BFA_PL_EID_LOGIN, 0,
+					"FDISC Fail (RJT or timeout)");
+			else
+				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+					BFA_PL_EID_LOGIN, 0,
+					"FLOGI Fail (RJT or timeout)");
+		}
+		bfa_lps_login_comp(lps);
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * login pending - awaiting space in request queue
+ */
+static void
+bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_RESUME:
+		bfa_sm_set_state(lps, bfa_lps_sm_login);
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		bfa_reqq_wcancel(&lps->wqe);
+		break;
+
+	case BFA_LPS_SM_RX_CVL:
+		/*
+		 * Login was not even sent out; so when getting out
+		 * of this state, it will appear like a login retry
+		 * after Clear virtual link
+		 */
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * login complete
+ */
+static void
+bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_LOGOUT:
+		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
+			bfa_sm_set_state(lps, bfa_lps_sm_logowait);
+			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
+		} else {
+			bfa_sm_set_state(lps, bfa_lps_sm_logout);
+			bfa_lps_send_logout(lps);
+		}
+		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+			BFA_PL_EID_LOGO, 0, "Logout");
+		break;
+
+	case BFA_LPS_SM_RX_CVL:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+
+		/* Let the vport module know about this event */
+		bfa_lps_cvl_event(lps);
+		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
+			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+	case BFA_LPS_SM_DELETE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * logout in progress - awaiting firmware response
+ */
+static void
+bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_FWRSP:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		bfa_lps_logout_comp(lps);
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+/**
+ * logout pending -- awaiting space in request queue
+ */
+static void
+bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
+{
+	bfa_trc(lps->bfa, lps->lp_tag);
+	bfa_trc(lps->bfa, event);
+
+	switch (event) {
+	case BFA_LPS_SM_RESUME:
+		bfa_sm_set_state(lps, bfa_lps_sm_logout);
+		bfa_lps_send_logout(lps);
+		break;
+
+	case BFA_LPS_SM_OFFLINE:
+		bfa_sm_set_state(lps, bfa_lps_sm_init);
+		bfa_reqq_wcancel(&lps->wqe);
+		break;
+
+	default:
+		bfa_sm_fault(lps->bfa, event);
+	}
+}
+
+
+
+/**
+ *  lps_pvt BFA LPS private functions
+ */
+
+/**
+ * return memory requirement
+ */
+static void
+bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+	u32 *dm_len)
+{
+	if (cfg->drvcfg.min_cfg)
+		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS;
+	else
+		*ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS;
+}
+
+/**
+ * bfa module attach at initialization time
+ */
+static void
+bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+	struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+	int			i;
+
+	bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s));
+	mod->num_lps = BFA_LPS_MAX_LPORTS;
+	if (cfg->drvcfg.min_cfg)
+		mod->num_lps = BFA_LPS_MIN_LPORTS;
+	else
+		mod->num_lps = BFA_LPS_MAX_LPORTS;
+	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo);
+
+	bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s);
+
+	INIT_LIST_HEAD(&mod->lps_free_q);
+	INIT_LIST_HEAD(&mod->lps_active_q);
+
+	for (i = 0; i < mod->num_lps; i++, lps++) {
+		lps->bfa	= bfa;
+		lps->lp_tag	= (u8) i;
+		lps->reqq	= BFA_REQQ_LPS;
+		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
+		list_add_tail(&lps->qe, &mod->lps_free_q);
+	}
+}
+
+static void
+bfa_lps_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_lps_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_lps_stop(struct bfa_s *bfa)
+{
+}
+
+/**
+ * IOC in disabled state -- consider all lps offline
+ */
+static void
+bfa_lps_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+	struct list_head		*qe, *qen;
+
+	list_for_each_safe(qe, qen, &mod->lps_active_q) {
+		lps = (struct bfa_lps_s *) qe;
+		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+	}
+}
+
+/**
+ * Firmware login response
+ */
+static void
+bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+
+	bfa_assert(rsp->lp_tag < mod->num_lps);
+	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+
+	lps->status = rsp->status;
+	switch (rsp->status) {
+	case BFA_STATUS_OK:
+		lps->fport	= rsp->f_port;
+		lps->npiv_en	= rsp->npiv_en;
+		lps->lp_pid	= rsp->lp_pid;
+		lps->pr_bbcred	= bfa_os_ntohs(rsp->bb_credit);
+		lps->pr_pwwn	= rsp->port_name;
+		lps->pr_nwwn	= rsp->node_name;
+		lps->auth_req	= rsp->auth_req;
+		lps->lp_mac	= rsp->lp_mac;
+		lps->brcd_switch = rsp->brcd_switch;
+		lps->fcf_mac	= rsp->fcf_mac;
+
+		break;
+
+	case BFA_STATUS_FABRIC_RJT:
+		lps->lsrjt_rsn = rsp->lsrjt_rsn;
+		lps->lsrjt_expl = rsp->lsrjt_expl;
+
+		break;
+
+	case BFA_STATUS_EPROTOCOL:
+		lps->ext_status = rsp->ext_status;
+
+		break;
+
+	default:
+		/* Nothing to do with other status */
+		break;
+	}
+
+	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+}
+
+/**
+ * Firmware logout response
+ */
+static void
+bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+
+	bfa_assert(rsp->lp_tag < mod->num_lps);
+	lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag);
+
+	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
+}
+
+/**
+ * Firmware received a Clear virtual link request (for FCoE)
+ */
+static void
+bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+
+	lps = BFA_LPS_FROM_TAG(mod, cvl->lp_tag);
+
+	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
+}
+
+/**
+ * Space is available in request queue, resume queueing request to firmware.
+ */
+static void
+bfa_lps_reqq_resume(void *lps_arg)
+{
+	struct bfa_lps_s	*lps = lps_arg;
+
+	bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
+}
+
+/**
+ * lps is freed -- triggered by vport delete
+ */
+static void
+bfa_lps_free(struct bfa_lps_s *lps)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
+
+	lps->lp_pid = 0;
+	list_del(&lps->qe);
+	list_add_tail(&lps->qe, &mod->lps_free_q);
+}
+
+/**
+ * send login request to firmware
+ */
+static void
+bfa_lps_send_login(struct bfa_lps_s *lps)
+{
+	struct bfi_lps_login_req_s	*m;
+
+	m = bfa_reqq_next(lps->bfa, lps->reqq);
+	bfa_assert(m);
+
+	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
+		bfa_lpuid(lps->bfa));
+
+	m->lp_tag	= lps->lp_tag;
+	m->alpa		= lps->alpa;
+	m->pdu_size	= bfa_os_htons(lps->pdusz);
+	m->pwwn		= lps->pwwn;
+	m->nwwn		= lps->nwwn;
+	m->fdisc	= lps->fdisc;
+	m->auth_en	= lps->auth_en;
+
+	bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/**
+ * send logout request to firmware
+ */
+static void
+bfa_lps_send_logout(struct bfa_lps_s *lps)
+{
+	struct bfi_lps_logout_req_s *m;
+
+	m = bfa_reqq_next(lps->bfa, lps->reqq);
+	bfa_assert(m);
+
+	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
+		bfa_lpuid(lps->bfa));
+
+	m->lp_tag    = lps->lp_tag;
+	m->port_name = lps->pwwn;
+	bfa_reqq_produce(lps->bfa, lps->reqq);
+}
+
+/**
+ * Indirect login completion handler for non-fcs
+ */
+static void
+bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
+{
+	struct bfa_lps_s *lps	= arg;
+
+	if (!complete)
+		return;
+
+	if (lps->fdisc)
+		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
+	else
+		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
+}
+
+/**
+ * Login completion handler -- direct call for fcs, queue for others
+ */
+static void
+bfa_lps_login_comp(struct bfa_lps_s *lps)
+{
+	if (!lps->bfa->fcs) {
+		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
+			lps);
+		return;
+	}
+
+	if (lps->fdisc)
+		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
+	else
+		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
+}
+
+/**
+ * Indirect logout completion handler for non-fcs
+ */
+static void
+bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
+{
+	struct bfa_lps_s *lps	= arg;
+
+	if (!complete)
+		return;
+
+	if (lps->fdisc)
+		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Logout completion handler -- direct call for fcs, queue for others
+ */
+static void
+bfa_lps_logout_comp(struct bfa_lps_s *lps)
+{
+	if (!lps->bfa->fcs) {
+		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
+			lps);
+		return;
+	}
+	if (lps->fdisc)
+		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Clear virtual link completion handler for non-fcs
+ */
+static void
+bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
+{
+	struct bfa_lps_s *lps	= arg;
+
+	if (!complete)
+		return;
+
+	/* Clear virtual link to base port will result in link down */
+	if (lps->fdisc)
+		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
+}
+
+/**
+ * Received Clear virtual link event --direct call for fcs,
+ * queue for others
+ */
+static void
+bfa_lps_cvl_event(struct bfa_lps_s *lps)
+{
+	if (!lps->bfa->fcs) {
+		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
+			lps);
+		return;
+	}
+
+	/* Clear virtual link to base port will result in link down */
+	if (lps->fdisc)
+		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
+}
+
+
+
+/**
+ *  lps_public BFA LPS public functions
+ */
+
+u32
+bfa_lps_get_max_vport(struct bfa_s *bfa)
+{
+	if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
+		return BFA_LPS_MAX_VPORTS_SUPP_CT;
+	else
+		return BFA_LPS_MAX_VPORTS_SUPP_CB;
+}
+
+/**
+ * Allocate a lport srvice tag.
+ */
+struct bfa_lps_s  *
+bfa_lps_alloc(struct bfa_s *bfa)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps = NULL;
+
+	bfa_q_deq(&mod->lps_free_q, &lps);
+
+	if (lps == NULL)
+		return NULL;
+
+	list_add_tail(&lps->qe, &mod->lps_active_q);
+
+	bfa_sm_set_state(lps, bfa_lps_sm_init);
+	return lps;
+}
+
+/**
+ * Free lport service tag. This can be called anytime after an alloc.
+ * No need to wait for any pending login/logout completions.
+ */
+void
+bfa_lps_delete(struct bfa_lps_s *lps)
+{
+	bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
+}
+
+/**
+ * Initiate a lport login.
+ */
+void
+bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
+	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
+{
+	lps->uarg	= uarg;
+	lps->alpa	= alpa;
+	lps->pdusz	= pdusz;
+	lps->pwwn	= pwwn;
+	lps->nwwn	= nwwn;
+	lps->fdisc	= BFA_FALSE;
+	lps->auth_en	= auth_en;
+	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
+}
+
+/**
+ * Initiate a lport fdisc login.
+ */
+void
+bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
+	wwn_t nwwn)
+{
+	lps->uarg	= uarg;
+	lps->alpa	= 0;
+	lps->pdusz	= pdusz;
+	lps->pwwn	= pwwn;
+	lps->nwwn	= nwwn;
+	lps->fdisc	= BFA_TRUE;
+	lps->auth_en	= BFA_FALSE;
+	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
+}
+
+/**
+ * Initiate a lport logout (flogi).
+ */
+void
+bfa_lps_flogo(struct bfa_lps_s *lps)
+{
+	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
+}
+
+/**
+ * Initiate a lport FDSIC logout.
+ */
+void
+bfa_lps_fdisclogo(struct bfa_lps_s *lps)
+{
+	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
+}
+
+/**
+ * Discard a pending login request -- should be called only for
+ * link down handling.
+ */
+void
+bfa_lps_discard(struct bfa_lps_s *lps)
+{
+	bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
+}
+
+/**
+ * Return lport services tag
+ */
+u8
+bfa_lps_get_tag(struct bfa_lps_s *lps)
+{
+	return lps->lp_tag;
+}
+
+/**
+ * Return lport services tag given the pid
+ */
+u8
+bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+	struct bfa_lps_s	*lps;
+	int			i;
+
+	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
+		if (lps->lp_pid == pid)
+			return lps->lp_tag;
+	}
+
+	/* Return base port tag anyway */
+	return 0;
+}
+
+/**
+ * return if fabric login indicates support for NPIV
+ */
+bfa_boolean_t
+bfa_lps_is_npiv_en(struct bfa_lps_s *lps)
+{
+	return lps->npiv_en;
+}
+
+/**
+ * Return TRUE if attached to F-Port, else return FALSE
+ */
+bfa_boolean_t
+bfa_lps_is_fport(struct bfa_lps_s *lps)
+{
+	return lps->fport;
+}
+
+/**
+ * Return TRUE if attached to a Brocade Fabric
+ */
+bfa_boolean_t
+bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps)
+{
+	return lps->brcd_switch;
+}
+/**
+ * return TRUE if authentication is required
+ */
+bfa_boolean_t
+bfa_lps_is_authreq(struct bfa_lps_s *lps)
+{
+	return lps->auth_req;
+}
+
+bfa_eproto_status_t
+bfa_lps_get_extstatus(struct bfa_lps_s *lps)
+{
+	return lps->ext_status;
+}
+
+/**
+ * return port id assigned to the lport
+ */
+u32
+bfa_lps_get_pid(struct bfa_lps_s *lps)
+{
+	return lps->lp_pid;
+}
+
+/**
+ * return port id assigned to the base lport
+ */
+u32
+bfa_lps_get_base_pid(struct bfa_s *bfa)
+{
+	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
+
+	return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
+}
+
+/**
+ * Return bb_credit assigned in FLOGI response
+ */
+u16
+bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps)
+{
+	return lps->pr_bbcred;
+}
+
+/**
+ * Return peer port name
+ */
+wwn_t
+bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps)
+{
+	return lps->pr_pwwn;
+}
+
+/**
+ * Return peer node name
+ */
+wwn_t
+bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps)
+{
+	return lps->pr_nwwn;
+}
+
+/**
+ * return reason code if login request is rejected
+ */
+u8
+bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps)
+{
+	return lps->lsrjt_rsn;
+}
+
+/**
+ * return explanation code if login request is rejected
+ */
+u8
+bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps)
+{
+	return lps->lsrjt_expl;
+}
+
+/**
+ * Return fpma/spma MAC for lport
+ */
+mac_t
+bfa_lps_get_lp_mac(struct bfa_lps_s *lps)
+{
+	return lps->lp_mac;
+}
+
+/**
+ * LPS firmware message class handler.
+ */
+void
+bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	union bfi_lps_i2h_msg_u	msg;
+
+	bfa_trc(bfa, m->mhdr.msg_id);
+	msg.msg = m;
+
+	switch (m->mhdr.msg_id) {
+	case BFI_LPS_H2I_LOGIN_RSP:
+		bfa_lps_login_rsp(bfa, msg.login_rsp);
+		break;
+
+	case BFI_LPS_H2I_LOGOUT_RSP:
+		bfa_lps_logout_rsp(bfa, msg.logout_rsp);
+		break;
+
+	case BFI_LPS_H2I_CVL_EVENT:
+		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
+		break;
+
+	default:
+		bfa_trc(bfa, m->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+/**
+ * FC PORT state machine functions
+ */
+static void
+bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
+			enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		/**
+		 * Start event after IOC is configured and BFA is started.
+		 */
+		if (bfa_fcport_send_enable(fcport)) {
+			bfa_trc(fcport->bfa, BFA_TRUE);
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		} else {
+			bfa_trc(fcport->bfa, BFA_FALSE);
+			bfa_sm_set_state(fcport,
+					bfa_fcport_sm_enabling_qwait);
+		}
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Port is persistently configured to be in enabled state. Do
+		 * not change state. Port enabling is done when START event is
+		 * received.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * If a port is persistently configured to be disabled, the
+		 * first event will a port disable request.
+		 */
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
+				enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_QRESUME:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		bfa_fcport_send_enable(fcport);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Already enable is in progress.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * Just send disable request to firmware when room becomes
+		 * available in request queue.
+		 */
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port disabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link events when doing back-to-back
+		 * enable/disables.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
+						enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_FWRSP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+		bfa_fcport_update_linkinfo(fcport);
+		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
+
+		bfa_assert(fcport->event_cbfn);
+		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Already being enabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		if (bfa_fcport_send_disable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_disabling_qwait);
+
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port disabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
+						enum bfa_fcport_sm_event event)
+{
+	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_LINKUP:
+		bfa_fcport_update_linkinfo(fcport);
+		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
+		bfa_assert(fcport->event_cbfn);
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
+		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
+
+			bfa_trc(fcport->bfa,
+				pevent->link_state.vc_fcf.fcf.fipenabled);
+			bfa_trc(fcport->bfa,
+				pevent->link_state.vc_fcf.fcf.fipfailed);
+
+			if (pevent->link_state.vc_fcf.fcf.fipfailed)
+				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+					BFA_PL_EID_FIP_FCF_DISC, 0,
+					"FIP FCF Discovery Failed");
+			else
+				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+					BFA_PL_EID_FIP_FCF_DISC, 0,
+					"FIP FCF Discovered");
+		}
+
+		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port online: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link down event.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Already enabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		if (bfa_fcport_send_disable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_disabling_qwait);
+
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port disabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
+	enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_ENABLE:
+		/**
+		 * Already enabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		if (bfa_fcport_send_disable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_disabling_qwait);
+
+		bfa_fcport_reset_linkinfo(fcport);
+		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port offline: WWN = %s\n", pwwn_buf);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port disabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_LINKDOWN:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
+		bfa_fcport_reset_linkinfo(fcport);
+		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		if (BFA_PORT_IS_DISABLED(fcport->bfa))
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"Base port offline: WWN = %s\n", pwwn_buf);
+		else
+			BFA_LOG(KERN_ERR, bfad, log_level,
+				"Base port (WWN = %s) "
+				"lost fabric connectivity\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		bfa_fcport_reset_linkinfo(fcport);
+		wwn2str(pwwn_buf, fcport->pwwn);
+		if (BFA_PORT_IS_DISABLED(fcport->bfa))
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"Base port offline: WWN = %s\n", pwwn_buf);
+		else
+			BFA_LOG(KERN_ERR, bfad, log_level,
+				"Base port (WWN = %s) "
+				"lost fabric connectivity\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		bfa_fcport_reset_linkinfo(fcport);
+		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
+		wwn2str(pwwn_buf, fcport->pwwn);
+		if (BFA_PORT_IS_DISABLED(fcport->bfa))
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"Base port offline: WWN = %s\n", pwwn_buf);
+		else
+			BFA_LOG(KERN_ERR, bfad, log_level,
+				"Base port (WWN = %s) "
+				"lost fabric connectivity\n", pwwn_buf);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
+				 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_QRESUME:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		bfa_fcport_send_disable(fcport);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * Already being disabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link events when doing back-to-back
+		 * enable/disables.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
+				 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_QRESUME:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
+		bfa_fcport_send_disable(fcport);
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link events when doing back-to-back
+		 * enable/disables.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+		bfa_reqq_wcancel(&fcport->reqq_wait);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
+						enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_FWRSP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * Already being disabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port enabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_LINKUP:
+	case BFA_FCPORT_SM_LINKDOWN:
+		/**
+		 * Possible to get link events when doing back-to-back
+		 * enable/disables.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
+						enum bfa_fcport_sm_event event)
+{
+	char pwwn_buf[BFA_STRING_32];
+	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		/**
+		 * Ignore start event for a port that is disabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_STOP:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
+		wwn2str(pwwn_buf, fcport->pwwn);
+		BFA_LOG(KERN_INFO, bfad, log_level,
+			"Base port enabled: WWN = %s\n", pwwn_buf);
+		break;
+
+	case BFA_FCPORT_SM_DISABLE:
+		/**
+		 * Already disabled.
+		 */
+		break;
+
+	case BFA_FCPORT_SM_HWFAIL:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
+		break;
+
+	default:
+		bfa_sm_fault(fcport->bfa, event);
+	}
+}
+
+static void
+bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
+			 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+		break;
+
+	default:
+		/**
+		 * Ignore all other events.
+		 */
+		;
+	}
+}
+
+/**
+ * Port is enabled. IOC is down/failed.
+ */
+static void
+bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
+			 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		if (bfa_fcport_send_enable(fcport))
+			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
+		else
+			bfa_sm_set_state(fcport,
+					 bfa_fcport_sm_enabling_qwait);
+		break;
+
+	default:
+		/**
+		 * Ignore all events.
+		 */
+		;
+	}
+}
+
+/**
+ * Port is disabled. IOC is down/failed.
+ */
+static void
+bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
+			 enum bfa_fcport_sm_event event)
+{
+	bfa_trc(fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_SM_START:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
+		break;
+
+	case BFA_FCPORT_SM_ENABLE:
+		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
+		break;
+
+	default:
+		/**
+		 * Ignore all events.
+		 */
+		;
+	}
+}
+
+/**
+ * Link state is down
+ */
+static void
+bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKUP:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for down notification
+ */
+static void
+bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKUP:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for down notification and there is a pending up
+ */
+static void
+bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is up
+ */
+static void
+bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for up notification
+ */
+static void
+bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for up notification and there is a pending down
+ */
+static void
+bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
+		enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKUP:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+/**
+ * Link state is waiting for up notification and there are pending down and up
+ */
+static void
+bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
+			enum bfa_fcport_ln_sm_event event)
+{
+	bfa_trc(ln->fcport->bfa, event);
+
+	switch (event) {
+	case BFA_FCPORT_LN_SM_LINKDOWN:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
+		break;
+
+	case BFA_FCPORT_LN_SM_NOTIFICATION:
+		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
+		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
+		break;
+
+	default:
+		bfa_sm_fault(ln->fcport->bfa, event);
+	}
+}
+
+
+
+/**
+ *  hal_port_private
+ */
+
+static void
+__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_fcport_ln_s *ln = cbarg;
+
+	if (complete)
+		ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
+	else
+		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
+}
+
+/**
+ * Send SCN notification to upper layers.
+ * trunk - false if caller is fcport to ignore fcport event in trunked mode
+ */
+static void
+bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
+	bfa_boolean_t trunk)
+{
+	if (fcport->cfg.trunked && !trunk)
+		return;
+
+	switch (event) {
+	case BFA_PORT_LINKUP:
+		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
+		break;
+	case BFA_PORT_LINKDOWN:
+		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
+		break;
+	default:
+		bfa_assert(0);
+	}
+}
+
+static void
+bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
+{
+	struct bfa_fcport_s *fcport = ln->fcport;
+
+	if (fcport->bfa->fcs) {
+		fcport->event_cbfn(fcport->event_cbarg, event);
+		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
+	} else {
+		ln->ln_event = event;
+		bfa_cb_queue(fcport->bfa, &ln->ln_qe,
+			__bfa_cb_fcport_event, ln);
+	}
+}
+
+#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
+							BFA_CACHELINE_SZ))
+
+static void
+bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len,
+		u32 *dm_len)
+{
+	*dm_len += FCPORT_STATS_DMA_SZ;
+}
+
+static void
+bfa_fcport_qresume(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = cbarg;
+
+	bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
+}
+
+static void
+bfa_fcport_mem_claim(struct bfa_fcport_s *fcport, struct bfa_meminfo_s *meminfo)
+{
+	u8		*dm_kva;
+	u64	dm_pa;
+
+	dm_kva = bfa_meminfo_dma_virt(meminfo);
+	dm_pa  = bfa_meminfo_dma_phys(meminfo);
+
+	fcport->stats_kva = dm_kva;
+	fcport->stats_pa  = dm_pa;
+	fcport->stats	  = (union bfa_fcport_stats_u *) dm_kva;
+
+	dm_kva += FCPORT_STATS_DMA_SZ;
+	dm_pa  += FCPORT_STATS_DMA_SZ;
+
+	bfa_meminfo_dma_virt(meminfo) = dm_kva;
+	bfa_meminfo_dma_phys(meminfo) = dm_pa;
+}
+
+/**
+ * Memory initialization.
+ */
+static void
+bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
+	struct bfa_fcport_ln_s *ln = &fcport->ln;
+	struct bfa_timeval_s tv;
+
+	bfa_os_memset(fcport, 0, sizeof(struct bfa_fcport_s));
+	fcport->bfa = bfa;
+	ln->fcport = fcport;
+
+	bfa_fcport_mem_claim(fcport, meminfo);
+
+	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
+	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
+
+	/**
+	 * initialize time stamp for stats reset
+	 */
+	bfa_os_gettimeofday(&tv);
+	fcport->stats_reset_time = tv.tv_sec;
+
+	/**
+	 * initialize and set default configuration
+	 */
+	port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
+	port_cfg->speed = BFA_PORT_SPEED_AUTO;
+	port_cfg->trunked = BFA_FALSE;
+	port_cfg->maxfrsize = 0;
+
+	port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
+
+	bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
+}
+
+static void
+bfa_fcport_detach(struct bfa_s *bfa)
+{
+}
+
+/**
+ * Called when IOC is ready.
+ */
+static void
+bfa_fcport_start(struct bfa_s *bfa)
+{
+	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
+}
+
+/**
+ * Called before IOC is stopped.
+ */
+static void
+bfa_fcport_stop(struct bfa_s *bfa)
+{
+	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_STOP);
+	bfa_trunk_iocdisable(bfa);
+}
+
+/**
+ * Called when IOC failure is detected.
+ */
+static void
+bfa_fcport_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
+	bfa_trunk_iocdisable(bfa);
+}
+
+static void
+bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
+{
+	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	fcport->speed = pevent->link_state.speed;
+	fcport->topology = pevent->link_state.topology;
+
+	if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP)
+		fcport->myalpa = 0;
+
+	/* QoS Details */
+	bfa_os_assign(fcport->qos_attr, pevent->link_state.qos_attr);
+	bfa_os_assign(fcport->qos_vc_attr,
+		pevent->link_state.vc_fcf.qos_vc_attr);
+
+	/**
+	 * update trunk state if applicable
+	 */
+	if (!fcport->cfg.trunked)
+		trunk->attr.state = BFA_TRUNK_DISABLED;
+
+	/* update FCoE specific */
+	fcport->fcoe_vlan = bfa_os_ntohs(pevent->link_state.vc_fcf.fcf.vlan);
+
+	bfa_trc(fcport->bfa, fcport->speed);
+	bfa_trc(fcport->bfa, fcport->topology);
+}
+
+static void
+bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
+{
+	fcport->speed = BFA_PORT_SPEED_UNKNOWN;
+	fcport->topology = BFA_PORT_TOPOLOGY_NONE;
+}
+
+/**
+ * Send port enable message to firmware.
+ */
+static bfa_boolean_t
+bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
+{
+	struct bfi_fcport_enable_req_s *m;
+
+	/**
+	 * Increment message tag before queue check, so that responses to old
+	 * requests are discarded.
+	 */
+	fcport->msgtag++;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+	if (!m) {
+		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+							&fcport->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
+			bfa_lpuid(fcport->bfa));
+	m->nwwn = fcport->nwwn;
+	m->pwwn = fcport->pwwn;
+	m->port_cfg = fcport->cfg;
+	m->msgtag = fcport->msgtag;
+	m->port_cfg.maxfrsize = bfa_os_htons(fcport->cfg.maxfrsize);
+	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
+	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
+	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+	return BFA_TRUE;
+}
+
+/**
+ * Send port disable message to firmware.
+ */
+static	bfa_boolean_t
+bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
+{
+	struct bfi_fcport_req_s *m;
+
+	/**
+	 * Increment message tag before queue check, so that responses to old
+	 * requests are discarded.
+	 */
+	fcport->msgtag++;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+	if (!m) {
+		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+							&fcport->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
+			bfa_lpuid(fcport->bfa));
+	m->msgtag = fcport->msgtag;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+
+	return BFA_TRUE;
+}
+
+static void
+bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
+{
+	fcport->pwwn = bfa_ioc_get_pwwn(&fcport->bfa->ioc);
+	fcport->nwwn = bfa_ioc_get_nwwn(&fcport->bfa->ioc);
+
+	bfa_trc(fcport->bfa, fcport->pwwn);
+	bfa_trc(fcport->bfa, fcport->nwwn);
+}
+
+static void
+bfa_fcport_send_txcredit(void *port_cbarg)
+{
+
+	struct bfa_fcport_s *fcport = port_cbarg;
+	struct bfi_fcport_set_svc_params_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+	if (!m) {
+		bfa_trc(fcport->bfa, fcport->cfg.tx_bbcredit);
+		return;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ,
+			bfa_lpuid(fcport->bfa));
+	m->tx_bbcredit = bfa_os_htons((u16)fcport->cfg.tx_bbcredit);
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+}
+
+static void
+bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
+	struct bfa_qos_stats_s *s)
+{
+	u32	*dip = (u32 *) d;
+	u32	*sip = (u32 *) s;
+	int		i;
+
+	/* Now swap the 32 bit fields */
+	for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
+		dip[i] = bfa_os_ntohl(sip[i]);
+}
+
+static void
+bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
+	struct bfa_fcoe_stats_s *s)
+{
+	u32	*dip = (u32 *) d;
+	u32	*sip = (u32 *) s;
+	int		i;
+
+	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
+	     i = i + 2) {
+#ifdef __BIGENDIAN
+		dip[i] = bfa_os_ntohl(sip[i]);
+		dip[i + 1] = bfa_os_ntohl(sip[i + 1]);
+#else
+		dip[i] = bfa_os_ntohl(sip[i + 1]);
+		dip[i + 1] = bfa_os_ntohl(sip[i]);
+#endif
+	}
+}
+
+static void
+__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_fcport_s *fcport = cbarg;
+
+	if (complete) {
+		if (fcport->stats_status == BFA_STATUS_OK) {
+			struct bfa_timeval_s tv;
+
+			/* Swap FC QoS or FCoE stats */
+			if (bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
+				bfa_fcport_qos_stats_swap(
+					&fcport->stats_ret->fcqos,
+					&fcport->stats->fcqos);
+			} else {
+				bfa_fcport_fcoe_stats_swap(
+					&fcport->stats_ret->fcoe,
+					&fcport->stats->fcoe);
+
+				bfa_os_gettimeofday(&tv);
+				fcport->stats_ret->fcoe.secs_reset =
+					tv.tv_sec - fcport->stats_reset_time;
+			}
+		}
+		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
+	} else {
+		fcport->stats_busy = BFA_FALSE;
+		fcport->stats_status = BFA_STATUS_OK;
+	}
+}
+
+static void
+bfa_fcport_stats_get_timeout(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+
+	bfa_trc(fcport->bfa, fcport->stats_qfull);
+
+	if (fcport->stats_qfull) {
+		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
+		fcport->stats_qfull = BFA_FALSE;
+	}
+
+	fcport->stats_status = BFA_STATUS_ETIMER;
+	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe, __bfa_cb_fcport_stats_get,
+		fcport);
+}
+
+static void
+bfa_fcport_send_stats_get(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+	struct bfi_fcport_req_s *msg;
+
+	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+
+	if (!msg) {
+		fcport->stats_qfull = BFA_TRUE;
+		bfa_reqq_winit(&fcport->stats_reqq_wait,
+				bfa_fcport_send_stats_get, fcport);
+		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+				&fcport->stats_reqq_wait);
+		return;
+	}
+	fcport->stats_qfull = BFA_FALSE;
+
+	bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
+	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
+			bfa_lpuid(fcport->bfa));
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+}
+
+static void
+__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_fcport_s *fcport = cbarg;
+
+	if (complete) {
+		struct bfa_timeval_s tv;
+
+		/**
+		 * re-initialize time stamp for stats reset
+		 */
+		bfa_os_gettimeofday(&tv);
+		fcport->stats_reset_time = tv.tv_sec;
+
+		fcport->stats_cbfn(fcport->stats_cbarg, fcport->stats_status);
+	} else {
+		fcport->stats_busy = BFA_FALSE;
+		fcport->stats_status = BFA_STATUS_OK;
+	}
+}
+
+static void
+bfa_fcport_stats_clr_timeout(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+
+	bfa_trc(fcport->bfa, fcport->stats_qfull);
+
+	if (fcport->stats_qfull) {
+		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
+		fcport->stats_qfull = BFA_FALSE;
+	}
+
+	fcport->stats_status = BFA_STATUS_ETIMER;
+	bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
+			__bfa_cb_fcport_stats_clr, fcport);
+}
+
+static void
+bfa_fcport_send_stats_clear(void *cbarg)
+{
+	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
+	struct bfi_fcport_req_s *msg;
+
+	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
+
+	if (!msg) {
+		fcport->stats_qfull = BFA_TRUE;
+		bfa_reqq_winit(&fcport->stats_reqq_wait,
+				bfa_fcport_send_stats_clear, fcport);
+		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
+						&fcport->stats_reqq_wait);
+		return;
+	}
+	fcport->stats_qfull = BFA_FALSE;
+
+	bfa_os_memset(msg, 0, sizeof(struct bfi_fcport_req_s));
+	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
+			bfa_lpuid(fcport->bfa));
+	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT);
+}
+
+/**
+ * Handle trunk SCN event from firmware.
+ */
+static void
+bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
+{
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+	struct bfi_fcport_trunk_link_s *tlink;
+	struct bfa_trunk_link_attr_s *lattr;
+	enum bfa_trunk_state state_prev;
+	int i;
+	int link_bm = 0;
+
+	bfa_trc(fcport->bfa, fcport->cfg.trunked);
+	bfa_assert(scn->trunk_state == BFA_TRUNK_ONLINE ||
+		   scn->trunk_state == BFA_TRUNK_OFFLINE);
+
+	bfa_trc(fcport->bfa, trunk->attr.state);
+	bfa_trc(fcport->bfa, scn->trunk_state);
+	bfa_trc(fcport->bfa, scn->trunk_speed);
+
+	/**
+	 * Save off new state for trunk attribute query
+	 */
+	state_prev = trunk->attr.state;
+	if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
+		trunk->attr.state = scn->trunk_state;
+	trunk->attr.speed = scn->trunk_speed;
+	for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
+		lattr = &trunk->attr.link_attr[i];
+		tlink = &scn->tlink[i];
+
+		lattr->link_state = tlink->state;
+		lattr->trunk_wwn  = tlink->trunk_wwn;
+		lattr->fctl	  = tlink->fctl;
+		lattr->speed	  = tlink->speed;
+		lattr->deskew	  = bfa_os_ntohl(tlink->deskew);
+
+		if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
+			fcport->speed	 = tlink->speed;
+			fcport->topology = BFA_PORT_TOPOLOGY_P2P;
+			link_bm |= 1 << i;
+		}
+
+		bfa_trc(fcport->bfa, lattr->link_state);
+		bfa_trc(fcport->bfa, lattr->trunk_wwn);
+		bfa_trc(fcport->bfa, lattr->fctl);
+		bfa_trc(fcport->bfa, lattr->speed);
+		bfa_trc(fcport->bfa, lattr->deskew);
+	}
+
+	switch (link_bm) {
+	case 3:
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
+		break;
+	case 2:
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
+		break;
+	case 1:
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
+		break;
+	default:
+		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
+			BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
+	}
+
+	/**
+	 * Notify upper layers if trunk state changed.
+	 */
+	if ((state_prev != trunk->attr.state) ||
+		(scn->trunk_state == BFA_TRUNK_OFFLINE)) {
+		bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
+			BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
+	}
+}
+
+static void
+bfa_trunk_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	int i = 0;
+
+	/**
+	 * In trunked mode, notify upper layers that link is down
+	 */
+	if (fcport->cfg.trunked) {
+		if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
+			bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
+
+		fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
+		fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
+		for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
+			fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
+			fcport->trunk.attr.link_attr[i].fctl =
+						BFA_TRUNK_LINK_FCTL_NORMAL;
+			fcport->trunk.attr.link_attr[i].link_state =
+						BFA_TRUNK_LINK_STATE_DN_LINKDN;
+			fcport->trunk.attr.link_attr[i].speed =
+						BFA_PORT_SPEED_UNKNOWN;
+			fcport->trunk.attr.link_attr[i].deskew = 0;
+		}
+	}
+}
+
+
+
+/**
+ *  hal_port_public
+ */
+
+/**
+ * Called to initialize port attributes
+ */
+void
+bfa_fcport_init(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	/**
+	 * Initialize port attributes from IOC hardware data.
+	 */
+	bfa_fcport_set_wwns(fcport);
+	if (fcport->cfg.maxfrsize == 0)
+		fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
+	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
+	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
+
+	bfa_assert(fcport->cfg.maxfrsize);
+	bfa_assert(fcport->cfg.rx_bbcredit);
+	bfa_assert(fcport->speed_sup);
+}
+
+/**
+ * Firmware message handler.
+ */
+void
+bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	union bfi_fcport_i2h_msg_u i2hmsg;
+
+	i2hmsg.msg = msg;
+	fcport->event_arg.i2hmsg = i2hmsg;
+
+	bfa_trc(bfa, msg->mhdr.msg_id);
+	bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
+
+	switch (msg->mhdr.msg_id) {
+	case BFI_FCPORT_I2H_ENABLE_RSP:
+		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
+			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
+		break;
+
+	case BFI_FCPORT_I2H_DISABLE_RSP:
+		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
+			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
+		break;
+
+	case BFI_FCPORT_I2H_EVENT:
+		if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
+			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
+		else
+			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKDOWN);
+		break;
+
+	case BFI_FCPORT_I2H_TRUNK_SCN:
+		bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
+		break;
+
+	case BFI_FCPORT_I2H_STATS_GET_RSP:
+		/*
+		 * check for timer pop before processing the rsp
+		 */
+		if (fcport->stats_busy == BFA_FALSE ||
+		    fcport->stats_status == BFA_STATUS_ETIMER)
+			break;
+
+		bfa_timer_stop(&fcport->timer);
+		fcport->stats_status = i2hmsg.pstatsget_rsp->status;
+		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
+				__bfa_cb_fcport_stats_get, fcport);
+		break;
+
+	case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
+		/*
+		 * check for timer pop before processing the rsp
+		 */
+		if (fcport->stats_busy == BFA_FALSE ||
+		    fcport->stats_status == BFA_STATUS_ETIMER)
+			break;
+
+		bfa_timer_stop(&fcport->timer);
+		fcport->stats_status = BFA_STATUS_OK;
+		bfa_cb_queue(fcport->bfa, &fcport->hcb_qe,
+				__bfa_cb_fcport_stats_clr, fcport);
+		break;
+
+	case BFI_FCPORT_I2H_ENABLE_AEN:
+		bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
+		break;
+
+	case BFI_FCPORT_I2H_DISABLE_AEN:
+		bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
+		break;
+
+	default:
+		bfa_assert(0);
+	break;
+	}
+}
+
+
+
+/**
+ *  hal_port_api
+ */
+
+/**
+ * Registered callback for port events.
+ */
+void
+bfa_fcport_event_register(struct bfa_s *bfa,
+				void (*cbfn) (void *cbarg,
+				enum bfa_port_linkstate event),
+				void *cbarg)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	fcport->event_cbfn = cbfn;
+	fcport->event_cbarg = cbarg;
+}
+
+bfa_status_t
+bfa_fcport_enable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	if (bfa_ioc_is_disabled(&bfa->ioc))
+		return BFA_STATUS_IOC_DISABLED;
+
+	if (fcport->diag_busy)
+		return BFA_STATUS_DIAG_BUSY;
+
+	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcport_disable(struct bfa_s *bfa)
+{
+
+	if (bfa_ioc_is_disabled(&bfa->ioc))
+		return BFA_STATUS_IOC_DISABLED;
+
+	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Configure port speed.
+ */
+bfa_status_t
+bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, speed);
+
+	if (fcport->cfg.trunked == BFA_TRUE)
+		return BFA_STATUS_TRUNK_ENABLED;
+	if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
+		bfa_trc(bfa, fcport->speed_sup);
+		return BFA_STATUS_UNSUPP_SPEED;
+	}
+
+	fcport->cfg.speed = speed;
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Get current speed.
+ */
+enum bfa_port_speed
+bfa_fcport_get_speed(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->speed;
+}
+
+/**
+ * Configure port topology.
+ */
+bfa_status_t
+bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, topology);
+	bfa_trc(bfa, fcport->cfg.topology);
+
+	switch (topology) {
+	case BFA_PORT_TOPOLOGY_P2P:
+	case BFA_PORT_TOPOLOGY_LOOP:
+	case BFA_PORT_TOPOLOGY_AUTO:
+		break;
+
+	default:
+		return BFA_STATUS_EINVAL;
+	}
+
+	fcport->cfg.topology = topology;
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Get current topology.
+ */
+enum bfa_port_topology
+bfa_fcport_get_topology(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->topology;
+}
+
+bfa_status_t
+bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, alpa);
+	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
+	bfa_trc(bfa, fcport->cfg.hardalpa);
+
+	fcport->cfg.cfg_hardalpa = BFA_TRUE;
+	fcport->cfg.hardalpa = alpa;
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
+	bfa_trc(bfa, fcport->cfg.hardalpa);
+
+	fcport->cfg.cfg_hardalpa = BFA_FALSE;
+	return BFA_STATUS_OK;
+}
+
+bfa_boolean_t
+bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	*alpa = fcport->cfg.hardalpa;
+	return fcport->cfg.cfg_hardalpa;
+}
+
+u8
+bfa_fcport_get_myalpa(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->myalpa;
+}
+
+bfa_status_t
+bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, maxfrsize);
+	bfa_trc(bfa, fcport->cfg.maxfrsize);
+
+	/* with in range */
+	if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
+		return BFA_STATUS_INVLD_DFSZ;
+
+	/* power of 2, if not the max frame size of 2112 */
+	if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
+		return BFA_STATUS_INVLD_DFSZ;
+
+	fcport->cfg.maxfrsize = maxfrsize;
+	return BFA_STATUS_OK;
+}
+
+u16
+bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->cfg.maxfrsize;
+}
+
+u8
+bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->cfg.rx_bbcredit;
+}
+
+void
+bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
+	bfa_fcport_send_txcredit(fcport);
+}
+
+/**
+ * Get port attributes.
+ */
+
+wwn_t
+bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	if (node)
+		return fcport->nwwn;
+	else
+		return fcport->pwwn;
+}
+
+void
+bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_os_memset(attr, 0, sizeof(struct bfa_port_attr_s));
+
+	attr->nwwn = fcport->nwwn;
+	attr->pwwn = fcport->pwwn;
+
+	attr->factorypwwn =  bfa_ioc_get_mfg_pwwn(&bfa->ioc);
+	attr->factorynwwn =  bfa_ioc_get_mfg_nwwn(&bfa->ioc);
+
+	bfa_os_memcpy(&attr->pport_cfg, &fcport->cfg,
+		sizeof(struct bfa_port_cfg_s));
+	/* speed attributes */
+	attr->pport_cfg.speed = fcport->cfg.speed;
+	attr->speed_supported = fcport->speed_sup;
+	attr->speed = fcport->speed;
+	attr->cos_supported = FC_CLASS_3;
+
+	/* topology attributes */
+	attr->pport_cfg.topology = fcport->cfg.topology;
+	attr->topology = fcport->topology;
+	attr->pport_cfg.trunked = fcport->cfg.trunked;
+
+	/* beacon attributes */
+	attr->beacon = fcport->beacon;
+	attr->link_e2e_beacon = fcport->link_e2e_beacon;
+	attr->plog_enabled = bfa_plog_get_setting(fcport->bfa->plog);
+	attr->io_profile = bfa_fcpim_get_io_profile(fcport->bfa);
+
+	attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
+	attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
+	attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
+	if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
+		attr->port_state = BFA_PORT_ST_IOCDIS;
+	else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
+		attr->port_state = BFA_PORT_ST_FWMISMATCH;
+
+	/* FCoE vlan */
+	attr->fcoe_vlan = fcport->fcoe_vlan;
+}
+
+#define BFA_FCPORT_STATS_TOV	1000
+
+/**
+ * Fetch port statistics (FCQoS or FCoE).
+ */
+bfa_status_t
+bfa_fcport_get_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
+	bfa_cb_port_t cbfn, void *cbarg)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	if (fcport->stats_busy) {
+		bfa_trc(bfa, fcport->stats_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	fcport->stats_busy  = BFA_TRUE;
+	fcport->stats_ret   = stats;
+	fcport->stats_cbfn  = cbfn;
+	fcport->stats_cbarg = cbarg;
+
+	bfa_fcport_send_stats_get(fcport);
+
+	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_get_timeout,
+			fcport, BFA_FCPORT_STATS_TOV);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Reset port statistics (FCQoS or FCoE).
+ */
+bfa_status_t
+bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	if (fcport->stats_busy) {
+		bfa_trc(bfa, fcport->stats_busy);
+		return BFA_STATUS_DEVBUSY;
+	}
+
+	fcport->stats_busy  = BFA_TRUE;
+	fcport->stats_cbfn  = cbfn;
+	fcport->stats_cbarg = cbarg;
+
+	bfa_fcport_send_stats_clear(fcport);
+
+	bfa_timer_start(bfa, &fcport->timer, bfa_fcport_stats_clr_timeout,
+			fcport, BFA_FCPORT_STATS_TOV);
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Fetch FCQoS port statistics
+ */
+bfa_status_t
+bfa_fcport_get_qos_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
+	bfa_cb_port_t cbfn, void *cbarg)
+{
+	/* Meaningful only for FC mode */
+	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
+
+	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
+}
+
+/**
+ * Reset FCoE port statistics
+ */
+bfa_status_t
+bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+{
+	/* Meaningful only for FC mode */
+	bfa_assert(bfa_ioc_get_fcmode(&bfa->ioc));
+
+	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
+}
+
+/**
+ * Fetch FCQoS port statistics
+ */
+bfa_status_t
+bfa_fcport_get_fcoe_stats(struct bfa_s *bfa, union bfa_fcport_stats_u *stats,
+	bfa_cb_port_t cbfn, void *cbarg)
+{
+	/* Meaningful only for FCoE mode */
+	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
+
+	return bfa_fcport_get_stats(bfa, stats, cbfn, cbarg);
+}
+
+/**
+ * Reset FCoE port statistics
+ */
+bfa_status_t
+bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn, void *cbarg)
+{
+	/* Meaningful only for FCoE mode */
+	bfa_assert(!bfa_ioc_get_fcmode(&bfa->ioc));
+
+	return bfa_fcport_clear_stats(bfa, cbfn, cbarg);
+}
+
+void
+bfa_fcport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	qos_attr->state = fcport->qos_attr.state;
+	qos_attr->total_bb_cr = bfa_os_ntohl(fcport->qos_attr.total_bb_cr);
+}
+
+void
+bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
+	struct bfa_qos_vc_attr_s *qos_vc_attr)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_qos_vc_attr_s *bfa_vc_attr = &fcport->qos_vc_attr;
+	u32 i = 0;
+
+	qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count);
+	qos_vc_attr->shared_credit  = bfa_os_ntohs(bfa_vc_attr->shared_credit);
+	qos_vc_attr->elp_opmode_flags  =
+			bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags);
+
+	/* Individual VC info */
+	while (i < qos_vc_attr->total_vc_count) {
+		qos_vc_attr->vc_info[i].vc_credit	=
+				bfa_vc_attr->vc_info[i].vc_credit;
+		qos_vc_attr->vc_info[i].borrow_credit	=
+				bfa_vc_attr->vc_info[i].borrow_credit;
+		qos_vc_attr->vc_info[i].priority	=
+				bfa_vc_attr->vc_info[i].priority;
+		++i;
+	}
+}
+
+/**
+ * Fetch port attributes.
+ */
+bfa_boolean_t
+bfa_fcport_is_disabled(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
+		BFA_PORT_ST_DISABLED;
+
+}
+
+bfa_boolean_t
+bfa_fcport_is_ratelim(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
+
+}
+
+void
+bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
+
+	bfa_trc(bfa, on_off);
+	bfa_trc(bfa, fcport->cfg.qos_enabled);
+
+	bfa_trc(bfa, ioc_type);
+
+	if (ioc_type == BFA_IOC_TYPE_FC) {
+		fcport->cfg.qos_enabled = on_off;
+		/**
+		 * Notify fcpim of the change in QoS state
+		 */
+		bfa_fcpim_update_ioredirect(bfa);
+	}
+}
+
+void
+bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, on_off);
+	bfa_trc(bfa, fcport->cfg.ratelimit);
+
+	fcport->cfg.ratelimit = on_off;
+	if (fcport->cfg.trl_def_speed == BFA_PORT_SPEED_UNKNOWN)
+		fcport->cfg.trl_def_speed = BFA_PORT_SPEED_1GBPS;
+}
+
+/**
+ * Configure default minimum ratelim speed
+ */
+bfa_status_t
+bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, speed);
+
+	/* Auto and speeds greater than the supported speed, are invalid */
+	if ((speed == BFA_PORT_SPEED_AUTO) || (speed > fcport->speed_sup)) {
+		bfa_trc(bfa, fcport->speed_sup);
+		return BFA_STATUS_UNSUPP_SPEED;
+	}
+
+	fcport->cfg.trl_def_speed = speed;
+
+	return BFA_STATUS_OK;
+}
+
+/**
+ * Get default minimum ratelim speed
+ */
+enum bfa_port_speed
+bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, fcport->cfg.trl_def_speed);
+	return fcport->cfg.trl_def_speed;
+
+}
+void
+bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, status);
+	bfa_trc(bfa, fcport->diag_busy);
+
+	fcport->diag_busy = status;
+}
+
+void
+bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+	bfa_boolean_t link_e2e_beacon)
+{
+	struct bfa_s *bfa = dev;
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	bfa_trc(bfa, beacon);
+	bfa_trc(bfa, link_e2e_beacon);
+	bfa_trc(bfa, fcport->beacon);
+	bfa_trc(bfa, fcport->link_e2e_beacon);
+
+	fcport->beacon = beacon;
+	fcport->link_e2e_beacon = link_e2e_beacon;
+}
+
+bfa_boolean_t
+bfa_fcport_is_linkup(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return	(!fcport->cfg.trunked &&
+		 bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
+		(fcport->cfg.trunked &&
+		 fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
+}
+
+bfa_boolean_t
+bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+
+	return fcport->cfg.qos_enabled;
+}
+
+bfa_status_t
+bfa_trunk_get_attr(struct bfa_s *bfa, struct bfa_trunk_attr_s *attr)
+
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	bfa_trc(bfa, fcport->cfg.trunked);
+	bfa_trc(bfa, trunk->attr.state);
+	*attr = trunk->attr;
+	attr->port_id = bfa_lps_get_base_pid(bfa);
+
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_trunk_enable_cfg(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	bfa_trc(bfa, 1);
+	trunk->attr.state = BFA_TRUNK_OFFLINE;
+	fcport->cfg.trunked = BFA_TRUE;
+}
+
+bfa_status_t
+bfa_trunk_enable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	bfa_trc(bfa, 1);
+
+	trunk->attr.state   = BFA_TRUNK_OFFLINE;
+	bfa_fcport_disable(bfa);
+	fcport->cfg.trunked = BFA_TRUE;
+	bfa_fcport_enable(bfa);
+
+	return BFA_STATUS_OK;
+}
+
+bfa_status_t
+bfa_trunk_disable(struct bfa_s *bfa)
+{
+	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
+	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
+
+	bfa_trc(bfa, 0);
+	trunk->attr.state   = BFA_TRUNK_DISABLED;
+	bfa_fcport_disable(bfa);
+	fcport->cfg.trunked = BFA_FALSE;
+	bfa_fcport_enable(bfa);
+	return BFA_STATUS_OK;
+}
+
+
+/**
+ * Rport State machine functions
+ */
+/**
+ * Beginning state, only online event expected.
+ */
+static void
+bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_CREATE:
+		bfa_stats(rp, sm_un_cr);
+		bfa_sm_set_state(rp, bfa_rport_sm_created);
+		break;
+
+	default:
+		bfa_stats(rp, sm_un_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+static void
+bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_ONLINE:
+		bfa_stats(rp, sm_cr_on);
+		if (bfa_rport_send_fwcreate(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_cr_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_cr_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	default:
+		bfa_stats(rp, sm_cr_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Waiting for rport create response from firmware.
+ */
+static void
+bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_fwc_rsp);
+		bfa_sm_set_state(rp, bfa_rport_sm_online);
+		bfa_rport_online_cb(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_fwc_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
+		break;
+
+	case BFA_RPORT_SM_OFFLINE:
+		bfa_stats(rp, sm_fwc_off);
+		bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_fwc_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	default:
+		bfa_stats(rp, sm_fwc_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Request queue is full, awaiting queue resume to send create request.
+ */
+static void
+bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_QRESUME:
+		bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+		bfa_rport_send_fwcreate(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_fwc_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_OFFLINE:
+		bfa_stats(rp, sm_fwc_off);
+		bfa_sm_set_state(rp, bfa_rport_sm_offline);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_fwc_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		break;
+
+	default:
+		bfa_stats(rp, sm_fwc_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Online state - normal parking state.
+ */
+static void
+bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	struct bfi_rport_qos_scn_s *qos_scn;
+
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_OFFLINE:
+		bfa_stats(rp, sm_on_off);
+		if (bfa_rport_send_fwdelete(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_on_del);
+		if (bfa_rport_send_fwdelete(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_on_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	case BFA_RPORT_SM_SET_SPEED:
+		bfa_rport_send_fwspeed(rp);
+		break;
+
+	case BFA_RPORT_SM_QOS_SCN:
+		qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
+		rp->qos_attr = qos_scn->new_qos_attr;
+		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
+		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
+		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
+		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
+
+		qos_scn->old_qos_attr.qos_flow_id  =
+			bfa_os_ntohl(qos_scn->old_qos_attr.qos_flow_id);
+		qos_scn->new_qos_attr.qos_flow_id  =
+			bfa_os_ntohl(qos_scn->new_qos_attr.qos_flow_id);
+
+		if (qos_scn->old_qos_attr.qos_flow_id !=
+			qos_scn->new_qos_attr.qos_flow_id)
+			bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
+						    qos_scn->old_qos_attr,
+						    qos_scn->new_qos_attr);
+		if (qos_scn->old_qos_attr.qos_priority !=
+			qos_scn->new_qos_attr.qos_priority)
+			bfa_cb_rport_qos_scn_prio(rp->rport_drv,
+						  qos_scn->old_qos_attr,
+						  qos_scn->new_qos_attr);
+		break;
+
+	default:
+		bfa_stats(rp, sm_on_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Firmware rport is being deleted - awaiting f/w response.
+ */
+static void
+bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_fwd_rsp);
+		bfa_sm_set_state(rp, bfa_rport_sm_offline);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_fwd_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_fwd_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	default:
+		bfa_stats(rp, sm_fwd_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+static void
+bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_QRESUME:
+		bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+		bfa_rport_send_fwdelete(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_fwd_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_fwd_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	default:
+		bfa_stats(rp, sm_fwd_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Offline state.
+ */
+static void
+bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_off_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_ONLINE:
+		bfa_stats(rp, sm_off_on);
+		if (bfa_rport_send_fwcreate(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_off_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	default:
+		bfa_stats(rp, sm_off_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Rport is deleted, waiting for firmware response to delete.
+ */
+static void
+bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_del_fwrsp);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_del_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	default:
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+static void
+bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_QRESUME:
+		bfa_stats(rp, sm_del_fwrsp);
+		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+		bfa_rport_send_fwdelete(rp);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_del_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_reqq_wcancel(&rp->reqq_wait);
+		bfa_rport_free(rp);
+		break;
+
+	default:
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Waiting for rport create response from firmware. A delete is pending.
+ */
+static void
+bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
+				enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_delp_fwrsp);
+		if (bfa_rport_send_fwdelete(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_delp_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	default:
+		bfa_stats(rp, sm_delp_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * Waiting for rport create response from firmware. Rport offline is pending.
+ */
+static void
+bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
+				 enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_FWRSP:
+		bfa_stats(rp, sm_offp_fwrsp);
+		if (bfa_rport_send_fwdelete(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_offp_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		bfa_stats(rp, sm_offp_hwf);
+		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
+		break;
+
+	default:
+		bfa_stats(rp, sm_offp_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+/**
+ * IOC h/w failed.
+ */
+static void
+bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
+{
+	bfa_trc(rp->bfa, rp->rport_tag);
+	bfa_trc(rp->bfa, event);
+
+	switch (event) {
+	case BFA_RPORT_SM_OFFLINE:
+		bfa_stats(rp, sm_iocd_off);
+		bfa_rport_offline_cb(rp);
+		break;
+
+	case BFA_RPORT_SM_DELETE:
+		bfa_stats(rp, sm_iocd_del);
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+		bfa_rport_free(rp);
+		break;
+
+	case BFA_RPORT_SM_ONLINE:
+		bfa_stats(rp, sm_iocd_on);
+		if (bfa_rport_send_fwcreate(rp))
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
+		else
+			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
+		break;
+
+	case BFA_RPORT_SM_HWFAIL:
+		break;
+
+	default:
+		bfa_stats(rp, sm_iocd_unexp);
+		bfa_sm_fault(rp->bfa, event);
+	}
+}
+
+
+
+/**
+ *  bfa_rport_private BFA rport private functions
+ */
+
+static void
+__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_rport_s *rp = cbarg;
+
+	if (complete)
+		bfa_cb_rport_online(rp->rport_drv);
+}
+
+static void
+__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_rport_s *rp = cbarg;
+
+	if (complete)
+		bfa_cb_rport_offline(rp->rport_drv);
+}
+
+static void
+bfa_rport_qresume(void *cbarg)
+{
+	struct bfa_rport_s	*rp = cbarg;
+
+	bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
+}
+
+static void
+bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		u32 *dm_len)
+{
+	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
+		cfg->fwcfg.num_rports = BFA_RPORT_MIN;
+
+	*km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s);
+}
+
+static void
+bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		     struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
+	struct bfa_rport_s *rp;
+	u16 i;
+
+	INIT_LIST_HEAD(&mod->rp_free_q);
+	INIT_LIST_HEAD(&mod->rp_active_q);
+
+	rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo);
+	mod->rps_list = rp;
+	mod->num_rports = cfg->fwcfg.num_rports;
+
+	bfa_assert(mod->num_rports &&
+		   !(mod->num_rports & (mod->num_rports - 1)));
+
+	for (i = 0; i < mod->num_rports; i++, rp++) {
+		bfa_os_memset(rp, 0, sizeof(struct bfa_rport_s));
+		rp->bfa = bfa;
+		rp->rport_tag = i;
+		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
+
+		/**
+		 *  - is unused
+		 */
+		if (i)
+			list_add_tail(&rp->qe, &mod->rp_free_q);
+
+		bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
+	}
+
+	/**
+	 * consume memory
+	 */
+	bfa_meminfo_kva(meminfo) = (u8 *) rp;
+}
+
+static void
+bfa_rport_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_rport_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
+	struct bfa_rport_s *rport;
+	struct list_head *qe, *qen;
+
+	list_for_each_safe(qe, qen, &mod->rp_active_q) {
+		rport = (struct bfa_rport_s *) qe;
+		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
+	}
+}
+
+static struct bfa_rport_s *
+bfa_rport_alloc(struct bfa_rport_mod_s *mod)
+{
+	struct bfa_rport_s *rport;
+
+	bfa_q_deq(&mod->rp_free_q, &rport);
+	if (rport)
+		list_add_tail(&rport->qe, &mod->rp_active_q);
+
+	return rport;
+}
+
+static void
+bfa_rport_free(struct bfa_rport_s *rport)
+{
+	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
+
+	bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport));
+	list_del(&rport->qe);
+	list_add_tail(&rport->qe, &mod->rp_free_q);
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
+{
+	struct bfi_rport_create_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+	if (!m) {
+		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
+			bfa_lpuid(rp->bfa));
+	m->bfa_handle = rp->rport_tag;
+	m->max_frmsz = bfa_os_htons(rp->rport_info.max_frmsz);
+	m->pid = rp->rport_info.pid;
+	m->lp_tag = rp->rport_info.lp_tag;
+	m->local_pid = rp->rport_info.local_pid;
+	m->fc_class = rp->rport_info.fc_class;
+	m->vf_en = rp->rport_info.vf_en;
+	m->vf_id = rp->rport_info.vf_id;
+	m->cisc = rp->rport_info.cisc;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+	return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
+{
+	struct bfi_rport_delete_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+	if (!m) {
+		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
+			bfa_lpuid(rp->bfa));
+	m->fw_handle = rp->fw_handle;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+	return BFA_TRUE;
+}
+
+static bfa_boolean_t
+bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
+{
+	struct bfa_rport_speed_req_s *m;
+
+	/**
+	 * check for room in queue to send request now
+	 */
+	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
+	if (!m) {
+		bfa_trc(rp->bfa, rp->rport_info.speed);
+		return BFA_FALSE;
+	}
+
+	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
+			bfa_lpuid(rp->bfa));
+	m->fw_handle = rp->fw_handle;
+	m->speed = (u8)rp->rport_info.speed;
+
+	/**
+	 * queue I/O message to firmware
+	 */
+	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT);
+	return BFA_TRUE;
+}
+
+
+
+/**
+ *  bfa_rport_public
+ */
+
+/**
+ * Rport interrupt processing.
+ */
+void
+bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
+{
+	union bfi_rport_i2h_msg_u msg;
+	struct bfa_rport_s *rp;
+
+	bfa_trc(bfa, m->mhdr.msg_id);
+
+	msg.msg = m;
+
+	switch (m->mhdr.msg_id) {
+	case BFI_RPORT_I2H_CREATE_RSP:
+		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
+		rp->fw_handle = msg.create_rsp->fw_handle;
+		rp->qos_attr = msg.create_rsp->qos_attr;
+		bfa_assert(msg.create_rsp->status == BFA_STATUS_OK);
+		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
+		break;
+
+	case BFI_RPORT_I2H_DELETE_RSP:
+		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
+		bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK);
+		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
+		break;
+
+	case BFI_RPORT_I2H_QOS_SCN:
+		rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
+		rp->event_arg.fw_msg = msg.qos_scn_evt;
+		bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
+		break;
+
+	default:
+		bfa_trc(bfa, m->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+
+
+/**
+ *  bfa_rport_api
+ */
+
+struct bfa_rport_s *
+bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
+{
+	struct bfa_rport_s *rp;
+
+	rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
+
+	if (rp == NULL)
+		return NULL;
+
+	rp->bfa = bfa;
+	rp->rport_drv = rport_drv;
+	bfa_rport_clear_stats(rp);
+
+	bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
+	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
+
+	return rp;
+}
+
+void
+bfa_rport_delete(struct bfa_rport_s *rport)
+{
+	bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE);
+}
+
+void
+bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
+{
+	bfa_assert(rport_info->max_frmsz != 0);
+
+	/**
+	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI
+	 * responses. Default to minimum size.
+	 */
+	if (rport_info->max_frmsz == 0) {
+		bfa_trc(rport->bfa, rport->rport_tag);
+		rport_info->max_frmsz = FC_MIN_PDUSZ;
+	}
+
+	bfa_os_assign(rport->rport_info, *rport_info);
+	bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
+}
+
+void
+bfa_rport_offline(struct bfa_rport_s *rport)
+{
+	bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE);
+}
+
+void
+bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
+{
+	bfa_assert(speed != 0);
+	bfa_assert(speed != BFA_PORT_SPEED_AUTO);
+
+	rport->rport_info.speed = speed;
+	bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
+}
+
+void
+bfa_rport_get_stats(struct bfa_rport_s *rport,
+	struct bfa_rport_hal_stats_s *stats)
+{
+	*stats = rport->stats;
+}
+
+void
+bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
+					struct bfa_rport_qos_attr_s *qos_attr)
+{
+	qos_attr->qos_priority  = rport->qos_attr.qos_priority;
+	qos_attr->qos_flow_id  = bfa_os_ntohl(rport->qos_attr.qos_flow_id);
+
+}
+
+void
+bfa_rport_clear_stats(struct bfa_rport_s *rport)
+{
+	bfa_os_memset(&rport->stats, 0, sizeof(rport->stats));
+}
+
+
+/**
+ * SGPG related functions
+ */
+
+/**
+ * Compute and return memory needed by FCP(im) module.
+ */
+static void
+bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len,
+		u32 *dm_len)
+{
+	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
+		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
+
+	*km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s);
+	*dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s);
+}
+
+
+static void
+bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		    struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+	int i;
+	struct bfa_sgpg_s *hsgpg;
+	struct bfi_sgpg_s *sgpg;
+	u64 align_len;
+
+	union {
+		u64 pa;
+		union bfi_addr_u addr;
+	} sgpg_pa, sgpg_pa_tmp;
+
+	INIT_LIST_HEAD(&mod->sgpg_q);
+	INIT_LIST_HEAD(&mod->sgpg_wait_q);
+
+	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
+
+	mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
+	mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo);
+	align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa);
+	mod->sgpg_arr_pa += align_len;
+	mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) +
+						align_len);
+	mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) +
+						align_len);
+
+	hsgpg = mod->hsgpg_arr;
+	sgpg = mod->sgpg_arr;
+	sgpg_pa.pa = mod->sgpg_arr_pa;
+	mod->free_sgpgs = mod->num_sgpgs;
+
+	bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1)));
+
+	for (i = 0; i < mod->num_sgpgs; i++) {
+		bfa_os_memset(hsgpg, 0, sizeof(*hsgpg));
+		bfa_os_memset(sgpg, 0, sizeof(*sgpg));
+
+		hsgpg->sgpg = sgpg;
+		sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
+		hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
+		list_add_tail(&hsgpg->qe, &mod->sgpg_q);
+
+		hsgpg++;
+		sgpg++;
+		sgpg_pa.pa += sizeof(struct bfi_sgpg_s);
+	}
+
+	bfa_meminfo_kva(minfo) = (u8 *) hsgpg;
+	bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg;
+	bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa;
+}
+
+static void
+bfa_sgpg_detach(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_start(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_sgpg_iocdisable(struct bfa_s *bfa)
+{
+}
+
+
+
+/**
+ *  hal_sgpg_public BFA SGPG public functions
+ */
+
+bfa_status_t
+bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+	struct bfa_sgpg_s *hsgpg;
+	int i;
+
+	bfa_trc_fp(bfa, nsgpgs);
+
+	if (mod->free_sgpgs < nsgpgs)
+		return BFA_STATUS_ENOMEM;
+
+	for (i = 0; i < nsgpgs; i++) {
+		bfa_q_deq(&mod->sgpg_q, &hsgpg);
+		bfa_assert(hsgpg);
+		list_add_tail(&hsgpg->qe, sgpg_q);
+	}
+
+	mod->free_sgpgs -= nsgpgs;
+	return BFA_STATUS_OK;
+}
+
+void
+bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+	struct bfa_sgpg_wqe_s *wqe;
+
+	bfa_trc_fp(bfa, nsgpg);
+
+	mod->free_sgpgs += nsgpg;
+	bfa_assert(mod->free_sgpgs <= mod->num_sgpgs);
+
+	list_splice_tail_init(sgpg_q, &mod->sgpg_q);
+
+	if (list_empty(&mod->sgpg_wait_q))
+		return;
+
+	/**
+	 * satisfy as many waiting requests as possible
+	 */
+	do {
+		wqe = bfa_q_first(&mod->sgpg_wait_q);
+		if (mod->free_sgpgs < wqe->nsgpg)
+			nsgpg = mod->free_sgpgs;
+		else
+			nsgpg = wqe->nsgpg;
+		bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
+		wqe->nsgpg -= nsgpg;
+		if (wqe->nsgpg == 0) {
+			list_del(&wqe->qe);
+			wqe->cbfn(wqe->cbarg);
+		}
+	} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
+}
+
+void
+bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+
+	bfa_assert(nsgpg > 0);
+	bfa_assert(nsgpg > mod->free_sgpgs);
+
+	wqe->nsgpg_total = wqe->nsgpg = nsgpg;
+
+	/**
+	 * allocate any left to this one first
+	 */
+	if (mod->free_sgpgs) {
+		/**
+		 * no one else is waiting for SGPG
+		 */
+		bfa_assert(list_empty(&mod->sgpg_wait_q));
+		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
+		wqe->nsgpg -= mod->free_sgpgs;
+		mod->free_sgpgs = 0;
+	}
+
+	list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
+}
+
+void
+bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
+{
+	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
+
+	bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
+	list_del(&wqe->qe);
+
+	if (wqe->nsgpg_total != wqe->nsgpg)
+		bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
+				   wqe->nsgpg_total - wqe->nsgpg);
+}
+
+void
+bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
+		   void *cbarg)
+{
+	INIT_LIST_HEAD(&wqe->sgpg_q);
+	wqe->cbfn = cbfn;
+	wqe->cbarg = cbarg;
+}
+
+/**
+ *  UF related functions
+ */
+/*
+ *****************************************************************************
+ * Internal functions
+ *****************************************************************************
+ */
+static void
+__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
+{
+	struct bfa_uf_s   *uf = cbarg;
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
+
+	if (complete)
+		ufm->ufrecv(ufm->cbarg, uf);
+}
+
+static void
+claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+	u32 uf_pb_tot_sz;
+
+	ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
+	ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
+	uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
+							BFA_DMA_ALIGN_SZ);
+
+	bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
+	bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
+
+	bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
+}
+
+static void
+claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+	struct bfi_uf_buf_post_s *uf_bp_msg;
+	struct bfi_sge_s      *sge;
+	union bfi_addr_u      sga_zero = { {0} };
+	u16 i;
+	u16 buf_len;
+
+	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
+	uf_bp_msg = ufm->uf_buf_posts;
+
+	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
+	     i++, uf_bp_msg++) {
+		bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
+
+		uf_bp_msg->buf_tag = i;
+		buf_len = sizeof(struct bfa_uf_buf_s);
+		uf_bp_msg->buf_len = bfa_os_htons(buf_len);
+		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
+			    bfa_lpuid(ufm->bfa));
+
+		sge = uf_bp_msg->sge;
+		sge[0].sg_len = buf_len;
+		sge[0].flags = BFI_SGE_DATA_LAST;
+		bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
+		bfa_sge_to_be(sge);
+
+		sge[1].sg_len = buf_len;
+		sge[1].flags = BFI_SGE_PGDLEN;
+		sge[1].sga = sga_zero;
+		bfa_sge_to_be(&sge[1]);
+	}
+
+	/**
+	 * advance pointer beyond consumed memory
+	 */
+	bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
+}
+
+static void
+claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+	u16 i;
+	struct bfa_uf_s   *uf;
+
+	/*
+	 * Claim block of memory for UF list
+	 */
+	ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
+
+	/*
+	 * Initialize UFs and queue it in UF free queue
+	 */
+	for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
+		bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s));
+		uf->bfa = ufm->bfa;
+		uf->uf_tag = i;
+		uf->pb_len = sizeof(struct bfa_uf_buf_s);
+		uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
+		uf->buf_pa = ufm_pbs_pa(ufm, i);
+		list_add_tail(&uf->qe, &ufm->uf_free_q);
+	}
+
+	/**
+	 * advance memory pointer
+	 */
+	bfa_meminfo_kva(mi) = (u8 *) uf;
+}
+
+static void
+uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
+{
+	claim_uf_pbs(ufm, mi);
+	claim_ufs(ufm, mi);
+	claim_uf_post_msgs(ufm, mi);
+}
+
+static void
+bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
+{
+	u32 num_ufs = cfg->fwcfg.num_uf_bufs;
+
+	/*
+	 * dma-able memory for UF posted bufs
+	 */
+	*dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
+							BFA_DMA_ALIGN_SZ);
+
+	/*
+	 * kernel Virtual memory for UFs and UF buf post msg copies
+	 */
+	*ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
+	*ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
+}
+
+static void
+bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
+		  struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
+{
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+
+	bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
+	ufm->bfa = bfa;
+	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
+	INIT_LIST_HEAD(&ufm->uf_free_q);
+	INIT_LIST_HEAD(&ufm->uf_posted_q);
+
+	uf_mem_claim(ufm, meminfo);
+}
+
+static void
+bfa_uf_detach(struct bfa_s *bfa)
+{
+}
+
+static struct bfa_uf_s *
+bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
+{
+	struct bfa_uf_s   *uf;
+
+	bfa_q_deq(&uf_mod->uf_free_q, &uf);
+	return uf;
+}
+
+static void
+bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
+{
+	list_add_tail(&uf->qe, &uf_mod->uf_free_q);
+}
+
+static bfa_status_t
+bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
+{
+	struct bfi_uf_buf_post_s *uf_post_msg;
+
+	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
+	if (!uf_post_msg)
+		return BFA_STATUS_FAILED;
+
+	bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
+		      sizeof(struct bfi_uf_buf_post_s));
+	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
+
+	bfa_trc(ufm->bfa, uf->uf_tag);
+
+	list_add_tail(&uf->qe, &ufm->uf_posted_q);
+	return BFA_STATUS_OK;
+}
+
+static void
+bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
+{
+	struct bfa_uf_s   *uf;
+
+	while ((uf = bfa_uf_get(uf_mod)) != NULL) {
+		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
+			break;
+	}
+}
+
+static void
+uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
+{
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+	u16 uf_tag = m->buf_tag;
+	struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
+	struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
+	u8 *buf = &uf_buf->d[0];
+	struct fchs_s *fchs;
+
+	m->frm_len = bfa_os_ntohs(m->frm_len);
+	m->xfr_len = bfa_os_ntohs(m->xfr_len);
+
+	fchs = (struct fchs_s *)uf_buf;
+
+	list_del(&uf->qe);	/* dequeue from posted queue */
+
+	uf->data_ptr = buf;
+	uf->data_len = m->xfr_len;
+
+	bfa_assert(uf->data_len >= sizeof(struct fchs_s));
+
+	if (uf->data_len == sizeof(struct fchs_s)) {
+		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
+			       uf->data_len, (struct fchs_s *)buf);
+	} else {
+		u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
+		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
+				      BFA_PL_EID_RX, uf->data_len,
+				      (struct fchs_s *)buf, pld_w0);
+	}
+
+	if (bfa->fcs)
+		__bfa_cb_uf_recv(uf, BFA_TRUE);
+	else
+		bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
+}
+
+static void
+bfa_uf_stop(struct bfa_s *bfa)
+{
+}
+
+static void
+bfa_uf_iocdisable(struct bfa_s *bfa)
+{
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+	struct bfa_uf_s *uf;
+	struct list_head *qe, *qen;
+
+	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
+		uf = (struct bfa_uf_s *) qe;
+		list_del(&uf->qe);
+		bfa_uf_put(ufm, uf);
+	}
+}
+
+static void
+bfa_uf_start(struct bfa_s *bfa)
+{
+	bfa_uf_post_all(BFA_UF_MOD(bfa));
+}
+
+
+
+/**
+ *  hal_uf_api
+ */
+
+/**
+ * Register handler for all unsolicted recieve frames.
+ *
+ * @param[in]	bfa		BFA instance
+ * @param[in]	ufrecv	receive handler function
+ * @param[in]	cbarg	receive handler arg
+ */
+void
+bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
+{
+	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
+
+	ufm->ufrecv = ufrecv;
+	ufm->cbarg = cbarg;
+}
+
+/**
+ *	Free an unsolicited frame back to BFA.
+ *
+ * @param[in]		uf		unsolicited frame to be freed
+ *
+ * @return None
+ */
+void
+bfa_uf_free(struct bfa_uf_s *uf)
+{
+	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
+	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
+}
+
+
+
+/**
+ *  uf_pub BFA uf module public functions
+ */
+void
+bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
+{
+	bfa_trc(bfa, msg->mhdr.msg_id);
+
+	switch (msg->mhdr.msg_id) {
+	case BFI_UF_I2H_FRM_RCVD:
+		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
+		break;
+
+	default:
+		bfa_trc(bfa, msg->mhdr.msg_id);
+		bfa_assert(0);
+	}
+}
+
+
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
new file mode 100644
index 0000000..9921dad
--- /dev/null
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -0,0 +1,657 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFA_SVC_H__
+#define __BFA_SVC_H__
+
+#include "bfa_cs.h"
+#include "bfi_ms.h"
+
+
+/**
+ * Scatter-gather DMA related defines
+ */
+#define BFA_SGPG_MIN	(16)
+
+/**
+ * Alignment macro for SG page allocation
+ */
+#define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1))	\
+			      & ~(sizeof(struct bfi_sgpg_s) - 1))
+
+struct bfa_sgpg_wqe_s {
+	struct list_head qe;	/*  queue sg page element	*/
+	int	nsgpg;		/*  pages to be allocated	*/
+	int	nsgpg_total;	/*  total pages required	*/
+	void	(*cbfn) (void *cbarg);	/*  callback function	*/
+	void	*cbarg;		/*  callback arg		*/
+	struct list_head sgpg_q;	/*  queue of alloced sgpgs	*/
+};
+
+struct bfa_sgpg_s {
+	struct list_head  qe;	/*  queue sg page element	*/
+	struct bfi_sgpg_s *sgpg;	/*  va of SG page		*/
+	union bfi_addr_u sgpg_pa;	/*  pa of SG page		*/
+};
+
+/**
+ * Given number of SG elements, BFA_SGPG_NPAGE() returns the number of
+ * SG pages required.
+ */
+#define BFA_SGPG_NPAGE(_nsges)  (((_nsges) / BFI_SGPG_DATA_SGES) + 1)
+
+struct bfa_sgpg_mod_s {
+	struct bfa_s *bfa;
+	int		num_sgpgs;	/*  number of SG pages		*/
+	int		free_sgpgs;	/*  number of free SG pages	*/
+	struct bfa_sgpg_s	*hsgpg_arr;	/*  BFA SG page array	*/
+	struct bfi_sgpg_s *sgpg_arr;	/*  actual SG page array	*/
+	u64	sgpg_arr_pa;	/*  SG page array DMA addr	*/
+	struct list_head	sgpg_q;		/*  queue of free SG pages */
+	struct list_head	sgpg_wait_q;	/*  wait queue for SG pages */
+};
+#define BFA_SGPG_MOD(__bfa)	(&(__bfa)->modules.sgpg_mod)
+
+bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q,
+			     int nsgpgs);
+void bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs);
+void bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe,
+		    void (*cbfn) (void *cbarg), void *cbarg);
+void bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpgs);
+void bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe);
+
+
+/**
+ * FCXP related defines
+ */
+#define BFA_FCXP_MIN		(1)
+#define BFA_FCXP_MAX_IBUF_SZ	(2 * 1024 + 256)
+#define BFA_FCXP_MAX_LBUF_SZ	(4 * 1024 + 256)
+
+struct bfa_fcxp_mod_s {
+	struct bfa_s      *bfa;		/* backpointer to BFA */
+	struct bfa_fcxp_s *fcxp_list;	/* array of FCXPs */
+	u16	num_fcxps;	/* max num FCXP requests */
+	struct list_head  fcxp_free_q;	/* free FCXPs */
+	struct list_head  fcxp_active_q;	/* active FCXPs */
+	void		*req_pld_list_kva;	/* list of FCXP req pld */
+	u64	req_pld_list_pa;	/* list of FCXP req pld */
+	void		*rsp_pld_list_kva;	/* list of FCXP resp pld */
+	u64	rsp_pld_list_pa;	/* list of FCXP resp pld */
+	struct list_head  wait_q;		/* wait queue for free fcxp */
+	u32	req_pld_sz;
+	u32	rsp_pld_sz;
+};
+
+#define BFA_FCXP_MOD(__bfa)		(&(__bfa)->modules.fcxp_mod)
+#define BFA_FCXP_FROM_TAG(__mod, __tag)	(&(__mod)->fcxp_list[__tag])
+
+typedef void    (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp,
+				   void *cb_arg, bfa_status_t req_status,
+				   u32 rsp_len, u32 resid_len,
+				   struct fchs_s *rsp_fchs);
+
+typedef u64 (*bfa_fcxp_get_sgaddr_t) (void *bfad_fcxp, int sgeid);
+typedef u32 (*bfa_fcxp_get_sglen_t) (void *bfad_fcxp, int sgeid);
+typedef void (*bfa_cb_fcxp_send_t) (void *bfad_fcxp, struct bfa_fcxp_s *fcxp,
+				    void *cbarg, enum bfa_status req_status,
+				    u32 rsp_len, u32 resid_len,
+				    struct fchs_s *rsp_fchs);
+typedef void (*bfa_fcxp_alloc_cbfn_t) (void *cbarg, struct bfa_fcxp_s *fcxp);
+
+
+
+/**
+ * Information needed for a FCXP request
+ */
+struct bfa_fcxp_req_info_s {
+	struct bfa_rport_s *bfa_rport;
+					/** Pointer to the bfa rport that was
+					 * returned from bfa_rport_create().
+					 * This could be left NULL for WKA or
+					 * for FCXP interactions before the
+					 * rport nexus is established
+					 */
+	struct fchs_s	fchs;	/*  request FC header structure */
+	u8		cts;	/*  continous sequence */
+	u8		class;	/*  FC class for the request/response */
+	u16	max_frmsz;	/*  max send frame size */
+	u16	vf_id;	/*  vsan tag if applicable */
+	u8		lp_tag;	/*  lport tag */
+	u32	req_tot_len;	/*  request payload total length */
+};
+
+struct bfa_fcxp_rsp_info_s {
+	struct fchs_s	rsp_fchs;
+				/** !< Response frame's FC header will
+				 * be sent back in this field */
+	u8		rsp_timeout;
+				/** !< timeout in seconds, 0-no response
+				 */
+	u8		rsvd2[3];
+	u32	rsp_maxlen;	/*  max response length expected */
+};
+
+struct bfa_fcxp_s {
+	struct list_head	qe;		/*  fcxp queue element */
+	bfa_sm_t	sm;		/*  state machine */
+	void		*caller;	/*  driver or fcs */
+	struct bfa_fcxp_mod_s *fcxp_mod;
+	/*  back pointer to fcxp mod */
+	u16	fcxp_tag;	/*  internal tag */
+	struct bfa_fcxp_req_info_s req_info;
+	/*  request info */
+	struct bfa_fcxp_rsp_info_s rsp_info;
+	/*  response info */
+	u8	use_ireqbuf;	/*  use internal req buf */
+	u8		use_irspbuf;	/*  use internal rsp buf */
+	u32	nreq_sgles;	/*  num request SGLEs */
+	u32	nrsp_sgles;	/*  num response SGLEs */
+	struct list_head req_sgpg_q;	/*  SG pages for request buf */
+	struct list_head req_sgpg_wqe;	/*  wait queue for req SG page */
+	struct list_head rsp_sgpg_q;	/*  SG pages for response buf */
+	struct list_head rsp_sgpg_wqe;	/*  wait queue for rsp SG page */
+
+	bfa_fcxp_get_sgaddr_t req_sga_cbfn;
+	/*  SG elem addr user function */
+	bfa_fcxp_get_sglen_t req_sglen_cbfn;
+	/*  SG elem len user function */
+	bfa_fcxp_get_sgaddr_t rsp_sga_cbfn;
+	/*  SG elem addr user function */
+	bfa_fcxp_get_sglen_t rsp_sglen_cbfn;
+	/*  SG elem len user function */
+	bfa_cb_fcxp_send_t send_cbfn;   /*  send completion callback */
+	void		*send_cbarg;	/*  callback arg */
+	struct bfa_sge_s   req_sge[BFA_FCXP_MAX_SGES];
+	/*  req SG elems */
+	struct bfa_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];
+	/*  rsp SG elems */
+	u8		rsp_status;	/*  comp: rsp status */
+	u32	rsp_len;	/*  comp: actual response len */
+	u32	residue_len;	/*  comp: residual rsp length */
+	struct fchs_s	rsp_fchs;	/*  comp: response fchs */
+	struct bfa_cb_qe_s    hcb_qe;	/*  comp: callback qelem */
+	struct bfa_reqq_wait_s	reqq_wqe;
+	bfa_boolean_t	reqq_waiting;
+};
+
+struct bfa_fcxp_wqe_s {
+	struct list_head		qe;
+	bfa_fcxp_alloc_cbfn_t	alloc_cbfn;
+	void		*alloc_cbarg;
+	void		*caller;
+	struct bfa_s	*bfa;
+	int		nreq_sgles;
+	int		nrsp_sgles;
+	bfa_fcxp_get_sgaddr_t	req_sga_cbfn;
+	bfa_fcxp_get_sglen_t	req_sglen_cbfn;
+	bfa_fcxp_get_sgaddr_t	rsp_sga_cbfn;
+	bfa_fcxp_get_sglen_t	rsp_sglen_cbfn;
+};
+
+#define BFA_FCXP_REQ_PLD(_fcxp)		(bfa_fcxp_get_reqbuf(_fcxp))
+#define BFA_FCXP_RSP_FCHS(_fcxp)	(&((_fcxp)->rsp_info.fchs))
+#define BFA_FCXP_RSP_PLD(_fcxp)		(bfa_fcxp_get_rspbuf(_fcxp))
+
+#define BFA_FCXP_REQ_PLD_PA(_fcxp)				\
+	((_fcxp)->fcxp_mod->req_pld_list_pa +			\
+	 ((_fcxp)->fcxp_mod->req_pld_sz  * (_fcxp)->fcxp_tag))
+
+#define BFA_FCXP_RSP_PLD_PA(_fcxp)				\
+	((_fcxp)->fcxp_mod->rsp_pld_list_pa +			\
+	 ((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag))
+
+void	bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+
+/**
+ * RPORT related defines
+ */
+#define BFA_RPORT_MIN	4
+
+struct bfa_rport_mod_s {
+	struct bfa_rport_s *rps_list;	/*  list of rports	*/
+	struct list_head	rp_free_q;	/*  free bfa_rports	*/
+	struct list_head	rp_active_q;	/*  free bfa_rports	*/
+	u16	num_rports;	/*  number of rports	*/
+};
+
+#define BFA_RPORT_MOD(__bfa)	(&(__bfa)->modules.rport_mod)
+
+/**
+ * Convert rport tag to RPORT
+ */
+#define BFA_RPORT_FROM_TAG(__bfa, _tag)				\
+	(BFA_RPORT_MOD(__bfa)->rps_list +			\
+	 ((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1)))
+
+/*
+ * protected functions
+ */
+void	bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+/**
+ *	BFA rport information.
+ */
+struct bfa_rport_info_s {
+	u16	max_frmsz;	/*  max rcv pdu size		    */
+	u32	pid:24,	/*  remote port ID		    */
+		lp_tag:8;	/*  tag			    */
+	u32	local_pid:24,	/*  local port ID		    */
+		cisc:8;	/*  CIRO supported		    */
+	u8	fc_class;	/*  supported FC classes. enum fc_cos */
+	u8	vf_en;		/*  virtual fabric enable	    */
+	u16	vf_id;		/*  virtual fabric ID		    */
+	enum bfa_port_speed speed;	/*  Rport's current speed	    */
+};
+
+/**
+ * BFA rport data structure
+ */
+struct bfa_rport_s {
+	struct list_head	qe;	/*  queue element		    */
+	bfa_sm_t	sm;		/*  state machine		    */
+	struct bfa_s	*bfa;		/*  backpointer to BFA		    */
+	void		*rport_drv;	/*  fcs/driver rport object	    */
+	u16	fw_handle;	/*  firmware rport handle	    */
+	u16	rport_tag;	/*  BFA rport tag		    */
+	struct bfa_rport_info_s rport_info; /*  rport info from fcs/driver */
+	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq     */
+	struct bfa_cb_qe_s hcb_qe;	/*  BFA callback qelem		    */
+	struct bfa_rport_hal_stats_s stats; /*  BFA rport statistics	    */
+	struct bfa_rport_qos_attr_s qos_attr;
+	union a {
+		bfa_status_t	status;	/*  f/w status */
+		void		*fw_msg; /*  QoS scn event		    */
+	} event_arg;
+};
+#define BFA_RPORT_FC_COS(_rport)	((_rport)->rport_info.fc_class)
+
+
+/**
+ * UF - unsolicited receive related defines
+ */
+
+#define BFA_UF_MIN	(4)
+
+
+struct bfa_uf_s {
+	struct list_head	qe;	/*  queue element		*/
+	struct bfa_s		*bfa;	/*  bfa instance		*/
+	u16	uf_tag;		/*  identifying tag fw msgs	*/
+	u16	vf_id;
+	u16	src_rport_handle;
+	u16	rsvd;
+	u8		*data_ptr;
+	u16	data_len;	/*  actual receive length	*/
+	u16	pb_len;		/*  posted buffer length	*/
+	void		*buf_kva;	/*  buffer virtual address	*/
+	u64	buf_pa;		/*  buffer physical address	*/
+	struct bfa_cb_qe_s hcb_qe;	/*  comp: BFA comp qelem	*/
+	struct bfa_sge_s sges[BFI_SGE_INLINE_MAX];
+};
+
+/**
+ *      Callback prototype for unsolicited frame receive handler.
+ *
+ * @param[in]           cbarg           callback arg for receive handler
+ * @param[in]           uf              unsolicited frame descriptor
+ *
+ * @return None
+ */
+typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf);
+
+struct bfa_uf_mod_s {
+	struct bfa_s *bfa;		/*  back pointer to BFA */
+	struct bfa_uf_s *uf_list;	/*  array of UFs */
+	u16	num_ufs;	/*  num unsolicited rx frames */
+	struct list_head	uf_free_q;	/*  free UFs */
+	struct list_head	uf_posted_q;	/*  UFs posted to IOC */
+	struct bfa_uf_buf_s *uf_pbs_kva;	/*  list UF bufs request pld */
+	u64	uf_pbs_pa;	/*  phy addr for UF bufs */
+	struct bfi_uf_buf_post_s *uf_buf_posts;
+	/*  pre-built UF post msgs */
+	bfa_cb_uf_recv_t ufrecv;	/*  uf recv handler function */
+	void		*cbarg;		/*  uf receive handler arg */
+};
+
+#define BFA_UF_MOD(__bfa)	(&(__bfa)->modules.uf_mod)
+
+#define ufm_pbs_pa(_ufmod, _uftag)					\
+	((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
+
+void	bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+#define BFA_UF_BUFSZ	(2 * 1024 + 256)
+
+/**
+ * @todo private
+ */
+struct bfa_uf_buf_s {
+	u8		d[BFA_UF_BUFSZ];
+};
+
+
+/**
+ * LPS - bfa lport login/logout service interface
+ */
+struct bfa_lps_s {
+	struct list_head	qe;	/*  queue element		*/
+	struct bfa_s	*bfa;		/*  parent bfa instance	*/
+	bfa_sm_t	sm;		/*  finite state machine	*/
+	u8		lp_tag;		/*  lport tag			*/
+	u8		reqq;		/*  lport request queue	*/
+	u8		alpa;		/*  ALPA for loop topologies	*/
+	u32	lp_pid;		/*  lport port ID		*/
+	bfa_boolean_t	fdisc;		/*  snd FDISC instead of FLOGI	*/
+	bfa_boolean_t	auth_en;	/*  enable authentication	*/
+	bfa_boolean_t	auth_req;	/*  authentication required	*/
+	bfa_boolean_t	npiv_en;	/*  NPIV is allowed by peer	*/
+	bfa_boolean_t	fport;		/*  attached peer is F_PORT	*/
+	bfa_boolean_t	brcd_switch;	/*  attached peer is brcd sw	*/
+	bfa_status_t	status;		/*  login status		*/
+	u16		pdusz;		/*  max receive PDU size	*/
+	u16		pr_bbcred;	/*  BB_CREDIT from peer		*/
+	u8		lsrjt_rsn;	/*  LSRJT reason		*/
+	u8		lsrjt_expl;	/*  LSRJT explanation		*/
+	wwn_t		pwwn;		/*  port wwn of lport		*/
+	wwn_t		nwwn;		/*  node wwn of lport		*/
+	wwn_t		pr_pwwn;	/*  port wwn of lport peer	*/
+	wwn_t		pr_nwwn;	/*  node wwn of lport peer	*/
+	mac_t		lp_mac;		/*  fpma/spma MAC for lport	*/
+	mac_t		fcf_mac;	/*  FCF MAC of lport		*/
+	struct bfa_reqq_wait_s	wqe;	/*  request wait queue element	*/
+	void		*uarg;		/*  user callback arg		*/
+	struct bfa_cb_qe_s hcb_qe;	/*  comp: callback qelem	*/
+	struct bfi_lps_login_rsp_s *loginrsp;
+	bfa_eproto_status_t ext_status;
+};
+
+struct bfa_lps_mod_s {
+	struct list_head		lps_free_q;
+	struct list_head		lps_active_q;
+	struct bfa_lps_s	*lps_arr;
+	int			num_lps;
+};
+
+#define BFA_LPS_MOD(__bfa)		(&(__bfa)->modules.lps_mod)
+#define BFA_LPS_FROM_TAG(__mod, __tag)	(&(__mod)->lps_arr[__tag])
+
+/*
+ * external functions
+ */
+void	bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+
+/**
+ * FCPORT related defines
+ */
+
+#define BFA_FCPORT(_bfa)	(&((_bfa)->modules.port))
+typedef void (*bfa_cb_port_t) (void *cbarg, enum bfa_status status);
+
+/**
+ * Link notification data structure
+ */
+struct bfa_fcport_ln_s {
+	struct bfa_fcport_s	*fcport;
+	bfa_sm_t		sm;
+	struct bfa_cb_qe_s	ln_qe;	/*  BFA callback queue elem for ln */
+	enum bfa_port_linkstate ln_event; /*  ln event for callback */
+};
+
+struct bfa_fcport_trunk_s {
+	struct bfa_trunk_attr_s	attr;
+};
+
+/**
+ * BFA FC port data structure
+ */
+struct bfa_fcport_s {
+	struct bfa_s		*bfa;	/*  parent BFA instance */
+	bfa_sm_t		sm;	/*  port state machine */
+	wwn_t			nwwn;	/*  node wwn of physical port */
+	wwn_t			pwwn;	/*  port wwn of physical oprt */
+	enum bfa_port_speed speed_sup;
+	/*  supported speeds */
+	enum bfa_port_speed speed;	/*  current speed */
+	enum bfa_port_topology topology;	/*  current topology */
+	u8			myalpa;	/*  my ALPA in LOOP topology */
+	u8			rsvd[3];
+	struct bfa_port_cfg_s	cfg;	/*  current port configuration */
+	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
+	struct bfa_qos_vc_attr_s qos_vc_attr;  /*  VC info from ELP */
+	struct bfa_reqq_wait_s	reqq_wait;
+	/*  to wait for room in reqq */
+	struct bfa_reqq_wait_s	svcreq_wait;
+	/*  to wait for room in reqq */
+	struct bfa_reqq_wait_s	stats_reqq_wait;
+	/*  to wait for room in reqq (stats) */
+	void			*event_cbarg;
+	void			(*event_cbfn) (void *cbarg,
+					       enum bfa_port_linkstate event);
+	union {
+		union bfi_fcport_i2h_msg_u i2hmsg;
+	} event_arg;
+	void			*bfad;	/*  BFA driver handle */
+	struct bfa_fcport_ln_s	ln; /*  Link Notification */
+	struct bfa_cb_qe_s	hcb_qe;	/*  BFA callback queue elem */
+	struct bfa_timer_s	timer;	/*  timer */
+	u32		msgtag;	/*  fimrware msg tag for reply */
+	u8			*stats_kva;
+	u64		stats_pa;
+	union bfa_fcport_stats_u *stats;
+	union bfa_fcport_stats_u *stats_ret; /*  driver stats location */
+	bfa_status_t		stats_status; /*  stats/statsclr status */
+	bfa_boolean_t		stats_busy; /*  outstanding stats/statsclr */
+	bfa_boolean_t		stats_qfull;
+	u32		stats_reset_time; /*  stats reset time stamp */
+	bfa_cb_port_t		stats_cbfn; /*  driver callback function */
+	void			*stats_cbarg; /* *!< user callback arg */
+	bfa_boolean_t		diag_busy; /*  diag busy status */
+	bfa_boolean_t		beacon; /*  port beacon status */
+	bfa_boolean_t		link_e2e_beacon; /*  link beacon status */
+	struct bfa_fcport_trunk_s trunk;
+	u16		fcoe_vlan;
+};
+
+#define BFA_FCPORT_MOD(__bfa)	(&(__bfa)->modules.fcport)
+
+/*
+ * protected functions
+ */
+void bfa_fcport_init(struct bfa_s *bfa);
+void bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
+
+/*
+ * bfa fcport API functions
+ */
+bfa_status_t bfa_fcport_enable(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_disable(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_speed(struct bfa_s *bfa,
+				  enum bfa_port_speed speed);
+enum bfa_port_speed bfa_fcport_get_speed(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,
+				     enum bfa_port_topology topo);
+enum bfa_port_topology bfa_fcport_get_topology(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
+bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
+u8 bfa_fcport_get_myalpa(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_clr_hardalpa(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxsize);
+u16 bfa_fcport_get_maxfrsize(struct bfa_s *bfa);
+u8 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa);
+void bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr);
+wwn_t bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node);
+void bfa_fcport_event_register(struct bfa_s *bfa,
+			void (*event_cbfn) (void *cbarg,
+			enum bfa_port_linkstate event), void *event_cbarg);
+bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
+void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off);
+void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off);
+bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa,
+					  enum bfa_port_speed speed);
+enum bfa_port_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
+
+void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
+void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status);
+void bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
+		       bfa_boolean_t link_e2e_beacon);
+void bfa_fcport_qos_get_attr(struct bfa_s *bfa,
+			     struct bfa_qos_attr_s *qos_attr);
+void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
+				struct bfa_qos_vc_attr_s *qos_vc_attr);
+bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa,
+				      union bfa_fcport_stats_u *stats,
+				      bfa_cb_port_t cbfn, void *cbarg);
+bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
+					void *cbarg);
+bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa,
+				       union bfa_fcport_stats_u *stats,
+				       bfa_cb_port_t cbfn, void *cbarg);
+bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
+					 void *cbarg);
+bfa_boolean_t     bfa_fcport_is_ratelim(struct bfa_s *bfa);
+bfa_boolean_t	bfa_fcport_is_linkup(struct bfa_s *bfa);
+bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
+				  union bfa_fcport_stats_u *stats,
+				  bfa_cb_port_t cbfn, void *cbarg);
+bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_port_t cbfn,
+				    void *cbarg);
+bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
+
+/*
+ * bfa rport API functions
+ */
+struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv);
+void bfa_rport_delete(struct bfa_rport_s *rport);
+void bfa_rport_online(struct bfa_rport_s *rport,
+		      struct bfa_rport_info_s *rport_info);
+void bfa_rport_offline(struct bfa_rport_s *rport);
+void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed);
+void bfa_rport_get_stats(struct bfa_rport_s *rport,
+			 struct bfa_rport_hal_stats_s *stats);
+void bfa_rport_clear_stats(struct bfa_rport_s *rport);
+void bfa_cb_rport_online(void *rport);
+void bfa_cb_rport_offline(void *rport);
+void bfa_cb_rport_qos_scn_flowid(void *rport,
+				 struct bfa_rport_qos_attr_s old_qos_attr,
+				 struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_cb_rport_qos_scn_prio(void *rport,
+			       struct bfa_rport_qos_attr_s old_qos_attr,
+			       struct bfa_rport_qos_attr_s new_qos_attr);
+void bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
+			    struct bfa_rport_qos_attr_s *qos_attr);
+
+/*
+ * bfa fcxp API functions
+ */
+struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
+				  int nreq_sgles, int nrsp_sgles,
+				  bfa_fcxp_get_sgaddr_t get_req_sga,
+				  bfa_fcxp_get_sglen_t get_req_sglen,
+				  bfa_fcxp_get_sgaddr_t get_rsp_sga,
+				  bfa_fcxp_get_sglen_t get_rsp_sglen);
+void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
+				bfa_fcxp_alloc_cbfn_t alloc_cbfn,
+				void *cbarg, void *bfad_fcxp,
+				int nreq_sgles, int nrsp_sgles,
+				bfa_fcxp_get_sgaddr_t get_req_sga,
+				bfa_fcxp_get_sglen_t get_req_sglen,
+				bfa_fcxp_get_sgaddr_t get_rsp_sga,
+				bfa_fcxp_get_sglen_t get_rsp_sglen);
+void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
+			    struct bfa_fcxp_wqe_s *wqe);
+void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
+
+void *bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp);
+void *bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp);
+
+void bfa_fcxp_free(struct bfa_fcxp_s *fcxp);
+
+void bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
+		   u16 vf_id, u8 lp_tag,
+		   bfa_boolean_t cts, enum fc_cos cos,
+		   u32 reqlen, struct fchs_s *fchs,
+		   bfa_cb_fcxp_send_t cbfn,
+		   void *cbarg,
+		   u32 rsp_maxlen, u8 rsp_timeout);
+bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);
+u32 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);
+u32 bfa_fcxp_get_maxrsp(struct bfa_s *bfa);
+
+static inline void *
+bfa_uf_get_frmbuf(struct bfa_uf_s *uf)
+{
+	return uf->data_ptr;
+}
+
+static inline   u16
+bfa_uf_get_frmlen(struct bfa_uf_s *uf)
+{
+	return uf->data_len;
+}
+
+/*
+ * bfa uf API functions
+ */
+void bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv,
+			  void *cbarg);
+void bfa_uf_free(struct bfa_uf_s *uf);
+
+/**
+ * bfa lport service api
+ */
+
+u32 bfa_lps_get_max_vport(struct bfa_s *bfa);
+struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
+void bfa_lps_delete(struct bfa_lps_s *lps);
+void bfa_lps_discard(struct bfa_lps_s *lps);
+void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa,
+		   u16 pdusz, wwn_t pwwn, wwn_t nwwn,
+		   bfa_boolean_t auth_en);
+void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz,
+		   wwn_t pwwn, wwn_t nwwn);
+void bfa_lps_flogo(struct bfa_lps_s *lps);
+void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
+u8 bfa_lps_get_tag(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps);
+bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps);
+bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps);
+u32 bfa_lps_get_pid(struct bfa_lps_s *lps);
+u32 bfa_lps_get_base_pid(struct bfa_s *bfa);
+u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
+u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps);
+wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps);
+wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps);
+u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps);
+u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps);
+mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps);
+void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
+void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
+void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
+void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
+
+void bfa_trunk_enable_cfg(struct bfa_s *bfa);
+bfa_status_t bfa_trunk_enable(struct bfa_s *bfa);
+bfa_status_t bfa_trunk_disable(struct bfa_s *bfa);
+bfa_status_t bfa_trunk_get_attr(struct bfa_s *bfa,
+		struct bfa_trunk_attr_s *attr);
+
+#endif /* __BFA_SVC_H__ */
diff --git a/drivers/scsi/bfa/bfa_timer.c b/drivers/scsi/bfa/bfa_timer.c
deleted file mode 100644
index cb76481..0000000
--- a/drivers/scsi/bfa/bfa_timer.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa_timer.h>
-#include <cs/bfa_debug.h>
-
-void
-bfa_timer_init(struct bfa_timer_mod_s *mod)
-{
-	INIT_LIST_HEAD(&mod->timer_q);
-}
-
-void
-bfa_timer_beat(struct bfa_timer_mod_s *mod)
-{
-	struct list_head        *qh = &mod->timer_q;
-	struct list_head        *qe, *qe_next;
-	struct bfa_timer_s *elem;
-	struct list_head         timedout_q;
-
-	INIT_LIST_HEAD(&timedout_q);
-
-	qe = bfa_q_next(qh);
-
-	while (qe != qh) {
-		qe_next = bfa_q_next(qe);
-
-		elem = (struct bfa_timer_s *) qe;
-		if (elem->timeout <= BFA_TIMER_FREQ) {
-			elem->timeout = 0;
-			list_del(&elem->qe);
-			list_add_tail(&elem->qe, &timedout_q);
-		} else {
-			elem->timeout -= BFA_TIMER_FREQ;
-		}
-
-		qe = qe_next;	/* go to next elem */
-	}
-
-	/*
-	 * Pop all the timeout entries
-	 */
-	while (!list_empty(&timedout_q)) {
-		bfa_q_deq(&timedout_q, &elem);
-		elem->timercb(elem->arg);
-	}
-}
-
-/**
- * Should be called with lock protection
- */
-void
-bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
-		    void (*timercb) (void *), void *arg, unsigned int timeout)
-{
-
-	bfa_assert(timercb != NULL);
-	bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
-
-	timer->timeout = timeout;
-	timer->timercb = timercb;
-	timer->arg = arg;
-
-	list_add_tail(&timer->qe, &mod->timer_q);
-}
-
-/**
- * Should be called with lock protection
- */
-void
-bfa_timer_stop(struct bfa_timer_s *timer)
-{
-	bfa_assert(!list_empty(&timer->qe));
-
-	list_del(&timer->qe);
-}
diff --git a/drivers/scsi/bfa/bfa_trcmod_priv.h b/drivers/scsi/bfa/bfa_trcmod_priv.h
deleted file mode 100644
index a7a8261..0000000
--- a/drivers/scsi/bfa/bfa_trcmod_priv.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  hal_trcmod.h BFA trace modules
- */
-
-#ifndef __BFA_TRCMOD_PRIV_H__
-#define __BFA_TRCMOD_PRIV_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
-	BFA_TRC_HAL_INTR	= 1,
-	BFA_TRC_HAL_FCXP	= 2,
-	BFA_TRC_HAL_UF		= 3,
-	BFA_TRC_HAL_RPORT	= 4,
-	BFA_TRC_HAL_FCPIM	= 5,
-	BFA_TRC_HAL_IOIM	= 6,
-	BFA_TRC_HAL_TSKIM	= 7,
-	BFA_TRC_HAL_ITNIM	= 8,
-	BFA_TRC_HAL_FCPORT	= 9,
-	BFA_TRC_HAL_SGPG	= 10,
-	BFA_TRC_HAL_FLASH	= 11,
-	BFA_TRC_HAL_DEBUG	= 12,
-	BFA_TRC_HAL_WWN		= 13,
-	BFA_TRC_HAL_FLASH_RAW	= 14,
-	BFA_TRC_HAL_SBOOT	= 15,
-	BFA_TRC_HAL_SBOOT_IO	= 16,
-	BFA_TRC_HAL_SBOOT_INTR	= 17,
-	BFA_TRC_HAL_SBTEST	= 18,
-	BFA_TRC_HAL_IPFC	= 19,
-	BFA_TRC_HAL_IOCFC	= 20,
-	BFA_TRC_HAL_FCPTM	= 21,
-	BFA_TRC_HAL_IOTM	= 22,
-	BFA_TRC_HAL_TSKTM	= 23,
-	BFA_TRC_HAL_TIN		= 24,
-	BFA_TRC_HAL_LPS		= 25,
-	BFA_TRC_HAL_FCDIAG	= 26,
-	BFA_TRC_HAL_PBIND	= 27,
-	BFA_TRC_HAL_IOCFC_CT	= 28,
-	BFA_TRC_HAL_IOCFC_CB	= 29,
-	BFA_TRC_HAL_IOCFC_Q	= 30,
-};
-
-#endif /* __BFA_TRCMOD_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfa_tskim.c b/drivers/scsi/bfa/bfa_tskim.c
deleted file mode 100644
index ad9aaae..0000000
--- a/drivers/scsi/bfa/bfa_tskim.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include <bfa_cb_ioim_macros.h>
-
-BFA_TRC_FILE(HAL, TSKIM);
-
-/**
- * task management completion handling
- */
-#define bfa_tskim_qcomp(__tskim, __cbfn) do {			\
-	bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe,	\
-			 __cbfn, (__tskim));      \
-	bfa_tskim_notify_comp(__tskim);      \
-} while (0)
-
-#define bfa_tskim_notify_comp(__tskim) do {			 \
-	if ((__tskim)->notify)					 \
-		bfa_itnim_tskdone((__tskim)->itnim);      \
-} while (0)
-
-/*
- * forward declarations
- */
-static void     __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete);
-static void     __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete);
-static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim,
-					       lun_t lun);
-static void     bfa_tskim_gather_ios(struct bfa_tskim_s *tskim);
-static void     bfa_tskim_cleanp_comp(void *tskim_cbarg);
-static void     bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim);
-static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim);
-static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim);
-static void     bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim);
-
-/**
- *  bfa_tskim_sm
- */
-
-enum bfa_tskim_event {
-	BFA_TSKIM_SM_START        = 1,  /*  TM command start            */
-	BFA_TSKIM_SM_DONE         = 2,  /*  TM completion               */
-	BFA_TSKIM_SM_QRESUME      = 3,  /*  resume after qfull          */
-	BFA_TSKIM_SM_HWFAIL       = 5,  /*  IOC h/w failure event       */
-	BFA_TSKIM_SM_HCB          = 6,  /*  BFA callback completion     */
-	BFA_TSKIM_SM_IOS_DONE     = 7,  /*  IO and sub TM completions   */
-	BFA_TSKIM_SM_CLEANUP      = 8,  /*  TM cleanup on ITN offline   */
-	BFA_TSKIM_SM_CLEANUP_DONE = 9,  /*  TM abort completion         */
-};
-
-static void     bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim,
-					enum bfa_tskim_event event);
-static void     bfa_tskim_sm_active(struct bfa_tskim_s *tskim,
-					enum bfa_tskim_event event);
-static void     bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim,
-					 enum bfa_tskim_event event);
-static void     bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim,
-					 enum bfa_tskim_event event);
-static void     bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim,
-				       enum bfa_tskim_event event);
-static void     bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
-				       enum bfa_tskim_event event);
-static void     bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim,
-				     enum bfa_tskim_event event);
-
-/**
- *      Task management command beginning state.
- */
-static void
-bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_START:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
-		bfa_tskim_gather_ios(tskim);
-
-		/**
-		 * If device is offline, do not send TM on wire. Just cleanup
-		 * any pending IO requests and complete TM request.
-		 */
-		if (!bfa_itnim_is_online(tskim->itnim)) {
-			bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
-			tskim->tsk_status = BFI_TSKIM_STS_OK;
-			bfa_tskim_cleanup_ios(tskim);
-			return;
-		}
-
-		if (!bfa_tskim_send(tskim)) {
-			bfa_sm_set_state(tskim, bfa_tskim_sm_qfull);
-			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
-					  &tskim->reqq_wait);
-		}
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- * brief
- *	TM command is active, awaiting completion from firmware to
- *	cleanup IO requests in TM scope.
- */
-static void
-bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_DONE:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
-		bfa_tskim_cleanup_ios(tskim);
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
-		if (!bfa_tskim_send_abort(tskim)) {
-			bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull);
-			bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq,
-				&tskim->reqq_wait);
-		}
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- *	An active TM is being cleaned up since ITN is offline. Awaiting cleanup
- *	completion event from firmware.
- */
-static void
-bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_DONE:
-		/**
-		 * Ignore and wait for ABORT completion from firmware.
-		 */
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP_DONE:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
-		bfa_tskim_cleanup_ios(tskim);
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-static void
-bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_IOS_DONE:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done);
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP:
-		/**
-		 * Ignore, TM command completed on wire.
-		 * Notify TM conmpletion on IO cleanup completion.
-		 */
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- *      Task management command is waiting for room in request CQ
- */
-static void
-bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_QRESUME:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_active);
-		bfa_tskim_send(tskim);
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP:
-		/**
-		 * No need to send TM on wire since ITN is offline.
-		 */
-		bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup);
-		bfa_reqq_wcancel(&tskim->reqq_wait);
-		bfa_tskim_cleanup_ios(tskim);
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_reqq_wcancel(&tskim->reqq_wait);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- *      Task management command is active, awaiting for room in request CQ
- *	to send clean up request.
- */
-static void
-bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim,
-		enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_DONE:
-		bfa_reqq_wcancel(&tskim->reqq_wait);
-		/**
-		 *
-		 * Fall through !!!
-		 */
-
-	case BFA_TSKIM_SM_QRESUME:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
-		bfa_tskim_send_abort(tskim);
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_hcb);
-		bfa_reqq_wcancel(&tskim->reqq_wait);
-		bfa_tskim_iocdisable_ios(tskim);
-		bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed);
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-/**
- *      BFA callback is pending
- */
-static void
-bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event)
-{
-	bfa_trc(tskim->bfa, event);
-
-	switch (event) {
-	case BFA_TSKIM_SM_HCB:
-		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
-		bfa_tskim_free(tskim);
-		break;
-
-	case BFA_TSKIM_SM_CLEANUP:
-		bfa_tskim_notify_comp(tskim);
-		break;
-
-	case BFA_TSKIM_SM_HWFAIL:
-		break;
-
-	default:
-		bfa_sm_fault(tskim->bfa, event);
-	}
-}
-
-
-
-/**
- *  bfa_tskim_private
- */
-
-static void
-__bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_tskim_s *tskim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
-		return;
-	}
-
-	bfa_stats(tskim->itnim, tm_success);
-	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status);
-}
-
-static void
-__bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_tskim_s *tskim = cbarg;
-
-	if (!complete) {
-		bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB);
-		return;
-	}
-
-	bfa_stats(tskim->itnim, tm_failures);
-	bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk,
-			   BFI_TSKIM_STS_FAILED);
-}
-
-static          bfa_boolean_t
-bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun)
-{
-	switch (tskim->tm_cmnd) {
-	case FCP_TM_TARGET_RESET:
-		return BFA_TRUE;
-
-	case FCP_TM_ABORT_TASK_SET:
-	case FCP_TM_CLEAR_TASK_SET:
-	case FCP_TM_LUN_RESET:
-	case FCP_TM_CLEAR_ACA:
-		return (tskim->lun == lun);
-
-	default:
-		bfa_assert(0);
-	}
-
-	return BFA_FALSE;
-}
-
-/**
- *      Gather affected IO requests and task management commands.
- */
-static void
-bfa_tskim_gather_ios(struct bfa_tskim_s *tskim)
-{
-	struct bfa_itnim_s *itnim = tskim->itnim;
-	struct bfa_ioim_s *ioim;
-	struct list_head        *qe, *qen;
-
-	INIT_LIST_HEAD(&tskim->io_q);
-
-	/**
-	 * Gather any active IO requests first.
-	 */
-	list_for_each_safe(qe, qen, &itnim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		if (bfa_tskim_match_scope
-		    (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
-			list_del(&ioim->qe);
-			list_add_tail(&ioim->qe, &tskim->io_q);
-		}
-	}
-
-	/**
-	 * Failback any pending IO requests immediately.
-	 */
-	list_for_each_safe(qe, qen, &itnim->pending_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		if (bfa_tskim_match_scope
-		    (tskim, bfa_cb_ioim_get_lun(ioim->dio))) {
-			list_del(&ioim->qe);
-			list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q);
-			bfa_ioim_tov(ioim);
-		}
-	}
-}
-
-/**
- * 		IO cleanup completion
- */
-static void
-bfa_tskim_cleanp_comp(void *tskim_cbarg)
-{
-	struct bfa_tskim_s *tskim = tskim_cbarg;
-
-	bfa_stats(tskim->itnim, tm_io_comps);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE);
-}
-
-/**
- *      Gather affected IO requests and task management commands.
- */
-static void
-bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim)
-{
-	struct bfa_ioim_s *ioim;
-	struct list_head        *qe, *qen;
-
-	bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim);
-
-	list_for_each_safe(qe, qen, &tskim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_wc_up(&tskim->wc);
-		bfa_ioim_cleanup_tm(ioim, tskim);
-	}
-
-	bfa_wc_wait(&tskim->wc);
-}
-
-/**
- *      Send task management request to firmware.
- */
-static bfa_boolean_t
-bfa_tskim_send(struct bfa_tskim_s *tskim)
-{
-	struct bfa_itnim_s *itnim = tskim->itnim;
-	struct bfi_tskim_req_s *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
-	if (!m)
-		return BFA_FALSE;
-
-	/**
-	 * build i/o request message next
-	 */
-	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ,
-			bfa_lpuid(tskim->bfa));
-
-	m->tsk_tag = bfa_os_htons(tskim->tsk_tag);
-	m->itn_fhdl = tskim->itnim->rport->fw_handle;
-	m->t_secs = tskim->tsecs;
-	m->lun = tskim->lun;
-	m->tm_flags = tskim->tm_cmnd;
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(tskim->bfa, itnim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- *      Send abort request to cleanup an active TM to firmware.
- */
-static bfa_boolean_t
-bfa_tskim_send_abort(struct bfa_tskim_s *tskim)
-{
-	struct bfa_itnim_s             *itnim = tskim->itnim;
-	struct bfi_tskim_abortreq_s    *m;
-
-	/**
-	 * check for room in queue to send request now
-	 */
-	m = bfa_reqq_next(tskim->bfa, itnim->reqq);
-	if (!m)
-		return BFA_FALSE;
-
-	/**
-	 * build i/o request message next
-	 */
-	bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ,
-			bfa_lpuid(tskim->bfa));
-
-	m->tsk_tag  = bfa_os_htons(tskim->tsk_tag);
-
-	/**
-	 * queue I/O message to firmware
-	 */
-	bfa_reqq_produce(tskim->bfa, itnim->reqq);
-	return BFA_TRUE;
-}
-
-/**
- *      Call to resume task management cmnd waiting for room in request queue.
- */
-static void
-bfa_tskim_qresume(void *cbarg)
-{
-	struct bfa_tskim_s *tskim = cbarg;
-
-	bfa_fcpim_stats(tskim->fcpim, qresumes);
-	bfa_stats(tskim->itnim, tm_qresumes);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME);
-}
-
-/**
- * Cleanup IOs associated with a task mangement command on IOC failures.
- */
-static void
-bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim)
-{
-	struct bfa_ioim_s *ioim;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &tskim->io_q) {
-		ioim = (struct bfa_ioim_s *) qe;
-		bfa_ioim_iocdisable(ioim);
-	}
-}
-
-
-
-/**
- *  bfa_tskim_friend
- */
-
-/**
- * Notification on completions from related ioim.
- */
-void
-bfa_tskim_iodone(struct bfa_tskim_s *tskim)
-{
-	bfa_wc_down(&tskim->wc);
-}
-
-/**
- * Handle IOC h/w failure notification from itnim.
- */
-void
-bfa_tskim_iocdisable(struct bfa_tskim_s *tskim)
-{
-	tskim->notify = BFA_FALSE;
-	bfa_stats(tskim->itnim, tm_iocdowns);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL);
-}
-
-/**
- * Cleanup TM command and associated IOs as part of ITNIM offline.
- */
-void
-bfa_tskim_cleanup(struct bfa_tskim_s *tskim)
-{
-	tskim->notify = BFA_TRUE;
-	bfa_stats(tskim->itnim, tm_cleanups);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP);
-}
-
-/**
- *      Memory allocation and initialization.
- */
-void
-bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo)
-{
-	struct bfa_tskim_s *tskim;
-	u16        i;
-
-	INIT_LIST_HEAD(&fcpim->tskim_free_q);
-
-	tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo);
-	fcpim->tskim_arr = tskim;
-
-	for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) {
-		/*
-		 * initialize TSKIM
-		 */
-		bfa_os_memset(tskim, 0, sizeof(struct bfa_tskim_s));
-		tskim->tsk_tag = i;
-		tskim->bfa     = fcpim->bfa;
-		tskim->fcpim   = fcpim;
-		tskim->notify  = BFA_FALSE;
-		bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume,
-				   tskim);
-		bfa_sm_set_state(tskim, bfa_tskim_sm_uninit);
-
-		list_add_tail(&tskim->qe, &fcpim->tskim_free_q);
-	}
-
-	bfa_meminfo_kva(minfo) = (u8 *) tskim;
-}
-
-void
-bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim)
-{
-    /**
-     * @todo
-     */
-}
-
-void
-bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m;
-	struct bfa_tskim_s *tskim;
-	u16        tsk_tag = bfa_os_ntohs(rsp->tsk_tag);
-
-	tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag);
-	bfa_assert(tskim->tsk_tag == tsk_tag);
-
-	tskim->tsk_status = rsp->tsk_status;
-
-	/**
-	 * Firmware sends BFI_TSKIM_STS_ABORTED status for abort
-	 * requests. All other statuses are for normal completions.
-	 */
-	if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) {
-		bfa_stats(tskim->itnim, tm_cleanup_comps);
-		bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE);
-	} else {
-		bfa_stats(tskim->itnim, tm_fw_rsps);
-		bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE);
-	}
-}
-
-
-
-/**
- *  bfa_tskim_api
- */
-
-
-struct bfa_tskim_s *
-bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk)
-{
-	struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa);
-	struct bfa_tskim_s *tskim;
-
-	bfa_q_deq(&fcpim->tskim_free_q, &tskim);
-
-	if (!tskim)
-		bfa_fcpim_stats(fcpim, no_tskims);
-	else
-		tskim->dtsk = dtsk;
-
-	return tskim;
-}
-
-void
-bfa_tskim_free(struct bfa_tskim_s *tskim)
-{
-	bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe));
-	list_del(&tskim->qe);
-	list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q);
-}
-
-/**
- *      Start a task management command.
- *
- * @param[in]       tskim       BFA task management command instance
- * @param[in]       itnim       i-t nexus for the task management command
- * @param[in]       lun         lun, if applicable
- * @param[in]       tm_cmnd     Task management command code.
- * @param[in]       t_secs      Timeout in seconds
- *
- * @return None.
- */
-void
-bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun,
-		    enum fcp_tm_cmnd tm_cmnd, u8 tsecs)
-{
-	tskim->itnim   = itnim;
-	tskim->lun     = lun;
-	tskim->tm_cmnd = tm_cmnd;
-	tskim->tsecs   = tsecs;
-	tskim->notify  = BFA_FALSE;
-	bfa_stats(itnim, tm_cmnds);
-
-	list_add_tail(&tskim->qe, &itnim->tsk_q);
-	bfa_sm_send_event(tskim, BFA_TSKIM_SM_START);
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_uf.c b/drivers/scsi/bfa/bfa_uf.c
deleted file mode 100644
index b9a9a68..0000000
--- a/drivers/scsi/bfa/bfa_uf.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_uf.c BFA unsolicited frame receive implementation
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_uf.h>
-#include <cs/bfa_debug.h>
-
-BFA_TRC_FILE(HAL, UF);
-BFA_MODULE(uf);
-
-/*
- *****************************************************************************
- * Internal functions
- *****************************************************************************
- */
-static void
-__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
-{
-	struct bfa_uf_s   *uf = cbarg;
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
-
-	if (complete)
-		ufm->ufrecv(ufm->cbarg, uf);
-}
-
-static void
-claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
-	u32        uf_pb_tot_sz;
-
-	ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi);
-	ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi);
-	uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs),
-							BFA_DMA_ALIGN_SZ);
-
-	bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz;
-	bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz;
-
-	bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz);
-}
-
-static void
-claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
-	struct bfi_uf_buf_post_s *uf_bp_msg;
-	struct bfi_sge_s      *sge;
-	union bfi_addr_u      sga_zero = { {0} };
-	u16        i;
-	u16        buf_len;
-
-	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi);
-	uf_bp_msg = ufm->uf_buf_posts;
-
-	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
-	     i++, uf_bp_msg++) {
-		bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
-
-		uf_bp_msg->buf_tag = i;
-		buf_len = sizeof(struct bfa_uf_buf_s);
-		uf_bp_msg->buf_len = bfa_os_htons(buf_len);
-		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
-			    bfa_lpuid(ufm->bfa));
-
-		sge = uf_bp_msg->sge;
-		sge[0].sg_len = buf_len;
-		sge[0].flags = BFI_SGE_DATA_LAST;
-		bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i));
-		bfa_sge_to_be(sge);
-
-		sge[1].sg_len = buf_len;
-		sge[1].flags = BFI_SGE_PGDLEN;
-		sge[1].sga = sga_zero;
-		bfa_sge_to_be(&sge[1]);
-	}
-
-	/**
-	 * advance pointer beyond consumed memory
-	 */
-	bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg;
-}
-
-static void
-claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
-	u16        i;
-	struct bfa_uf_s   *uf;
-
-	/*
-	 * Claim block of memory for UF list
-	 */
-	ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi);
-
-	/*
-	 * Initialize UFs and queue it in UF free queue
-	 */
-	for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
-		bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s));
-		uf->bfa = ufm->bfa;
-		uf->uf_tag = i;
-		uf->pb_len = sizeof(struct bfa_uf_buf_s);
-		uf->buf_kva = (void *)&ufm->uf_pbs_kva[i];
-		uf->buf_pa = ufm_pbs_pa(ufm, i);
-		list_add_tail(&uf->qe, &ufm->uf_free_q);
-	}
-
-	/**
-	 * advance memory pointer
-	 */
-	bfa_meminfo_kva(mi) = (u8 *) uf;
-}
-
-static void
-uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi)
-{
-	claim_uf_pbs(ufm, mi);
-	claim_ufs(ufm, mi);
-	claim_uf_post_msgs(ufm, mi);
-}
-
-static void
-bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len)
-{
-	u32        num_ufs = cfg->fwcfg.num_uf_bufs;
-
-	/*
-	 * dma-able memory for UF posted bufs
-	 */
-	*dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs),
-							BFA_DMA_ALIGN_SZ);
-
-	/*
-	 * kernel Virtual memory for UFs and UF buf post msg copies
-	 */
-	*ndm_len += sizeof(struct bfa_uf_s) * num_ufs;
-	*ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs;
-}
-
-static void
-bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-		  struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev)
-{
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-
-	bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s));
-	ufm->bfa = bfa;
-	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
-	INIT_LIST_HEAD(&ufm->uf_free_q);
-	INIT_LIST_HEAD(&ufm->uf_posted_q);
-
-	uf_mem_claim(ufm, meminfo);
-}
-
-static void
-bfa_uf_detach(struct bfa_s *bfa)
-{
-}
-
-static struct bfa_uf_s *
-bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
-{
-	struct bfa_uf_s   *uf;
-
-	bfa_q_deq(&uf_mod->uf_free_q, &uf);
-	return uf;
-}
-
-static void
-bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
-{
-	list_add_tail(&uf->qe, &uf_mod->uf_free_q);
-}
-
-static bfa_status_t
-bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
-{
-	struct bfi_uf_buf_post_s *uf_post_msg;
-
-	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
-	if (!uf_post_msg)
-		return BFA_STATUS_FAILED;
-
-	bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
-		      sizeof(struct bfi_uf_buf_post_s));
-	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP);
-
-	bfa_trc(ufm->bfa, uf->uf_tag);
-
-	list_add_tail(&uf->qe, &ufm->uf_posted_q);
-	return BFA_STATUS_OK;
-}
-
-static void
-bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
-{
-	struct bfa_uf_s   *uf;
-
-	while ((uf = bfa_uf_get(uf_mod)) != NULL) {
-		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
-			break;
-	}
-}
-
-static void
-uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
-{
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-	u16        uf_tag = m->buf_tag;
-	struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag];
-	struct bfa_uf_s   *uf = &ufm->uf_list[uf_tag];
-	u8        *buf = &uf_buf->d[0];
-	struct fchs_s         *fchs;
-
-	m->frm_len = bfa_os_ntohs(m->frm_len);
-	m->xfr_len = bfa_os_ntohs(m->xfr_len);
-
-	fchs = (struct fchs_s *) uf_buf;
-
-	list_del(&uf->qe);	/* dequeue from posted queue */
-
-	uf->data_ptr = buf;
-	uf->data_len = m->xfr_len;
-
-	bfa_assert(uf->data_len >= sizeof(struct fchs_s));
-
-	if (uf->data_len == sizeof(struct fchs_s)) {
-		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
-			       uf->data_len, (struct fchs_s *) buf);
-	} else {
-		u32        pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
-		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
-				      BFA_PL_EID_RX, uf->data_len,
-				      (struct fchs_s *) buf, pld_w0);
-	}
-
-	if (bfa->fcs)
-		__bfa_cb_uf_recv(uf, BFA_TRUE);
-	else
-		bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
-}
-
-static void
-bfa_uf_stop(struct bfa_s *bfa)
-{
-}
-
-static void
-bfa_uf_iocdisable(struct bfa_s *bfa)
-{
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-	struct bfa_uf_s   *uf;
-	struct list_head        *qe, *qen;
-
-	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
-		uf = (struct bfa_uf_s *) qe;
-		list_del(&uf->qe);
-		bfa_uf_put(ufm, uf);
-	}
-}
-
-static void
-bfa_uf_start(struct bfa_s *bfa)
-{
-	bfa_uf_post_all(BFA_UF_MOD(bfa));
-}
-
-
-
-/**
- *  bfa_uf_api
- */
-
-/**
- * 		Register handler for all unsolicted recieve frames.
- *
- * @param[in]	bfa		BFA instance
- * @param[in]	ufrecv	receive handler function
- * @param[in]	cbarg	receive handler arg
- */
-void
-bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
-{
-	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
-
-	ufm->ufrecv = ufrecv;
-	ufm->cbarg = cbarg;
-}
-
-/**
- * 		Free an unsolicited frame back to BFA.
- *
- * @param[in]		uf		unsolicited frame to be freed
- *
- * @return None
- */
-void
-bfa_uf_free(struct bfa_uf_s *uf)
-{
-	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
-	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
-}
-
-
-
-/**
- *  uf_pub BFA uf module public functions
- */
-
-void
-bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
-{
-	bfa_trc(bfa, msg->mhdr.msg_id);
-
-	switch (msg->mhdr.msg_id) {
-	case BFI_UF_I2H_FRM_RCVD:
-		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
-		break;
-
-	default:
-		bfa_trc(bfa, msg->mhdr.msg_id);
-		bfa_assert(0);
-	}
-}
-
-
diff --git a/drivers/scsi/bfa/bfa_uf_priv.h b/drivers/scsi/bfa/bfa_uf_priv.h
deleted file mode 100644
index bcb490f..0000000
--- a/drivers/scsi/bfa/bfa_uf_priv.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_UF_PRIV_H__
-#define __BFA_UF_PRIV_H__
-
-#include <cs/bfa_sm.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_uf.h>
-
-#define BFA_UF_MIN	(4)
-
-struct bfa_uf_mod_s {
-	struct bfa_s *bfa;		/*  back pointer to BFA */
-	struct bfa_uf_s *uf_list;	/*  array of UFs */
-	u16	num_ufs;	/*  num unsolicited rx frames */
-	struct list_head 	uf_free_q;	/*  free UFs */
-	struct list_head 	uf_posted_q;	/*  UFs posted to IOC */
-	struct bfa_uf_buf_s *uf_pbs_kva;	/*  list UF bufs request pld */
-	u64	uf_pbs_pa;	/*  phy addr for UF bufs */
-	struct bfi_uf_buf_post_s *uf_buf_posts;
-					/*  pre-built UF post msgs */
-	bfa_cb_uf_recv_t ufrecv;	/*  uf recv handler function */
-	void		*cbarg;		/*  uf receive handler arg */
-};
-
-#define BFA_UF_MOD(__bfa)	(&(__bfa)->modules.uf_mod)
-
-#define ufm_pbs_pa(_ufmod, _uftag)	\
-	((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag))
-
-void	bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg);
-
-#endif /* __BFA_UF_PRIV_H__ */
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index ca04cc9..4d8784e 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -18,46 +18,62 @@
 /**
  *  bfad.c Linux driver PCI interface module.
  */
-
-#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/kthread.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <asm/uaccess.h>
+#include <asm/fcntl.h>
+
 #include "bfad_drv.h"
 #include "bfad_im.h"
-#include "bfad_tm.h"
-#include "bfad_ipfc.h"
-#include "bfad_trcmod.h"
-#include <fcb/bfa_fcb_vf.h>
-#include <fcb/bfa_fcb_rport.h>
-#include <fcb/bfa_fcb_port.h>
-#include <fcb/bfa_fcb.h>
+#include "bfa_fcs.h"
+#include "bfa_os_inc.h"
+#include "bfa_defs.h"
+#include "bfa.h"
 
 BFA_TRC_FILE(LDRV, BFAD);
 DEFINE_MUTEX(bfad_mutex);
 LIST_HEAD(bfad_list);
-static int      bfad_inst;
-int bfad_supported_fc4s;
 
-static char     *host_name;
-static char     *os_name;
-static char     *os_patch;
-static int      num_rports;
-static int      num_ios;
-static int      num_tms;
-static int      num_fcxps;
-static int      num_ufbufs;
-static int      reqq_size;
-static int      rspq_size;
-static int      num_sgpgs;
-static int      rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
-static int      bfa_io_max_sge = BFAD_IO_MAX_SGE;
-static int      log_level = BFA_LOG_WARNING;
-static int      ioc_auto_recover = BFA_TRUE;
-static int      ipfc_enable = BFA_FALSE;
-static int	fdmi_enable = BFA_TRUE;
-int 		bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
-int      	bfa_linkup_delay = -1;
+static int	bfad_inst;
+static int      num_sgpgs_parm;
+int		supported_fc4s;
+char		*host_name, *os_name, *os_patch;
+int		num_rports, num_ios, num_tms;
+int		num_fcxps, num_ufbufs;
+int		reqq_size, rspq_size, num_sgpgs;
+int		rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
+int		bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
+int		bfa_io_max_sge = BFAD_IO_MAX_SGE;
+int		log_level = 3; /* WARNING log level */
+int		ioc_auto_recover = BFA_TRUE;
+int		bfa_linkup_delay = -1;
+int		fdmi_enable = BFA_TRUE;
+int		pcie_max_read_reqsz;
 int		bfa_debugfs_enable = 1;
+int		msix_disable_cb = 0, msix_disable_ct = 0;
+
+u32	bfi_image_ct_fc_size, bfi_image_ct_cna_size, bfi_image_cb_fc_size;
+u32     *bfi_image_ct_fc, *bfi_image_ct_cna, *bfi_image_cb_fc;
+
+const char *msix_name_ct[] = {
+	"cpe0", "cpe1", "cpe2", "cpe3",
+	"rme0", "rme1", "rme2", "rme3",
+	"ctrl" };
+
+const char *msix_name_cb[] = {
+	"cpe0", "cpe1", "cpe2", "cpe3",
+	"rme0", "rme1", "rme2", "rme3",
+	"eemc", "elpu0", "elpu1", "epss", "mlpu" };
+
+MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC);
+MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA);
+MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC);
 
 module_param(os_name, charp, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(os_name, "OS name of the hba host machine");
@@ -66,8 +82,8 @@
 module_param(host_name, charp, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(host_name, "Hostname of the hba host machine");
 module_param(num_rports, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(num_rports, "Max number of rports supported per port"
-		" (physical/logical), default=1024");
+MODULE_PARM_DESC(num_rports, "Max number of rports supported per port "
+				"(physical/logical), default=1024");
 module_param(num_ios, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(num_ios, "Max number of ioim requests, default=2000");
 module_param(num_tms, int, S_IRUGO | S_IWUSR);
@@ -75,120 +91,277 @@
 module_param(num_fcxps, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(num_fcxps, "Max number of fcxp requests, default=64");
 module_param(num_ufbufs, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(num_ufbufs, "Max number of unsolicited frame buffers,"
-		" default=64");
+MODULE_PARM_DESC(num_ufbufs, "Max number of unsolicited frame "
+				"buffers, default=64");
 module_param(reqq_size, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(reqq_size, "Max number of request queue elements,"
-		" default=256");
+MODULE_PARM_DESC(reqq_size, "Max number of request queue elements, "
+				"default=256");
 module_param(rspq_size, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rspq_size, "Max number of response queue elements,"
-		" default=64");
+MODULE_PARM_DESC(rspq_size, "Max number of response queue elements, "
+				"default=64");
 module_param(num_sgpgs, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(num_sgpgs, "Number of scatter/gather pages, default=2048");
 module_param(rport_del_timeout, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rport_del_timeout, "Rport delete timeout, default=90 secs,"
-		" Range[>0]");
+MODULE_PARM_DESC(rport_del_timeout, "Rport delete timeout, default=90 secs, "
+					"Range[>0]");
 module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32,"
-		" Range[>0]");
+MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32, Range[>0]");
 module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(bfa_io_max_sge, "Max io scatter/gather elements, default=255");
 module_param(log_level, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(log_level, "Driver log level, default=3,"
-		" Range[Critical:1|Error:2|Warning:3|Info:4]");
+MODULE_PARM_DESC(log_level, "Driver log level, default=3, "
+				"Range[Critical:1|Error:2|Warning:3|Info:4]");
 module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1,"
-		" Range[off:0|on:1]");
-module_param(ipfc_enable, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ipfc_enable, "Enable IPoFC, default=0, Range[off:0|on:1]");
+MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1, "
+				"Range[off:0|on:1]");
 module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for boot"
-		" port. Otherwise Range[>0]");
+MODULE_PARM_DESC(bfa_linkup_delay, "Link up delay, default=30 secs for "
+			"boot port. Otherwise 10 secs in RHEL4 & 0 for "
+			"[RHEL5, SLES10, ESX40] Range[>0]");
+module_param(msix_disable_cb, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msix_disable_cb, "Disable Message Signaled Interrupts "
+			"for Brocade-415/425/815/825 cards, default=0, "
+			" Range[false:0|true:1]");
+module_param(msix_disable_ct, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msix_disable_ct, "Disable Message Signaled Interrupts "
+			"if possible for Brocade-1010/1020/804/1007/902/1741 "
+			"cards, default=0, Range[false:0|true:1]");
 module_param(fdmi_enable, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1,"
-		" Range[false:0|true:1]");
+MODULE_PARM_DESC(fdmi_enable, "Enables fdmi registration, default=1, "
+				"Range[false:0|true:1]");
+module_param(pcie_max_read_reqsz, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pcie_max_read_reqsz, "PCIe max read request size, default=0 "
+		"(use system setting), Range[128|256|512|1024|2048|4096]");
 module_param(bfa_debugfs_enable, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(bfa_debugfs_enable, "Enables debugfs feature, default=1,"
 		" Range[false:0|true:1]");
 
-/*
- * Stores the module parm num_sgpgs value;
- * used to reset for bfad next instance.
+static void
+bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_operational(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_stopping(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event);
+static void
+bfad_sm_fcs_exit(struct bfad_s *bfad, enum bfad_sm_event event);
+
+/**
+ * Beginning state for the driver instance, awaiting the pci_probe event
  */
-static int num_sgpgs_parm;
-
-static bfa_status_t
-bfad_fc4_probe(struct bfad_s *bfad)
+static void
+bfad_sm_uninit(struct bfad_s *bfad, enum bfad_sm_event event)
 {
-	int             rc;
+	bfa_trc(bfad, event);
 
-	rc = bfad_im_probe(bfad);
-	if (rc != BFA_STATUS_OK)
-		goto ext;
+	switch (event) {
+	case BFAD_E_CREATE:
+		bfa_sm_set_state(bfad, bfad_sm_created);
+		bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad,
+						"%s", "bfad_worker");
+		if (IS_ERR(bfad->bfad_tsk)) {
+			printk(KERN_INFO "bfad[%d]: Kernel thread "
+				"creation failed!\n", bfad->inst_no);
+			bfa_sm_send_event(bfad, BFAD_E_KTHREAD_CREATE_FAILED);
+		}
+		bfa_sm_send_event(bfad, BFAD_E_INIT);
+		break;
 
-	bfad_tm_probe(bfad);
+	case BFAD_E_STOP:
+		/* Ignore stop; already in uninit */
+		break;
 
-	if (ipfc_enable)
-		bfad_ipfc_probe(bfad);
+	default:
+		bfa_sm_fault(bfad, event);
+	}
+}
 
-	bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
-ext:
-	return rc;
+/**
+ * Driver Instance is created, awaiting event INIT to initialize the bfad
+ */
+static void
+bfad_sm_created(struct bfad_s *bfad, enum bfad_sm_event event)
+{
+	unsigned long flags;
+
+	bfa_trc(bfad, event);
+
+	switch (event) {
+	case BFAD_E_INIT:
+		bfa_sm_set_state(bfad, bfad_sm_initializing);
+
+		init_completion(&bfad->comp);
+
+		/* Enable Interrupt and wait bfa_init completion */
+		if (bfad_setup_intr(bfad)) {
+			printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
+					bfad->inst_no);
+			bfa_sm_send_event(bfad, BFAD_E_INTR_INIT_FAILED);
+			break;
+		}
+
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfa_init(&bfad->bfa);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+		/* Set up interrupt handler for each vectors */
+		if ((bfad->bfad_flags & BFAD_MSIX_ON) &&
+			bfad_install_msix_handler(bfad)) {
+			printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
+				__func__, bfad->inst_no);
+		}
+
+		bfad_init_timer(bfad);
+
+		wait_for_completion(&bfad->comp);
+
+		if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
+			bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
+		} else {
+			bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
+			bfa_sm_send_event(bfad, BFAD_E_INIT_FAILED);
+		}
+
+		break;
+
+	case BFAD_E_KTHREAD_CREATE_FAILED:
+		bfa_sm_set_state(bfad, bfad_sm_uninit);
+		break;
+
+	default:
+		bfa_sm_fault(bfad, event);
+	}
 }
 
 static void
-bfad_fc4_probe_undo(struct bfad_s *bfad)
+bfad_sm_initializing(struct bfad_s *bfad, enum bfad_sm_event event)
 {
-	bfad_im_probe_undo(bfad);
-	bfad_tm_probe_undo(bfad);
-	if (ipfc_enable)
-		bfad_ipfc_probe_undo(bfad);
-	bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+	int	retval;
+	unsigned long	flags;
+
+	bfa_trc(bfad, event);
+
+	switch (event) {
+	case BFAD_E_INIT_SUCCESS:
+		kthread_stop(bfad->bfad_tsk);
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfad->bfad_tsk = NULL;
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+		retval = bfad_start_ops(bfad);
+		if (retval != BFA_STATUS_OK)
+			break;
+		bfa_sm_set_state(bfad, bfad_sm_operational);
+		break;
+
+	case BFAD_E_INTR_INIT_FAILED:
+		bfa_sm_set_state(bfad, bfad_sm_uninit);
+		kthread_stop(bfad->bfad_tsk);
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfad->bfad_tsk = NULL;
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		break;
+
+	case BFAD_E_INIT_FAILED:
+		bfa_sm_set_state(bfad, bfad_sm_failed);
+		break;
+	default:
+		bfa_sm_fault(bfad, event);
+	}
 }
 
 static void
-bfad_fc4_probe_post(struct bfad_s *bfad)
+bfad_sm_failed(struct bfad_s *bfad, enum bfad_sm_event event)
 {
-	if (bfad->im)
-		bfad_im_probe_post(bfad->im);
+	int	retval;
 
-	bfad_tm_probe_post(bfad);
-	if (ipfc_enable)
-		bfad_ipfc_probe_post(bfad);
-}
+	bfa_trc(bfad, event);
 
-static bfa_status_t
-bfad_fc4_port_new(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
-{
-	int             rc = BFA_STATUS_FAILED;
+	switch (event) {
+	case BFAD_E_INIT_SUCCESS:
+		retval = bfad_start_ops(bfad);
+		if (retval != BFA_STATUS_OK)
+			break;
+		bfa_sm_set_state(bfad, bfad_sm_operational);
+		break;
 
-	if (roles & BFA_PORT_ROLE_FCP_IM)
-		rc = bfad_im_port_new(bfad, port);
-	if (rc != BFA_STATUS_OK)
-		goto ext;
+	case BFAD_E_STOP:
+		if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
+			bfad_uncfg_pport(bfad);
+		if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE) {
+			bfad_im_probe_undo(bfad);
+			bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+		}
+		bfad_stop(bfad);
+		break;
 
-	if (roles & BFA_PORT_ROLE_FCP_TM)
-		rc = bfad_tm_port_new(bfad, port);
-	if (rc != BFA_STATUS_OK)
-		goto ext;
+	case BFAD_E_EXIT_COMP:
+		bfa_sm_set_state(bfad, bfad_sm_uninit);
+		bfad_remove_intr(bfad);
+		del_timer_sync(&bfad->hal_tmo);
+		break;
 
-	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
-		rc = bfad_ipfc_port_new(bfad, port, port->pvb_type);
-ext:
-	return rc;
+	default:
+		bfa_sm_fault(bfad, event);
+	}
 }
 
 static void
-bfad_fc4_port_delete(struct bfad_s *bfad, struct bfad_port_s *port, int roles)
+bfad_sm_operational(struct bfad_s *bfad, enum bfad_sm_event event)
 {
-	if (roles & BFA_PORT_ROLE_FCP_IM)
-		bfad_im_port_delete(bfad, port);
+	bfa_trc(bfad, event);
 
-	if (roles & BFA_PORT_ROLE_FCP_TM)
-		bfad_tm_port_delete(bfad, port);
+	switch (event) {
+	case BFAD_E_STOP:
+		bfa_sm_set_state(bfad, bfad_sm_fcs_exit);
+		bfad_fcs_stop(bfad);
+		break;
 
-	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
-		bfad_ipfc_port_delete(bfad, port);
+	default:
+		bfa_sm_fault(bfad, event);
+	}
+}
+
+static void
+bfad_sm_fcs_exit(struct bfad_s *bfad, enum bfad_sm_event event)
+{
+	bfa_trc(bfad, event);
+
+	switch (event) {
+	case BFAD_E_FCS_EXIT_COMP:
+		bfa_sm_set_state(bfad, bfad_sm_stopping);
+		bfad_stop(bfad);
+		break;
+
+	default:
+		bfa_sm_fault(bfad, event);
+	}
+}
+
+static void
+bfad_sm_stopping(struct bfad_s *bfad, enum bfad_sm_event event)
+{
+	bfa_trc(bfad, event);
+
+	switch (event) {
+	case BFAD_E_EXIT_COMP:
+		bfa_sm_set_state(bfad, bfad_sm_uninit);
+		bfad_remove_intr(bfad);
+		del_timer_sync(&bfad->hal_tmo);
+		bfad_im_probe_undo(bfad);
+		bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+		bfad_uncfg_pport(bfad);
+		break;
+
+	default:
+		bfa_sm_fault(bfad, event);
+		break;
+	}
 }
 
 /**
@@ -209,12 +382,13 @@
 void
 bfa_cb_init(void *drv, bfa_status_t init_status)
 {
-	struct bfad_s  *bfad = drv;
+	struct bfad_s	      *bfad = drv;
 
 	if (init_status == BFA_STATUS_OK) {
 		bfad->bfad_flags |= BFAD_HAL_INIT_DONE;
 
-		/* If BFAD_HAL_INIT_FAIL flag is set:
+		/*
+		 * If BFAD_HAL_INIT_FAIL flag is set:
 		 * Wake up the kernel thread to start
 		 * the bfad operations after HAL init done
 		 */
@@ -227,26 +401,16 @@
 	complete(&bfad->comp);
 }
 
-
-
 /**
  *  BFA_FCS callbacks
  */
-static struct bfad_port_s *
-bfad_get_drv_port(struct bfad_s *bfad, struct bfad_vf_s *vf_drv,
-		  struct bfad_vport_s *vp_drv)
-{
-	return (vp_drv) ? (&(vp_drv)->drv_port)
-		: ((vf_drv) ? (&(vf_drv)->base_port) : (&(bfad)->pport));
-}
-
 struct bfad_port_s *
-bfa_fcb_port_new(struct bfad_s *bfad, struct bfa_fcs_port_s *port,
-		 enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
+bfa_fcb_lport_new(struct bfad_s *bfad, struct bfa_fcs_lport_s *port,
+		 enum bfa_lport_role roles, struct bfad_vf_s *vf_drv,
 		 struct bfad_vport_s *vp_drv)
 {
-	bfa_status_t    rc;
-	struct bfad_port_s *port_drv;
+	bfa_status_t	rc;
+	struct bfad_port_s    *port_drv;
 
 	if (!vp_drv && !vf_drv) {
 		port_drv = &bfad->pport;
@@ -264,71 +428,32 @@
 
 	port_drv->fcs_port = port;
 	port_drv->roles = roles;
-	rc = bfad_fc4_port_new(bfad, port_drv, roles);
-	if (rc != BFA_STATUS_OK) {
-		bfad_fc4_port_delete(bfad, port_drv, roles);
-		port_drv = NULL;
+
+	if (roles & BFA_LPORT_ROLE_FCP_IM) {
+		rc = bfad_im_port_new(bfad, port_drv);
+		if (rc != BFA_STATUS_OK) {
+			bfad_im_port_delete(bfad, port_drv);
+			port_drv = NULL;
+		}
 	}
 
 	return port_drv;
 }
 
 void
-bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
+bfa_fcb_lport_delete(struct bfad_s *bfad, enum bfa_lport_role roles,
 		    struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
 {
-	struct bfad_port_s *port_drv;
+	struct bfad_port_s    *port_drv;
 
-	/*
-	 * this will be only called from rmmod context
-	 */
+	/* this will be only called from rmmod context */
 	if (vp_drv && !vp_drv->comp_del) {
-		port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
+		port_drv = (vp_drv) ? (&(vp_drv)->drv_port) :
+				((vf_drv) ? (&(vf_drv)->base_port) :
+				(&(bfad)->pport));
 		bfa_trc(bfad, roles);
-		bfad_fc4_port_delete(bfad, port_drv, roles);
-	}
-}
-
-void
-bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
-		    struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
-{
-	struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
-
-	if (roles & BFA_PORT_ROLE_FCP_IM)
-		bfad_im_port_online(bfad, port_drv);
-
-	if (roles & BFA_PORT_ROLE_FCP_TM)
-		bfad_tm_port_online(bfad, port_drv);
-
-	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
-		bfad_ipfc_port_online(bfad, port_drv);
-
-	bfad->bfad_flags |= BFAD_PORT_ONLINE;
-}
-
-void
-bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
-		     struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv)
-{
-	struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv);
-
-	if (roles & BFA_PORT_ROLE_FCP_IM)
-		bfad_im_port_offline(bfad, port_drv);
-
-	if (roles & BFA_PORT_ROLE_FCP_TM)
-		bfad_tm_port_offline(bfad, port_drv);
-
-	if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable)
-		bfad_ipfc_port_offline(bfad, port_drv);
-}
-
-void
-bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv)
-{
-	if (vport_drv->comp_del) {
-		complete(vport_drv->comp_del);
-		return;
+		if (roles & BFA_LPORT_ROLE_FCP_IM)
+			bfad_im_port_delete(bfad, port_drv);
 	}
 }
 
@@ -339,7 +464,7 @@
 bfa_fcb_rport_alloc(struct bfad_s *bfad, struct bfa_fcs_rport_s **rport,
 		    struct bfad_rport_s **rport_drv)
 {
-	bfa_status_t    rc = BFA_STATUS_OK;
+	bfa_status_t	rc = BFA_STATUS_OK;
 
 	*rport_drv = kzalloc(sizeof(struct bfad_rport_s), GFP_ATOMIC);
 	if (*rport_drv == NULL) {
@@ -354,35 +479,43 @@
 }
 
 /**
- * @brief
  * FCS PBC VPORT Create
  */
 void
 bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s pbc_vport)
 {
 
-	struct bfad_pcfg_s *pcfg;
+	struct bfa_lport_cfg_s port_cfg = {0};
+	struct bfad_vport_s   *vport;
+	int rc;
 
-	pcfg = kzalloc(sizeof(struct bfad_pcfg_s), GFP_ATOMIC);
-	if (!pcfg) {
+	vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
+	if (!vport) {
 		bfa_trc(bfad, 0);
 		return;
 	}
 
-	pcfg->port_cfg.roles = BFA_PORT_ROLE_FCP_IM;
-	pcfg->port_cfg.pwwn = pbc_vport.vp_pwwn;
-	pcfg->port_cfg.nwwn = pbc_vport.vp_nwwn;
-	pcfg->port_cfg.preboot_vp  = BFA_TRUE;
+	vport->drv_port.bfad = bfad;
+	port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;
+	port_cfg.pwwn = pbc_vport.vp_pwwn;
+	port_cfg.nwwn = pbc_vport.vp_nwwn;
+	port_cfg.preboot_vp  = BFA_TRUE;
 
-	list_add_tail(&pcfg->list_entry, &bfad->pbc_pcfg_list);
+	rc = bfa_fcs_pbc_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, 0,
+				  &port_cfg, vport);
 
-	return;
+	if (rc != BFA_STATUS_OK) {
+		bfa_trc(bfad, 0);
+		return;
+	}
+
+	list_add_tail(&vport->list_entry, &bfad->pbc_vport_list);
 }
 
 void
 bfad_hal_mem_release(struct bfad_s *bfad)
 {
-	int             i;
+	int		i;
 	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
 	struct bfa_mem_elem_s *meminfo_elem;
 
@@ -395,9 +528,9 @@
 				break;
 			case BFA_MEM_TYPE_DMA:
 				dma_free_coherent(&bfad->pcidev->dev,
-						meminfo_elem->mem_len,
-						meminfo_elem->kva,
-						(dma_addr_t) meminfo_elem->dma);
+					meminfo_elem->mem_len,
+					meminfo_elem->kva,
+					(dma_addr_t) meminfo_elem->dma);
 				break;
 			default:
 				bfa_assert(0);
@@ -434,27 +567,27 @@
 	 * otherwise, the default values will be shown as 0 in sysfs
 	 */
 	num_rports = bfa_cfg->fwcfg.num_rports;
-	num_ios    = bfa_cfg->fwcfg.num_ioim_reqs;
-	num_tms	   = bfa_cfg->fwcfg.num_tskim_reqs;
-	num_fcxps  = bfa_cfg->fwcfg.num_fcxp_reqs;
+	num_ios = bfa_cfg->fwcfg.num_ioim_reqs;
+	num_tms = bfa_cfg->fwcfg.num_tskim_reqs;
+	num_fcxps = bfa_cfg->fwcfg.num_fcxp_reqs;
 	num_ufbufs = bfa_cfg->fwcfg.num_uf_bufs;
-	reqq_size  = bfa_cfg->drvcfg.num_reqq_elems;
-	rspq_size  = bfa_cfg->drvcfg.num_rspq_elems;
-	num_sgpgs  = bfa_cfg->drvcfg.num_sgpgs;
+	reqq_size = bfa_cfg->drvcfg.num_reqq_elems;
+	rspq_size = bfa_cfg->drvcfg.num_rspq_elems;
+	num_sgpgs = bfa_cfg->drvcfg.num_sgpgs;
 }
 
 bfa_status_t
 bfad_hal_mem_alloc(struct bfad_s *bfad)
 {
+	int		i;
 	struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo;
 	struct bfa_mem_elem_s *meminfo_elem;
-	bfa_status_t    rc = BFA_STATUS_OK;
-	dma_addr_t      phys_addr;
-	int             retry_count = 0;
-	int             reset_value = 1;
-	int             min_num_sgpgs = 512;
-	void           *kva;
-	int             i;
+	dma_addr_t	phys_addr;
+	void	       *kva;
+	bfa_status_t	rc = BFA_STATUS_OK;
+	int retry_count = 0;
+	int reset_value = 1;
+	int min_num_sgpgs = 512;
 
 	bfa_cfg_get_default(&bfad->ioc_cfg);
 
@@ -478,8 +611,7 @@
 			break;
 		case BFA_MEM_TYPE_DMA:
 			kva = dma_alloc_coherent(&bfad->pcidev->dev,
-					meminfo_elem->mem_len,
-					&phys_addr, GFP_KERNEL);
+				meminfo_elem->mem_len, &phys_addr, GFP_KERNEL);
 			if (kva == NULL) {
 				bfad_hal_mem_release(bfad);
 				/*
@@ -487,14 +619,14 @@
 				 * num_sgpages try with half the value.
 				 */
 				if (num_sgpgs > min_num_sgpgs) {
-					printk(KERN_INFO "bfad[%d]: memory"
-						" allocation failed with"
-						" num_sgpgs: %d\n",
+					printk(KERN_INFO
+					"bfad[%d]: memory allocation failed"
+					" with num_sgpgs: %d\n",
 						bfad->inst_no, num_sgpgs);
 					nextLowerInt(&num_sgpgs);
-					printk(KERN_INFO "bfad[%d]: trying to"
-						" allocate memory with"
-						" num_sgpgs: %d\n",
+					printk(KERN_INFO
+					"bfad[%d]: trying to allocate memory"
+					" with num_sgpgs: %d\n",
 						bfad->inst_no, num_sgpgs);
 					retry_count++;
 					goto retry;
@@ -536,11 +668,11 @@
  */
 bfa_status_t
 bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
-			struct bfa_port_cfg_s *port_cfg, struct device *dev)
+		  struct bfa_lport_cfg_s *port_cfg, struct device *dev)
 {
-	struct bfad_vport_s *vport;
-	int rc = BFA_STATUS_OK;
-	unsigned long   flags;
+	struct bfad_vport_s   *vport;
+	int		rc = BFA_STATUS_OK;
+	unsigned long	flags;
 	struct completion fcomp;
 
 	vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL);
@@ -551,18 +683,14 @@
 
 	vport->drv_port.bfad = bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	if (port_cfg->preboot_vp == BFA_TRUE)
-		rc = bfa_fcs_pbc_vport_create(&vport->fcs_vport,
-				&bfad->bfa_fcs, vf_id, port_cfg, vport);
-	else
-		rc = bfa_fcs_vport_create(&vport->fcs_vport,
-				&bfad->bfa_fcs, vf_id, port_cfg, vport);
+	rc = bfa_fcs_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, vf_id,
+				  port_cfg, vport);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	if (rc != BFA_STATUS_OK)
 		goto ext_free_vport;
 
-	if (port_cfg->roles & BFA_PORT_ROLE_FCP_IM) {
+	if (port_cfg->roles & BFA_LPORT_ROLE_FCP_IM) {
 		rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port,
 							dev);
 		if (rc != BFA_STATUS_OK)
@@ -593,10 +721,10 @@
  */
 bfa_status_t
 bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
-	       struct bfa_port_cfg_s *port_cfg)
+	       struct bfa_lport_cfg_s *port_cfg)
 {
-	struct bfad_vf_s *vf;
-	int             rc = BFA_STATUS_OK;
+	struct bfad_vf_s      *vf;
+	int		rc = BFA_STATUS_OK;
 
 	vf = kzalloc(sizeof(struct bfad_vf_s), GFP_KERNEL);
 	if (!vf) {
@@ -615,9 +743,9 @@
 void
 bfad_bfa_tmo(unsigned long data)
 {
-	struct bfad_s  *bfad = (struct bfad_s *)data;
-	unsigned long   flags;
-	struct list_head  doneq;
+	struct bfad_s	      *bfad = (struct bfad_s *) data;
+	unsigned long	flags;
+	struct list_head	       doneq;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 
@@ -633,7 +761,8 @@
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	}
 
-	mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
+	mod_timer(&bfad->hal_tmo,
+		  jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
 }
 
 void
@@ -643,16 +772,17 @@
 	bfad->hal_tmo.function = bfad_bfa_tmo;
 	bfad->hal_tmo.data = (unsigned long)bfad;
 
-	mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
+	mod_timer(&bfad->hal_tmo,
+		  jiffies + msecs_to_jiffies(BFA_TIMER_FREQ));
 }
 
 int
 bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
 {
-	int             rc = -ENODEV;
+	int		rc = -ENODEV;
 
 	if (pci_enable_device(pdev)) {
-		BFA_PRINTF(BFA_ERR, "pci_enable_device fail %p\n", pdev);
+		printk(KERN_ERR "pci_enable_device fail %p\n", pdev);
 		goto out;
 	}
 
@@ -664,14 +794,14 @@
 
 	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
 		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
-			BFA_PRINTF(BFA_ERR, "pci_set_dma_mask fail %p\n", pdev);
+			printk(KERN_ERR "pci_set_dma_mask fail %p\n", pdev);
 			goto out_release_region;
 		}
 
 	bfad->pci_bar0_kva = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
 
 	if (bfad->pci_bar0_kva == NULL) {
-		BFA_PRINTF(BFA_ERR, "Fail to map bar0\n");
+		printk(KERN_ERR "Fail to map bar0\n");
 		goto out_release_region;
 	}
 
@@ -688,6 +818,54 @@
 	bfad->pci_attr.pcifn = PCI_FUNC(pdev->devfn);
 
 	bfad->pcidev = pdev;
+
+	/* Adjust PCIe Maximum Read Request Size */
+	if (pcie_max_read_reqsz > 0) {
+		int pcie_cap_reg;
+		u16 pcie_dev_ctl;
+		u16 mask = 0xffff;
+
+		switch (pcie_max_read_reqsz) {
+		case 128:
+			mask = 0x0;
+			break;
+		case 256:
+			mask = 0x1000;
+			break;
+		case 512:
+			mask = 0x2000;
+			break;
+		case 1024:
+			mask = 0x3000;
+			break;
+		case 2048:
+			mask = 0x4000;
+			break;
+		case 4096:
+			mask = 0x5000;
+			break;
+		default:
+			break;
+		}
+
+		pcie_cap_reg = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+		if (mask != 0xffff && pcie_cap_reg) {
+			pcie_cap_reg += 0x08;
+			pci_read_config_word(pdev, pcie_cap_reg, &pcie_dev_ctl);
+			if ((pcie_dev_ctl & 0x7000) != mask) {
+				printk(KERN_WARNING "BFA[%s]: "
+				"pcie_max_read_request_size is %d, "
+				"reset to %d\n", bfad->pci_name,
+				(1 << ((pcie_dev_ctl & 0x7000) >> 12)) << 7,
+				pcie_max_read_reqsz);
+
+				pcie_dev_ctl &= ~0x7000;
+				pci_write_config_word(pdev, pcie_cap_reg,
+						pcie_dev_ctl | mask);
+			}
+		}
+	}
+
 	return 0;
 
 out_release_region:
@@ -710,25 +888,22 @@
 void
 bfad_fcs_port_cfg(struct bfad_s *bfad)
 {
-	struct bfa_port_cfg_s port_cfg;
-	struct bfa_pport_attr_s attr;
-	char            symname[BFA_SYMNAME_MAXLEN];
+	struct bfa_lport_cfg_s  port_cfg;
+	struct bfa_port_attr_s attr;
+	char		symname[BFA_SYMNAME_MAXLEN];
 
 	sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no);
 	memcpy(port_cfg.sym_name.symname, symname, strlen(symname));
 	bfa_fcport_get_attr(&bfad->bfa, &attr);
 	port_cfg.nwwn = attr.nwwn;
 	port_cfg.pwwn = attr.pwwn;
-
-	bfa_fcs_cfg_base_port(&bfad->bfa_fcs, &port_cfg);
 }
 
 bfa_status_t
 bfad_drv_init(struct bfad_s *bfad)
 {
-	bfa_status_t    rc;
-	unsigned long   flags;
-	struct bfa_fcs_driver_info_s driver_info;
+	bfa_status_t	rc;
+	unsigned long	flags;
 
 	bfad->cfg_data.rport_del_timeout = rport_del_timeout;
 	bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth;
@@ -740,15 +915,12 @@
 		printk(KERN_WARNING "bfad%d bfad_hal_mem_alloc failure\n",
 		       bfad->inst_no);
 		printk(KERN_WARNING
-			"Not enough memory to attach all Brocade HBA ports,"
-			" System may need more memory.\n");
+			"Not enough memory to attach all Brocade HBA ports, %s",
+			"System may need more memory.\n");
 		goto out_hal_mem_alloc_failure;
 	}
 
-	bfa_init_log(&bfad->bfa, bfad->logmod);
 	bfa_init_trc(&bfad->bfa, bfad->trcmod);
-	bfa_init_aen(&bfad->bfa, bfad->aen);
-	memset(bfad->file_map, 0, sizeof(bfad->file_map));
 	bfa_init_plog(&bfad->bfa, &bfad->plog_buf);
 	bfa_plog_init(&bfad->plog_buf);
 	bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START,
@@ -757,77 +929,17 @@
 	bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg, &bfad->meminfo,
 		   &bfad->hal_pcidev);
 
-	init_completion(&bfad->comp);
-
-	/*
-	 * Enable Interrupt and wait bfa_init completion
-	 */
-	if (bfad_setup_intr(bfad)) {
-		printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n",
-		       bfad->inst_no);
-		goto out_setup_intr_failure;
-	}
-
+	/* FCS INIT */
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	bfa_init(&bfad->bfa);
-	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
-	/*
-	 * Set up interrupt handler for each vectors
-	 */
-	if ((bfad->bfad_flags & BFAD_MSIX_ON)
-	    && bfad_install_msix_handler(bfad)) {
-		printk(KERN_WARNING "%s: install_msix failed, bfad%d\n",
-		       __func__, bfad->inst_no);
-	}
-
-	bfad_init_timer(bfad);
-
-	wait_for_completion(&bfad->comp);
-
-	memset(&driver_info, 0, sizeof(driver_info));
-	strncpy(driver_info.version, BFAD_DRIVER_VERSION,
-		sizeof(driver_info.version) - 1);
-	__kernel_param_lock();
-	if (host_name)
-		strncpy(driver_info.host_machine_name, host_name,
-			sizeof(driver_info.host_machine_name) - 1);
-	if (os_name)
-		strncpy(driver_info.host_os_name, os_name,
-			sizeof(driver_info.host_os_name) - 1);
-	if (os_patch)
-		strncpy(driver_info.host_os_patch, os_patch,
-			sizeof(driver_info.host_os_patch) - 1);
-	__kernel_param_unlock();
-
-	strncpy(driver_info.os_device_name, bfad->pci_name,
-		sizeof(driver_info.os_device_name - 1));
-
-	/*
-	 * FCS INIT
-	 */
-	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod);
 	bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod);
-	bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen);
 	bfa_fcs_attach(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE);
-
-	/* Do FCS init only when HAL init is done */
-	if ((bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
-		bfa_fcs_init(&bfad->bfa_fcs);
-		bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
-	}
-
-	bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
 	bfa_fcs_set_fdmi_param(&bfad->bfa_fcs, fdmi_enable);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	bfad->bfad_flags |= BFAD_DRV_INIT_DONE;
+
 	return BFA_STATUS_OK;
 
-out_setup_intr_failure:
-	bfa_detach(&bfad->bfa);
-	bfad_hal_mem_release(bfad);
 out_hal_mem_alloc_failure:
 	return BFA_STATUS_FAILED;
 }
@@ -855,7 +967,7 @@
 void
 bfad_drv_start(struct bfad_s *bfad)
 {
-	unsigned long   flags;
+	unsigned long	flags;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	bfa_start(&bfad->bfa);
@@ -863,13 +975,14 @@
 	bfad->bfad_flags |= BFAD_HAL_START_DONE;
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
-	bfad_fc4_probe_post(bfad);
+	if (bfad->im)
+		flush_workqueue(bfad->im->drv_workq);
 }
 
 void
-bfad_drv_stop(struct bfad_s *bfad)
+bfad_fcs_stop(struct bfad_s *bfad)
 {
-	unsigned long   flags;
+	unsigned long	flags;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	init_completion(&bfad->comp);
@@ -878,24 +991,32 @@
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	wait_for_completion(&bfad->comp);
 
+	bfa_sm_send_event(bfad, BFAD_E_FCS_EXIT_COMP);
+}
+
+void
+bfad_stop(struct bfad_s *bfad)
+{
+	unsigned long	flags;
+
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	init_completion(&bfad->comp);
 	bfa_stop(&bfad->bfa);
 	bfad->bfad_flags &= ~BFAD_HAL_START_DONE;
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	wait_for_completion(&bfad->comp);
+
+	bfa_sm_send_event(bfad, BFAD_E_EXIT_COMP);
 }
 
 bfa_status_t
-bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role)
+bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role)
 {
-	int             rc = BFA_STATUS_OK;
+	int		rc = BFA_STATUS_OK;
 
-	/*
-	 * Allocate scsi_host for the physical port
-	 */
-	if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
-	    && (role & BFA_PORT_ROLE_FCP_IM)) {
+	/* Allocate scsi_host for the physical port */
+	if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&
+	    (role & BFA_LPORT_ROLE_FCP_IM)) {
 		if (bfad->pport.im_port == NULL) {
 			rc = BFA_STATUS_FAILED;
 			goto out;
@@ -906,7 +1027,7 @@
 		if (rc != BFA_STATUS_OK)
 			goto out;
 
-		bfad->pport.roles |= BFA_PORT_ROLE_FCP_IM;
+		bfad->pport.roles |= BFA_LPORT_ROLE_FCP_IM;
 	}
 
 	/* Setup the debugfs node for this scsi_host */
@@ -922,74 +1043,102 @@
 void
 bfad_uncfg_pport(struct bfad_s *bfad)
 {
-	 /* Remove the debugfs node for this scsi_host */
+	/* Remove the debugfs node for this scsi_host */
 	kfree(bfad->regdata);
 	bfad_debugfs_exit(&bfad->pport);
 
-	if ((bfad->pport.roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) {
-		bfad_ipfc_port_delete(bfad, &bfad->pport);
-		bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
-	}
-
-	if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM)
-	    && (bfad->pport.roles & BFA_PORT_ROLE_FCP_IM)) {
+	if ((supported_fc4s & BFA_LPORT_ROLE_FCP_IM) &&
+	    (bfad->pport.roles & BFA_LPORT_ROLE_FCP_IM)) {
 		bfad_im_scsi_host_free(bfad, bfad->pport.im_port);
 		bfad_im_port_clean(bfad->pport.im_port);
 		kfree(bfad->pport.im_port);
-		bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IM;
+		bfad->pport.roles &= ~BFA_LPORT_ROLE_FCP_IM;
 	}
 
 	bfad->bfad_flags &= ~BFAD_CFG_PPORT_DONE;
 }
 
-void
-bfad_drv_log_level_set(struct bfad_s *bfad)
-{
-	if (log_level > BFA_LOG_INVALID && log_level <= BFA_LOG_LEVEL_MAX)
-		bfa_log_set_level_all(&bfad->log_data, log_level);
-}
-
 bfa_status_t
-bfad_start_ops(struct bfad_s *bfad)
-{
-	int retval;
-	struct bfad_pcfg_s *pcfg, *pcfg_new;
+bfad_start_ops(struct bfad_s *bfad) {
+
+	int	retval;
+	unsigned long	flags;
+	struct bfad_vport_s *vport, *vport_new;
+	struct bfa_fcs_driver_info_s driver_info;
+
+	/* Fill the driver_info info to fcs*/
+	memset(&driver_info, 0, sizeof(driver_info));
+	strncpy(driver_info.version, BFAD_DRIVER_VERSION,
+		sizeof(driver_info.version) - 1);
+	if (host_name)
+		strncpy(driver_info.host_machine_name, host_name,
+			sizeof(driver_info.host_machine_name) - 1);
+	if (os_name)
+		strncpy(driver_info.host_os_name, os_name,
+			sizeof(driver_info.host_os_name) - 1);
+	if (os_patch)
+		strncpy(driver_info.host_os_patch, os_patch,
+			sizeof(driver_info.host_os_patch) - 1);
+
+	strncpy(driver_info.os_device_name, bfad->pci_name,
+		sizeof(driver_info.os_device_name - 1));
+
+	/* FCS INIT */
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info);
+	bfa_fcs_init(&bfad->bfa_fcs);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	/* PPORT FCS config */
 	bfad_fcs_port_cfg(bfad);
 
-	retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM);
-	if (retval != BFA_STATUS_OK)
-		goto out_cfg_pport_failure;
-
-	/* BFAD level FC4 (IM/TM/IPFC) specific resource allocation */
-	retval = bfad_fc4_probe(bfad);
+	retval = bfad_cfg_pport(bfad, BFA_LPORT_ROLE_FCP_IM);
 	if (retval != BFA_STATUS_OK) {
-		printk(KERN_WARNING "bfad_fc4_probe failed\n");
-		goto out_fc4_probe_failure;
+		if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
+			bfa_sm_set_state(bfad, bfad_sm_failed);
+		bfad_stop(bfad);
+		return BFA_STATUS_FAILED;
 	}
 
+	/* BFAD level FC4 IM specific resource allocation */
+	retval = bfad_im_probe(bfad);
+	if (retval != BFA_STATUS_OK) {
+		printk(KERN_WARNING "bfad_im_probe failed\n");
+		if (bfa_sm_cmp_state(bfad, bfad_sm_initializing))
+			bfa_sm_set_state(bfad, bfad_sm_failed);
+		bfad_im_probe_undo(bfad);
+		bfad->bfad_flags &= ~BFAD_FC4_PROBE_DONE;
+		bfad_uncfg_pport(bfad);
+		bfad_stop(bfad);
+		return BFA_STATUS_FAILED;
+	} else
+		bfad->bfad_flags |= BFAD_FC4_PROBE_DONE;
+
 	bfad_drv_start(bfad);
 
-	/* pbc vport creation */
-	list_for_each_entry_safe(pcfg, pcfg_new,  &bfad->pbc_pcfg_list,
-					list_entry) {
+	/* Complete pbc vport create */
+	list_for_each_entry_safe(vport, vport_new, &bfad->pbc_vport_list,
+				list_entry) {
 		struct fc_vport_identifiers vid;
 		struct fc_vport *fc_vport;
+		char pwwn_buf[BFA_STRING_32];
 
 		memset(&vid, 0, sizeof(vid));
 		vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
 		vid.vport_type = FC_PORTTYPE_NPIV;
 		vid.disable = false;
-		vid.node_name = wwn_to_u64((u8 *)&pcfg->port_cfg.nwwn);
-		vid.port_name = wwn_to_u64((u8 *)&pcfg->port_cfg.pwwn);
+		vid.node_name = wwn_to_u64((u8 *)
+				(&((vport->fcs_vport).lport.port_cfg.nwwn)));
+		vid.port_name = wwn_to_u64((u8 *)
+				(&((vport->fcs_vport).lport.port_cfg.pwwn)));
 		fc_vport = fc_vport_create(bfad->pport.im_port->shost, 0, &vid);
-		if (!fc_vport)
+		if (!fc_vport) {
+			wwn2str(pwwn_buf, vid.port_name);
 			printk(KERN_WARNING "bfad%d: failed to create pbc vport"
-				" %llx\n", bfad->inst_no, vid.port_name);
-		list_del(&pcfg->list_entry);
-		kfree(pcfg);
-
+				" %s\n", bfad->inst_no, pwwn_buf);
+		}
+		list_del(&vport->list_entry);
+		kfree(vport);
 	}
 
 	/*
@@ -998,24 +1147,15 @@
 	 * passed in module param value as the bfa_linkup_delay.
 	 */
 	if (bfa_linkup_delay < 0) {
-
 		bfa_linkup_delay = bfad_os_get_linkup_delay(bfad);
 		bfad_os_rport_online_wait(bfad);
 		bfa_linkup_delay = -1;
-
-	} else {
+	} else
 		bfad_os_rport_online_wait(bfad);
-	}
 
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name);
+	BFA_LOG(KERN_INFO, bfad, log_level, "bfa device claimed\n");
 
 	return BFA_STATUS_OK;
-
-out_fc4_probe_failure:
-	bfad_fc4_probe_undo(bfad);
-	bfad_uncfg_pport(bfad);
-out_cfg_pport_failure:
-	return BFA_STATUS_FAILED;
 }
 
 int
@@ -1028,18 +1168,8 @@
 
 	while (!kthread_should_stop()) {
 
-		/* Check if the FCS init is done from bfad_drv_init;
-		 * if not done do FCS init and set the flag.
-		 */
-		if (!(bfad->bfad_flags & BFAD_FCS_INIT_DONE)) {
-			spin_lock_irqsave(&bfad->bfad_lock, flags);
-			bfa_fcs_init(&bfad->bfa_fcs);
-			bfad->bfad_flags |= BFAD_FCS_INIT_DONE;
-			spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		}
-
-		/* Start the bfad operations after HAL init done */
-		bfad_start_ops(bfad);
+		/* Send event BFAD_E_INIT_SUCCESS */
+		bfa_sm_send_event(bfad, BFAD_E_INIT_SUCCESS);
 
 		spin_lock_irqsave(&bfad->bfad_lock, flags);
 		bfad->bfad_tsk = NULL;
@@ -1051,9 +1181,198 @@
 	return 0;
 }
 
- /*
-  *  PCI_entry PCI driver entries * {
-  */
+/**
+ *  BFA driver interrupt functions
+ */
+irqreturn_t
+bfad_intx(int irq, void *dev_id)
+{
+	struct bfad_s	*bfad = dev_id;
+	struct list_head	doneq;
+	unsigned long	flags;
+	bfa_boolean_t rc;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+	rc = bfa_intx(&bfad->bfa);
+	if (!rc) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		return IRQ_NONE;
+	}
+
+	bfa_comp_deq(&bfad->bfa, &doneq);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (!list_empty(&doneq)) {
+		bfa_comp_process(&bfad->bfa, &doneq);
+
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfa_comp_free(&bfad->bfa, &doneq);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+		bfa_trc_fp(bfad, irq);
+	}
+
+	return IRQ_HANDLED;
+
+}
+
+static irqreturn_t
+bfad_msix(int irq, void *dev_id)
+{
+	struct bfad_msix_s *vec = dev_id;
+	struct bfad_s *bfad = vec->bfad;
+	struct list_head doneq;
+	unsigned long   flags;
+
+	spin_lock_irqsave(&bfad->bfad_lock, flags);
+
+	bfa_msix(&bfad->bfa, vec->msix.entry);
+	bfa_comp_deq(&bfad->bfa, &doneq);
+	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+
+	if (!list_empty(&doneq)) {
+		bfa_comp_process(&bfad->bfa, &doneq);
+
+		spin_lock_irqsave(&bfad->bfad_lock, flags);
+		bfa_comp_free(&bfad->bfa, &doneq);
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * Initialize the MSIX entry table.
+ */
+static void
+bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
+			 int mask, int max_bit)
+{
+	int	i;
+	int	match = 0x00000001;
+
+	for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
+		if (mask & match) {
+			bfad->msix_tab[bfad->nvec].msix.entry = i;
+			bfad->msix_tab[bfad->nvec].bfad = bfad;
+			msix_entries[bfad->nvec].entry = i;
+			bfad->nvec++;
+		}
+
+		match <<= 1;
+	}
+
+}
+
+int
+bfad_install_msix_handler(struct bfad_s *bfad)
+{
+	int i, error = 0;
+
+	for (i = 0; i < bfad->nvec; i++) {
+		sprintf(bfad->msix_tab[i].name, "bfa-%s-%s",
+				bfad->pci_name,
+				((bfa_asic_id_ct(bfad->hal_pcidev.device_id)) ?
+				msix_name_ct[i] : msix_name_cb[i]));
+
+		error = request_irq(bfad->msix_tab[i].msix.vector,
+				    (irq_handler_t) bfad_msix, 0,
+				    bfad->msix_tab[i].name, &bfad->msix_tab[i]);
+		bfa_trc(bfad, i);
+		bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
+		if (error) {
+			int	j;
+
+			for (j = 0; j < i; j++)
+				free_irq(bfad->msix_tab[j].msix.vector,
+						&bfad->msix_tab[j]);
+
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Setup MSIX based interrupt.
+ */
+int
+bfad_setup_intr(struct bfad_s *bfad)
+{
+	int error = 0;
+	u32 mask = 0, i, num_bit = 0, max_bit = 0;
+	struct msix_entry msix_entries[MAX_MSIX_ENTRY];
+	struct pci_dev *pdev = bfad->pcidev;
+
+	/* Call BFA to get the msix map for this PCI function.  */
+	bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
+
+	/* Set up the msix entry table */
+	bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
+
+	if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) ||
+	    (!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) {
+
+		error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
+		if (error) {
+			/*
+			 * Only error number of vector is available.
+			 * We don't have a mechanism to map multiple
+			 * interrupts into one vector, so even if we
+			 * can try to request less vectors, we don't
+			 * know how to associate interrupt events to
+			 *  vectors. Linux doesn't dupicate vectors
+			 * in the MSIX table for this case.
+			 */
+
+			printk(KERN_WARNING "bfad%d: "
+				"pci_enable_msix failed (%d),"
+				" use line based.\n", bfad->inst_no, error);
+
+			goto line_based;
+		}
+
+		/* Save the vectors */
+		for (i = 0; i < bfad->nvec; i++) {
+			bfa_trc(bfad, msix_entries[i].vector);
+			bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
+		}
+
+		bfa_msix_init(&bfad->bfa, bfad->nvec);
+
+		bfad->bfad_flags |= BFAD_MSIX_ON;
+
+		return error;
+	}
+
+line_based:
+	error = 0;
+	if (request_irq
+	    (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
+	     BFAD_DRIVER_NAME, bfad) != 0) {
+		/* Enable interrupt handler failed */
+		return 1;
+	}
+
+	return error;
+}
+
+void
+bfad_remove_intr(struct bfad_s *bfad)
+{
+	int	i;
+
+	if (bfad->bfad_flags & BFAD_MSIX_ON) {
+		for (i = 0; i < bfad->nvec; i++)
+			free_irq(bfad->msix_tab[i].msix.vector,
+					&bfad->msix_tab[i]);
+
+		pci_disable_msix(bfad->pcidev);
+		bfad->bfad_flags &= ~BFAD_MSIX_ON;
+	} else {
+		free_irq(bfad->pcidev->irq, bfad);
+	}
+}
 
 /**
  * PCI probe entry.
@@ -1061,18 +1380,14 @@
 int
 bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
-	struct bfad_s  *bfad;
-	int             error = -ENODEV, retval;
+	struct bfad_s	*bfad;
+	int		error = -ENODEV, retval;
 
-	/*
-	 * For single port cards - only claim function 0
-	 */
-	if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P)
-	    && (PCI_FUNC(pdev->devfn) != 0))
+	/* For single port cards - only claim function 0 */
+	if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P) &&
+		(PCI_FUNC(pdev->devfn) != 0))
 		return -ENODEV;
 
-	BFA_TRACE(BFA_INFO, "bfad_pci_probe entry");
-
 	bfad = kzalloc(sizeof(struct bfad_s), GFP_KERNEL);
 	if (!bfad) {
 		error = -ENOMEM;
@@ -1086,21 +1401,11 @@
 		goto out_alloc_trace_failure;
 	}
 
-	/*
-	 * LOG/TRACE INIT
-	 */
+	/* TRACE INIT */
 	bfa_trc_init(bfad->trcmod);
 	bfa_trc(bfad, bfad_inst);
 
-	bfad->logmod = &bfad->log_data;
-	bfa_log_init(bfad->logmod, (char *)pci_name(pdev), bfa_os_printf);
-
-	bfad_drv_log_level_set(bfad);
-
-	bfad->aen = &bfad->aen_buf;
-
 	if (!(bfad_load_fwimg(pdev))) {
-		printk(KERN_WARNING "bfad_load_fwimg failure!\n");
 		kfree(bfad->trcmod);
 		goto out_alloc_trace_failure;
 	}
@@ -1117,46 +1422,31 @@
 	list_add_tail(&bfad->list_entry, &bfad_list);
 	mutex_unlock(&bfad_mutex);
 
+	/* Initializing the state machine: State set to uninit */
+	bfa_sm_set_state(bfad, bfad_sm_uninit);
+
 	spin_lock_init(&bfad->bfad_lock);
 	pci_set_drvdata(pdev, bfad);
 
 	bfad->ref_count = 0;
 	bfad->pport.bfad = bfad;
-	INIT_LIST_HEAD(&bfad->pbc_pcfg_list);
-
-	bfad->bfad_tsk = kthread_create(bfad_worker, (void *) bfad, "%s",
-					"bfad_worker");
-	if (IS_ERR(bfad->bfad_tsk)) {
-		printk(KERN_INFO "bfad[%d]: Kernel thread"
-			" creation failed!\n",
-			bfad->inst_no);
-		goto out_kthread_create_failure;
-	}
+	INIT_LIST_HEAD(&bfad->pbc_vport_list);
 
 	retval = bfad_drv_init(bfad);
 	if (retval != BFA_STATUS_OK)
 		goto out_drv_init_failure;
-	if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
-		bfad->bfad_flags |= BFAD_HAL_INIT_FAIL;
-		printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no);
-		goto ok;
-	}
 
-	retval = bfad_start_ops(bfad);
-	if (retval != BFA_STATUS_OK)
-		goto out_start_ops_failure;
+	bfa_sm_send_event(bfad, BFAD_E_CREATE);
 
-	kthread_stop(bfad->bfad_tsk);
-	bfad->bfad_tsk = NULL;
+	if (bfa_sm_cmp_state(bfad, bfad_sm_uninit))
+		goto out_bfad_sm_failure;
 
-ok:
 	return 0;
 
-out_start_ops_failure:
-	bfad_drv_uninit(bfad);
+out_bfad_sm_failure:
+	bfa_detach(&bfad->bfa);
+	bfad_hal_mem_release(bfad);
 out_drv_init_failure:
-	kthread_stop(bfad->bfad_tsk);
-out_kthread_create_failure:
 	mutex_lock(&bfad_mutex);
 	bfad_inst--;
 	list_del(&bfad->list_entry);
@@ -1176,62 +1466,29 @@
 void
 bfad_pci_remove(struct pci_dev *pdev)
 {
-	struct bfad_s  *bfad = pci_get_drvdata(pdev);
-	unsigned long   flags;
+	struct bfad_s	      *bfad = pci_get_drvdata(pdev);
+	unsigned long	flags;
 
 	bfa_trc(bfad, bfad->inst_no);
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	if (bfad->bfad_tsk != NULL)
+	if (bfad->bfad_tsk != NULL) {
+		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 		kthread_stop(bfad->bfad_tsk);
-	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
-	if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE)
-	    && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) {
-
-		spin_lock_irqsave(&bfad->bfad_lock, flags);
-		init_completion(&bfad->comp);
-		bfa_stop(&bfad->bfa);
+	} else {
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		wait_for_completion(&bfad->comp);
-
-		bfad_remove_intr(bfad);
-		del_timer_sync(&bfad->hal_tmo);
-		goto hal_detach;
-	} else if (!(bfad->bfad_flags & BFAD_DRV_INIT_DONE)) {
-		goto remove_sysfs;
 	}
 
-	if (bfad->bfad_flags & BFAD_HAL_START_DONE) {
-		bfad_drv_stop(bfad);
-	} else if (bfad->bfad_flags & BFAD_DRV_INIT_DONE) {
-		/* Invoking bfa_stop() before bfa_detach
-		 * when HAL and DRV init are success
-		 * but HAL start did not occur.
-		 */
-		spin_lock_irqsave(&bfad->bfad_lock, flags);
-		init_completion(&bfad->comp);
-		bfa_stop(&bfad->bfa);
-		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		wait_for_completion(&bfad->comp);
-	}
+	/* Send Event BFAD_E_STOP */
+	bfa_sm_send_event(bfad, BFAD_E_STOP);
 
-	bfad_remove_intr(bfad);
-	del_timer_sync(&bfad->hal_tmo);
-
-	if (bfad->bfad_flags & BFAD_FC4_PROBE_DONE)
-		bfad_fc4_probe_undo(bfad);
-
-	if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE)
-		bfad_uncfg_pport(bfad);
-
-hal_detach:
+	/* Driver detach and dealloc mem */
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	bfa_detach(&bfad->bfa);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	bfad_hal_mem_release(bfad);
-remove_sysfs:
 
+	/* Cleaning the BFAD instance */
 	mutex_lock(&bfad_mutex);
 	bfad_inst--;
 	list_del(&bfad->list_entry);
@@ -1242,35 +1499,34 @@
 	kfree(bfad);
 }
 
-
-static struct pci_device_id bfad_id_table[] = {
+struct pci_device_id bfad_id_table[] = {
 	{
-	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
-	 .device = BFA_PCI_DEVICE_ID_FC_8G2P,
-	 .subvendor = PCI_ANY_ID,
-	 .subdevice = PCI_ANY_ID,
-	 },
+		.vendor = BFA_PCI_VENDOR_ID_BROCADE,
+		.device = BFA_PCI_DEVICE_ID_FC_8G2P,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+	},
 	{
-	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
-	 .device = BFA_PCI_DEVICE_ID_FC_8G1P,
-	 .subvendor = PCI_ANY_ID,
-	 .subdevice = PCI_ANY_ID,
-	 },
+		.vendor = BFA_PCI_VENDOR_ID_BROCADE,
+		.device = BFA_PCI_DEVICE_ID_FC_8G1P,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+	},
 	{
-	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
-	 .device = BFA_PCI_DEVICE_ID_CT,
-	 .subvendor = PCI_ANY_ID,
-	 .subdevice = PCI_ANY_ID,
-	 .class = (PCI_CLASS_SERIAL_FIBER << 8),
-	 .class_mask = ~0,
-	 },
+		.vendor = BFA_PCI_VENDOR_ID_BROCADE,
+		.device = BFA_PCI_DEVICE_ID_CT,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+		.class = (PCI_CLASS_SERIAL_FIBER << 8),
+		.class_mask = ~0,
+	},
 	{
-	 .vendor = BFA_PCI_VENDOR_ID_BROCADE,
-	 .device = BFA_PCI_DEVICE_ID_CT_FC,
-	 .subvendor = PCI_ANY_ID,
-	 .subdevice = PCI_ANY_ID,
-	 .class = (PCI_CLASS_SERIAL_FIBER << 8),
-	 .class_mask = ~0,
+		.vendor = BFA_PCI_VENDOR_ID_BROCADE,
+		.device = BFA_PCI_DEVICE_ID_CT_FC,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+		.class = (PCI_CLASS_SERIAL_FIBER << 8),
+		.class_mask = ~0,
 	},
 
 	{0, 0},
@@ -1286,89 +1542,104 @@
 };
 
 /**
- *  Linux driver module functions
- */
-bfa_status_t
-bfad_fc4_module_init(void)
-{
-	int             rc;
-
-	rc = bfad_im_module_init();
-	if (rc != BFA_STATUS_OK)
-		goto ext;
-
-	bfad_tm_module_init();
-	if (ipfc_enable)
-		bfad_ipfc_module_init();
-ext:
-	return rc;
-}
-
-void
-bfad_fc4_module_exit(void)
-{
-	if (ipfc_enable)
-		bfad_ipfc_module_exit();
-	bfad_tm_module_exit();
-	bfad_im_module_exit();
-}
-
-/**
  * Driver module init.
  */
-static int      __init
+static int __init
 bfad_init(void)
 {
-	int             error = 0;
+	int		error = 0;
 
 	printk(KERN_INFO "Brocade BFA FC/FCOE SCSI driver - version: %s\n",
-	       BFAD_DRIVER_VERSION);
+			BFAD_DRIVER_VERSION);
 
 	if (num_sgpgs > 0)
 		num_sgpgs_parm = num_sgpgs;
 
-	error = bfad_fc4_module_init();
+	error = bfad_im_module_init();
 	if (error) {
 		error = -ENOMEM;
-		printk(KERN_WARNING "bfad_fc4_module_init failure\n");
+		printk(KERN_WARNING "bfad_im_module_init failure\n");
 		goto ext;
 	}
 
-	if (!strcmp(FCPI_NAME, " fcpim"))
-		bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IM;
-	if (!strcmp(FCPT_NAME, " fcptm"))
-		bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_TM;
-	if (!strcmp(IPFC_NAME, " ipfc"))
-		bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IPFC;
+	if (strcmp(FCPI_NAME, " fcpim") == 0)
+		supported_fc4s |= BFA_LPORT_ROLE_FCP_IM;
 
 	bfa_ioc_auto_recover(ioc_auto_recover);
 	bfa_fcs_rport_set_del_timeout(rport_del_timeout);
-	error = pci_register_driver(&bfad_pci_driver);
 
+	error = pci_register_driver(&bfad_pci_driver);
 	if (error) {
-		printk(KERN_WARNING "bfad pci_register_driver failure\n");
+		printk(KERN_WARNING "pci_register_driver failure\n");
 		goto ext;
 	}
 
 	return 0;
 
 ext:
-	bfad_fc4_module_exit();
+	bfad_im_module_exit();
 	return error;
 }
 
 /**
  * Driver module exit.
  */
-static void     __exit
+static void __exit
 bfad_exit(void)
 {
 	pci_unregister_driver(&bfad_pci_driver);
-	bfad_fc4_module_exit();
+	bfad_im_module_exit();
 	bfad_free_fwimg();
 }
 
-#define BFAD_PROTO_NAME FCPI_NAME FCPT_NAME IPFC_NAME
+/* Firmware handling */
+u32 *
+bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+		u32 *bfi_image_size, char *fw_name)
+{
+	const struct firmware *fw;
+
+	if (request_firmware(&fw, fw_name, &pdev->dev)) {
+		printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
+		goto error;
+	}
+
+	*bfi_image = vmalloc(fw->size);
+	if (NULL == *bfi_image) {
+		printk(KERN_ALERT "Fail to allocate buffer for fw image "
+			"size=%x!\n", (u32) fw->size);
+		goto error;
+	}
+
+	memcpy(*bfi_image, fw->data, fw->size);
+	*bfi_image_size = fw->size/sizeof(u32);
+
+	return *bfi_image;
+
+error:
+	return NULL;
+}
+
+u32 *
+bfad_get_firmware_buf(struct pci_dev *pdev)
+{
+	if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) {
+		if (bfi_image_ct_fc_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_ct_fc,
+				&bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC);
+		return bfi_image_ct_fc;
+	} else if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
+		if (bfi_image_ct_cna_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_ct_cna,
+				&bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA);
+		return bfi_image_ct_cna;
+	} else {
+		if (bfi_image_cb_fc_size == 0)
+			bfad_read_firmware(pdev, &bfi_image_cb_fc,
+				&bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC);
+		return bfi_image_cb_fc;
+	}
+}
 
 module_init(bfad_init);
 module_exit(bfad_exit);
@@ -1376,5 +1647,3 @@
 MODULE_DESCRIPTION("Brocade Fibre Channel HBA Driver" BFAD_PROTO_NAME);
 MODULE_AUTHOR("Brocade Communications Systems, Inc.");
 MODULE_VERSION(BFAD_DRIVER_VERSION);
-
-
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index 0818eb0..d884372 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -19,15 +19,8 @@
  *  bfa_attr.c Linux driver configuration interface module.
  */
 
-#include <linux/slab.h>
 #include "bfad_drv.h"
 #include "bfad_im.h"
-#include "bfad_trcmod.h"
-#include "bfad_attr.h"
-
-/**
- *  FC_transport_template FC transport template
- */
 
 /**
  * FC transport template entry, get SCSI target port ID.
@@ -42,7 +35,7 @@
 	u32        fc_id = -1;
 	unsigned long   flags;
 
-	shost = bfad_os_starget_to_shost(starget);
+	shost = dev_to_shost(starget->dev.parent);
 	im_port = (struct bfad_im_port_s *) shost->hostdata[0];
 	bfad = im_port->bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -68,7 +61,7 @@
 	u64             node_name = 0;
 	unsigned long   flags;
 
-	shost = bfad_os_starget_to_shost(starget);
+	shost = dev_to_shost(starget->dev.parent);
 	im_port = (struct bfad_im_port_s *) shost->hostdata[0];
 	bfad = im_port->bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -94,7 +87,7 @@
 	u64             port_name = 0;
 	unsigned long   flags;
 
-	shost = bfad_os_starget_to_shost(starget);
+	shost = dev_to_shost(starget->dev.parent);
 	im_port = (struct bfad_im_port_s *) shost->hostdata[0];
 	bfad = im_port->bfad;
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
@@ -118,17 +111,7 @@
 	struct bfad_port_s    *port = im_port->port;
 
 	fc_host_port_id(shost) =
-			bfa_os_hton3b(bfa_fcs_port_get_fcid(port->fcs_port));
-}
-
-
-
-
-
-struct Scsi_Host *
-bfad_os_starget_to_shost(struct scsi_target *starget)
-{
-	return dev_to_shost(starget->dev.parent);
+			bfa_os_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port));
 }
 
 /**
@@ -140,21 +123,21 @@
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s         *bfad = im_port->bfad;
-	struct bfa_pport_attr_s attr;
+	struct bfa_lport_attr_s port_attr;
 
-	bfa_fcport_get_attr(&bfad->bfa, &attr);
+	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
 
-	switch (attr.port_type) {
-	case BFA_PPORT_TYPE_NPORT:
+	switch (port_attr.port_type) {
+	case BFA_PORT_TYPE_NPORT:
 		fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
 		break;
-	case BFA_PPORT_TYPE_NLPORT:
+	case BFA_PORT_TYPE_NLPORT:
 		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
 		break;
-	case BFA_PPORT_TYPE_P2P:
+	case BFA_PORT_TYPE_P2P:
 		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
 		break;
-	case BFA_PPORT_TYPE_LPORT:
+	case BFA_PORT_TYPE_LPORT:
 		fc_host_port_type(shost) = FC_PORTTYPE_LPORT;
 		break;
 	default:
@@ -172,25 +155,28 @@
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s         *bfad = im_port->bfad;
-	struct bfa_pport_attr_s attr;
+	struct bfa_port_attr_s attr;
 
 	bfa_fcport_get_attr(&bfad->bfa, &attr);
 
 	switch (attr.port_state) {
-	case BFA_PPORT_ST_LINKDOWN:
+	case BFA_PORT_ST_LINKDOWN:
 		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
 		break;
-	case BFA_PPORT_ST_LINKUP:
+	case BFA_PORT_ST_LINKUP:
 		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
 		break;
-	case BFA_PPORT_ST_UNINIT:
-	case BFA_PPORT_ST_ENABLING_QWAIT:
-	case BFA_PPORT_ST_ENABLING:
-	case BFA_PPORT_ST_DISABLING_QWAIT:
-	case BFA_PPORT_ST_DISABLING:
-	case BFA_PPORT_ST_DISABLED:
-	case BFA_PPORT_ST_STOPPED:
-	case BFA_PPORT_ST_IOCDOWN:
+	case BFA_PORT_ST_DISABLED:
+	case BFA_PORT_ST_STOPPED:
+	case BFA_PORT_ST_IOCDOWN:
+	case BFA_PORT_ST_IOCDIS:
+		fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
+		break;
+	case BFA_PORT_ST_UNINIT:
+	case BFA_PORT_ST_ENABLING_QWAIT:
+	case BFA_PORT_ST_ENABLING:
+	case BFA_PORT_ST_DISABLING_QWAIT:
+	case BFA_PORT_ST_DISABLING:
 	default:
 		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
 		break;
@@ -210,13 +196,9 @@
 	memset(fc_host_active_fc4s(shost), 0,
 	       sizeof(fc_host_active_fc4s(shost)));
 
-	if (port->supported_fc4s &
-		(BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
+	if (port->supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
 		fc_host_active_fc4s(shost)[2] = 1;
 
-	if (port->supported_fc4s & BFA_PORT_ROLE_FCP_IPFC)
-		fc_host_active_fc4s(shost)[3] = 0x20;
-
 	fc_host_active_fc4s(shost)[7] = 1;
 }
 
@@ -229,29 +211,29 @@
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s         *bfad = im_port->bfad;
-	struct bfa_pport_attr_s attr;
-	unsigned long   flags;
+	struct bfa_port_attr_s attr;
 
-	spin_lock_irqsave(shost->host_lock, flags);
 	bfa_fcport_get_attr(&bfad->bfa, &attr);
 	switch (attr.speed) {
-	case BFA_PPORT_SPEED_8GBPS:
+	case BFA_PORT_SPEED_10GBPS:
+		fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
+		break;
+	case BFA_PORT_SPEED_8GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
 		break;
-	case BFA_PPORT_SPEED_4GBPS:
+	case BFA_PORT_SPEED_4GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
 		break;
-	case BFA_PPORT_SPEED_2GBPS:
+	case BFA_PORT_SPEED_2GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_2GBIT;
 		break;
-	case BFA_PPORT_SPEED_1GBPS:
+	case BFA_PORT_SPEED_1GBPS:
 		fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
 		break;
 	default:
 		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 		break;
 	}
-	spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
 /**
@@ -265,7 +247,7 @@
 	struct bfad_port_s    *port = im_port->port;
 	wwn_t           fabric_nwwn = 0;
 
-	fabric_nwwn = bfa_fcs_port_get_fabric_name(port->fcs_port);
+	fabric_nwwn = bfa_fcs_lport_get_fabric_name(port->fcs_port);
 
 	fc_host_fabric_name(shost) = bfa_os_htonll(fabric_nwwn);
 
@@ -281,23 +263,44 @@
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s         *bfad = im_port->bfad;
 	struct bfad_hal_comp fcomp;
+	union bfa_port_stats_u *fcstats;
 	struct fc_host_statistics *hstats;
 	bfa_status_t    rc;
 	unsigned long   flags;
 
+	fcstats = kzalloc(sizeof(union bfa_port_stats_u), GFP_KERNEL);
+	if (fcstats == NULL)
+		return NULL;
+
 	hstats = &bfad->link_stats;
 	init_completion(&fcomp.comp);
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	memset(hstats, 0, sizeof(struct fc_host_statistics));
-	rc =  bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
-				     (union bfa_pport_stats_u *) hstats,
-				     bfad_hcb_comp, &fcomp);
+	rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
+				fcstats, bfad_hcb_comp, &fcomp);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	if (rc != BFA_STATUS_OK)
 		return NULL;
 
 	wait_for_completion(&fcomp.comp);
 
+	/* Fill the fc_host_statistics structure */
+	hstats->seconds_since_last_reset = fcstats->fc.secs_reset;
+	hstats->tx_frames = fcstats->fc.tx_frames;
+	hstats->tx_words  = fcstats->fc.tx_words;
+	hstats->rx_frames = fcstats->fc.rx_frames;
+	hstats->rx_words  = fcstats->fc.rx_words;
+	hstats->lip_count = fcstats->fc.lip_count;
+	hstats->nos_count = fcstats->fc.nos_count;
+	hstats->error_frames = fcstats->fc.error_frames;
+	hstats->dumped_frames = fcstats->fc.dropped_frames;
+	hstats->link_failure_count = fcstats->fc.link_failures;
+	hstats->loss_of_sync_count = fcstats->fc.loss_of_syncs;
+	hstats->loss_of_signal_count = fcstats->fc.loss_of_signals;
+	hstats->prim_seq_protocol_err_count = fcstats->fc.primseq_errs;
+	hstats->invalid_crc_count = fcstats->fc.invalid_crcs;
+
+	kfree(fcstats);
 	return hstats;
 }
 
@@ -317,7 +320,7 @@
 	init_completion(&fcomp.comp);
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	rc = bfa_port_clear_stats(BFA_FCPORT(&bfad->bfa), bfad_hcb_comp,
-		&fcomp);
+					&fcomp);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	if (rc != BFA_STATUS_OK)
@@ -372,8 +375,8 @@
 	struct bfad_im_port_s *im_port =
 		(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s *bfad = im_port->bfad;
-	struct bfa_port_cfg_s port_cfg;
-	struct bfad_pcfg_s *pcfg;
+	struct bfa_lport_cfg_s port_cfg;
+	struct bfad_vport_s *vp;
 	int status = 0, rc;
 	unsigned long flags;
 
@@ -382,12 +385,14 @@
 	u64_to_wwn(fc_vport->port_name, (u8 *)&port_cfg.pwwn);
 	if (strlen(vname) > 0)
 		strcpy((char *)&port_cfg.sym_name, vname);
-	port_cfg.roles = BFA_PORT_ROLE_FCP_IM;
+	port_cfg.roles = BFA_LPORT_ROLE_FCP_IM;
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	list_for_each_entry(pcfg, &bfad->pbc_pcfg_list, list_entry) {
-		if (port_cfg.pwwn == pcfg->port_cfg.pwwn) {
-			port_cfg.preboot_vp = pcfg->port_cfg.preboot_vp;
+	list_for_each_entry(vp, &bfad->pbc_vport_list, list_entry) {
+		if (port_cfg.pwwn ==
+				vp->fcs_vport.lport.port_cfg.pwwn) {
+			port_cfg.preboot_vp =
+				vp->fcs_vport.lport.port_cfg.preboot_vp;
 			break;
 		}
 	}
@@ -638,7 +643,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
 
 	bfa_get_adapter_serial_num(&bfad->bfa, serial_num);
@@ -652,7 +657,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char model[BFA_ADAPTER_MODEL_NAME_LEN];
 
 	bfa_get_adapter_model(&bfad->bfa, model);
@@ -666,10 +671,54 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
+	char model[BFA_ADAPTER_MODEL_NAME_LEN];
 	char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
 
-	bfa_get_adapter_model(&bfad->bfa, model_descr);
+	bfa_get_adapter_model(&bfad->bfa, model);
+	if (!strcmp(model, "Brocade-425"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 4Gbps PCIe dual port FC HBA");
+	else if (!strcmp(model, "Brocade-825"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 8Gbps PCIe dual port FC HBA");
+	else if (!strcmp(model, "Brocade-42B"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP 4Gbps PCIe dual port FC HBA");
+	else if (!strcmp(model, "Brocade-82B"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP 8Gbps PCIe dual port FC HBA");
+	else if (!strcmp(model, "Brocade-1010"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 10Gbps single port CNA");
+	else if (!strcmp(model, "Brocade-1020"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 10Gbps dual port CNA");
+	else if (!strcmp(model, "Brocade-1007"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 10Gbps CNA");
+	else if (!strcmp(model, "Brocade-415"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 4Gbps PCIe single port FC HBA");
+	else if (!strcmp(model, "Brocade-815"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 8Gbps PCIe single port FC HBA");
+	else if (!strcmp(model, "Brocade-41B"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP 4Gbps PCIe single port FC HBA");
+	else if (!strcmp(model, "Brocade-81B"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP 8Gbps PCIe single port FC HBA");
+	else if (!strcmp(model, "Brocade-804"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"HP Bladesystem C-class 8Gbps FC HBA");
+	else if (!strcmp(model, "Brocade-902"))
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Brocade 10Gbps CNA");
+	else
+		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
+			"Invalid Model");
+
 	return snprintf(buf, PAGE_SIZE, "%s\n", model_descr);
 }
 
@@ -683,7 +732,7 @@
 	struct bfad_port_s    *port = im_port->port;
 	u64        nwwn;
 
-	nwwn = bfa_fcs_port_get_nwwn(port->fcs_port);
+	nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port);
 	return snprintf(buf, PAGE_SIZE, "0x%llx\n", bfa_os_htonll(nwwn));
 }
 
@@ -694,14 +743,14 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
-	char model[BFA_ADAPTER_MODEL_NAME_LEN];
-	char fw_ver[BFA_VERSION_LEN];
+	struct bfad_s *bfad = im_port->bfad;
+	struct bfa_lport_attr_s port_attr;
+	char symname[BFA_SYMNAME_MAXLEN];
 
-	bfa_get_adapter_model(&bfad->bfa, model);
-	bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
-	return snprintf(buf, PAGE_SIZE, "Brocade %s FV%s DV%s\n",
-		model, fw_ver, BFAD_DRIVER_VERSION);
+	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
+	strncpy(symname, port_attr.port_cfg.sym_name.symname,
+			BFA_SYMNAME_MAXLEN);
+	return snprintf(buf, PAGE_SIZE, "%s\n", symname);
 }
 
 static ssize_t
@@ -711,7 +760,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char hw_ver[BFA_VERSION_LEN];
 
 	bfa_get_pci_chip_rev(&bfad->bfa, hw_ver);
@@ -732,7 +781,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char optrom_ver[BFA_VERSION_LEN];
 
 	bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver);
@@ -746,7 +795,7 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 	char fw_ver[BFA_VERSION_LEN];
 
 	bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
@@ -760,10 +809,10 @@
 	struct Scsi_Host *shost = class_to_shost(dev);
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
-		bfa_get_nports(&bfad->bfa));
+			bfa_get_nports(&bfad->bfa));
 }
 
 static ssize_t
@@ -788,10 +837,10 @@
 
 	rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC);
 	if (rports == NULL)
-		return -ENOMEM;
+		return snprintf(buf, PAGE_SIZE, "Failed\n");
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	bfa_fcs_port_get_rports(port->fcs_port, rports, &nrports);
+	bfa_fcs_lport_get_rports(port->fcs_port, rports, &nrports);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	kfree(rports);
 
@@ -837,19 +886,19 @@
 };
 
 struct device_attribute *bfad_im_vport_attrs[] = {
-    &dev_attr_serial_number,
-    &dev_attr_model,
-    &dev_attr_model_description,
-    &dev_attr_node_name,
-    &dev_attr_symbolic_name,
-    &dev_attr_hardware_version,
-    &dev_attr_driver_version,
-    &dev_attr_option_rom_version,
-    &dev_attr_firmware_version,
-    &dev_attr_number_of_ports,
-    &dev_attr_driver_name,
-    &dev_attr_number_of_discovered_ports,
-    NULL,
+	&dev_attr_serial_number,
+	&dev_attr_model,
+	&dev_attr_model_description,
+	&dev_attr_node_name,
+	&dev_attr_symbolic_name,
+	&dev_attr_hardware_version,
+	&dev_attr_driver_version,
+	&dev_attr_option_rom_version,
+	&dev_attr_firmware_version,
+	&dev_attr_number_of_ports,
+	&dev_attr_driver_name,
+	&dev_attr_number_of_discovered_ports,
+	NULL,
 };
 
 
diff --git a/drivers/scsi/bfa/bfad_attr.h b/drivers/scsi/bfa/bfad_attr.h
deleted file mode 100644
index bf01020..0000000
--- a/drivers/scsi/bfa/bfad_attr.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFAD_ATTR_H__
-#define __BFAD_ATTR_H__
-
-/**
- *  FC_transport_template FC transport template
- */
-
-struct Scsi_Host*
-bfad_os_dev_to_shost(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI target port ID.
- */
-void
-bfad_im_get_starget_port_id(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI target nwwn.
- */
-void
-bfad_im_get_starget_node_name(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI target pwwn.
- */
-void
-bfad_im_get_starget_port_name(struct scsi_target *starget);
-
-/**
- * FC transport template entry, get SCSI host port ID.
- */
-void
-bfad_im_get_host_port_id(struct Scsi_Host *shost);
-
-struct Scsi_Host*
-bfad_os_starget_to_shost(struct scsi_target *starget);
-
-
-#endif /*  __BFAD_ATTR_H__ */
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 4b82f12..69ed1c4 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -17,8 +17,8 @@
 
 #include <linux/debugfs.h>
 
-#include <bfad_drv.h>
-#include <bfad_im.h>
+#include "bfad_drv.h"
+#include "bfad_im.h"
 
 /*
  * BFA debufs interface
@@ -28,7 +28,7 @@
  * mount -t debugfs none /sys/kernel/debug
  *
  * BFA Hierarchy:
- * 	- bfa/host#
+ *	- bfa/host#
  * where the host number corresponds to the one under /sys/class/scsi_host/host#
  *
  * Debugging service available per host:
@@ -217,7 +217,7 @@
 #define BFA_REG_ADDRSZ(__bfa)	\
 	((bfa_ioc_devid(&(__bfa)->ioc) == BFA_PCI_DEVICE_ID_CT) ?	\
 		BFA_REG_CT_ADDRSZ : BFA_REG_CB_ADDRSZ)
-#define BFA_REG_ADDRMSK(__bfa)  ((uint32_t)(BFA_REG_ADDRSZ(__bfa) - 1))
+#define BFA_REG_ADDRMSK(__bfa)  ((u32)(BFA_REG_ADDRSZ(__bfa) - 1))
 
 static bfa_status_t
 bfad_reg_offset_check(struct bfa_s *bfa, u32 offset, u32 len)
@@ -359,7 +359,7 @@
 		return -EINVAL;
 	}
 
-	reg_addr = (uint32_t *) ((uint8_t *) bfa_ioc_bar0(ioc) + addr);
+	reg_addr = (u32 *) ((u8 *) bfa_ioc_bar0(ioc) + addr);
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	bfa_reg_write(reg_addr, val);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 465b8b8..98420bb 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -28,30 +28,27 @@
 
 #include "bfa_os_inc.h"
 
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs.h>
-#include <defs/bfa_defs_pci.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_rport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <defs/bfa_defs_vport.h>
-#include <fcs/bfa_fcs_vport.h>
+#include "bfa_modules.h"
+#include "bfa_fcs.h"
+#include "bfa_defs_fcs.h"
 
-#include <cs/bfa_plog.h>
-#include "aen/bfa_aen.h"
-#include <log/bfa_log_linux.h>
+#include "bfa_plog.h"
+#include "bfa_cs.h"
 
-#define BFAD_DRIVER_NAME        "bfa"
+#define BFAD_DRIVER_NAME	"bfa"
 #ifdef BFA_DRIVER_VERSION
 #define BFAD_DRIVER_VERSION    BFA_DRIVER_VERSION
 #else
-#define BFAD_DRIVER_VERSION    "2.2.2.1"
+#define BFAD_DRIVER_VERSION    "2.3.2.0"
 #endif
 
-
+#define BFAD_PROTO_NAME FCPI_NAME
 #define BFAD_IRQ_FLAGS IRQF_SHARED
 
+#ifndef FC_PORTSPEED_8GBIT
+#define FC_PORTSPEED_8GBIT 0x10
+#endif
+
 /*
  * BFAD flags
  */
@@ -62,9 +59,9 @@
 #define BFAD_HAL_START_DONE			0x00000010
 #define BFAD_PORT_ONLINE			0x00000020
 #define BFAD_RPORT_ONLINE			0x00000040
-#define BFAD_FCS_INIT_DONE                      0x00000080
-#define BFAD_HAL_INIT_FAIL                      0x00000100
-#define BFAD_FC4_PROBE_DONE                     0x00000200
+#define BFAD_FCS_INIT_DONE			0x00000080
+#define BFAD_HAL_INIT_FAIL			0x00000100
+#define BFAD_FC4_PROBE_DONE			0x00000200
 #define BFAD_PORT_DELETE			0x00000001
 
 /*
@@ -77,8 +74,8 @@
 /*
  * BFAD configuration parameter default values
  */
-#define BFAD_LUN_QUEUE_DEPTH 		32
-#define BFAD_IO_MAX_SGE 		SG_ALL
+#define BFAD_LUN_QUEUE_DEPTH	32
+#define BFAD_IO_MAX_SGE		SG_ALL
 
 #define bfad_isr_t irq_handler_t
 
@@ -87,6 +84,16 @@
 struct bfad_msix_s {
 	struct bfad_s *bfad;
 	struct msix_entry msix;
+	char name[32];
+};
+
+/*
+ * Only append to the enums defined here to avoid any versioning
+ * needed between trace utility and driver version
+ */
+enum {
+	BFA_TRC_LDRV_BFAD		= 1,
+	BFA_TRC_LDRV_IM			= 2,
 };
 
 enum bfad_port_pvb_type {
@@ -101,17 +108,13 @@
  */
 struct bfad_port_s {
 	struct list_head list_entry;
-	struct bfad_s         *bfad;
-	struct bfa_fcs_port_s *fcs_port;
-	u32        roles;
-	s32         flags;
-	u32        supported_fc4s;
-	u8		ipfc_flags;
+	struct bfad_s	*bfad;
+	struct bfa_fcs_lport_s *fcs_port;
+	u32	roles;
+	s32		flags;
+	u32	supported_fc4s;
 	enum bfad_port_pvb_type pvb_type;
 	struct bfad_im_port_s *im_port;	/* IM specific data */
-	struct bfad_tm_port_s *tm_port;	/* TM specific data */
-	struct bfad_ipfc_port_s *ipfc_port;	/* IPFC specific data */
-
 	/* port debugfs specific data */
 	struct dentry *port_debugfs_root;
 };
@@ -124,7 +127,6 @@
 	struct bfa_fcs_vport_s fcs_vport;
 	struct completion *comp_del;
 	struct list_head list_entry;
-	struct bfa_port_cfg_s port_cfg;
 };
 
 /*
@@ -137,20 +139,35 @@
 };
 
 struct bfad_cfg_param_s {
-	u32        rport_del_timeout;
-	u32        ioc_queue_depth;
-	u32        lun_queue_depth;
-	u32        io_max_sge;
-	u32        binding_method;
+	u32	rport_del_timeout;
+	u32	ioc_queue_depth;
+	u32	lun_queue_depth;
+	u32	io_max_sge;
+	u32	binding_method;
+};
+
+union bfad_tmp_buf {
+	/* From struct bfa_adapter_attr_s */
+	char		manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
+	char		serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
+	char		model[BFA_ADAPTER_MODEL_NAME_LEN];
+	char		fw_ver[BFA_VERSION_LEN];
+	char		optrom_ver[BFA_VERSION_LEN];
+
+	/* From struct bfa_ioc_pci_attr_s */
+	u8		chip_rev[BFA_IOC_CHIP_REV_LEN];  /*  chip revision */
+
+	wwn_t		wwn[BFA_FCS_MAX_LPORTS];
 };
 
 /*
  * BFAD (PCI function) data structure
  */
 struct bfad_s {
+	bfa_sm_t	sm;	/* state machine */
 	struct list_head list_entry;
-	struct bfa_s       bfa;
-	struct bfa_fcs_s       bfa_fcs;
+	struct bfa_s	bfa;
+	struct bfa_fcs_s bfa_fcs;
 	struct pci_dev *pcidev;
 	const char *pci_name;
 	struct bfa_pcidev_s hal_pcidev;
@@ -163,41 +180,41 @@
 	struct bfad_port_s     pport;	/* physical port of the BFAD */
 	struct bfa_meminfo_s meminfo;
 	struct bfa_iocfc_cfg_s   ioc_cfg;
-	u32        inst_no;	/* BFAD instance number */
-	u32        bfad_flags;
+	u32	inst_no;	/* BFAD instance number */
+	u32	bfad_flags;
 	spinlock_t      bfad_lock;
 	struct task_struct *bfad_tsk;
 	struct bfad_cfg_param_s cfg_data;
 	struct bfad_msix_s msix_tab[MAX_MSIX_ENTRY];
-	int             nvec;
-	char            adapter_name[BFA_ADAPTER_SYM_NAME_LEN];
-	char            port_name[BFA_ADAPTER_SYM_NAME_LEN];
+	int		nvec;
+	char	adapter_name[BFA_ADAPTER_SYM_NAME_LEN];
+	char	port_name[BFA_ADAPTER_SYM_NAME_LEN];
 	struct timer_list hal_tmo;
 	unsigned long   hs_start;
 	struct bfad_im_s *im;		/* IM specific data */
-	struct bfad_tm_s *tm;		/* TM specific data */
-	struct bfad_ipfc_s *ipfc;	/* IPFC specific data */
-	struct bfa_log_mod_s   log_data;
 	struct bfa_trc_mod_s  *trcmod;
-	struct bfa_log_mod_s  *logmod;
-	struct bfa_aen_s      *aen;
-	struct bfa_aen_s       aen_buf;
-	void		*file_map[BFA_AEN_MAX_APP];
 	struct bfa_plog_s      plog_buf;
-	int             ref_count;
-	bfa_boolean_t	ipfc_enabled;
+	int		ref_count;
+	union bfad_tmp_buf tmp_buf;
 	struct fc_host_statistics link_stats;
-	struct list_head pbc_pcfg_list;
-	atomic_t wq_reqcnt;
+	struct list_head pbc_vport_list;
 	/* debugfs specific data */
 	char *regdata;
 	u32 reglen;
 	struct dentry *bfad_dentry_files[5];
 };
 
-struct bfad_pcfg_s {
-	struct list_head list_entry;
-	struct bfa_port_cfg_s port_cfg;
+/* BFAD state machine events */
+enum bfad_sm_event {
+	BFAD_E_CREATE			= 1,
+	BFAD_E_KTHREAD_CREATE_FAILED	= 2,
+	BFAD_E_INIT			= 3,
+	BFAD_E_INIT_SUCCESS		= 4,
+	BFAD_E_INIT_FAILED		= 5,
+	BFAD_E_INTR_INIT_FAILED		= 6,
+	BFAD_E_FCS_EXIT_COMP		= 7,
+	BFAD_E_EXIT_COMP		= 8,
+	BFAD_E_STOP			= 9
 };
 
 /*
@@ -208,30 +225,30 @@
 };
 
 struct bfad_buf_info {
-	void           *virt;
+	void		*virt;
 	dma_addr_t      phys;
-	u32        size;
+	u32	size;
 };
 
 struct bfad_fcxp {
 	struct bfad_port_s    *port;
 	struct bfa_rport_s *bfa_rport;
 	bfa_status_t    req_status;
-	u16        tag;
-	u16        rsp_len;
-	u16        rsp_maxlen;
-	u8         use_ireqbuf;
-	u8         use_irspbuf;
-	u32        num_req_sgles;
-	u32        num_rsp_sgles;
-	struct fchs_s          fchs;
-	void           *reqbuf_info;
-	void           *rspbuf_info;
+	u16	tag;
+	u16	rsp_len;
+	u16	rsp_maxlen;
+	u8		use_ireqbuf;
+	u8		use_irspbuf;
+	u32	num_req_sgles;
+	u32	num_rsp_sgles;
+	struct fchs_s	fchs;
+	void		*reqbuf_info;
+	void		*rspbuf_info;
 	struct bfa_sge_s  *req_sge;
 	struct bfa_sge_s  *rsp_sge;
 	fcxp_send_cb_t  send_cbfn;
-	void           *send_cbarg;
-	void           *bfa_fcxp;
+	void		*send_cbarg;
+	void		*bfa_fcxp;
 	struct completion comp;
 };
 
@@ -244,34 +261,48 @@
  * Macro to obtain the immediate lower power
  * of two for the integer.
  */
-#define nextLowerInt(x)                         	\
-do {                                            	\
-	int j;                                  	\
-	(*x)--;    		                	\
-	for (j = 1; j < (sizeof(int) * 8); j <<= 1)     \
-		(*x) = (*x) | (*x) >> j;        	\
-	(*x)++;                  	        	\
-	(*x) = (*x) >> 1;                       	\
+#define nextLowerInt(x)                         \
+do {                                            \
+	int i;                                  \
+	(*x)--;					\
+	for (i = 1; i < (sizeof(int)*8); i <<= 1) \
+		(*x) = (*x) | (*x) >> i;	\
+	(*x)++;					\
+	(*x) = (*x) >> 1;			\
 } while (0)
 
 
-bfa_status_t    bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
-			  struct bfa_port_cfg_s *port_cfg, struct device *dev);
-bfa_status_t    bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
-			       struct bfa_port_cfg_s *port_cfg);
-bfa_status_t    bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role);
-bfa_status_t    bfad_drv_init(struct bfad_s *bfad);
+#define list_remove_head(list, entry, type, member)		\
+do {								\
+	entry = NULL;                                           \
+	if (!list_empty(list)) {                                \
+		entry = list_entry((list)->next, type, member);	\
+		list_del_init(&entry->member);			\
+	}							\
+} while (0)
+
+#define list_get_first(list, type, member)				\
+((list_empty(list)) ? NULL :						\
+	list_entry((list)->next, type, member))
+
+bfa_status_t	bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
+				  struct bfa_lport_cfg_s *port_cfg,
+				  struct device *dev);
+bfa_status_t	bfad_vf_create(struct bfad_s *bfad, u16 vf_id,
+			       struct bfa_lport_cfg_s *port_cfg);
+bfa_status_t	bfad_cfg_pport(struct bfad_s *bfad, enum bfa_lport_role role);
+bfa_status_t	bfad_drv_init(struct bfad_s *bfad);
 bfa_status_t	bfad_start_ops(struct bfad_s *bfad);
-void            bfad_drv_start(struct bfad_s *bfad);
-void            bfad_uncfg_pport(struct bfad_s *bfad);
-void            bfad_drv_stop(struct bfad_s *bfad);
-void            bfad_remove_intr(struct bfad_s *bfad);
-void            bfad_hal_mem_release(struct bfad_s *bfad);
-void            bfad_hcb_comp(void *arg, bfa_status_t status);
+void		bfad_drv_start(struct bfad_s *bfad);
+void		bfad_uncfg_pport(struct bfad_s *bfad);
+void		bfad_stop(struct bfad_s *bfad);
+void		bfad_fcs_stop(struct bfad_s *bfad);
+void		bfad_remove_intr(struct bfad_s *bfad);
+void		bfad_hal_mem_release(struct bfad_s *bfad);
+void		bfad_hcb_comp(void *arg, bfa_status_t status);
 
-int             bfad_setup_intr(struct bfad_s *bfad);
-void            bfad_remove_intr(struct bfad_s *bfad);
-
+int		bfad_setup_intr(struct bfad_s *bfad);
+void		bfad_remove_intr(struct bfad_s *bfad);
 void		bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg);
 bfa_status_t	bfad_hal_mem_alloc(struct bfad_s *bfad);
 void		bfad_bfa_tmo(unsigned long data);
@@ -280,9 +311,6 @@
 void		bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad);
 void		bfad_fcs_port_cfg(struct bfad_s *bfad);
 void		bfad_drv_uninit(struct bfad_s *bfad);
-void		bfad_drv_log_level_set(struct bfad_s *bfad);
-bfa_status_t	bfad_fc4_module_init(void);
-void		bfad_fc4_module_exit(void);
 int		bfad_worker(void *ptr);
 void		bfad_debugfs_init(struct bfad_port_s *port);
 void		bfad_debugfs_exit(struct bfad_port_s *port);
@@ -294,10 +322,30 @@
 int bfad_install_msix_handler(struct bfad_s *bfad);
 
 extern struct idr bfad_im_port_index;
+extern struct pci_device_id bfad_id_table[];
 extern struct list_head bfad_list;
-extern int bfa_lun_queue_depth;
-extern int bfad_supported_fc4s;
-extern int bfa_linkup_delay;
+extern char	*os_name;
+extern char	*os_patch;
+extern char	*host_name;
+extern int	num_rports;
+extern int	num_ios;
+extern int	num_tms;
+extern int	num_fcxps;
+extern int	num_ufbufs;
+extern int	reqq_size;
+extern int	rspq_size;
+extern int	num_sgpgs;
+extern int      rport_del_timeout;
+extern int      bfa_lun_queue_depth;
+extern int      bfa_io_max_sge;
+extern int      log_level;
+extern int      ioc_auto_recover;
+extern int      bfa_linkup_delay;
+extern int      msix_disable_cb;
+extern int      msix_disable_ct;
+extern int      fdmi_enable;
+extern int      supported_fc4s;
+extern int	pcie_max_read_reqsz;
 extern int bfa_debugfs_enable;
 extern struct mutex bfad_mutex;
 
diff --git a/drivers/scsi/bfa/bfad_fwimg.c b/drivers/scsi/bfa/bfad_fwimg.c
deleted file mode 100644
index 1baca1a..0000000
--- a/drivers/scsi/bfa/bfad_fwimg.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfad_fwimg.c Linux driver PCI interface module.
- */
-#include <bfa_os_inc.h>
-#include <bfad_drv.h>
-#include <bfad_im_compat.h>
-#include <defs/bfa_defs_version.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <asm/uaccess.h>
-#include <asm/fcntl.h>
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <bfa_fwimg_priv.h>
-#include <bfa.h>
-
-u32 bfi_image_ct_fc_size;
-u32 bfi_image_ct_cna_size;
-u32 bfi_image_cb_fc_size;
-u32 *bfi_image_ct_fc;
-u32 *bfi_image_ct_cna;
-u32 *bfi_image_cb_fc;
-
-
-#define	BFAD_FW_FILE_CT_FC	"ctfw_fc.bin"
-#define	BFAD_FW_FILE_CT_CNA	"ctfw_cna.bin"
-#define	BFAD_FW_FILE_CB_FC	"cbfw_fc.bin"
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_FC);
-MODULE_FIRMWARE(BFAD_FW_FILE_CT_CNA);
-MODULE_FIRMWARE(BFAD_FW_FILE_CB_FC);
-
-u32 *
-bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
-			u32 *bfi_image_size, char *fw_name)
-{
-	const struct firmware *fw;
-
-	if (request_firmware(&fw, fw_name, &pdev->dev)) {
-		printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
-		goto error;
-	}
-
-	*bfi_image = vmalloc(fw->size);
-	if (NULL == *bfi_image) {
-		printk(KERN_ALERT "Fail to allocate buffer for fw image "
-			"size=%x!\n", (u32) fw->size);
-		goto error;
-	}
-
-	memcpy(*bfi_image, fw->data, fw->size);
-	*bfi_image_size = fw->size/sizeof(u32);
-
-	return *bfi_image;
-
-error:
-	return NULL;
-}
-
-u32 *
-bfad_get_firmware_buf(struct pci_dev *pdev)
-{
-	if (pdev->device == BFA_PCI_DEVICE_ID_CT_FC) {
-		if (bfi_image_ct_fc_size == 0)
-			bfad_read_firmware(pdev, &bfi_image_ct_fc,
-				&bfi_image_ct_fc_size, BFAD_FW_FILE_CT_FC);
-		return bfi_image_ct_fc;
-	} else if (pdev->device == BFA_PCI_DEVICE_ID_CT) {
-		if (bfi_image_ct_cna_size == 0)
-			bfad_read_firmware(pdev, &bfi_image_ct_cna,
-				&bfi_image_ct_cna_size, BFAD_FW_FILE_CT_CNA);
-		return bfi_image_ct_cna;
-	} else {
-		if (bfi_image_cb_fc_size == 0)
-			bfad_read_firmware(pdev, &bfi_image_cb_fc,
-				&bfi_image_cb_fc_size, BFAD_FW_FILE_CB_FC);
-		return bfi_image_cb_fc;
-	}
-}
-
-u32 *
-bfi_image_ct_fc_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_ct_fc + off); }
-
-u32 *
-bfi_image_ct_cna_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_ct_cna + off); }
-
-u32 *
-bfi_image_cb_fc_get_chunk(u32 off)
-{ return (u32 *)(bfi_image_cb_fc + off); }
-
-uint32_t *
-bfi_image_get_chunk(int type, uint32_t off)
-{
-	switch (type) {
-	case BFI_IMAGE_CT_FC: return bfi_image_ct_fc_get_chunk(off); break;
-	case BFI_IMAGE_CT_CNA: return bfi_image_ct_cna_get_chunk(off); break;
-	case BFI_IMAGE_CB_FC: return bfi_image_cb_fc_get_chunk(off); break;
-	default: return 0; break;
-	}
-}
-
-uint32_t
-bfi_image_get_size(int type)
-{
-	switch (type) {
-	case BFI_IMAGE_CT_FC: return bfi_image_ct_fc_size; break;
-	case BFI_IMAGE_CT_CNA: return bfi_image_ct_cna_size; break;
-	case BFI_IMAGE_CB_FC: return bfi_image_cb_fc_size; break;
-	default: return 0; break;
-	}
-}
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 6ef87f6..d950ee4 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -19,12 +19,10 @@
  *  bfad_im.c Linux driver IM module.
  */
 
-#include <linux/slab.h>
 #include "bfad_drv.h"
 #include "bfad_im.h"
-#include "bfad_trcmod.h"
-#include "bfa_cb_ioim_macros.h"
-#include <fcb/bfa_fcb_fcpim.h>
+#include "bfa_cb_ioim.h"
+#include "bfa_fcs.h"
 
 BFA_TRC_FILE(LDRV, IM);
 
@@ -33,8 +31,10 @@
 struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
 static void bfad_im_itnim_work_handler(struct work_struct *work);
 static int bfad_im_queuecommand(struct scsi_cmnd *cmnd,
-		void (*done)(struct scsi_cmnd *));
+				void (*done)(struct scsi_cmnd *));
 static int bfad_im_slave_alloc(struct scsi_device *sdev);
+static void bfad_im_fc_rport_add(struct bfad_im_port_s  *im_port,
+				struct bfad_itnim_s *itnim);
 
 void
 bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio,
@@ -58,6 +58,7 @@
 				sns_len = SCSI_SENSE_BUFFERSIZE;
 			memcpy(cmnd->sense_buffer, sns_info, sns_len);
 		}
+
 		if (residue > 0) {
 			bfa_trc(bfad, residue);
 			scsi_set_resid(cmnd, residue);
@@ -76,7 +77,8 @@
 	case BFI_IOIM_STS_TIMEDOUT:
 	case BFI_IOIM_STS_PATHTOV:
 	default:
-		cmnd->result = ScsiResult(DID_ERROR, 0);
+		host_status = DID_ERROR;
+		cmnd->result = ScsiResult(host_status, 0);
 	}
 
 	/* Unmap DMA, if host is NULL, it means a scsi passthru cmd */
@@ -162,11 +164,6 @@
 		wake_up(wq);
 }
 
-void
-bfa_cb_ioim_resfree(void *drv)
-{
-}
-
 /**
  *  Scsi_Host_template SCSI host template
  */
@@ -179,15 +176,23 @@
 	static char     bfa_buf[256];
 	struct bfad_im_port_s *im_port =
 			(struct bfad_im_port_s *) shost->hostdata[0];
-	struct bfad_s         *bfad = im_port->bfad;
+	struct bfad_s *bfad = im_port->bfad;
+	struct bfa_s *bfa = &bfad->bfa;
+	struct bfa_ioc_s *ioc = &bfa->ioc;
 	char model[BFA_ADAPTER_MODEL_NAME_LEN];
 
-	bfa_get_adapter_model(&bfad->bfa, model);
+	bfa_get_adapter_model(bfa, model);
 
 	memset(bfa_buf, 0, sizeof(bfa_buf));
-	snprintf(bfa_buf, sizeof(bfa_buf),
-		"Brocade FC/FCOE Adapter, " "model: %s hwpath: %s driver: %s",
+	if (ioc->ctdev)
+		snprintf(bfa_buf, sizeof(bfa_buf),
+		"Brocade FCOE Adapter, " "model: %s hwpath: %s driver: %s",
+		 model, bfad->pci_name, BFAD_DRIVER_VERSION);
+	else
+		snprintf(bfa_buf, sizeof(bfa_buf),
+		"Brocade FC Adapter, " "model: %s hwpath: %s driver: %s",
 		model, bfad->pci_name, BFAD_DRIVER_VERSION);
+
 	return bfa_buf;
 }
 
@@ -221,9 +226,9 @@
 	}
 
 	bfa_trc(bfad, hal_io->iotag);
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT,
+	BFA_LOG(KERN_INFO, bfad, log_level, "scsi%d: abort cmnd %p iotag %x\n",
 		im_port->shost->host_no, cmnd, hal_io->iotag);
-	bfa_ioim_abort(hal_io);
+	(void) bfa_ioim_abort(hal_io);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 
 	/* Need to wait until the command get aborted */
@@ -237,7 +242,8 @@
 
 	cmnd->scsi_done(cmnd);
 	bfa_trc(bfad, hal_io->iotag);
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT_COMP,
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"scsi%d: complete abort 0x%p iotag 0x%x\n",
 		im_port->shost->host_no, cmnd, hal_io->iotag);
 	return SUCCESS;
 out:
@@ -255,8 +261,8 @@
 
 	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
 	if (!tskim) {
-		BFA_DEV_PRINTF(bfad, BFA_ERR,
-			       "target reset, fail to allocate tskim\n");
+		BFA_LOG(KERN_ERR, bfad, log_level,
+			"target reset, fail to allocate tskim\n");
 		rc = BFA_STATUS_FAILED;
 		goto out;
 	}
@@ -306,7 +312,7 @@
 
 	tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
 	if (!tskim) {
-		BFA_DEV_PRINTF(bfad, BFA_ERR,
+		BFA_LOG(KERN_ERR, bfad, log_level,
 				"LUN reset, fail to allocate tskim");
 		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 		rc = FAILED;
@@ -331,8 +337,8 @@
 
 	task_status = cmnd->SCp.Status >> 1;
 	if (task_status != BFI_TSKIM_STS_OK) {
-		BFA_DEV_PRINTF(bfad, BFA_ERR, "LUN reset failure, status: %d\n",
-			       task_status);
+		BFA_LOG(KERN_ERR, bfad, log_level,
+			"LUN reset failure, status: %d\n", task_status);
 		rc = FAILED;
 	}
 
@@ -375,7 +381,7 @@
 
 			task_status = cmnd->SCp.Status >> 1;
 			if (task_status != BFI_TSKIM_STS_OK) {
-				BFA_DEV_PRINTF(bfad, BFA_ERR,
+				BFA_LOG(KERN_ERR, bfad, log_level,
 					"target reset failure,"
 					" status: %d\n", task_status);
 				err_cnt++;
@@ -438,6 +444,7 @@
 	wwn_t wwpn;
 	u32 fcid;
 	char wwpn_str[32], fcid_str[16];
+	struct bfad_im_s	*im = itnim_drv->im;
 
 	/* online to free state transtion should not happen */
 	bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE);
@@ -454,10 +461,14 @@
 	fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim);
 	wwn2str(wwpn_str, wwpn);
 	fcid2str(fcid_str, fcid);
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_FREE,
+	BFA_LOG(KERN_INFO, bfad, log_level,
+		"ITNIM FREE scsi%d: FCID: %s WWPN: %s\n",
 		port->im_port->shost->host_no,
 		fcid_str, wwpn_str);
-	bfad_os_itnim_process(itnim_drv);
+
+	/* ITNIM processing */
+	if (itnim_drv->queue_work)
+		queue_work(im->drv_workq, &itnim_drv->itnim_work);
 }
 
 /**
@@ -468,13 +479,17 @@
 bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv)
 {
 	struct bfad_port_s    *port;
+	struct bfad_im_s	*im = itnim_drv->im;
 
 	itnim_drv->bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim_drv->fcs_itnim);
 	port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
 	itnim_drv->state = ITNIM_STATE_ONLINE;
 	itnim_drv->queue_work = 1;
 	itnim_drv->im_port = port->im_port;
-	bfad_os_itnim_process(itnim_drv);
+
+	/* ITNIM processing */
+	if (itnim_drv->queue_work)
+		queue_work(im->drv_workq, &itnim_drv->itnim_work);
 }
 
 /**
@@ -486,6 +501,7 @@
 {
 	struct bfad_port_s    *port;
 	struct bfad_s *bfad;
+	struct bfad_im_s	*im = itnim_drv->im;
 
 	port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim);
 	bfad = port->bfad;
@@ -497,16 +513,10 @@
 	itnim_drv->im_port = port->im_port;
 	itnim_drv->state = ITNIM_STATE_OFFLINE_PENDING;
 	itnim_drv->queue_work = 1;
-	bfad_os_itnim_process(itnim_drv);
-}
 
-/**
- * BFA FCS itnim timeout callback.
- * Context: Interrupt. bfad_lock is held
- */
-void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim)
-{
-	itnim->state = ITNIM_STATE_TIMEOUT;
+	/* ITNIM processing */
+	if (itnim_drv->queue_work)
+		queue_work(im->drv_workq, &itnim_drv->itnim_work);
 }
 
 /**
@@ -514,7 +524,7 @@
  */
 int
 bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
-				struct device *dev)
+			struct device *dev)
 {
 	int error = 1;
 
@@ -580,7 +590,7 @@
 bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
 {
 	bfa_trc(bfad, bfad->inst_no);
-	bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_HOST_FREE,
+	BFA_LOG(KERN_INFO, bfad, log_level, "Free scsi%d\n",
 			im_port->shost->host_no);
 
 	fc_remove_host(im_port->shost);
@@ -598,14 +608,11 @@
 {
 	struct bfad_im_port_s *im_port =
 		container_of(work, struct bfad_im_port_s, port_delete_work);
-	struct bfad_s *bfad = im_port->bfad;
 
 	if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) {
 		im_port->flags |= BFAD_PORT_DELETE;
 		fc_vport_terminate(im_port->fc_vport);
-		atomic_dec(&bfad->wq_reqcnt);
 	}
-
 }
 
 bfa_status_t
@@ -636,11 +643,8 @@
 {
 	struct bfad_im_port_s *im_port = port->im_port;
 
-	if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) {
-		atomic_inc(&bfad->wq_reqcnt);
-		queue_work(bfad->im->drv_workq,
+	queue_work(bfad->im->drv_workq,
 				&im_port->port_delete_work);
-	}
 }
 
 void
@@ -663,16 +667,6 @@
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 }
 
-void
-bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port)
-{
-}
-
-void
-bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port)
-{
-}
-
 bfa_status_t
 bfad_im_probe(struct bfad_s *bfad)
 {
@@ -701,27 +695,12 @@
 bfad_im_probe_undo(struct bfad_s *bfad)
 {
 	if (bfad->im) {
-		while (atomic_read(&bfad->wq_reqcnt)) {
-			printk(KERN_INFO "bfa %s: waiting workq processing,"
-				" wq_reqcnt:%x\n", bfad->pci_name,
-				atomic_read(&bfad->wq_reqcnt));
-			schedule_timeout_uninterruptible(HZ);
-		}
 		bfad_os_destroy_workq(bfad->im);
 		kfree(bfad->im);
 		bfad->im = NULL;
 	}
 }
 
-/**
- * Call back function to handle IO redirection state change
- */
-void
-bfa_cb_ioredirect_state_change(void *hcb_bfad, bfa_boolean_t ioredirect)
-{
-	/* Do nothing */
-}
-
 struct Scsi_Host *
 bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
 {
@@ -751,6 +730,7 @@
 bfad_os_destroy_workq(struct bfad_im_s *im)
 {
 	if (im && im->drv_workq) {
+		flush_workqueue(im->drv_workq);
 		destroy_workqueue(im->drv_workq);
 		im->drv_workq = NULL;
 	}
@@ -762,7 +742,7 @@
 	struct bfad_im_s      *im = bfad->im;
 
 	bfa_trc(bfad, 0);
-	snprintf(im->drv_workq_name, BFAD_KOBJ_NAME_LEN, "bfad_wq_%d",
+	snprintf(im->drv_workq_name, KOBJ_NAME_LEN, "bfad_wq_%d",
 		 bfad->inst_no);
 	im->drv_workq = create_singlethread_workqueue(im->drv_workq_name);
 	if (!im->drv_workq)
@@ -832,12 +812,6 @@
 	.max_sectors = 0xFFFF,
 };
 
-void
-bfad_im_probe_post(struct bfad_im_s *im)
-{
-	flush_workqueue(im->drv_workq);
-}
-
 bfa_status_t
 bfad_im_module_init(void)
 {
@@ -861,20 +835,12 @@
 {
 	if (bfad_im_scsi_transport_template)
 		fc_release_transport(bfad_im_scsi_transport_template);
+
 	if (bfad_im_scsi_vport_transport_template)
 		fc_release_transport(bfad_im_scsi_vport_transport_template);
 }
 
 void
-bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv)
-{
-	struct bfad_im_s      *im = itnim_drv->im;
-
-	if (itnim_drv->queue_work)
-		queue_work(im->drv_workq, &itnim_drv->itnim_work);
-}
-
-void
 bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
 {
 	struct scsi_device *tmp_sdev;
@@ -916,9 +882,6 @@
 	}
 }
 
-
-
-
 struct bfad_itnim_s *
 bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id)
 {
@@ -949,44 +912,64 @@
 	return 0;
 }
 
+static u32
+bfad_im_supported_speeds(struct bfa_s *bfa)
+{
+	struct bfa_ioc_attr_s ioc_attr;
+	u32 supported_speed = 0;
+
+	bfa_get_attr(bfa, &ioc_attr);
+	if (ioc_attr.adapter_attr.max_speed == BFA_PORT_SPEED_8GBPS) {
+		if (ioc_attr.adapter_attr.is_mezz) {
+			supported_speed |= FC_PORTSPEED_8GBIT |
+				FC_PORTSPEED_4GBIT |
+				FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
+		} else {
+			supported_speed |= FC_PORTSPEED_8GBIT |
+				FC_PORTSPEED_4GBIT |
+				FC_PORTSPEED_2GBIT;
+		}
+	} else if (ioc_attr.adapter_attr.max_speed == BFA_PORT_SPEED_4GBPS) {
+		supported_speed |=  FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
+				FC_PORTSPEED_1GBIT;
+	} else if (ioc_attr.adapter_attr.max_speed == BFA_PORT_SPEED_10GBPS) {
+		supported_speed |= FC_PORTSPEED_10GBIT;
+	}
+	return supported_speed;
+}
+
 void
 bfad_os_fc_host_init(struct bfad_im_port_s *im_port)
 {
 	struct Scsi_Host *host = im_port->shost;
 	struct bfad_s         *bfad = im_port->bfad;
 	struct bfad_port_s    *port = im_port->port;
-	struct bfa_pport_attr_s pattr;
-	char model[BFA_ADAPTER_MODEL_NAME_LEN];
-	char fw_ver[BFA_VERSION_LEN];
+	struct bfa_port_attr_s pattr;
+	struct bfa_lport_attr_s port_attr;
+	char symname[BFA_SYMNAME_MAXLEN];
 
 	fc_host_node_name(host) =
-		bfa_os_htonll((bfa_fcs_port_get_nwwn(port->fcs_port)));
+		bfa_os_htonll((bfa_fcs_lport_get_nwwn(port->fcs_port)));
 	fc_host_port_name(host) =
-		bfa_os_htonll((bfa_fcs_port_get_pwwn(port->fcs_port)));
+		bfa_os_htonll((bfa_fcs_lport_get_pwwn(port->fcs_port)));
 	fc_host_max_npiv_vports(host) = bfa_lps_get_max_vport(&bfad->bfa);
 
 	fc_host_supported_classes(host) = FC_COS_CLASS3;
 
 	memset(fc_host_supported_fc4s(host), 0,
 	       sizeof(fc_host_supported_fc4s(host)));
-	if (bfad_supported_fc4s & (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM))
+	if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM)
 		/* For FCP type 0x08 */
 		fc_host_supported_fc4s(host)[2] = 1;
-	if (bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IPFC)
-		/* For LLC/SNAP type 0x05 */
-		fc_host_supported_fc4s(host)[3] = 0x20;
 	/* For fibre channel services type 0x20 */
 	fc_host_supported_fc4s(host)[7] = 1;
 
-	bfa_get_adapter_model(&bfad->bfa, model);
-	bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
-	sprintf(fc_host_symbolic_name(host), "Brocade %s FV%s DV%s",
-		model, fw_ver, BFAD_DRIVER_VERSION);
+	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
+	strncpy(symname, port_attr.port_cfg.sym_name.symname,
+		BFA_SYMNAME_MAXLEN);
+	sprintf(fc_host_symbolic_name(host), "%s", symname);
 
-	fc_host_supported_speeds(host) = 0;
-	fc_host_supported_speeds(host) |=
-		FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
-		FC_PORTSPEED_1GBIT;
+	fc_host_supported_speeds(host) = bfad_im_supported_speeds(&bfad->bfa);
 
 	bfa_fcport_get_attr(&bfad->bfa, &pattr);
 	fc_host_maxframe_size(host) = pattr.pport_cfg.maxfrsize;
@@ -1065,7 +1048,9 @@
 			fcid2str(fcid_str, fcid);
 			list_add_tail(&itnim->list_entry,
 				&im_port->itnim_mapped_list);
-			bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_ONLINE,
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"ITNIM ONLINE Target: %d:0:%d "
+				"FCID: %s WWPN: %s\n",
 				im_port->shost->host_no,
 				itnim->scsi_tgt_id,
 				fcid_str, wwpn_str);
@@ -1096,7 +1081,9 @@
 			wwn2str(wwpn_str, wwpn);
 			fcid2str(fcid_str, fcid);
 			list_del(&itnim->list_entry);
-			bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_OFFLINE,
+			BFA_LOG(KERN_INFO, bfad, log_level,
+				"ITNIM OFFLINE Target: %d:0:%d "
+				"FCID: %s WWPN: %s\n",
 				im_port->shost->host_no,
 				itnim->scsi_tgt_id,
 				fcid_str, wwpn_str);
@@ -1142,7 +1129,7 @@
 	struct bfa_ioim_s *hal_io;
 	unsigned long   flags;
 	int             rc;
-	s16        sg_cnt = 0;
+	int       sg_cnt = 0;
 	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
 
 	rc = fc_remote_port_chkready(rport);
@@ -1153,7 +1140,6 @@
 	}
 
 	sg_cnt = scsi_dma_map(cmnd);
-
 	if (sg_cnt < 0)
 		return SCSI_MLQUEUE_HOST_BUSY;
 
@@ -1168,6 +1154,7 @@
 		goto out_fail_cmd;
 	}
 
+
 	itnim = itnim_data->itnim;
 	if (!itnim) {
 		cmnd->result = ScsiResult(DID_IMM_RETRY, 0);
@@ -1206,47 +1193,49 @@
 	int rport_delay = 10;
 
 	for (i = 0; !(bfad->bfad_flags & BFAD_PORT_ONLINE)
-		 && i < bfa_linkup_delay; i++)
-		schedule_timeout_uninterruptible(HZ);
+		&& i < bfa_linkup_delay; i++) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ);
+	}
 
 	if (bfad->bfad_flags & BFAD_PORT_ONLINE) {
 		rport_delay = rport_delay < bfa_linkup_delay ?
-				 rport_delay : bfa_linkup_delay;
+			rport_delay : bfa_linkup_delay;
 		for (i = 0; !(bfad->bfad_flags & BFAD_RPORT_ONLINE)
-			 && i < rport_delay; i++)
-			schedule_timeout_uninterruptible(HZ);
+			&& i < rport_delay; i++) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ);
+		}
 
-		if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE))
-			schedule_timeout_uninterruptible(rport_delay * HZ);
+		if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE)) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(rport_delay * HZ);
+		}
 	}
 }
 
 int
 bfad_os_get_linkup_delay(struct bfad_s *bfad)
 {
-
-	u8      nwwns = 0;
-	wwn_t	wwns[BFA_PREBOOT_BOOTLUN_MAX];
-	int     ldelay;
+	u8		nwwns = 0;
+	wwn_t		wwns[BFA_PREBOOT_BOOTLUN_MAX];
+	int		linkup_delay;
 
 	/*
 	 * Querying for the boot target port wwns
 	 * -- read from boot information in flash.
-	 * If nwwns > 0 => boot over SAN and set bfa_linkup_delay = 30
-	 * else => local boot machine set bfa_linkup_delay = 10
+	 * If nwwns > 0 => boot over SAN and set linkup_delay = 30
+	 * else => local boot machine set linkup_delay = 0
 	 */
 
 	bfa_iocfc_get_bootwwns(&bfad->bfa, &nwwns, wwns);
 
-	if (nwwns > 0) {
-		/* If boot over SAN; linkup_delay = 30sec */
-		ldelay = 30;
-	} else {
-		/* If local boot; linkup_delay = 10sec */
-		ldelay = 0;
-	}
+	if (nwwns > 0)
+		/* If Boot over SAN set linkup_delay = 30sec */
+		linkup_delay = 30;
+	else
+		/* If local boot; no linkup_delay */
+		linkup_delay = 0;
 
-	return ldelay;
+	return linkup_delay;
 }
-
-
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
index 973cab4..b038c0e 100644
--- a/drivers/scsi/bfa/bfad_im.h
+++ b/drivers/scsi/bfa/bfad_im.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  * All rights reserved
  * www.brocade.com
  *
@@ -18,20 +18,20 @@
 #ifndef __BFAD_IM_H__
 #define __BFAD_IM_H__
 
-#include "fcs/bfa_fcs_fcpim.h"
-#include "bfad_im_compat.h"
+#include "bfa_fcs.h"
 
 #define FCPI_NAME " fcpim"
 
+#ifndef KOBJ_NAME_LEN
+#define KOBJ_NAME_LEN           20
+#endif
+
 bfa_status_t bfad_im_module_init(void);
 void bfad_im_module_exit(void);
 bfa_status_t bfad_im_probe(struct bfad_s *bfad);
 void bfad_im_probe_undo(struct bfad_s *bfad);
-void bfad_im_probe_post(struct bfad_im_s *im);
 bfa_status_t bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port);
 void bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port);
-void bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port);
-void bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port);
 void bfad_im_port_clean(struct bfad_im_port_s *im_port);
 int  bfad_im_scsi_host_alloc(struct bfad_s *bfad,
 		struct bfad_im_port_s *im_port, struct device *dev);
@@ -44,14 +44,10 @@
 #define BFAD_LUN_RESET_TMO 60
 #define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code)
 #define BFA_QUEUE_FULL_RAMP_UP_TIME 120
-#define BFAD_KOBJ_NAME_LEN 20
 
 /*
  * itnim flags
  */
-#define ITNIM_MAPPED		0x00000001
-
-#define SCSI_TASK_MGMT		0x00000001
 #define IO_DONE_BIT			0
 
 struct bfad_itnim_data_s {
@@ -64,7 +60,7 @@
 	struct work_struct port_delete_work;
 	int             idr_id;
 	u16        cur_scsi_id;
-	u16	   flags;
+	u16	flags;
 	struct list_head binding_list;
 	struct Scsi_Host *shost;
 	struct list_head itnim_mapped_list;
@@ -118,14 +114,13 @@
 struct bfad_im_s {
 	struct bfad_s         *bfad;
 	struct workqueue_struct *drv_workq;
-	char   drv_workq_name[BFAD_KOBJ_NAME_LEN];
+	char            drv_workq_name[KOBJ_NAME_LEN];
 };
 
 struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port,
 				struct bfad_s *);
 bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad);
 void bfad_os_destroy_workq(struct bfad_im_s *im);
-void bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv);
 void bfad_os_fc_host_init(struct bfad_im_port_s *im_port);
 void bfad_os_scsi_host_free(struct bfad_s *bfad,
 				 struct bfad_im_port_s *im_port);
@@ -133,11 +128,6 @@
 				 struct scsi_device *sdev);
 void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev);
 struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id);
-int bfad_os_scsi_add_host(struct Scsi_Host *shost,
-		struct bfad_im_port_s *im_port, struct bfad_s *bfad);
-
-void bfad_im_itnim_unmap(struct bfad_im_port_s  *im_port,
-			 struct bfad_itnim_s *itnim);
 
 extern struct scsi_host_template bfad_im_scsi_host_template;
 extern struct scsi_host_template bfad_im_vport_template;
@@ -146,4 +136,34 @@
 extern struct scsi_transport_template *bfad_im_scsi_transport_template;
 extern struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
 
+extern struct device_attribute *bfad_im_host_attrs[];
+extern struct device_attribute *bfad_im_vport_attrs[];
+
+irqreturn_t bfad_intx(int irq, void *dev_id);
+
+/* Firmware releated */
+#define BFAD_FW_FILE_CT_FC      "ctfw_fc.bin"
+#define BFAD_FW_FILE_CT_CNA     "ctfw_cna.bin"
+#define BFAD_FW_FILE_CB_FC      "cbfw_fc.bin"
+
+u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
+u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
+		u32 *bfi_image_size, char *fw_name);
+
+static inline u32 *
+bfad_load_fwimg(struct pci_dev *pdev)
+{
+	return bfad_get_firmware_buf(pdev);
+}
+
+static inline void
+bfad_free_fwimg(void)
+{
+	if (bfi_image_ct_fc_size && bfi_image_ct_fc)
+		vfree(bfi_image_ct_fc);
+	if (bfi_image_ct_cna_size && bfi_image_ct_cna)
+		vfree(bfi_image_ct_cna);
+	if (bfi_image_cb_fc_size && bfi_image_cb_fc)
+		vfree(bfi_image_cb_fc);
+}
 #endif
diff --git a/drivers/scsi/bfa/bfad_im_compat.h b/drivers/scsi/bfa/bfad_im_compat.h
deleted file mode 100644
index 0a122ab..0000000
--- a/drivers/scsi/bfa/bfad_im_compat.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFAD_IM_COMPAT_H__
-#define __BFAD_IM_COMPAT_H__
-
-extern struct device_attribute *bfad_im_host_attrs[];
-extern struct device_attribute *bfad_im_vport_attrs[];
-
-u32 *bfad_get_firmware_buf(struct pci_dev *pdev);
-u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image,
-			u32 *bfi_image_size, char *fw_name);
-
-static inline u32 *
-bfad_load_fwimg(struct pci_dev *pdev)
-{
-	return bfad_get_firmware_buf(pdev);
-}
-
-static inline void
-bfad_free_fwimg(void)
-{
-	if (bfi_image_ct_fc_size && bfi_image_ct_fc)
-		vfree(bfi_image_ct_fc);
-	if (bfi_image_ct_cna_size && bfi_image_ct_cna)
-		vfree(bfi_image_ct_cna);
-	if (bfi_image_cb_fc_size && bfi_image_cb_fc)
-		vfree(bfi_image_cb_fc);
-}
-
-#endif
diff --git a/drivers/scsi/bfa/bfad_intr.c b/drivers/scsi/bfa/bfad_intr.c
deleted file mode 100644
index 56a3515..0000000
--- a/drivers/scsi/bfa/bfad_intr.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include "bfad_drv.h"
-#include "bfad_trcmod.h"
-
-BFA_TRC_FILE(LDRV, INTR);
-
-/**
- *  bfa_isr BFA driver interrupt functions
- */
-static int msix_disable_cb;
-static int msix_disable_ct;
-module_param(msix_disable_cb, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msix_disable_cb, "Disable MSIX for Brocade-415/425/815/825"
-		" cards, default=0, Range[false:0|true:1]");
-module_param(msix_disable_ct, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msix_disable_ct, "Disable MSIX for Brocade-1010/1020/804"
-		" cards, default=0, Range[false:0|true:1]");
-/**
- * Line based interrupt handler.
- */
-static irqreturn_t
-bfad_intx(int irq, void *dev_id)
-{
-	struct bfad_s         *bfad = dev_id;
-	struct list_head         doneq;
-	unsigned long   flags;
-	bfa_boolean_t rc;
-
-	spin_lock_irqsave(&bfad->bfad_lock, flags);
-	rc = bfa_intx(&bfad->bfa);
-	if (!rc) {
-		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		return IRQ_NONE;
-	}
-
-	bfa_comp_deq(&bfad->bfa, &doneq);
-	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
-	if (!list_empty(&doneq)) {
-		bfa_comp_process(&bfad->bfa, &doneq);
-
-		spin_lock_irqsave(&bfad->bfad_lock, flags);
-		bfa_comp_free(&bfad->bfa, &doneq);
-		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-		bfa_trc_fp(bfad, irq);
-	}
-
-	return IRQ_HANDLED;
-
-}
-
-static irqreturn_t
-bfad_msix(int irq, void *dev_id)
-{
-	struct bfad_msix_s *vec = dev_id;
-	struct bfad_s *bfad = vec->bfad;
-	struct list_head doneq;
-	unsigned long   flags;
-
-	spin_lock_irqsave(&bfad->bfad_lock, flags);
-
-	bfa_msix(&bfad->bfa, vec->msix.entry);
-	bfa_comp_deq(&bfad->bfa, &doneq);
-	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-
-	if (!list_empty(&doneq)) {
-		bfa_comp_process(&bfad->bfa, &doneq);
-
-		spin_lock_irqsave(&bfad->bfad_lock, flags);
-		bfa_comp_free(&bfad->bfa, &doneq);
-		spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/**
- * Initialize the MSIX entry table.
- */
-static void
-bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries,
-			 int mask, int max_bit)
-{
-	int             i;
-	int             match = 0x00000001;
-
-	for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) {
-		if (mask & match) {
-			bfad->msix_tab[bfad->nvec].msix.entry = i;
-			bfad->msix_tab[bfad->nvec].bfad = bfad;
-			msix_entries[bfad->nvec].entry = i;
-			bfad->nvec++;
-		}
-
-		match <<= 1;
-	}
-
-}
-
-int
-bfad_install_msix_handler(struct bfad_s *bfad)
-{
-	int             i, error = 0;
-
-	for (i = 0; i < bfad->nvec; i++) {
-		error = request_irq(bfad->msix_tab[i].msix.vector,
-				    (irq_handler_t) bfad_msix, 0,
-				    BFAD_DRIVER_NAME, &bfad->msix_tab[i]);
-		bfa_trc(bfad, i);
-		bfa_trc(bfad, bfad->msix_tab[i].msix.vector);
-		if (error) {
-			int             j;
-
-			for (j = 0; j < i; j++)
-				free_irq(bfad->msix_tab[j].msix.vector,
-						&bfad->msix_tab[j]);
-
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-/**
- * Setup MSIX based interrupt.
- */
-int
-bfad_setup_intr(struct bfad_s *bfad)
-{
-	int error = 0;
-	u32 mask = 0, i, num_bit = 0, max_bit = 0;
-	struct msix_entry msix_entries[MAX_MSIX_ENTRY];
-	struct pci_dev *pdev = bfad->pcidev;
-
-	/* Call BFA to get the msix map for this PCI function.  */
-	bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit);
-
-	/* Set up the msix entry table */
-	bfad_init_msix_entry(bfad, msix_entries, mask, max_bit);
-
-	if ((bfa_asic_id_ct(pdev->device) && !msix_disable_ct) ||
-		(!bfa_asic_id_ct(pdev->device) && !msix_disable_cb)) {
-
-		error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec);
-		if (error) {
-			/*
-			 * Only error number of vector is available.
-			 * We don't have a mechanism to map multiple
-			 * interrupts into one vector, so even if we
-			 * can try to request less vectors, we don't
-			 * know how to associate interrupt events to
-			 *  vectors. Linux doesn't dupicate vectors
-			 * in the MSIX table for this case.
-			 */
-
-			printk(KERN_WARNING "bfad%d: "
-				"pci_enable_msix failed (%d),"
-				" use line based.\n", bfad->inst_no, error);
-
-			goto line_based;
-		}
-
-		/* Save the vectors */
-		for (i = 0; i < bfad->nvec; i++) {
-			bfa_trc(bfad, msix_entries[i].vector);
-			bfad->msix_tab[i].msix.vector = msix_entries[i].vector;
-		}
-
-		bfa_msix_init(&bfad->bfa, bfad->nvec);
-
-		bfad->bfad_flags |= BFAD_MSIX_ON;
-
-		return error;
-	}
-
-line_based:
-	error = 0;
-	if (request_irq
-	    (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS,
-	     BFAD_DRIVER_NAME, bfad) != 0) {
-		/* Enable interrupt handler failed */
-		return 1;
-	}
-
-	return error;
-}
-
-void
-bfad_remove_intr(struct bfad_s *bfad)
-{
-	int             i;
-
-	if (bfad->bfad_flags & BFAD_MSIX_ON) {
-		for (i = 0; i < bfad->nvec; i++)
-			free_irq(bfad->msix_tab[i].msix.vector,
-					&bfad->msix_tab[i]);
-
-		pci_disable_msix(bfad->pcidev);
-		bfad->bfad_flags &= ~BFAD_MSIX_ON;
-	} else {
-		free_irq(bfad->pcidev->irq, bfad);
-	}
-}
-
-
diff --git a/drivers/scsi/bfa/bfad_ipfc.h b/drivers/scsi/bfa/bfad_ipfc.h
deleted file mode 100644
index 718bc52..0000000
--- a/drivers/scsi/bfa/bfad_ipfc.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DRV_IPFC_H__
-#define __BFA_DRV_IPFC_H__
-
-
-#define IPFC_NAME ""
-
-#define bfad_ipfc_module_init(x) do {} while (0)
-#define bfad_ipfc_module_exit(x) do {} while (0)
-#define bfad_ipfc_probe(x) do {} while (0)
-#define bfad_ipfc_probe_undo(x) do {} while (0)
-#define bfad_ipfc_port_config(x, y) BFA_STATUS_OK
-#define bfad_ipfc_port_unconfig(x, y) do {} while (0)
-
-#define bfad_ipfc_probe_post(x) do {} while (0)
-#define bfad_ipfc_port_new(x, y, z) BFA_STATUS_OK
-#define bfad_ipfc_port_delete(x, y) do {} while (0)
-#define bfad_ipfc_port_online(x, y) do {} while (0)
-#define bfad_ipfc_port_offline(x, y) do {} while (0)
-
-#define bfad_ip_get_attr(x) BFA_STATUS_FAILED
-#define bfad_ip_reset_drv_stats(x) BFA_STATUS_FAILED
-#define bfad_ip_get_drv_stats(x, y) BFA_STATUS_FAILED
-#define bfad_ip_enable_ipfc(x, y, z) BFA_STATUS_FAILED
-
-
-#endif
diff --git a/drivers/scsi/bfa/bfad_os.c b/drivers/scsi/bfa/bfad_os.c
deleted file mode 100644
index faf47b4..0000000
--- a/drivers/scsi/bfa/bfad_os.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfad_os.c Linux driver OS specific calls.
- */
-
-#include "bfa_os_inc.h"
-#include "bfad_drv.h"
-
-void
-bfa_os_gettimeofday(struct bfa_timeval_s *tv)
-{
-	struct timeval  tmp_tv;
-
-	do_gettimeofday(&tmp_tv);
-	tv->tv_sec = (u32) tmp_tv.tv_sec;
-	tv->tv_usec = (u32) tmp_tv.tv_usec;
-}
-
-void
-bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id,
-			const char *fmt, ...)
-{
-	va_list ap;
-	#define BFA_STRING_256	256
-	char tmp[BFA_STRING_256];
-
-	va_start(ap, fmt);
-	vsprintf(tmp, fmt, ap);
-	va_end(ap);
-
-	printk(tmp);
-}
-
-
diff --git a/drivers/scsi/bfa/bfad_tm.h b/drivers/scsi/bfa/bfad_tm.h
deleted file mode 100644
index 4901b1b..0000000
--- a/drivers/scsi/bfa/bfad_tm.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/*
- * Brocade Fibre Channel HBA Linux Target Mode Driver
- */
-
-/**
- *  tm/dummy/bfad_tm.h BFA callback dummy header file for BFA Linux target mode PCI interface module.
- */
-
-#ifndef __BFAD_TM_H__
-#define __BFAD_TM_H__
-
-#include <defs/bfa_defs_status.h>
-
-#define FCPT_NAME 		""
-
-/*
- * Called from base Linux driver on (De)Init events
- */
-
-/* attach tgt template with scst */
-#define bfad_tm_module_init()	do {} while (0)
-
-/* detach/release tgt template */
-#define bfad_tm_module_exit()	do {} while (0)
-
-#define bfad_tm_probe(x)	do {} while (0)
-#define bfad_tm_probe_undo(x)	do {} while (0)
-#define bfad_tm_probe_post(x)	do {} while (0)
-
-/*
- * Called by base Linux driver but triggered by BFA FCS on config events
- */
-#define bfad_tm_port_new(x, y)		BFA_STATUS_OK
-#define bfad_tm_port_delete(x, y)	do {} while (0)
-
-/*
- * Called by base Linux driver but triggered by BFA FCS on PLOGI/O events
- */
-#define bfad_tm_port_online(x, y)	do {} while (0)
-#define bfad_tm_port_offline(x, y)	do {} while (0)
-
-#endif
diff --git a/drivers/scsi/bfa/bfad_trcmod.h b/drivers/scsi/bfa/bfad_trcmod.h
deleted file mode 100644
index 2827b2a..0000000
--- a/drivers/scsi/bfa/bfad_trcmod.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfad_trcmod.h Linux driver trace modules
- */
-
-
-#ifndef __BFAD_TRCMOD_H__
-#define __BFAD_TRCMOD_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
-	/* 2.6 Driver */
-	BFA_TRC_LDRV_BFAD		= 1,
-	BFA_TRC_LDRV_BFAD_2_6		= 2,
-	BFA_TRC_LDRV_BFAD_2_6_9		= 3,
-	BFA_TRC_LDRV_BFAD_2_6_10	= 4,
-	BFA_TRC_LDRV_INTR		= 5,
-	BFA_TRC_LDRV_IOCTL		= 6,
-	BFA_TRC_LDRV_OS			= 7,
-	BFA_TRC_LDRV_IM			= 8,
-	BFA_TRC_LDRV_IM_2_6		= 9,
-	BFA_TRC_LDRV_IM_2_6_9		= 10,
-	BFA_TRC_LDRV_IM_2_6_10		= 11,
-	BFA_TRC_LDRV_TM			= 12,
-	BFA_TRC_LDRV_IPFC		= 13,
-	BFA_TRC_LDRV_IM_2_4		= 14,
-	BFA_TRC_LDRV_IM_VMW		= 15,
-	BFA_TRC_LDRV_IM_LT_2_6_10	= 16,
-};
-
-#endif /* __BFAD_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
new file mode 100644
index 0000000..85f2224
--- /dev/null
+++ b/drivers/scsi/bfa/bfi.h
@@ -0,0 +1,579 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFI_H__
+#define __BFI_H__
+
+#include "bfa_defs.h"
+#include "bfa_defs_svc.h"
+
+#pragma pack(1)
+
+/**
+ * BFI FW image type
+ */
+#define	BFI_FLASH_CHUNK_SZ			256	/*  Flash chunk size */
+#define	BFI_FLASH_CHUNK_SZ_WORDS	(BFI_FLASH_CHUNK_SZ/sizeof(u32))
+enum {
+	BFI_IMAGE_CB_FC,
+	BFI_IMAGE_CT_FC,
+	BFI_IMAGE_CT_CNA,
+	BFI_IMAGE_MAX,
+};
+
+/**
+ * Msg header common to all msgs
+ */
+struct bfi_mhdr_s {
+	u8		msg_class;	/*  @ref bfi_mclass_t		    */
+	u8		msg_id;		/*  msg opcode with in the class   */
+	union {
+		struct {
+			u8	rsvd;
+			u8	lpu_id;	/*  msg destination		    */
+		} h2i;
+		u16	i2htok;	/*  token in msgs to host	    */
+	} mtag;
+};
+
+#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
+	(_mh).msg_class		= (_mc);      \
+	(_mh).msg_id		= (_op);      \
+	(_mh).mtag.h2i.lpu_id	= (_lpuid);      \
+} while (0)
+
+#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\
+	(_mh).msg_class		= (_mc);      \
+	(_mh).msg_id		= (_op);      \
+	(_mh).mtag.i2htok	= (_i2htok);      \
+} while (0)
+
+/*
+ * Message opcodes: 0-127 to firmware, 128-255 to host
+ */
+#define BFI_I2H_OPCODE_BASE	128
+#define BFA_I2HM(_x)		((_x) + BFI_I2H_OPCODE_BASE)
+
+/**
+ ****************************************************************************
+ *
+ * Scatter Gather Element and Page definition
+ *
+ ****************************************************************************
+ */
+
+#define BFI_SGE_INLINE	1
+#define BFI_SGE_INLINE_MAX	(BFI_SGE_INLINE + 1)
+
+/**
+ * SG Flags
+ */
+enum {
+	BFI_SGE_DATA		= 0,	/*  data address, not last	     */
+	BFI_SGE_DATA_CPL	= 1,	/*  data addr, last in current page */
+	BFI_SGE_DATA_LAST	= 3,	/*  data address, last		     */
+	BFI_SGE_LINK		= 2,	/*  link address		     */
+	BFI_SGE_PGDLEN		= 2,	/*  cumulative data length for page */
+};
+
+/**
+ * DMA addresses
+ */
+union bfi_addr_u {
+	struct {
+		u32	addr_lo;
+		u32	addr_hi;
+	} a32;
+};
+
+/**
+ * Scatter Gather Element
+ */
+struct bfi_sge_s {
+#ifdef __BIGENDIAN
+	u32	flags:2,
+			rsvd:2,
+			sg_len:28;
+#else
+	u32	sg_len:28,
+			rsvd:2,
+			flags:2;
+#endif
+	union bfi_addr_u sga;
+};
+
+/**
+ * Scatter Gather Page
+ */
+#define BFI_SGPG_DATA_SGES		7
+#define BFI_SGPG_SGES_MAX		(BFI_SGPG_DATA_SGES + 1)
+#define BFI_SGPG_RSVD_WD_LEN	8
+struct bfi_sgpg_s {
+	struct bfi_sge_s sges[BFI_SGPG_SGES_MAX];
+	u32	rsvd[BFI_SGPG_RSVD_WD_LEN];
+};
+
+/*
+ * Large Message structure - 128 Bytes size Msgs
+ */
+#define BFI_LMSG_SZ		128
+#define BFI_LMSG_PL_WSZ	\
+			((BFI_LMSG_SZ - sizeof(struct bfi_mhdr_s)) / 4)
+
+struct bfi_msg_s {
+	struct bfi_mhdr_s mhdr;
+	u32	pl[BFI_LMSG_PL_WSZ];
+};
+
+/**
+ * Mailbox message structure
+ */
+#define BFI_MBMSG_SZ		7
+struct bfi_mbmsg_s {
+	struct bfi_mhdr_s	mh;
+	u32		pl[BFI_MBMSG_SZ];
+};
+
+/**
+ * Message Classes
+ */
+enum bfi_mclass {
+	BFI_MC_IOC		= 1,	/*  IO Controller (IOC)	    */
+	BFI_MC_FCPORT		= 5,	/*  FC port			    */
+	BFI_MC_IOCFC		= 6,	/*  FC - IO Controller (IOC)	    */
+	BFI_MC_LL               = 7,    /*  Link Layer                      */
+	BFI_MC_UF		= 8,	/*  Unsolicited frame receive	    */
+	BFI_MC_FCXP		= 9,	/*  FC Transport		    */
+	BFI_MC_LPS		= 10,	/*  lport fc login services	    */
+	BFI_MC_RPORT		= 11,	/*  Remote port		    */
+	BFI_MC_ITNIM		= 12,	/*  I-T nexus (Initiator mode)	    */
+	BFI_MC_IOIM_READ	= 13,	/*  read IO (Initiator mode)	    */
+	BFI_MC_IOIM_WRITE	= 14,	/*  write IO (Initiator mode)	    */
+	BFI_MC_IOIM_IO		= 15,	/*  IO (Initiator mode)	    */
+	BFI_MC_IOIM		= 16,	/*  IO (Initiator mode)	    */
+	BFI_MC_IOIM_IOCOM	= 17,	/*  good IO completion		    */
+	BFI_MC_TSKIM		= 18,	/*  Initiator Task management	    */
+	BFI_MC_PORT		= 21,	/*  Physical port		    */
+	BFI_MC_MAX		= 32
+};
+
+#define BFI_IOC_MAX_CQS		4
+#define BFI_IOC_MAX_CQS_ASIC	8
+#define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */
+
+#define BFI_BOOT_TYPE_OFF		8
+#define BFI_BOOT_LOADER_OFF		12
+
+#define BFI_BOOT_TYPE_NORMAL		0
+#define	BFI_BOOT_TYPE_FLASH		1
+#define	BFI_BOOT_TYPE_MEMTEST		2
+
+#define BFI_BOOT_LOADER_OS		0
+#define BFI_BOOT_LOADER_BIOS		1
+#define BFI_BOOT_LOADER_UEFI		2
+
+/**
+ *----------------------------------------------------------------------
+ *				IOC
+ *----------------------------------------------------------------------
+ */
+
+enum bfi_ioc_h2i_msgs {
+	BFI_IOC_H2I_ENABLE_REQ		= 1,
+	BFI_IOC_H2I_DISABLE_REQ		= 2,
+	BFI_IOC_H2I_GETATTR_REQ		= 3,
+	BFI_IOC_H2I_DBG_SYNC		= 4,
+	BFI_IOC_H2I_DBG_DUMP		= 5,
+};
+
+enum bfi_ioc_i2h_msgs {
+	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
+	BFI_IOC_I2H_DISABLE_REPLY	= BFA_I2HM(2),
+	BFI_IOC_I2H_GETATTR_REPLY	= BFA_I2HM(3),
+	BFI_IOC_I2H_READY_EVENT		= BFA_I2HM(4),
+	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
+};
+
+/**
+ * BFI_IOC_H2I_GETATTR_REQ message
+ */
+struct bfi_ioc_getattr_req_s {
+	struct bfi_mhdr_s	mh;
+	union bfi_addr_u	attr_addr;
+};
+
+struct bfi_ioc_attr_s {
+	wwn_t		mfg_pwwn;	/*  Mfg port wwn	   */
+	wwn_t		mfg_nwwn;	/*  Mfg node wwn	   */
+	mac_t		mfg_mac;	/*  Mfg mac		   */
+	u16	rsvd_a;
+	wwn_t		pwwn;
+	wwn_t		nwwn;
+	mac_t		mac;		/*  PBC or Mfg mac	   */
+	u16	rsvd_b;
+	mac_t		fcoe_mac;
+	u16	rsvd_c;
+	char		brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
+	u8		pcie_gen;
+	u8		pcie_lanes_orig;
+	u8		pcie_lanes;
+	u8		rx_bbcredit;	/*  receive buffer credits */
+	u32	adapter_prop;	/*  adapter properties     */
+	u16	maxfrsize;	/*  max receive frame size */
+	char		asic_rev;
+	u8		rsvd_d;
+	char		fw_version[BFA_VERSION_LEN];
+	char		optrom_version[BFA_VERSION_LEN];
+	struct		bfa_mfg_vpd_s	vpd;
+	u32	card_type;	/*  card type			*/
+};
+
+/**
+ * BFI_IOC_I2H_GETATTR_REPLY message
+ */
+struct bfi_ioc_getattr_reply_s {
+	struct	bfi_mhdr_s	mh;	/*  Common msg header		*/
+	u8			status;	/*  cfg reply status		*/
+	u8			rsvd[3];
+};
+
+/**
+ * Firmware memory page offsets
+ */
+#define BFI_IOC_SMEM_PG0_CB	(0x40)
+#define BFI_IOC_SMEM_PG0_CT	(0x180)
+
+/**
+ * Firmware statistic offset
+ */
+#define BFI_IOC_FWSTATS_OFF	(0x6B40)
+#define BFI_IOC_FWSTATS_SZ	(4096)
+
+/**
+ * Firmware trace offset
+ */
+#define BFI_IOC_TRC_OFF		(0x4b00)
+#define BFI_IOC_TRC_ENTS	256
+
+#define BFI_IOC_FW_SIGNATURE	(0xbfadbfad)
+#define BFI_IOC_MD5SUM_SZ	4
+struct bfi_ioc_image_hdr_s {
+	u32	signature;	/*  constant signature */
+	u32	rsvd_a;
+	u32	exec;		/*  exec vector	*/
+	u32	param;		/*  parameters		*/
+	u32	rsvd_b[4];
+	u32	md5sum[BFI_IOC_MD5SUM_SZ];
+};
+
+/**
+ *  BFI_IOC_I2H_READY_EVENT message
+ */
+struct bfi_ioc_rdy_event_s {
+	struct bfi_mhdr_s	mh;		/*  common msg header */
+	u8			init_status;	/*  init event status */
+	u8			rsvd[3];
+};
+
+struct bfi_ioc_hbeat_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u32	   hb_count;	/*  current heart beat count	*/
+};
+
+/**
+ * IOC hardware/firmware state
+ */
+enum bfi_ioc_state {
+	BFI_IOC_UNINIT		= 0,	/*  not initialized		     */
+	BFI_IOC_INITING		= 1,	/*  h/w is being initialized	     */
+	BFI_IOC_HWINIT		= 2,	/*  h/w is initialized		     */
+	BFI_IOC_CFG		= 3,	/*  IOC configuration in progress   */
+	BFI_IOC_OP		= 4,	/*  IOC is operational		     */
+	BFI_IOC_DISABLING	= 5,	/*  IOC is being disabled	     */
+	BFI_IOC_DISABLED	= 6,	/*  IOC is disabled		     */
+	BFI_IOC_CFG_DISABLED	= 7,	/*  IOC is being disabled;transient */
+	BFI_IOC_FAIL		= 8,	/*  IOC heart-beat failure	     */
+	BFI_IOC_MEMTEST		= 9,	/*  IOC is doing memtest	     */
+};
+
+#define BFI_IOC_ENDIAN_SIG  0x12345678
+
+enum {
+	BFI_ADAPTER_TYPE_FC	= 0x01,		/*  FC adapters	   */
+	BFI_ADAPTER_TYPE_MK	= 0x0f0000,	/*  adapter type mask     */
+	BFI_ADAPTER_TYPE_SH	= 16,	        /*  adapter type shift    */
+	BFI_ADAPTER_NPORTS_MK	= 0xff00,	/*  number of ports mask  */
+	BFI_ADAPTER_NPORTS_SH	= 8,	        /*  number of ports shift */
+	BFI_ADAPTER_SPEED_MK	= 0xff,		/*  adapter speed mask    */
+	BFI_ADAPTER_SPEED_SH	= 0,	        /*  adapter speed shift   */
+	BFI_ADAPTER_PROTO	= 0x100000,	/*  prototype adapaters   */
+	BFI_ADAPTER_TTV		= 0x200000,	/*  TTV debug capable     */
+	BFI_ADAPTER_UNSUPP	= 0x400000,	/*  unknown adapter type  */
+};
+
+#define BFI_ADAPTER_GETP(__prop, __adap_prop)			\
+	(((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >>	\
+		BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_SETP(__prop, __val)				\
+	((__val) << BFI_ADAPTER_ ## __prop ## _SH)
+#define BFI_ADAPTER_IS_PROTO(__adap_type)			\
+	((__adap_type) & BFI_ADAPTER_PROTO)
+#define BFI_ADAPTER_IS_TTV(__adap_type)				\
+	((__adap_type) & BFI_ADAPTER_TTV)
+#define BFI_ADAPTER_IS_UNSUPP(__adap_type)			\
+	((__adap_type) & BFI_ADAPTER_UNSUPP)
+#define BFI_ADAPTER_IS_SPECIAL(__adap_type)			\
+	((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO |	\
+			BFI_ADAPTER_UNSUPP))
+
+/**
+ * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
+ */
+struct bfi_ioc_ctrl_req_s {
+	struct bfi_mhdr_s	mh;
+	u8			ioc_class;
+	u8			rsvd[3];
+	u32		tv_sec;
+};
+#define bfi_ioc_enable_req_t struct bfi_ioc_ctrl_req_s;
+#define bfi_ioc_disable_req_t struct bfi_ioc_ctrl_req_s;
+
+/**
+ * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
+ */
+struct bfi_ioc_ctrl_reply_s {
+	struct bfi_mhdr_s	mh;		/*  Common msg header     */
+	u8			status;		/*  enable/disable status */
+	u8			rsvd[3];
+};
+#define bfi_ioc_enable_reply_t struct bfi_ioc_ctrl_reply_s;
+#define bfi_ioc_disable_reply_t struct bfi_ioc_ctrl_reply_s;
+
+#define BFI_IOC_MSGSZ   8
+/**
+ * H2I Messages
+ */
+union bfi_ioc_h2i_msg_u {
+	struct bfi_mhdr_s		mh;
+	struct bfi_ioc_ctrl_req_s	enable_req;
+	struct bfi_ioc_ctrl_req_s	disable_req;
+	struct bfi_ioc_getattr_req_s	getattr_req;
+	u32			mboxmsg[BFI_IOC_MSGSZ];
+};
+
+/**
+ * I2H Messages
+ */
+union bfi_ioc_i2h_msg_u {
+	struct bfi_mhdr_s		mh;
+	struct bfi_ioc_rdy_event_s	rdy_event;
+	u32			mboxmsg[BFI_IOC_MSGSZ];
+};
+
+
+/**
+ *----------------------------------------------------------------------
+ *				PBC
+ *----------------------------------------------------------------------
+ */
+
+#define BFI_PBC_MAX_BLUNS	8
+#define BFI_PBC_MAX_VPORTS	16
+
+/**
+ * PBC boot lun configuration
+ */
+struct bfi_pbc_blun_s {
+	wwn_t		tgt_pwwn;
+	lun_t		tgt_lun;
+};
+
+/**
+ * PBC virtual port configuration
+ */
+struct bfi_pbc_vport_s {
+	wwn_t		vp_pwwn;
+	wwn_t		vp_nwwn;
+};
+
+/**
+ * BFI pre-boot configuration information
+ */
+struct bfi_pbc_s {
+	u8		port_enabled;
+	u8		boot_enabled;
+	u8		nbluns;
+	u8		nvports;
+	u8		port_speed;
+	u8		rsvd_a;
+	u16	hss;
+	wwn_t		pbc_pwwn;
+	wwn_t		pbc_nwwn;
+	struct bfi_pbc_blun_s blun[BFI_PBC_MAX_BLUNS];
+	struct bfi_pbc_vport_s vport[BFI_PBC_MAX_VPORTS];
+};
+
+/**
+ *----------------------------------------------------------------------
+ *				MSGQ
+ *----------------------------------------------------------------------
+ */
+#define BFI_MSGQ_FULL(_q)	(((_q->pi + 1) % _q->q_depth) == _q->ci)
+#define BFI_MSGQ_EMPTY(_q)	(_q->pi == _q->ci)
+#define BFI_MSGQ_UPDATE_CI(_q)	(_q->ci = (_q->ci + 1) % _q->q_depth)
+#define BFI_MSGQ_UPDATE_PI(_q)	(_q->pi = (_q->pi + 1) % _q->q_depth)
+
+/* q_depth must be power of 2 */
+#define BFI_MSGQ_FREE_CNT(_q)	((_q->ci - _q->pi - 1) & (_q->q_depth - 1))
+
+enum bfi_msgq_h2i_msgs_e {
+	BFI_MSGQ_H2I_INIT_REQ	= 1,
+	BFI_MSGQ_H2I_DOORBELL	= 2,
+	BFI_MSGQ_H2I_SHUTDOWN	= 3,
+};
+
+enum bfi_msgq_i2h_msgs_e {
+	BFI_MSGQ_I2H_INIT_RSP	= 1,
+	BFI_MSGQ_I2H_DOORBELL	= 2,
+};
+
+
+/* Messages(commands/responsed/AENS will have the following header */
+struct bfi_msgq_mhdr_s {
+	u8		msg_class;
+	u8		msg_id;
+	u16	msg_token;
+	u16	num_entries;
+	u8		enet_id;
+	u8		rsvd[1];
+};
+
+#define bfi_msgq_mhdr_set(_mh, _mc, _mid, _tok, _enet_id) do {        \
+	(_mh).msg_class		= (_mc);      \
+	(_mh).msg_id		= (_mid);      \
+	(_mh).msg_token		= (_tok);      \
+	(_mh).enet_id		= (_enet_id);      \
+} while (0)
+
+/*
+ * Mailbox  for messaging interface
+ *
+*/
+#define BFI_MSGQ_CMD_ENTRY_SIZE		(64)    /* TBD */
+#define BFI_MSGQ_RSP_ENTRY_SIZE		(64)    /* TBD */
+#define BFI_MSGQ_MSG_SIZE_MAX		(2048)  /* TBD */
+
+struct bfi_msgq_s {
+	union bfi_addr_u addr;
+	u16 q_depth;     /* Total num of entries in the queue */
+	u8 rsvd[2];
+};
+
+/* BFI_ENET_MSGQ_CFG_REQ TBD init or cfg? */
+struct bfi_msgq_cfg_req_s {
+	struct bfi_mhdr_s mh;
+	struct bfi_msgq_s cmdq;
+	struct bfi_msgq_s rspq;
+};
+
+/* BFI_ENET_MSGQ_CFG_RSP */
+struct bfi_msgq_cfg_rsp_s {
+	struct bfi_mhdr_s mh;
+	u8 cmd_status;
+	u8 rsvd[3];
+};
+
+
+/* BFI_MSGQ_H2I_DOORBELL */
+struct bfi_msgq_h2i_db_s {
+	struct bfi_mhdr_s mh;
+	u16 cmdq_pi;
+	u16 rspq_ci;
+};
+
+/* BFI_MSGQ_I2H_DOORBELL */
+struct bfi_msgq_i2h_db_s {
+	struct bfi_mhdr_s mh;
+	u16 rspq_pi;
+	u16 cmdq_ci;
+};
+
+#pragma pack()
+
+/* BFI port specific */
+#pragma pack(1)
+
+enum bfi_port_h2i {
+	BFI_PORT_H2I_ENABLE_REQ         = (1),
+	BFI_PORT_H2I_DISABLE_REQ        = (2),
+	BFI_PORT_H2I_GET_STATS_REQ      = (3),
+	BFI_PORT_H2I_CLEAR_STATS_REQ    = (4),
+};
+
+enum bfi_port_i2h {
+	BFI_PORT_I2H_ENABLE_RSP         = BFA_I2HM(1),
+	BFI_PORT_I2H_DISABLE_RSP        = BFA_I2HM(2),
+	BFI_PORT_I2H_GET_STATS_RSP      = BFA_I2HM(3),
+	BFI_PORT_I2H_CLEAR_STATS_RSP    = BFA_I2HM(4),
+};
+
+/**
+ * Generic REQ type
+ */
+struct bfi_port_generic_req_s {
+	struct bfi_mhdr_s  mh;          /*  msg header		*/
+	u32     msgtag;         /*  msgtag for reply                */
+	u32     rsvd;
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_port_generic_rsp_s {
+	struct bfi_mhdr_s  mh;          /*  common msg header               */
+	u8              status;         /*  port enable status              */
+	u8              rsvd[3];
+	u32     msgtag;         /*  msgtag for reply                */
+};
+
+/**
+ * BFI_PORT_H2I_GET_STATS_REQ
+ */
+struct bfi_port_get_stats_req_s {
+	struct bfi_mhdr_s  mh;          /*  common msg header               */
+	union bfi_addr_u   dma_addr;
+};
+
+union bfi_port_h2i_msg_u {
+	struct bfi_mhdr_s               mh;
+	struct bfi_port_generic_req_s   enable_req;
+	struct bfi_port_generic_req_s   disable_req;
+	struct bfi_port_get_stats_req_s getstats_req;
+	struct bfi_port_generic_req_s   clearstats_req;
+};
+
+union bfi_port_i2h_msg_u {
+	struct bfi_mhdr_s               mh;
+	struct bfi_port_generic_rsp_s   enable_rsp;
+	struct bfi_port_generic_rsp_s   disable_rsp;
+	struct bfi_port_generic_rsp_s   getstats_rsp;
+	struct bfi_port_generic_rsp_s   clearstats_rsp;
+};
+
+#pragma pack()
+
+#endif /* __BFI_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cbreg.h b/drivers/scsi/bfa/bfi_cbreg.h
similarity index 94%
rename from drivers/scsi/bfa/include/bfi/bfi_cbreg.h
rename to drivers/scsi/bfa/bfi_cbreg.h
index a51ee61..6f03ed3 100644
--- a/drivers/scsi/bfa/include/bfi/bfi_cbreg.h
+++ b/drivers/scsi/bfa/bfi_cbreg.h
@@ -1,19 +1,3 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
 
 /*
  * bfi_cbreg.h crossbow host block register definitions
@@ -177,8 +161,8 @@
 #define __PSS_LMEM_INIT_EN               0x00000100
 #define __PSS_LPU1_RESET                 0x00000002
 #define __PSS_LPU0_RESET                 0x00000001
-#define PSS_ERR_STATUS_REG		 0x00018810
-#define __PSS_LMEM1_CORR_ERR		 0x00000800
+#define PSS_ERR_STATUS_REG               0x00018810
+#define __PSS_LMEM1_CORR_ERR             0x00000800
 #define __PSS_LMEM0_CORR_ERR             0x00000400
 #define __PSS_LMEM1_UNCORR_ERR           0x00000200
 #define __PSS_LMEM0_UNCORR_ERR           0x00000100
@@ -190,8 +174,9 @@
 #define __PSS_SGM_IF_ERR                 0x00000004
 #define __PSS_LPU1_RAM_ERR               0x00000002
 #define __PSS_LPU0_RAM_ERR               0x00000001
-#define ERR_SET_REG			 0x00018818
-#define __PSS_ERR_STATUS_SET		 0x00000fff
+#define ERR_SET_REG                      0x00018818
+#define __PSS_ERR_STATUS_SET             0x00000fff
+
 
 /*
  * These definitions are either in error/missing in spec. Its auto-generated
diff --git a/drivers/scsi/bfa/bfi_ctreg.h b/drivers/scsi/bfa/bfi_ctreg.h
new file mode 100644
index 0000000..62b86a4
--- /dev/null
+++ b/drivers/scsi/bfa/bfi_ctreg.h
@@ -0,0 +1,627 @@
+
+/*
+ * bfi_ctreg.h catapult host block register definitions
+ *
+ * !!! Do not edit. Auto generated. !!!
+ */
+
+#ifndef __BFI_CTREG_H__
+#define __BFI_CTREG_H__
+
+
+#define HOSTFN0_LPU_MBOX0_0		0x00019200
+#define HOSTFN1_LPU_MBOX0_8		0x00019260
+#define LPU_HOSTFN0_MBOX0_0		0x00019280
+#define LPU_HOSTFN1_MBOX0_8		0x000192e0
+#define HOSTFN2_LPU_MBOX0_0		0x00019400
+#define HOSTFN3_LPU_MBOX0_8		0x00019460
+#define LPU_HOSTFN2_MBOX0_0		0x00019480
+#define LPU_HOSTFN3_MBOX0_8		0x000194e0
+#define HOSTFN0_INT_STATUS		0x00014000
+#define __HOSTFN0_HALT_OCCURRED		0x01000000
+#define __HOSTFN0_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN0_INT_STATUS_LVL_SH	20
+#define __HOSTFN0_INT_STATUS_LVL(_v)	((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
+#define __HOSTFN0_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN0_INT_STATUS_P_SH	16
+#define __HOSTFN0_INT_STATUS_P(_v)	((_v) << __HOSTFN0_INT_STATUS_P_SH)
+#define __HOSTFN0_INT_STATUS_F		0x0000ffff
+#define HOSTFN0_INT_MSK			0x00014004
+#define HOST_PAGE_NUM_FN0		0x00014008
+#define __HOST_PAGE_NUM_FN		0x000001ff
+#define HOST_MSIX_ERR_INDEX_FN0		0x0001400c
+#define __MSIX_ERR_INDEX_FN		0x000001ff
+#define HOSTFN1_INT_STATUS		0x00014100
+#define __HOSTFN1_HALT_OCCURRED		0x01000000
+#define __HOSTFN1_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN1_INT_STATUS_LVL_SH	20
+#define __HOSTFN1_INT_STATUS_LVL(_v)	((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
+#define __HOSTFN1_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN1_INT_STATUS_P_SH	16
+#define __HOSTFN1_INT_STATUS_P(_v)	((_v) << __HOSTFN1_INT_STATUS_P_SH)
+#define __HOSTFN1_INT_STATUS_F		0x0000ffff
+#define HOSTFN1_INT_MSK			0x00014104
+#define HOST_PAGE_NUM_FN1		0x00014108
+#define HOST_MSIX_ERR_INDEX_FN1		0x0001410c
+#define APP_PLL_425_CTL_REG		0x00014204
+#define __P_425_PLL_LOCK		0x80000000
+#define __APP_PLL_425_SRAM_USE_100MHZ	0x00100000
+#define __APP_PLL_425_RESET_TIMER_MK	0x000e0000
+#define __APP_PLL_425_RESET_TIMER_SH	17
+#define __APP_PLL_425_RESET_TIMER(_v)	((_v) << __APP_PLL_425_RESET_TIMER_SH)
+#define __APP_PLL_425_LOGIC_SOFT_RESET	0x00010000
+#define __APP_PLL_425_CNTLMT0_1_MK	0x0000c000
+#define __APP_PLL_425_CNTLMT0_1_SH	14
+#define __APP_PLL_425_CNTLMT0_1(_v)	((_v) << __APP_PLL_425_CNTLMT0_1_SH)
+#define __APP_PLL_425_JITLMT0_1_MK	0x00003000
+#define __APP_PLL_425_JITLMT0_1_SH	12
+#define __APP_PLL_425_JITLMT0_1(_v)	((_v) << __APP_PLL_425_JITLMT0_1_SH)
+#define __APP_PLL_425_HREF		0x00000800
+#define __APP_PLL_425_HDIV		0x00000400
+#define __APP_PLL_425_P0_1_MK		0x00000300
+#define __APP_PLL_425_P0_1_SH		8
+#define __APP_PLL_425_P0_1(_v)		((_v) << __APP_PLL_425_P0_1_SH)
+#define __APP_PLL_425_Z0_2_MK		0x000000e0
+#define __APP_PLL_425_Z0_2_SH		5
+#define __APP_PLL_425_Z0_2(_v)		((_v) << __APP_PLL_425_Z0_2_SH)
+#define __APP_PLL_425_RSEL200500	0x00000010
+#define __APP_PLL_425_ENARST		0x00000008
+#define __APP_PLL_425_BYPASS		0x00000004
+#define __APP_PLL_425_LRESETN		0x00000002
+#define __APP_PLL_425_ENABLE		0x00000001
+#define APP_PLL_312_CTL_REG		0x00014208
+#define __P_312_PLL_LOCK		0x80000000
+#define __ENABLE_MAC_AHB_1		0x00800000
+#define __ENABLE_MAC_AHB_0		0x00400000
+#define __ENABLE_MAC_1			0x00200000
+#define __ENABLE_MAC_0			0x00100000
+#define __APP_PLL_312_RESET_TIMER_MK	0x000e0000
+#define __APP_PLL_312_RESET_TIMER_SH	17
+#define __APP_PLL_312_RESET_TIMER(_v)	((_v) << __APP_PLL_312_RESET_TIMER_SH)
+#define __APP_PLL_312_LOGIC_SOFT_RESET	0x00010000
+#define __APP_PLL_312_CNTLMT0_1_MK	0x0000c000
+#define __APP_PLL_312_CNTLMT0_1_SH	14
+#define __APP_PLL_312_CNTLMT0_1(_v)	((_v) << __APP_PLL_312_CNTLMT0_1_SH)
+#define __APP_PLL_312_JITLMT0_1_MK	0x00003000
+#define __APP_PLL_312_JITLMT0_1_SH	12
+#define __APP_PLL_312_JITLMT0_1(_v)	((_v) << __APP_PLL_312_JITLMT0_1_SH)
+#define __APP_PLL_312_HREF		0x00000800
+#define __APP_PLL_312_HDIV		0x00000400
+#define __APP_PLL_312_P0_1_MK		0x00000300
+#define __APP_PLL_312_P0_1_SH		8
+#define __APP_PLL_312_P0_1(_v)		((_v) << __APP_PLL_312_P0_1_SH)
+#define __APP_PLL_312_Z0_2_MK		0x000000e0
+#define __APP_PLL_312_Z0_2_SH		5
+#define __APP_PLL_312_Z0_2(_v)		((_v) << __APP_PLL_312_Z0_2_SH)
+#define __APP_PLL_312_RSEL200500	0x00000010
+#define __APP_PLL_312_ENARST		0x00000008
+#define __APP_PLL_312_BYPASS		0x00000004
+#define __APP_PLL_312_LRESETN		0x00000002
+#define __APP_PLL_312_ENABLE		0x00000001
+#define MBIST_CTL_REG			0x00014220
+#define __EDRAM_BISTR_START		0x00000004
+#define __MBIST_RESET			0x00000002
+#define __MBIST_START			0x00000001
+#define MBIST_STAT_REG			0x00014224
+#define __EDRAM_BISTR_STATUS		0x00000008
+#define __EDRAM_BISTR_DONE		0x00000004
+#define __MEM_BIT_STATUS		0x00000002
+#define __MBIST_DONE			0x00000001
+#define HOST_SEM0_REG			0x00014230
+#define __HOST_SEMAPHORE		0x00000001
+#define HOST_SEM1_REG			0x00014234
+#define HOST_SEM2_REG			0x00014238
+#define HOST_SEM3_REG			0x0001423c
+#define HOST_SEM0_INFO_REG		0x00014240
+#define HOST_SEM1_INFO_REG		0x00014244
+#define HOST_SEM2_INFO_REG		0x00014248
+#define HOST_SEM3_INFO_REG		0x0001424c
+#define ETH_MAC_SER_REG			0x00014288
+#define __APP_EMS_CKBUFAMPIN		0x00000020
+#define __APP_EMS_REFCLKSEL		0x00000010
+#define __APP_EMS_CMLCKSEL		0x00000008
+#define __APP_EMS_REFCKBUFEN2		0x00000004
+#define __APP_EMS_REFCKBUFEN1		0x00000002
+#define __APP_EMS_CHANNEL_SEL		0x00000001
+#define HOSTFN2_INT_STATUS		0x00014300
+#define __HOSTFN2_HALT_OCCURRED		0x01000000
+#define __HOSTFN2_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN2_INT_STATUS_LVL_SH	20
+#define __HOSTFN2_INT_STATUS_LVL(_v)	((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
+#define __HOSTFN2_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN2_INT_STATUS_P_SH	16
+#define __HOSTFN2_INT_STATUS_P(_v)	((_v) << __HOSTFN2_INT_STATUS_P_SH)
+#define __HOSTFN2_INT_STATUS_F		0x0000ffff
+#define HOSTFN2_INT_MSK			0x00014304
+#define HOST_PAGE_NUM_FN2		0x00014308
+#define HOST_MSIX_ERR_INDEX_FN2		0x0001430c
+#define HOSTFN3_INT_STATUS		0x00014400
+#define __HALT_OCCURRED			0x01000000
+#define __HOSTFN3_INT_STATUS_LVL_MK	0x00f00000
+#define __HOSTFN3_INT_STATUS_LVL_SH	20
+#define __HOSTFN3_INT_STATUS_LVL(_v)	((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
+#define __HOSTFN3_INT_STATUS_P_MK	0x000f0000
+#define __HOSTFN3_INT_STATUS_P_SH	16
+#define __HOSTFN3_INT_STATUS_P(_v)	((_v) << __HOSTFN3_INT_STATUS_P_SH)
+#define __HOSTFN3_INT_STATUS_F		0x0000ffff
+#define HOSTFN3_INT_MSK			0x00014404
+#define HOST_PAGE_NUM_FN3		0x00014408
+#define HOST_MSIX_ERR_INDEX_FN3		0x0001440c
+#define FNC_ID_REG			0x00014600
+#define __FUNCTION_NUMBER		0x00000007
+#define FNC_PERS_REG			0x00014604
+#define __F3_FUNCTION_ACTIVE		0x80000000
+#define __F3_FUNCTION_MODE		0x40000000
+#define __F3_PORT_MAP_MK		0x30000000
+#define __F3_PORT_MAP_SH		28
+#define __F3_PORT_MAP(_v)		((_v) << __F3_PORT_MAP_SH)
+#define __F3_VM_MODE			0x08000000
+#define __F3_INTX_STATUS_MK		0x07000000
+#define __F3_INTX_STATUS_SH		24
+#define __F3_INTX_STATUS(_v)		((_v) << __F3_INTX_STATUS_SH)
+#define __F2_FUNCTION_ACTIVE		0x00800000
+#define __F2_FUNCTION_MODE		0x00400000
+#define __F2_PORT_MAP_MK		0x00300000
+#define __F2_PORT_MAP_SH		20
+#define __F2_PORT_MAP(_v)		((_v) << __F2_PORT_MAP_SH)
+#define __F2_VM_MODE			0x00080000
+#define __F2_INTX_STATUS_MK		0x00070000
+#define __F2_INTX_STATUS_SH		16
+#define __F2_INTX_STATUS(_v)		((_v) << __F2_INTX_STATUS_SH)
+#define __F1_FUNCTION_ACTIVE		0x00008000
+#define __F1_FUNCTION_MODE		0x00004000
+#define __F1_PORT_MAP_MK		0x00003000
+#define __F1_PORT_MAP_SH		12
+#define __F1_PORT_MAP(_v)		((_v) << __F1_PORT_MAP_SH)
+#define __F1_VM_MODE			0x00000800
+#define __F1_INTX_STATUS_MK		0x00000700
+#define __F1_INTX_STATUS_SH		8
+#define __F1_INTX_STATUS(_v)		((_v) << __F1_INTX_STATUS_SH)
+#define __F0_FUNCTION_ACTIVE		0x00000080
+#define __F0_FUNCTION_MODE		0x00000040
+#define __F0_PORT_MAP_MK		0x00000030
+#define __F0_PORT_MAP_SH		4
+#define __F0_PORT_MAP(_v)		((_v) << __F0_PORT_MAP_SH)
+#define __F0_VM_MODE		0x00000008
+#define __F0_INTX_STATUS		0x00000007
+enum {
+	__F0_INTX_STATUS_MSIX		= 0x0,
+	__F0_INTX_STATUS_INTA		= 0x1,
+	__F0_INTX_STATUS_INTB		= 0x2,
+	__F0_INTX_STATUS_INTC		= 0x3,
+	__F0_INTX_STATUS_INTD		= 0x4,
+};
+#define OP_MODE				0x0001460c
+#define __APP_ETH_CLK_LOWSPEED		0x00000004
+#define __GLOBAL_CORECLK_HALFSPEED	0x00000002
+#define __GLOBAL_FCOE_MODE		0x00000001
+#define HOST_SEM4_REG			0x00014610
+#define HOST_SEM5_REG			0x00014614
+#define HOST_SEM6_REG			0x00014618
+#define HOST_SEM7_REG			0x0001461c
+#define HOST_SEM4_INFO_REG		0x00014620
+#define HOST_SEM5_INFO_REG		0x00014624
+#define HOST_SEM6_INFO_REG		0x00014628
+#define HOST_SEM7_INFO_REG		0x0001462c
+#define HOSTFN0_LPU0_MBOX0_CMD_STAT	0x00019000
+#define __HOSTFN0_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN0_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN0_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN0_LPU1_MBOX0_CMD_STAT	0x00019004
+#define __HOSTFN0_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN0_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN0_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN0_MBOX0_CMD_STAT	0x00019008
+#define __LPU0_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN0_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN0_MBOX0_CMD_STAT	0x0001900c
+#define __LPU1_HOSTFN0_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN0_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN0_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU0_MBOX0_CMD_STAT	0x00019010
+#define __HOSTFN1_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN1_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN1_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN1_LPU1_MBOX0_CMD_STAT	0x00019014
+#define __HOSTFN1_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN1_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN1_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN1_MBOX0_CMD_STAT	0x00019018
+#define __LPU0_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN1_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN1_MBOX0_CMD_STAT	0x0001901c
+#define __LPU1_HOSTFN1_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN1_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN1_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU0_MBOX0_CMD_STAT	0x00019150
+#define __HOSTFN2_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN2_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN2_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN2_LPU1_MBOX0_CMD_STAT	0x00019154
+#define __HOSTFN2_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN2_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN2_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN2_MBOX0_CMD_STAT	0x00019158
+#define __LPU0_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN2_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN2_MBOX0_CMD_STAT	0x0001915c
+#define __LPU1_HOSTFN2_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN2_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN2_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU0_MBOX0_CMD_STAT	0x00019160
+#define __HOSTFN3_LPU0_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN3_LPU0_MBOX0_INFO_SH	1
+#define __HOSTFN3_LPU0_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001
+#define HOSTFN3_LPU1_MBOX0_CMD_STAT	0x00019164
+#define __HOSTFN3_LPU1_MBOX0_INFO_MK	0xfffffffe
+#define __HOSTFN3_LPU1_MBOX0_INFO_SH	1
+#define __HOSTFN3_LPU1_MBOX0_INFO(_v)	((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
+#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001
+#define LPU0_HOSTFN3_MBOX0_CMD_STAT	0x00019168
+#define __LPU0_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
+#define __LPU0_HOSTFN3_MBOX0_INFO_SH	1
+#define __LPU0_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001
+#define LPU1_HOSTFN3_MBOX0_CMD_STAT	0x0001916c
+#define __LPU1_HOSTFN3_MBOX0_INFO_MK	0xfffffffe
+#define __LPU1_HOSTFN3_MBOX0_INFO_SH	1
+#define __LPU1_HOSTFN3_MBOX0_INFO(_v)	((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
+#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS	0x00000001
+#define FW_INIT_HALT_P0			0x000191ac
+#define __FW_INIT_HALT_P		0x00000001
+#define FW_INIT_HALT_P1			0x000191bc
+#define CPE_PI_PTR_Q0			0x00038000
+#define __CPE_PI_UNUSED_MK		0xffff0000
+#define __CPE_PI_UNUSED_SH		16
+#define __CPE_PI_UNUSED(_v)		((_v) << __CPE_PI_UNUSED_SH)
+#define __CPE_PI_PTR			0x0000ffff
+#define CPE_PI_PTR_Q1			0x00038040
+#define CPE_CI_PTR_Q0			0x00038004
+#define __CPE_CI_UNUSED_MK		0xffff0000
+#define __CPE_CI_UNUSED_SH		16
+#define __CPE_CI_UNUSED(_v)		((_v) << __CPE_CI_UNUSED_SH)
+#define __CPE_CI_PTR			0x0000ffff
+#define CPE_CI_PTR_Q1			0x00038044
+#define CPE_DEPTH_Q0			0x00038008
+#define __CPE_DEPTH_UNUSED_MK		0xf8000000
+#define __CPE_DEPTH_UNUSED_SH		27
+#define __CPE_DEPTH_UNUSED(_v)		((_v) << __CPE_DEPTH_UNUSED_SH)
+#define __CPE_MSIX_VEC_INDEX_MK		0x07ff0000
+#define __CPE_MSIX_VEC_INDEX_SH		16
+#define __CPE_MSIX_VEC_INDEX(_v)	((_v) << __CPE_MSIX_VEC_INDEX_SH)
+#define __CPE_DEPTH			0x0000ffff
+#define CPE_DEPTH_Q1			0x00038048
+#define CPE_QCTRL_Q0			0x0003800c
+#define __CPE_CTRL_UNUSED30_MK		0xfc000000
+#define __CPE_CTRL_UNUSED30_SH		26
+#define __CPE_CTRL_UNUSED30(_v)		((_v) << __CPE_CTRL_UNUSED30_SH)
+#define __CPE_FUNC_INT_CTRL_MK		0x03000000
+#define __CPE_FUNC_INT_CTRL_SH		24
+#define __CPE_FUNC_INT_CTRL(_v)		((_v) << __CPE_FUNC_INT_CTRL_SH)
+enum {
+	__CPE_FUNC_INT_CTRL_DISABLE		= 0x0,
+	__CPE_FUNC_INT_CTRL_F2NF		= 0x1,
+	__CPE_FUNC_INT_CTRL_3QUART		= 0x2,
+	__CPE_FUNC_INT_CTRL_HALF		= 0x3,
+};
+#define __CPE_CTRL_UNUSED20_MK		0x00f00000
+#define __CPE_CTRL_UNUSED20_SH		20
+#define __CPE_CTRL_UNUSED20(_v)		((_v) << __CPE_CTRL_UNUSED20_SH)
+#define __CPE_SCI_TH_MK			0x000f0000
+#define __CPE_SCI_TH_SH			16
+#define __CPE_SCI_TH(_v)		((_v) << __CPE_SCI_TH_SH)
+#define __CPE_CTRL_UNUSED10_MK		0x0000c000
+#define __CPE_CTRL_UNUSED10_SH		14
+#define __CPE_CTRL_UNUSED10(_v)		((_v) << __CPE_CTRL_UNUSED10_SH)
+#define __CPE_ACK_PENDING		0x00002000
+#define __CPE_CTRL_UNUSED40_MK		0x00001c00
+#define __CPE_CTRL_UNUSED40_SH		10
+#define __CPE_CTRL_UNUSED40(_v)		((_v) << __CPE_CTRL_UNUSED40_SH)
+#define __CPE_PCIEID_MK			0x00000300
+#define __CPE_PCIEID_SH			8
+#define __CPE_PCIEID(_v)		((_v) << __CPE_PCIEID_SH)
+#define __CPE_CTRL_UNUSED00_MK		0x000000fe
+#define __CPE_CTRL_UNUSED00_SH		1
+#define __CPE_CTRL_UNUSED00(_v)		((_v) << __CPE_CTRL_UNUSED00_SH)
+#define __CPE_ESIZE			0x00000001
+#define CPE_QCTRL_Q1			0x0003804c
+#define __CPE_CTRL_UNUSED31_MK		0xfc000000
+#define __CPE_CTRL_UNUSED31_SH		26
+#define __CPE_CTRL_UNUSED31(_v)		((_v) << __CPE_CTRL_UNUSED31_SH)
+#define __CPE_CTRL_UNUSED21_MK		0x00f00000
+#define __CPE_CTRL_UNUSED21_SH		20
+#define __CPE_CTRL_UNUSED21(_v)		((_v) << __CPE_CTRL_UNUSED21_SH)
+#define __CPE_CTRL_UNUSED11_MK		0x0000c000
+#define __CPE_CTRL_UNUSED11_SH		14
+#define __CPE_CTRL_UNUSED11(_v)		((_v) << __CPE_CTRL_UNUSED11_SH)
+#define __CPE_CTRL_UNUSED41_MK		0x00001c00
+#define __CPE_CTRL_UNUSED41_SH		10
+#define __CPE_CTRL_UNUSED41(_v)		((_v) << __CPE_CTRL_UNUSED41_SH)
+#define __CPE_CTRL_UNUSED01_MK		0x000000fe
+#define __CPE_CTRL_UNUSED01_SH		1
+#define __CPE_CTRL_UNUSED01(_v)		((_v) << __CPE_CTRL_UNUSED01_SH)
+#define RME_PI_PTR_Q0			0x00038020
+#define __LATENCY_TIME_STAMP_MK		0xffff0000
+#define __LATENCY_TIME_STAMP_SH		16
+#define __LATENCY_TIME_STAMP(_v)	((_v) << __LATENCY_TIME_STAMP_SH)
+#define __RME_PI_PTR			0x0000ffff
+#define RME_PI_PTR_Q1			0x00038060
+#define RME_CI_PTR_Q0			0x00038024
+#define __DELAY_TIME_STAMP_MK		0xffff0000
+#define __DELAY_TIME_STAMP_SH		16
+#define __DELAY_TIME_STAMP(_v)		((_v) << __DELAY_TIME_STAMP_SH)
+#define __RME_CI_PTR			0x0000ffff
+#define RME_CI_PTR_Q1			0x00038064
+#define RME_DEPTH_Q0			0x00038028
+#define __RME_DEPTH_UNUSED_MK		0xf8000000
+#define __RME_DEPTH_UNUSED_SH		27
+#define __RME_DEPTH_UNUSED(_v)		((_v) << __RME_DEPTH_UNUSED_SH)
+#define __RME_MSIX_VEC_INDEX_MK		0x07ff0000
+#define __RME_MSIX_VEC_INDEX_SH		16
+#define __RME_MSIX_VEC_INDEX(_v)	((_v) << __RME_MSIX_VEC_INDEX_SH)
+#define __RME_DEPTH			0x0000ffff
+#define RME_DEPTH_Q1			0x00038068
+#define RME_QCTRL_Q0			0x0003802c
+#define __RME_INT_LATENCY_TIMER_MK	0xff000000
+#define __RME_INT_LATENCY_TIMER_SH	24
+#define __RME_INT_LATENCY_TIMER(_v)	((_v) << __RME_INT_LATENCY_TIMER_SH)
+#define __RME_INT_DELAY_TIMER_MK	0x00ff0000
+#define __RME_INT_DELAY_TIMER_SH	16
+#define __RME_INT_DELAY_TIMER(_v)	((_v) << __RME_INT_DELAY_TIMER_SH)
+#define __RME_INT_DELAY_DISABLE		0x00008000
+#define __RME_DLY_DELAY_DISABLE		0x00004000
+#define __RME_ACK_PENDING		0x00002000
+#define __RME_FULL_INTERRUPT_DISABLE	0x00001000
+#define __RME_CTRL_UNUSED10_MK		0x00000c00
+#define __RME_CTRL_UNUSED10_SH		10
+#define __RME_CTRL_UNUSED10(_v)		((_v) << __RME_CTRL_UNUSED10_SH)
+#define __RME_PCIEID_MK			0x00000300
+#define __RME_PCIEID_SH			8
+#define __RME_PCIEID(_v)		((_v) << __RME_PCIEID_SH)
+#define __RME_CTRL_UNUSED00_MK		0x000000fe
+#define __RME_CTRL_UNUSED00_SH		1
+#define __RME_CTRL_UNUSED00(_v)		((_v) << __RME_CTRL_UNUSED00_SH)
+#define __RME_ESIZE			0x00000001
+#define RME_QCTRL_Q1			0x0003806c
+#define __RME_CTRL_UNUSED11_MK		0x00000c00
+#define __RME_CTRL_UNUSED11_SH		10
+#define __RME_CTRL_UNUSED11(_v)		((_v) << __RME_CTRL_UNUSED11_SH)
+#define __RME_CTRL_UNUSED01_MK		0x000000fe
+#define __RME_CTRL_UNUSED01_SH		1
+#define __RME_CTRL_UNUSED01(_v)		((_v) << __RME_CTRL_UNUSED01_SH)
+#define PSS_CTL_REG			0x00018800
+#define __PSS_I2C_CLK_DIV_MK		0x007f0000
+#define __PSS_I2C_CLK_DIV_SH		16
+#define __PSS_I2C_CLK_DIV(_v)		((_v) << __PSS_I2C_CLK_DIV_SH)
+#define __PSS_LMEM_INIT_DONE		0x00001000
+#define __PSS_LMEM_RESET		0x00000200
+#define __PSS_LMEM_INIT_EN		0x00000100
+#define __PSS_LPU1_RESET		0x00000002
+#define __PSS_LPU0_RESET		0x00000001
+#define PSS_ERR_STATUS_REG		0x00018810
+#define __PSS_LPU1_TCM_READ_ERR		0x00200000
+#define __PSS_LPU0_TCM_READ_ERR		0x00100000
+#define __PSS_LMEM5_CORR_ERR		0x00080000
+#define __PSS_LMEM4_CORR_ERR		0x00040000
+#define __PSS_LMEM3_CORR_ERR		0x00020000
+#define __PSS_LMEM2_CORR_ERR		0x00010000
+#define __PSS_LMEM1_CORR_ERR		0x00008000
+#define __PSS_LMEM0_CORR_ERR		0x00004000
+#define __PSS_LMEM5_UNCORR_ERR		0x00002000
+#define __PSS_LMEM4_UNCORR_ERR		0x00001000
+#define __PSS_LMEM3_UNCORR_ERR		0x00000800
+#define __PSS_LMEM2_UNCORR_ERR		0x00000400
+#define __PSS_LMEM1_UNCORR_ERR		0x00000200
+#define __PSS_LMEM0_UNCORR_ERR		0x00000100
+#define __PSS_BAL_PERR			0x00000080
+#define __PSS_DIP_IF_ERR		0x00000040
+#define __PSS_IOH_IF_ERR		0x00000020
+#define __PSS_TDS_IF_ERR		0x00000010
+#define __PSS_RDS_IF_ERR		0x00000008
+#define __PSS_SGM_IF_ERR		0x00000004
+#define __PSS_LPU1_RAM_ERR		0x00000002
+#define __PSS_LPU0_RAM_ERR		0x00000001
+#define ERR_SET_REG			0x00018818
+#define __PSS_ERR_STATUS_SET		0x003fffff
+#define PMM_1T_RESET_REG_P0		0x0002381c
+#define __PMM_1T_RESET_P		0x00000001
+#define PMM_1T_RESET_REG_P1		0x00023c1c
+#define HQM_QSET0_RXQ_DRBL_P0		0x00038000
+#define __RXQ0_ADD_VECTORS_P		0x80000000
+#define __RXQ0_STOP_P			0x40000000
+#define __RXQ0_PRD_PTR_P		0x0000ffff
+#define HQM_QSET1_RXQ_DRBL_P0		0x00038080
+#define __RXQ1_ADD_VECTORS_P		0x80000000
+#define __RXQ1_STOP_P			0x40000000
+#define __RXQ1_PRD_PTR_P		0x0000ffff
+#define HQM_QSET0_RXQ_DRBL_P1		0x0003c000
+#define HQM_QSET1_RXQ_DRBL_P1		0x0003c080
+#define HQM_QSET0_TXQ_DRBL_P0		0x00038020
+#define __TXQ0_ADD_VECTORS_P		0x80000000
+#define __TXQ0_STOP_P			0x40000000
+#define __TXQ0_PRD_PTR_P		0x0000ffff
+#define HQM_QSET1_TXQ_DRBL_P0		0x000380a0
+#define __TXQ1_ADD_VECTORS_P		0x80000000
+#define __TXQ1_STOP_P			0x40000000
+#define __TXQ1_PRD_PTR_P		0x0000ffff
+#define HQM_QSET0_TXQ_DRBL_P1		0x0003c020
+#define HQM_QSET1_TXQ_DRBL_P1		0x0003c0a0
+#define HQM_QSET0_IB_DRBL_1_P0		0x00038040
+#define __IB1_0_ACK_P			0x80000000
+#define __IB1_0_DISABLE_P		0x40000000
+#define __IB1_0_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB1_0_COALESCING_CFG_P_SH	16
+#define __IB1_0_COALESCING_CFG_P(_v)	((_v) << __IB1_0_COALESCING_CFG_P_SH)
+#define __IB1_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET1_IB_DRBL_1_P0		0x000380c0
+#define __IB1_1_ACK_P			0x80000000
+#define __IB1_1_DISABLE_P		0x40000000
+#define __IB1_1_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB1_1_COALESCING_CFG_P_SH	16
+#define __IB1_1_COALESCING_CFG_P(_v)	((_v) << __IB1_1_COALESCING_CFG_P_SH)
+#define __IB1_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET0_IB_DRBL_1_P1		0x0003c040
+#define HQM_QSET1_IB_DRBL_1_P1		0x0003c0c0
+#define HQM_QSET0_IB_DRBL_2_P0		0x00038060
+#define __IB2_0_ACK_P			0x80000000
+#define __IB2_0_DISABLE_P		0x40000000
+#define __IB2_0_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB2_0_COALESCING_CFG_P_SH	16
+#define __IB2_0_COALESCING_CFG_P(_v)	((_v) << __IB2_0_COALESCING_CFG_P_SH)
+#define __IB2_0_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET1_IB_DRBL_2_P0		0x000380e0
+#define __IB2_1_ACK_P			0x80000000
+#define __IB2_1_DISABLE_P		0x40000000
+#define __IB2_1_COALESCING_CFG_P_MK	0x00ff0000
+#define __IB2_1_COALESCING_CFG_P_SH	16
+#define __IB2_1_COALESCING_CFG_P(_v)	((_v) << __IB2_1_COALESCING_CFG_P_SH)
+#define __IB2_1_NUM_OF_ACKED_EVENTS_P	0x0000ffff
+#define HQM_QSET0_IB_DRBL_2_P1		0x0003c060
+#define HQM_QSET1_IB_DRBL_2_P1		0x0003c0e0
+
+
+/*
+ * These definitions are either in error/missing in spec. Its auto-generated
+ * from hard coded values in regparse.pl.
+ */
+#define __EMPHPOST_AT_4G_MK_FIX		0x0000001c
+#define __EMPHPOST_AT_4G_SH_FIX		0x00000002
+#define __EMPHPRE_AT_4G_FIX		0x00000003
+#define __SFP_TXRATE_EN_FIX		0x00000100
+#define __SFP_RXRATE_EN_FIX		0x00000080
+
+
+/*
+ * These register definitions are auto-generated from hard coded values
+ * in regparse.pl.
+ */
+
+
+/*
+ * These register mapping definitions are auto-generated from mapping tables
+ * in regparse.pl.
+ */
+#define BFA_IOC0_HBEAT_REG		HOST_SEM0_INFO_REG
+#define BFA_IOC0_STATE_REG		HOST_SEM1_INFO_REG
+#define BFA_IOC1_HBEAT_REG		HOST_SEM2_INFO_REG
+#define BFA_IOC1_STATE_REG		HOST_SEM3_INFO_REG
+#define BFA_FW_USE_COUNT		 HOST_SEM4_INFO_REG
+
+#define CPE_DEPTH_Q(__n) \
+	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
+#define CPE_QCTRL_Q(__n) \
+	(CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
+#define CPE_PI_PTR_Q(__n) \
+	(CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
+#define CPE_CI_PTR_Q(__n) \
+	(CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
+#define RME_DEPTH_Q(__n) \
+	(RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
+#define RME_QCTRL_Q(__n) \
+	(RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
+#define RME_PI_PTR_Q(__n) \
+	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
+#define RME_CI_PTR_Q(__n) \
+	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
+#define HQM_QSET_RXQ_DRBL_P0(__n) (HQM_QSET0_RXQ_DRBL_P0 + (__n) \
+	* (HQM_QSET1_RXQ_DRBL_P0 - HQM_QSET0_RXQ_DRBL_P0))
+#define HQM_QSET_TXQ_DRBL_P0(__n) (HQM_QSET0_TXQ_DRBL_P0 + (__n) \
+	* (HQM_QSET1_TXQ_DRBL_P0 - HQM_QSET0_TXQ_DRBL_P0))
+#define HQM_QSET_IB_DRBL_1_P0(__n) (HQM_QSET0_IB_DRBL_1_P0 + (__n) \
+	* (HQM_QSET1_IB_DRBL_1_P0 - HQM_QSET0_IB_DRBL_1_P0))
+#define HQM_QSET_IB_DRBL_2_P0(__n) (HQM_QSET0_IB_DRBL_2_P0 + (__n) \
+	* (HQM_QSET1_IB_DRBL_2_P0 - HQM_QSET0_IB_DRBL_2_P0))
+#define HQM_QSET_RXQ_DRBL_P1(__n) (HQM_QSET0_RXQ_DRBL_P1 + (__n) \
+	* (HQM_QSET1_RXQ_DRBL_P1 - HQM_QSET0_RXQ_DRBL_P1))
+#define HQM_QSET_TXQ_DRBL_P1(__n) (HQM_QSET0_TXQ_DRBL_P1 + (__n) \
+	* (HQM_QSET1_TXQ_DRBL_P1 - HQM_QSET0_TXQ_DRBL_P1))
+#define HQM_QSET_IB_DRBL_1_P1(__n) (HQM_QSET0_IB_DRBL_1_P1 + (__n) \
+	* (HQM_QSET1_IB_DRBL_1_P1 - HQM_QSET0_IB_DRBL_1_P1))
+#define HQM_QSET_IB_DRBL_2_P1(__n) (HQM_QSET0_IB_DRBL_2_P1 + (__n) \
+	* (HQM_QSET1_IB_DRBL_2_P1 - HQM_QSET0_IB_DRBL_2_P1))
+
+#define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q))
+#define CPE_Q_MASK(__q) ((__q) & 0x3)
+#define RME_Q_MASK(__q) ((__q) & 0x3)
+
+
+/*
+ * PCI MSI-X vector defines
+ */
+enum {
+	BFA_MSIX_CPE_Q0 = 0,
+	BFA_MSIX_CPE_Q1 = 1,
+	BFA_MSIX_CPE_Q2 = 2,
+	BFA_MSIX_CPE_Q3 = 3,
+	BFA_MSIX_RME_Q0 = 4,
+	BFA_MSIX_RME_Q1 = 5,
+	BFA_MSIX_RME_Q2 = 6,
+	BFA_MSIX_RME_Q3 = 7,
+	BFA_MSIX_LPU_ERR = 8,
+	BFA_MSIX_CT_MAX = 9,
+};
+
+/*
+ * And corresponding host interrupt status bit field defines
+ */
+#define __HFN_INT_CPE_Q0		0x00000001U
+#define __HFN_INT_CPE_Q1		0x00000002U
+#define __HFN_INT_CPE_Q2		0x00000004U
+#define __HFN_INT_CPE_Q3		0x00000008U
+#define __HFN_INT_CPE_Q4		0x00000010U
+#define __HFN_INT_CPE_Q5		0x00000020U
+#define __HFN_INT_CPE_Q6		0x00000040U
+#define __HFN_INT_CPE_Q7		0x00000080U
+#define __HFN_INT_RME_Q0		0x00000100U
+#define __HFN_INT_RME_Q1		0x00000200U
+#define __HFN_INT_RME_Q2		0x00000400U
+#define __HFN_INT_RME_Q3		0x00000800U
+#define __HFN_INT_RME_Q4		0x00001000U
+#define __HFN_INT_RME_Q5		0x00002000U
+#define __HFN_INT_RME_Q6		0x00004000U
+#define __HFN_INT_RME_Q7		0x00008000U
+#define __HFN_INT_ERR_EMC		0x00010000U
+#define __HFN_INT_ERR_LPU0		0x00020000U
+#define __HFN_INT_ERR_LPU1		0x00040000U
+#define __HFN_INT_ERR_PSS		0x00080000U
+#define __HFN_INT_MBOX_LPU0		0x00100000U
+#define __HFN_INT_MBOX_LPU1		0x00200000U
+#define __HFN_INT_MBOX1_LPU0		0x00400000U
+#define __HFN_INT_MBOX1_LPU1		0x00800000U
+#define __HFN_INT_LL_HALT		0x01000000U
+#define __HFN_INT_CPE_MASK		0x000000ffU
+#define __HFN_INT_RME_MASK		0x0000ff00U
+
+
+/*
+ * catapult memory map.
+ */
+#define LL_PGN_HQM0		0x0096
+#define LL_PGN_HQM1		0x0097
+#define PSS_SMEM_PAGE_START	0x8000
+#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
+#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
+
+/*
+ * End of catapult memory map
+ */
+
+
+#endif /* __BFI_CTREG_H__ */
diff --git a/drivers/scsi/bfa/bfi_ms.h b/drivers/scsi/bfa/bfi_ms.h
new file mode 100644
index 0000000..69ac85f
--- /dev/null
+++ b/drivers/scsi/bfa/bfi_ms.h
@@ -0,0 +1,765 @@
+/*
+ * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
+ * All rights reserved
+ * www.brocade.com
+ *
+ * Linux driver for Brocade Fibre Channel Host Bus Adapter.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License (GPL) 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.
+ */
+
+#ifndef __BFI_MS_H__
+#define __BFI_MS_H__
+
+#include "bfi.h"
+#include "bfa_fc.h"
+#include "bfa_defs_svc.h"
+
+#pragma pack(1)
+
+enum bfi_iocfc_h2i_msgs {
+	BFI_IOCFC_H2I_CFG_REQ		= 1,
+	BFI_IOCFC_H2I_SET_INTR_REQ	= 2,
+	BFI_IOCFC_H2I_UPDATEQ_REQ	= 3,
+};
+
+enum bfi_iocfc_i2h_msgs {
+	BFI_IOCFC_I2H_CFG_REPLY		= BFA_I2HM(1),
+	BFI_IOCFC_I2H_UPDATEQ_RSP	= BFA_I2HM(3),
+};
+
+struct bfi_iocfc_cfg_s {
+	u8	num_cqs;	/*  Number of CQs to be used	*/
+	u8	 sense_buf_len;	/*  SCSI sense length	    */
+	u16	rsvd_1;
+	u32	endian_sig;	/*  endian signature of host     */
+
+	/**
+	 * Request and response circular queue base addresses, size and
+	 * shadow index pointers.
+	 */
+	union bfi_addr_u  req_cq_ba[BFI_IOC_MAX_CQS];
+	union bfi_addr_u  req_shadow_ci[BFI_IOC_MAX_CQS];
+	u16    req_cq_elems[BFI_IOC_MAX_CQS];
+	union bfi_addr_u  rsp_cq_ba[BFI_IOC_MAX_CQS];
+	union bfi_addr_u  rsp_shadow_pi[BFI_IOC_MAX_CQS];
+	u16    rsp_cq_elems[BFI_IOC_MAX_CQS];
+
+	union bfi_addr_u  stats_addr;	/*  DMA-able address for stats	  */
+	union bfi_addr_u  cfgrsp_addr;	/*  config response dma address  */
+	union bfi_addr_u  ioim_snsbase;  /*  IO sense buffer base address */
+	struct bfa_iocfc_intr_attr_s intr_attr; /*  IOC interrupt attributes */
+};
+
+/**
+ * Boot target wwn information for this port. This contains either the stored
+ * or discovered boot target port wwns for the port.
+ */
+struct bfi_iocfc_bootwwns {
+	wwn_t		wwn[BFA_BOOT_BOOTLUN_MAX];
+	u8		nwwns;
+	u8		rsvd[7];
+};
+
+struct bfi_iocfc_cfgrsp_s {
+	struct bfa_iocfc_fwcfg_s	fwcfg;
+	struct bfa_iocfc_intr_attr_s	intr_attr;
+	struct bfi_iocfc_bootwwns	bootwwns;
+	struct bfi_pbc_s		pbc_cfg;
+};
+
+/**
+ * BFI_IOCFC_H2I_CFG_REQ message
+ */
+struct bfi_iocfc_cfg_req_s {
+	struct bfi_mhdr_s      mh;
+	union bfi_addr_u      ioc_cfg_dma_addr;
+};
+
+
+/**
+ * BFI_IOCFC_I2H_CFG_REPLY message
+ */
+struct bfi_iocfc_cfg_reply_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header	  */
+	u8	 cfg_success;	/*  cfg reply status	   */
+	u8	 lpu_bm;		/*  LPUs assigned for this IOC */
+	u8	 rsvd[2];
+};
+
+
+/**
+ * BFI_IOCFC_H2I_SET_INTR_REQ message
+ */
+struct bfi_iocfc_set_intr_req_s {
+	struct bfi_mhdr_s mh;		/*  common msg header		*/
+	u8		coalesce;	/*  enable intr coalescing	*/
+	u8		rsvd[3];
+	u16	delay;		/*  delay timer 0..1125us	*/
+	u16	latency;	/*  latency timer 0..225us	*/
+};
+
+
+/**
+ * BFI_IOCFC_H2I_UPDATEQ_REQ message
+ */
+struct bfi_iocfc_updateq_req_s {
+	struct bfi_mhdr_s mh;		/*  common msg header		*/
+	u32 reqq_ba;		/*  reqq base addr		*/
+	u32 rspq_ba;		/*  rspq base addr		*/
+	u32 reqq_sci;		/*  reqq shadow ci		*/
+	u32 rspq_spi;		/*  rspq shadow pi		*/
+};
+
+
+/**
+ * BFI_IOCFC_I2H_UPDATEQ_RSP message
+ */
+struct bfi_iocfc_updateq_rsp_s {
+	struct bfi_mhdr_s mh;		/*  common msg header	*/
+	u8	status;			/*  updateq  status	*/
+	u8	rsvd[3];
+};
+
+
+/**
+ * H2I Messages
+ */
+union bfi_iocfc_h2i_msg_u {
+	struct bfi_mhdr_s		mh;
+	struct bfi_iocfc_cfg_req_s	cfg_req;
+	struct bfi_iocfc_updateq_req_s updateq_req;
+	u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+
+/**
+ * I2H Messages
+ */
+union bfi_iocfc_i2h_msg_u {
+	struct bfi_mhdr_s		mh;
+	struct bfi_iocfc_cfg_reply_s	cfg_reply;
+	struct bfi_iocfc_updateq_rsp_s updateq_rsp;
+	u32 mboxmsg[BFI_IOC_MSGSZ];
+};
+
+
+enum bfi_fcport_h2i {
+	BFI_FCPORT_H2I_ENABLE_REQ		= (1),
+	BFI_FCPORT_H2I_DISABLE_REQ		= (2),
+	BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ	= (3),
+	BFI_FCPORT_H2I_STATS_GET_REQ		= (4),
+	BFI_FCPORT_H2I_STATS_CLEAR_REQ		= (5),
+};
+
+
+enum bfi_fcport_i2h {
+	BFI_FCPORT_I2H_ENABLE_RSP		= BFA_I2HM(1),
+	BFI_FCPORT_I2H_DISABLE_RSP		= BFA_I2HM(2),
+	BFI_FCPORT_I2H_SET_SVC_PARAMS_RSP	= BFA_I2HM(3),
+	BFI_FCPORT_I2H_STATS_GET_RSP		= BFA_I2HM(4),
+	BFI_FCPORT_I2H_STATS_CLEAR_RSP		= BFA_I2HM(5),
+	BFI_FCPORT_I2H_EVENT			= BFA_I2HM(6),
+	BFI_FCPORT_I2H_TRUNK_SCN		= BFA_I2HM(7),
+	BFI_FCPORT_I2H_ENABLE_AEN		= BFA_I2HM(8),
+	BFI_FCPORT_I2H_DISABLE_AEN		= BFA_I2HM(9),
+};
+
+
+/**
+ * Generic REQ type
+ */
+struct bfi_fcport_req_s {
+	struct bfi_mhdr_s  mh;		/*  msg header			    */
+	u32	   msgtag;	/*  msgtag for reply		    */
+};
+
+/**
+ * Generic RSP type
+ */
+struct bfi_fcport_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		    */
+	u8		   status;	/*  port enable status		    */
+	u8		   rsvd[3];
+	u32	   msgtag;	/*  msgtag for reply		    */
+};
+
+/**
+ * BFI_FCPORT_H2I_ENABLE_REQ
+ */
+struct bfi_fcport_enable_req_s {
+	struct bfi_mhdr_s  mh;		/*  msg header			    */
+	u32	   rsvd1;
+	wwn_t		   nwwn;	/*  node wwn of physical port	    */
+	wwn_t		   pwwn;	/*  port wwn of physical port	    */
+	struct bfa_port_cfg_s port_cfg; /*  port configuration	    */
+	union bfi_addr_u   stats_dma_addr; /*  DMA address for stats	    */
+	u32	   msgtag;	/*  msgtag for reply		    */
+	u32	   rsvd2;
+};
+
+/**
+ * BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ
+ */
+struct bfi_fcport_set_svc_params_req_s {
+	struct bfi_mhdr_s  mh;		/*  msg header */
+	u16	   tx_bbcredit;	/*  Tx credits */
+	u16	   rsvd;
+};
+
+/**
+ * BFI_FCPORT_I2H_EVENT
+ */
+struct bfi_fcport_event_s {
+	struct bfi_mhdr_s	mh;	/*  common msg header */
+	struct bfa_port_link_s	link_state;
+};
+
+/**
+ * BFI_FCPORT_I2H_TRUNK_SCN
+ */
+struct bfi_fcport_trunk_link_s {
+	wwn_t			trunk_wwn;
+	u8			fctl;		/* bfa_trunk_link_fctl_t */
+	u8			state;		/* bfa_trunk_link_state_t */
+	u8			speed;		/* bfa_port_speed_t */
+	u8			rsvd;
+	u32		deskew;
+};
+
+#define BFI_FCPORT_MAX_LINKS	2
+struct bfi_fcport_trunk_scn_s {
+	struct bfi_mhdr_s	mh;
+	u8			trunk_state;	/* bfa_trunk_state_t */
+	u8			trunk_speed;	/* bfa_port_speed_t */
+	u8			rsvd_a[2];
+	struct bfi_fcport_trunk_link_s tlink[BFI_FCPORT_MAX_LINKS];
+};
+
+/**
+ * fcport H2I message
+ */
+union bfi_fcport_h2i_msg_u {
+	struct bfi_mhdr_s			*mhdr;
+	struct bfi_fcport_enable_req_s		*penable;
+	struct bfi_fcport_req_s			*pdisable;
+	struct bfi_fcport_set_svc_params_req_s	*psetsvcparams;
+	struct bfi_fcport_req_s			*pstatsget;
+	struct bfi_fcport_req_s			*pstatsclear;
+};
+
+/**
+ * fcport I2H message
+ */
+union bfi_fcport_i2h_msg_u {
+	struct bfi_msg_s			*msg;
+	struct bfi_fcport_rsp_s			*penable_rsp;
+	struct bfi_fcport_rsp_s			*pdisable_rsp;
+	struct bfi_fcport_rsp_s			*psetsvcparams_rsp;
+	struct bfi_fcport_rsp_s			*pstatsget_rsp;
+	struct bfi_fcport_rsp_s			*pstatsclear_rsp;
+	struct bfi_fcport_event_s		*event;
+	struct bfi_fcport_trunk_scn_s		*trunk_scn;
+};
+
+enum bfi_fcxp_h2i {
+	BFI_FCXP_H2I_SEND_REQ = 1,
+};
+
+enum bfi_fcxp_i2h {
+	BFI_FCXP_I2H_SEND_RSP = BFA_I2HM(1),
+};
+
+#define BFA_FCXP_MAX_SGES	2
+
+/**
+ * FCXP send request structure
+ */
+struct bfi_fcxp_send_req_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
+	u16	fcxp_tag;	/*  driver request tag		    */
+	u16	max_frmsz;	/*  max send frame size	    */
+	u16	vf_id;		/*  vsan tag if applicable	    */
+	u16	rport_fw_hndl;	/*  FW Handle for the remote port  */
+	u8	 class;		/*  FC class used for req/rsp	    */
+	u8	 rsp_timeout;	/*  timeout in secs, 0-no response */
+	u8	 cts;		/*  continue sequence		    */
+	u8	 lp_tag;	/*  lport tag			    */
+	struct fchs_s	fchs;	/*  request FC header structure    */
+	u32	req_len;	/*  request payload length	    */
+	u32	rsp_maxlen;	/*  max response length expected   */
+	struct bfi_sge_s   req_sge[BFA_FCXP_MAX_SGES];	/*  request buf    */
+	struct bfi_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];	/*  response buf   */
+};
+
+/**
+ * FCXP send response structure
+ */
+struct bfi_fcxp_send_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
+	u16	fcxp_tag;	/*  send request tag		    */
+	u8	 req_status;	/*  request status		    */
+	u8	 rsvd;
+	u32	rsp_len;	/*  actual response length	    */
+	u32	residue_len;	/*  residual response length	    */
+	struct fchs_s	fchs;	/*  response FC header structure   */
+};
+
+enum bfi_uf_h2i {
+	BFI_UF_H2I_BUF_POST = 1,
+};
+
+enum bfi_uf_i2h {
+	BFI_UF_I2H_FRM_RCVD = BFA_I2HM(1),
+};
+
+#define BFA_UF_MAX_SGES	2
+
+struct bfi_uf_buf_post_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
+	u16	buf_tag;	/*  buffer tag			*/
+	u16	buf_len;	/*  total buffer length	*/
+	struct bfi_sge_s   sge[BFA_UF_MAX_SGES]; /*  buffer DMA SGEs	*/
+};
+
+struct bfi_uf_frm_rcvd_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
+	u16	buf_tag;	/*  buffer tag			*/
+	u16	rsvd;
+	u16	frm_len;	/*  received frame length	*/
+	u16	xfr_len;	/*  tranferred length		*/
+};
+
+enum bfi_lps_h2i_msgs {
+	BFI_LPS_H2I_LOGIN_REQ	= 1,
+	BFI_LPS_H2I_LOGOUT_REQ	= 2,
+};
+
+enum bfi_lps_i2h_msgs {
+	BFI_LPS_H2I_LOGIN_RSP	= BFA_I2HM(1),
+	BFI_LPS_H2I_LOGOUT_RSP	= BFA_I2HM(2),
+	BFI_LPS_H2I_CVL_EVENT	= BFA_I2HM(3),
+};
+
+struct bfi_lps_login_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		alpa;
+	u16	pdu_size;
+	wwn_t		pwwn;
+	wwn_t		nwwn;
+	u8		fdisc;
+	u8		auth_en;
+	u8		rsvd[2];
+};
+
+struct bfi_lps_login_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		status;
+	u8		lsrjt_rsn;
+	u8		lsrjt_expl;
+	wwn_t		port_name;
+	wwn_t		node_name;
+	u16	bb_credit;
+	u8		f_port;
+	u8		npiv_en;
+	u32	lp_pid:24;
+	u32	auth_req:8;
+	mac_t		lp_mac;
+	mac_t		fcf_mac;
+	u8		ext_status;
+	u8		brcd_switch;	/*  attached peer is brcd switch */
+};
+
+struct bfi_lps_logout_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		rsvd[3];
+	wwn_t		port_name;
+};
+
+struct bfi_lps_logout_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		status;
+	u8		rsvd[2];
+};
+
+struct bfi_lps_cvl_event_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		lp_tag;
+	u8		rsvd[3];
+};
+
+union bfi_lps_h2i_msg_u {
+	struct bfi_mhdr_s		*msg;
+	struct bfi_lps_login_req_s	*login_req;
+	struct bfi_lps_logout_req_s	*logout_req;
+};
+
+union bfi_lps_i2h_msg_u {
+	struct bfi_msg_s		*msg;
+	struct bfi_lps_login_rsp_s	*login_rsp;
+	struct bfi_lps_logout_rsp_s	*logout_rsp;
+	struct bfi_lps_cvl_event_s	*cvl_event;
+};
+
+enum bfi_rport_h2i_msgs {
+	BFI_RPORT_H2I_CREATE_REQ = 1,
+	BFI_RPORT_H2I_DELETE_REQ = 2,
+	BFI_RPORT_H2I_SET_SPEED_REQ  = 3,
+};
+
+enum bfi_rport_i2h_msgs {
+	BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
+	BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
+	BFI_RPORT_I2H_QOS_SCN    = BFA_I2HM(3),
+};
+
+struct bfi_rport_create_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	bfa_handle;	/*  host rport handle		*/
+	u16	max_frmsz;	/*  max rcv pdu size		*/
+	u32	pid:24,	/*  remote port ID		*/
+		lp_tag:8;	/*  local port tag		*/
+	u32	local_pid:24,	/*  local port ID		*/
+		cisc:8;
+	u8	fc_class;	/*  supported FC classes	*/
+	u8	vf_en;		/*  virtual fabric enable	*/
+	u16	vf_id;		/*  virtual fabric ID		*/
+};
+
+struct bfi_rport_create_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u8		status;		/*  rport creation status	*/
+	u8		rsvd[3];
+	u16	bfa_handle;	/*  host rport handle		*/
+	u16	fw_handle;	/*  firmware rport handle	*/
+	struct bfa_rport_qos_attr_s qos_attr;  /* QoS Attributes */
+};
+
+struct bfa_rport_speed_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	fw_handle;	/*  firmware rport handle	*/
+	u8		speed;		/*  rport's speed via RPSC	*/
+	u8		rsvd;
+};
+
+struct bfi_rport_delete_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	fw_handle;	/*  firmware rport handle	*/
+	u16	rsvd;
+};
+
+struct bfi_rport_delete_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	bfa_handle;	/*  host rport handle		*/
+	u8		status;		/*  rport deletion status	*/
+	u8		rsvd;
+};
+
+struct bfi_rport_qos_scn_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		*/
+	u16	bfa_handle;	/*  host rport handle		*/
+	u16	rsvd;
+	struct bfa_rport_qos_attr_s old_qos_attr;  /* Old QoS Attributes */
+	struct bfa_rport_qos_attr_s new_qos_attr;  /* New QoS Attributes */
+};
+
+union bfi_rport_h2i_msg_u {
+	struct bfi_msg_s		*msg;
+	struct bfi_rport_create_req_s	*create_req;
+	struct bfi_rport_delete_req_s	*delete_req;
+	struct bfi_rport_speed_req_s	*speed_req;
+};
+
+union bfi_rport_i2h_msg_u {
+	struct bfi_msg_s		*msg;
+	struct bfi_rport_create_rsp_s	*create_rsp;
+	struct bfi_rport_delete_rsp_s	*delete_rsp;
+	struct bfi_rport_qos_scn_s	*qos_scn_evt;
+};
+
+/*
+ * Initiator mode I-T nexus interface defines.
+ */
+
+enum bfi_itnim_h2i {
+	BFI_ITNIM_H2I_CREATE_REQ = 1,	/*  i-t nexus creation */
+	BFI_ITNIM_H2I_DELETE_REQ = 2,	/*  i-t nexus deletion */
+};
+
+enum bfi_itnim_i2h {
+	BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1),
+	BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2),
+	BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3),
+};
+
+struct bfi_itnim_create_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	fw_handle;	/*  f/w handle for itnim	 */
+	u8	class;		/*  FC class for IO		 */
+	u8	seq_rec;	/*  sequence recovery support	 */
+	u8	msg_no;		/*  seq id of the msg		 */
+};
+
+struct bfi_itnim_create_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	bfa_handle;	/*  bfa handle for itnim	 */
+	u8	status;		/*  fcp request status		 */
+	u8	seq_id;		/*  seq id of the msg		 */
+};
+
+struct bfi_itnim_delete_req_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	fw_handle;	/*  f/w itnim handle		 */
+	u8	seq_id;		/*  seq id of the msg		 */
+	u8	rsvd;
+};
+
+struct bfi_itnim_delete_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	bfa_handle;	/*  bfa handle for itnim	 */
+	u8	status;		/*  fcp request status		 */
+	u8	seq_id;		/*  seq id of the msg		 */
+};
+
+struct bfi_itnim_sler_event_s {
+	struct bfi_mhdr_s  mh;		/*  common msg header		 */
+	u16	bfa_handle;	/*  bfa handle for itnim	 */
+	u16	rsvd;
+};
+
+union bfi_itnim_h2i_msg_u {
+	struct bfi_itnim_create_req_s *create_req;
+	struct bfi_itnim_delete_req_s *delete_req;
+	struct bfi_msg_s	*msg;
+};
+
+union bfi_itnim_i2h_msg_u {
+	struct bfi_itnim_create_rsp_s *create_rsp;
+	struct bfi_itnim_delete_rsp_s *delete_rsp;
+	struct bfi_itnim_sler_event_s *sler_event;
+	struct bfi_msg_s	*msg;
+};
+
+/*
+ * Initiator mode IO interface defines.
+ */
+
+enum bfi_ioim_h2i {
+	BFI_IOIM_H2I_IOABORT_REQ = 1,	/*  IO abort request	 */
+	BFI_IOIM_H2I_IOCLEANUP_REQ = 2,	/*  IO cleanup request	 */
+};
+
+enum bfi_ioim_i2h {
+	BFI_IOIM_I2H_IO_RSP = BFA_I2HM(1),	/*  non-fp IO response	 */
+	BFI_IOIM_I2H_IOABORT_RSP = BFA_I2HM(2),	/*  ABORT rsp	 */
+};
+
+/**
+ * IO command DIF info
+ */
+struct bfi_ioim_dif_s {
+	u32	dif_info[4];
+};
+
+/**
+ * FCP IO messages overview
+ *
+ * @note
+ * - Max CDB length supported is 64 bytes.
+ * - SCSI Linked commands and SCSI bi-directional Commands not
+ *	supported.
+ *
+ */
+struct bfi_ioim_req_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
+	u16	io_tag;		/*  I/O tag			 */
+	u16	rport_hdl;	/*  itnim/rport firmware handle */
+	struct fcp_cmnd_s	cmnd;	/*  IO request info	*/
+
+	/**
+	 * SG elements array within the IO request must be double word
+	 * aligned. This aligment is required to optimize SGM setup for the IO.
+	 */
+	struct bfi_sge_s	sges[BFI_SGE_INLINE_MAX];
+	u8	io_timeout;
+	u8	dif_en;
+	u8	rsvd_a[2];
+	struct bfi_ioim_dif_s  dif;
+};
+
+/**
+ *	This table shows various IO status codes from firmware and their
+ *	meaning. Host driver can use these status codes to further process
+ *	IO completions.
+ *
+ *	BFI_IOIM_STS_OK		: IO completed with error free SCSI &
+ *					transport status.
+ *					 io-tag can be reused.
+ *
+ *	BFA_IOIM_STS_SCSI_ERR		: IO completed with scsi error.
+ *	- io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_HOST_ABORTED	: IO was aborted successfully due to
+ *						host request.
+ *					- io-tag cannot be reused yet.
+ *
+ *	BFI_IOIM_STS_ABORTED		: IO was aborted successfully
+ *						internally by f/w.
+ *					- io-tag cannot be reused yet.
+ *
+ *	BFI_IOIM_STS_TIMEDOUT	: IO timedout and ABTS/RRQ is happening
+ *					in the firmware and
+ *					- io-tag cannot be reused yet.
+ *
+ *	BFI_IOIM_STS_SQER_NEEDED	: Firmware could not recover the IO
+ *					  with sequence level error
+ *	logic and hence host needs to retry
+ *					  this IO with a different IO tag
+ *					- io-tag cannot be used yet.
+ *
+ *	BFI_IOIM_STS_NEXUS_ABORT	: Second Level Error Recovery from host
+ *					  is required because 2 consecutive ABTS
+ *					  timedout and host needs logout and
+ *					  re-login with the target
+ *					- io-tag cannot be used yet.
+ *
+ *	BFI_IOIM_STS_UNDERRUN	: IO completed with SCSI status good,
+ *					  but the data tranferred is less than
+ *					  the fcp data length in the command.
+ *					  ex. SCSI INQUIRY where transferred
+ *					  data length and residue count in FCP
+ *					  response accounts for total fcp-dl
+ *					  - io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_OVERRUN	: IO completed with SCSI status good,
+ *					  but the data transerred is more than
+ *					  fcp data length in the command. ex.
+ *					  TAPE IOs where blocks can of unequal
+ *					  lengths.
+ *					- io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_RES_FREE	: Firmware has completed using io-tag
+ *					  during abort process
+ *					- io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_PROTO_ERR	: Firmware detected a protocol error.
+ *					  ex target sent more data than
+ *					  requested, or there was data frame
+ *					  loss and other reasons
+ *					- io-tag cannot be used yet.
+ *
+ *	BFI_IOIM_STS_DIF_ERR	: Firwmare detected DIF error. ex: DIF
+ *					CRC err or Ref Tag err or App tag err.
+ *					- io-tag can be reused.
+ *
+ *	BFA_IOIM_STS_TSK_MGT_ABORT	: IO was aborted because of Task
+ *					  Management command from the host
+ *					  - io-tag can be reused.
+ *
+ *	BFI_IOIM_STS_UTAG		: Firmware does not know about this
+ *					  io_tag.
+ *					- io-tag can be reused.
+ */
+enum bfi_ioim_status {
+	BFI_IOIM_STS_OK = 0,
+	BFI_IOIM_STS_HOST_ABORTED = 1,
+	BFI_IOIM_STS_ABORTED = 2,
+	BFI_IOIM_STS_TIMEDOUT = 3,
+	BFI_IOIM_STS_RES_FREE = 4,
+	BFI_IOIM_STS_SQER_NEEDED = 5,
+	BFI_IOIM_STS_PROTO_ERR = 6,
+	BFI_IOIM_STS_UTAG = 7,
+	BFI_IOIM_STS_PATHTOV = 8,
+};
+
+#define BFI_IOIM_SNSLEN	(256)
+/**
+ * I/O response message
+ */
+struct bfi_ioim_rsp_s {
+	struct bfi_mhdr_s	mh;	/*  common msg header		*/
+	u16	io_tag;		/*  completed IO tag		 */
+	u16	bfa_rport_hndl;	/*  releated rport handle	 */
+	u8	io_status;	/*  IO completion status	 */
+	u8	reuse_io_tag;	/*  IO tag can be reused	*/
+	u16	abort_tag;	/*  host abort request tag	*/
+	u8		scsi_status;	/*  scsi status from target	 */
+	u8		sns_len;	/*  scsi sense length		 */
+	u8		resid_flags;	/*  IO residue flags		 */
+	u8		rsvd_a;
+	u32	residue;	/*  IO residual length in bytes */
+	u32	rsvd_b[3];
+};
+
+struct bfi_ioim_abort_req_s {
+	struct bfi_mhdr_s  mh;	/*  Common msg header  */
+	u16	io_tag;	/*  I/O tag	*/
+	u16	abort_tag;	/*  unique request tag */
+};
+
+/*
+ * Initiator mode task management command interface defines.
+ */
+
+enum bfi_tskim_h2i {
+	BFI_TSKIM_H2I_TM_REQ	= 1, /*  task-mgmt command	*/
+	BFI_TSKIM_H2I_ABORT_REQ = 2, /*  task-mgmt command	*/
+};
+
+enum bfi_tskim_i2h {
+	BFI_TSKIM_I2H_TM_RSP = BFA_I2HM(1),
+};
+
+struct bfi_tskim_req_s {
+	struct bfi_mhdr_s  mh;	/*  Common msg header	*/
+	u16	tsk_tag;	/*  task management tag	*/
+	u16	itn_fhdl;	/*  itn firmware handle	*/
+	lun_t	lun;	/*  LU number	*/
+	u8	tm_flags;	/*  see enum fcp_tm_cmnd	*/
+	u8	t_secs;	/*  Timeout value in seconds	*/
+	u8	rsvd[2];
+};
+
+struct bfi_tskim_abortreq_s {
+	struct bfi_mhdr_s  mh;	/*  Common msg header	*/
+	u16	tsk_tag;	/*  task management tag	*/
+	u16	rsvd;
+};
+
+enum bfi_tskim_status {
+	/*
+	 * Following are FCP-4 spec defined status codes,
+	 * **DO NOT CHANGE THEM **
+	 */
+	BFI_TSKIM_STS_OK	= 0,
+	BFI_TSKIM_STS_NOT_SUPP = 4,
+	BFI_TSKIM_STS_FAILED	= 5,
+
+	/**
+	 * Defined by BFA
+	 */
+	BFI_TSKIM_STS_TIMEOUT  = 10,	/*  TM request timedout	*/
+	BFI_TSKIM_STS_ABORTED  = 11,	/*  Aborted on host request */
+};
+
+struct bfi_tskim_rsp_s {
+	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
+	u16	tsk_tag;	/*  task mgmt cmnd tag		 */
+	u8	tsk_status;	/*  @ref bfi_tskim_status */
+	u8	rsvd;
+};
+
+#pragma pack()
+
+#endif /* __BFI_MS_H__ */
diff --git a/drivers/scsi/bfa/fab.c b/drivers/scsi/bfa/fab.c
deleted file mode 100644
index 7e3a4d5..0000000
--- a/drivers/scsi/bfa/fab.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "lport_priv.h"
-
-/**
- *  fab.c port fab implementation.
- */
-
-/**
- *  bfa_fcs_port_fab_public port fab public functions
- */
-
-/**
- *   Called by port to initialize fabric services of the base port.
- */
-void
-bfa_fcs_port_fab_init(struct bfa_fcs_port_s *port)
-{
-	bfa_fcs_port_ns_init(port);
-	bfa_fcs_port_scn_init(port);
-	bfa_fcs_port_ms_init(port);
-}
-
-/**
- *   Called by port to notify transition to online state.
- */
-void
-bfa_fcs_port_fab_online(struct bfa_fcs_port_s *port)
-{
-	bfa_fcs_port_ns_online(port);
-	bfa_fcs_port_scn_online(port);
-}
-
-/**
- *   Called by port to notify transition to offline state.
- */
-void
-bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *port)
-{
-	bfa_fcs_port_ns_offline(port);
-	bfa_fcs_port_scn_offline(port);
-	bfa_fcs_port_ms_offline(port);
-}
diff --git a/drivers/scsi/bfa/fabric.c b/drivers/scsi/bfa/fabric.c
deleted file mode 100644
index ddd4ba9..0000000
--- a/drivers/scsi/bfa/fabric.c
+++ /dev/null
@@ -1,1323 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fabric.c Fabric module implementation.
- */
-
-#include "fcs_fabric.h"
-#include "fcs_lport.h"
-#include "fcs_vport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs_auth.h"
-#include "fcs.h"
-#include "fcbuild.h"
-#include <log/bfa_log_fcs.h>
-#include <aen/bfa_aen_port.h>
-#include <bfa_svc.h>
-
-BFA_TRC_FILE(FCS, FABRIC);
-
-#define BFA_FCS_FABRIC_RETRY_DELAY	(2000)	/* Milliseconds */
-#define BFA_FCS_FABRIC_CLEANUP_DELAY	(10000)	/* Milliseconds */
-
-#define bfa_fcs_fabric_set_opertype(__fabric) do {             \
-	if (bfa_fcport_get_topology((__fabric)->fcs->bfa)       \
-				== BFA_PPORT_TOPOLOGY_P2P)     \
-		(__fabric)->oper_type = BFA_PPORT_TYPE_NPORT;  \
-	else                                                   \
-		(__fabric)->oper_type = BFA_PPORT_TYPE_NLPORT; \
-} while (0)
-
-/*
- * forward declarations
- */
-static void     bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_delay(void *cbarg);
-static void     bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_delete_comp(void *cbarg);
-static void     bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
-					  struct fchs_s *fchs, u16 len);
-static void     bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
-					     struct fchs_s *fchs, u16 len);
-static void     bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
-static void     bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg, bfa_status_t status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rspfchs);
-/**
- *  fcs_fabric_sm fabric state machine functions
- */
-
-/**
- * Fabric state machine events
- */
-enum bfa_fcs_fabric_event {
-	BFA_FCS_FABRIC_SM_CREATE = 1,	/*  fabric create from driver */
-	BFA_FCS_FABRIC_SM_DELETE = 2,	/*  fabric delete from driver */
-	BFA_FCS_FABRIC_SM_LINK_DOWN = 3,	/*  link down from port */
-	BFA_FCS_FABRIC_SM_LINK_UP = 4,	/*  link up from port */
-	BFA_FCS_FABRIC_SM_CONT_OP = 5,	/*  continue op from flogi/auth */
-	BFA_FCS_FABRIC_SM_RETRY_OP = 6,	/*  continue op from flogi/auth */
-	BFA_FCS_FABRIC_SM_NO_FABRIC = 7,	/*  no fabric from flogi/auth
-						 */
-	BFA_FCS_FABRIC_SM_PERF_EVFP = 8,	/*  perform EVFP from
-						 *flogi/auth */
-	BFA_FCS_FABRIC_SM_ISOLATE = 9,	/*  isolate from EVFP processing */
-	BFA_FCS_FABRIC_SM_NO_TAGGING = 10,/*  no VFT tagging from EVFP */
-	BFA_FCS_FABRIC_SM_DELAYED = 11,	/*  timeout delay event */
-	BFA_FCS_FABRIC_SM_AUTH_FAILED = 12,	/*  authentication failed */
-	BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13,	/*  authentication successful
-						 */
-	BFA_FCS_FABRIC_SM_DELCOMP = 14,	/*  all vports deleted event */
-	BFA_FCS_FABRIC_SM_LOOPBACK = 15,	/*  Received our own FLOGI */
-	BFA_FCS_FABRIC_SM_START = 16,	/*  fabric delete from driver */
-};
-
-static void     bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
-					 enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
-					  enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
-					enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
-					      enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
-				       enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
-					      enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
-					 enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
-				       enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
-					    enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-static void     bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
-					   enum bfa_fcs_fabric_event event);
-/**
- *   Beginning state before fabric creation.
- */
-static void
-bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
-			 enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_CREATE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
-		bfa_fcs_fabric_init(fabric);
-		bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_UP:
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Beginning state before fabric creation.
- */
-static void
-bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
-			  enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_START:
-		if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
-			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
-			bfa_fcs_fabric_login(fabric);
-		} else
-			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_UP:
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-		bfa_fcs_modexit_comp(fabric->fcs);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Link is down, awaiting LINK UP event from port. This is also the
- *   first state at fabric creation.
- */
-static void
-bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_UP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
-		bfa_fcs_fabric_login(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_RETRY_OP:
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   FLOGI is in progress, awaiting FLOGI reply.
- */
-static void
-bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
-			enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_CONT_OP:
-
-		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
-		fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
-
-		if (fabric->auth_reqd && fabric->is_auth) {
-			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
-			bfa_trc(fabric->fcs, event);
-		} else {
-			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
-			bfa_fcs_fabric_notify_online(fabric);
-		}
-		break;
-
-	case BFA_FCS_FABRIC_SM_RETRY_OP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
-		bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
-				bfa_fcs_fabric_delay, fabric,
-				BFA_FCS_FABRIC_RETRY_DELAY);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LOOPBACK:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
-		bfa_lps_discard(fabric->lps);
-		bfa_fcs_fabric_set_opertype(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_NO_FABRIC:
-		fabric->fab_type = BFA_FCS_FABRIC_N2N;
-		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
-		bfa_fcs_fabric_notify_online(fabric);
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_lps_discard(fabric->lps);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-
-static void
-bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
-			      enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_DELAYED:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
-		bfa_fcs_fabric_login(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_timer_stop(&fabric->delay_timer);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_timer_stop(&fabric->delay_timer);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Authentication is in progress, awaiting authentication results.
- */
-static void
-bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
-		       enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-		bfa_lps_discard(fabric->lps);
-		break;
-
-	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
-		bfa_fcs_fabric_notify_online(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_PERF_EVFP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Authentication failed
- */
-static void
-bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
-			      enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Port is in loopback mode.
- */
-static void
-bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   There is no attached fabric - private loop or NPort-to-NPort topology.
- */
-static void
-bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_NO_FABRIC:
-		bfa_trc(fabric->fcs, fabric->bb_credit);
-		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Fabric is online - normal operating state.
- */
-static void
-bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
-			 enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
-		bfa_lps_discard(fabric->lps);
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_DELETE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
-		bfa_fcs_fabric_delete(fabric);
-		break;
-
-	case BFA_FCS_FABRIC_SM_AUTH_FAILED:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-		bfa_lps_discard(fabric->lps);
-		break;
-
-	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   Exchanging virtual fabric parameters.
- */
-static void
-bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
-		       enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_CONT_OP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
-		break;
-
-	case BFA_FCS_FABRIC_SM_ISOLATE:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-/**
- *   EVFP exchange complete and VFT tagging is enabled.
- */
-static void
-bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
-			    enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-}
-
-/**
- *   Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
- */
-static void
-bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	bfa_log(fabric->fcs->logm, BFA_LOG_FCS_FABRIC_ISOLATED,
-		fabric->bport.port_cfg.pwwn, fabric->fcs->port_vfid,
-		fabric->event_arg.swp_vfid);
-}
-
-/**
- *   Fabric is being deleted, awaiting vport delete completions.
- */
-static void
-bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
-			   enum bfa_fcs_fabric_event event)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, event);
-
-	switch (event) {
-	case BFA_FCS_FABRIC_SM_DELCOMP:
-		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-		bfa_fcs_modexit_comp(fabric->fcs);
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_UP:
-		break;
-
-	case BFA_FCS_FABRIC_SM_LINK_DOWN:
-		bfa_fcs_fabric_notify_offline(fabric);
-		break;
-
-	default:
-		bfa_sm_fault(fabric->fcs, event);
-	}
-}
-
-
-
-/**
- *  fcs_fabric_private fabric private functions
- */
-
-static void
-bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
-
-	port_cfg->roles = BFA_PORT_ROLE_FCP_IM;
-	port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc);
-	port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc);
-}
-
-/**
- * Port Symbolic Name Creation for base port.
- */
-void
-bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg;
-	char            model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
-	struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
-
-	bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
-
-	/*
-	 * Model name/number
-	 */
-	strncpy((char *)&port_cfg->sym_name, model,
-		BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
-	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
-	/*
-	 * Driver Version
-	 */
-	strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
-		BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
-	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
-	/*
-	 * Host machine name
-	 */
-	strncat((char *)&port_cfg->sym_name,
-		(char *)driver_info->host_machine_name,
-		BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
-	strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-		sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
-	/*
-	 * Host OS Info :
-	 * If OS Patch Info is not there, do not truncate any bytes from the
-	 * OS name string and instead copy the entire OS info string (64 bytes).
-	 */
-	if (driver_info->host_os_patch[0] == '\0') {
-		strncat((char *)&port_cfg->sym_name,
-			(char *)driver_info->host_os_name, BFA_FCS_OS_STR_LEN);
-		strncat((char *)&port_cfg->sym_name,
-			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-	} else {
-		strncat((char *)&port_cfg->sym_name,
-			(char *)driver_info->host_os_name,
-			BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
-		strncat((char *)&port_cfg->sym_name,
-			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-
-		/*
-		 * Append host OS Patch Info
-		 */
-		strncat((char *)&port_cfg->sym_name,
-			(char *)driver_info->host_os_patch,
-			BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
-	}
-
-	/*
-	 * null terminate
-	 */
-	port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
-}
-
-/**
- * bfa lps login completion callback
- */
-void
-bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
-{
-	struct bfa_fcs_fabric_s *fabric = uarg;
-
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_trc(fabric->fcs, status);
-
-	switch (status) {
-	case BFA_STATUS_OK:
-		fabric->stats.flogi_accepts++;
-		break;
-
-	case BFA_STATUS_INVALID_MAC:
-		/*
-		 * Only for CNA
-		 */
-		fabric->stats.flogi_acc_err++;
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-
-		return;
-
-	case BFA_STATUS_EPROTOCOL:
-		switch (bfa_lps_get_extstatus(fabric->lps)) {
-		case BFA_EPROTO_BAD_ACCEPT:
-			fabric->stats.flogi_acc_err++;
-			break;
-
-		case BFA_EPROTO_UNKNOWN_RSP:
-			fabric->stats.flogi_unknown_rsp++;
-			break;
-
-		default:
-			break;
-		}
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-
-		return;
-
-	case BFA_STATUS_FABRIC_RJT:
-		fabric->stats.flogi_rejects++;
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-		return;
-
-	default:
-		fabric->stats.flogi_rsp_err++;
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
-		return;
-	}
-
-	fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps);
-	bfa_trc(fabric->fcs, fabric->bb_credit);
-
-	if (!bfa_lps_is_brcd_fabric(fabric->lps))
-		fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps);
-
-	/*
-	 * Check port type. It should be 1 = F-port.
-	 */
-	if (bfa_lps_is_fport(fabric->lps)) {
-		fabric->bport.pid = bfa_lps_get_pid(fabric->lps);
-		fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps);
-		fabric->is_auth = bfa_lps_is_authreq(fabric->lps);
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
-	} else {
-		/*
-		 * Nport-2-Nport direct attached
-		 */
-		fabric->bport.port_topo.pn2n.rem_port_wwn =
-			bfa_lps_get_peer_pwwn(fabric->lps);
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
-	}
-
-	bfa_trc(fabric->fcs, fabric->bport.pid);
-	bfa_trc(fabric->fcs, fabric->is_npiv);
-	bfa_trc(fabric->fcs, fabric->is_auth);
-}
-
-/**
- * 		Allocate and send FLOGI.
- */
-static void
-bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_s   *bfa = fabric->fcs->bfa;
-	struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
-	u8         alpa = 0;
-
-	if (bfa_fcport_get_topology(bfa) == BFA_PPORT_TOPOLOGY_LOOP)
-		alpa = bfa_fcport_get_myalpa(bfa);
-
-	bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
-		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
-
-	fabric->stats.flogi_sent++;
-}
-
-static void
-bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe, *qen;
-
-	bfa_trc(fabric->fcs, fabric->fabric_name);
-
-	bfa_fcs_fabric_set_opertype(fabric);
-	fabric->stats.fabric_onlines++;
-
-	/**
-	 * notify online event to base and then virtual ports
-	 */
-	bfa_fcs_port_online(&fabric->bport);
-
-	list_for_each_safe(qe, qen, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		bfa_fcs_vport_online(vport);
-	}
-}
-
-static void
-bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe, *qen;
-
-	bfa_trc(fabric->fcs, fabric->fabric_name);
-	fabric->stats.fabric_offlines++;
-
-	/**
-	 * notify offline event first to vports and then base port.
-	 */
-	list_for_each_safe(qe, qen, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		bfa_fcs_vport_offline(vport);
-	}
-
-	bfa_fcs_port_offline(&fabric->bport);
-
-	fabric->fabric_name = 0;
-	fabric->fabric_ip_addr[0] = 0;
-}
-
-static void
-bfa_fcs_fabric_delay(void *cbarg)
-{
-	struct bfa_fcs_fabric_s *fabric = cbarg;
-
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
-}
-
-/**
- * Delete all vports and wait for vport delete completions.
- */
-static void
-bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe, *qen;
-
-	list_for_each_safe(qe, qen, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		bfa_fcs_vport_fcs_delete(vport);
-	}
-
-	bfa_fcs_port_delete(&fabric->bport);
-	bfa_wc_wait(&fabric->wc);
-}
-
-static void
-bfa_fcs_fabric_delete_comp(void *cbarg)
-{
-	struct bfa_fcs_fabric_s *fabric = cbarg;
-
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
-}
-
-
-
-/**
- *  fcs_fabric_public fabric public functions
- */
-
-/**
- *   Attach time initialization
- */
-void
-bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
-{
-	struct bfa_fcs_fabric_s *fabric;
-
-	fabric = &fcs->fabric;
-	bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
-
-	/**
-	 * Initialize base fabric.
-	 */
-	fabric->fcs = fcs;
-	INIT_LIST_HEAD(&fabric->vport_q);
-	INIT_LIST_HEAD(&fabric->vf_q);
-	fabric->lps = bfa_lps_alloc(fcs->bfa);
-	bfa_assert(fabric->lps);
-
-	/**
-	 * Initialize fabric delete completion handler. Fabric deletion is complete
-	 * when the last vport delete is complete.
-	 */
-	bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
-	bfa_wc_up(&fabric->wc);	/* For the base port */
-
-	bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
-	bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
-}
-
-void
-bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
-{
-	bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
-	bfa_trc(fcs, 0);
-}
-
-/**
- *   Module cleanup
- */
-void
-bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
-{
-	struct bfa_fcs_fabric_s *fabric;
-
-	bfa_trc(fcs, 0);
-
-	/**
-	 * Cleanup base fabric.
-	 */
-	fabric = &fcs->fabric;
-	bfa_lps_delete(fabric->lps);
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
-}
-
-/**
- * Fabric module start -- kick starts FCS actions
- */
-void
-bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
-{
-	struct bfa_fcs_fabric_s *fabric;
-
-	bfa_trc(fcs, 0);
-	fabric = &fcs->fabric;
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
-}
-
-/**
- *   Suspend fabric activity as part of driver suspend.
- */
-void
-bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs)
-{
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric)
-{
-	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback);
-}
-
-bfa_boolean_t
-bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric)
-{
-	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_auth_failed);
-}
-
-enum bfa_pport_type
-bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric)
-{
-	return fabric->oper_type;
-}
-
-/**
- *   Link up notification from BFA physical port module.
- */
-void
-bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
-}
-
-/**
- *   Link down notification from BFA physical port module.
- */
-void
-bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
-{
-	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
-}
-
-/**
- *   A child vport is being created in the fabric.
- *
- *   Call from vport module at vport creation. A list of base port and vports
- *   belonging to a fabric is maintained to propagate link events.
- *
- *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *   param[in] vport  - Vport being created.
- *
- *   @return None (always succeeds)
- */
-void
-bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
-			struct bfa_fcs_vport_s *vport)
-{
-	/**
-	 * - add vport to fabric's vport_q
-	 */
-	bfa_trc(fabric->fcs, fabric->vf_id);
-
-	list_add_tail(&vport->qe, &fabric->vport_q);
-	fabric->num_vports++;
-	bfa_wc_up(&fabric->wc);
-}
-
-/**
- *   A child vport is being deleted from fabric.
- *
- *   Vport is being deleted.
- */
-void
-bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
-			struct bfa_fcs_vport_s *vport)
-{
-	list_del(&vport->qe);
-	fabric->num_vports--;
-	bfa_wc_down(&fabric->wc);
-}
-
-/**
- *   Base port is deleted.
- */
-void
-bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric)
-{
-	bfa_wc_down(&fabric->wc);
-}
-
-/**
- *    Check if fabric is online.
- *
- *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
- *   @return  TRUE/FALSE
- */
-int
-bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric)
-{
-	return bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online);
-}
-
-
-bfa_status_t
-bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs,
-		     struct bfa_port_cfg_s *port_cfg,
-		     struct bfad_vf_s *vf_drv)
-{
-	bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit);
-	return BFA_STATUS_OK;
-}
-
-/**
- * Lookup for a vport withing a fabric given its pwwn
- */
-struct bfa_fcs_vport_s *
-bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe;
-
-	list_for_each(qe, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		if (bfa_fcs_port_get_pwwn(&vport->lport) == pwwn)
-			return vport;
-	}
-
-	return NULL;
-}
-
-/**
- *    In a given fabric, return the number of lports.
- *
- *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
- *
-*    @return : 1 or more.
- */
-u16
-bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric)
-{
-	return fabric->num_vports;
-}
-
-/*
- *  Get OUI of the attached switch.
- *
- *  Note : Use of this function should be avoided as much as possible.
- *         This function should be used only if there is any requirement
- *         to check for FOS version below 6.3.
- *         To check if the attached fabric is a brocade fabric, use
- *         bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
- *         or above only.
- */
-
-u16
-bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
-{
-	wwn_t fab_nwwn;
-	u8 *tmp;
-	u16 oui;
-
-	fab_nwwn = bfa_lps_get_peer_nwwn(fabric->lps);
-
-	tmp = (uint8_t *)&fab_nwwn;
-	oui = (tmp[3] << 8) | tmp[4];
-
-	return oui;
-}
-
-/**
- * 		Unsolicited frame receive handling.
- */
-void
-bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
-		       u16 len)
-{
-	u32        pid = fchs->d_id;
-	struct bfa_fcs_vport_s *vport;
-	struct list_head *qe;
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-	struct fc_logi_s     *flogi = (struct fc_logi_s *) els_cmd;
-
-	bfa_trc(fabric->fcs, len);
-	bfa_trc(fabric->fcs, pid);
-
-	/**
-	 * Look for our own FLOGI frames being looped back. This means an
-	 * external loopback cable is in place. Our own FLOGI frames are
-	 * sometimes looped back when switch port gets temporarily bypassed.
-	 */
-	if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT))
-	    && (els_cmd->els_code == FC_ELS_FLOGI)
-	    && (flogi->port_name == bfa_fcs_port_get_pwwn(&fabric->bport))) {
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
-		return;
-	}
-
-	/**
-	 * FLOGI/EVFP exchanges should be consumed by base fabric.
-	 */
-	if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) {
-		bfa_trc(fabric->fcs, pid);
-		bfa_fcs_fabric_process_uf(fabric, fchs, len);
-		return;
-	}
-
-	if (fabric->bport.pid == pid) {
-		/**
-		 * All authentication frames should be routed to auth
-		 */
-		bfa_trc(fabric->fcs, els_cmd->els_code);
-		if (els_cmd->els_code == FC_ELS_AUTH) {
-			bfa_trc(fabric->fcs, els_cmd->els_code);
-			fabric->auth.response = (u8 *) els_cmd;
-			return;
-		}
-
-		bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
-		bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
-		return;
-	}
-
-	/**
-	 * look for a matching local port ID
-	 */
-	list_for_each(qe, &fabric->vport_q) {
-		vport = (struct bfa_fcs_vport_s *)qe;
-		if (vport->lport.pid == pid) {
-			bfa_fcs_port_uf_recv(&vport->lport, fchs, len);
-			return;
-		}
-	}
-	bfa_trc(fabric->fcs, els_cmd->els_code);
-	bfa_fcs_port_uf_recv(&fabric->bport, fchs, len);
-}
-
-/**
- * 		Unsolicited frames to be processed by fabric.
- */
-static void
-bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
-			  u16 len)
-{
-	struct fc_els_cmd_s   *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-
-	bfa_trc(fabric->fcs, els_cmd->els_code);
-
-	switch (els_cmd->els_code) {
-	case FC_ELS_FLOGI:
-		bfa_fcs_fabric_process_flogi(fabric, fchs, len);
-		break;
-
-	default:
-		/*
-		 * need to generate a LS_RJT
-		 */
-		break;
-	}
-}
-
-/**
- * 	Process	incoming FLOGI
- */
-static void
-bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
-			struct fchs_s *fchs, u16 len)
-{
-	struct fc_logi_s     *flogi = (struct fc_logi_s *) (fchs + 1);
-	struct bfa_fcs_port_s *bport = &fabric->bport;
-
-	bfa_trc(fabric->fcs, fchs->s_id);
-
-	fabric->stats.flogi_rcvd++;
-	/*
-	 * Check port type. It should be 0 = n-port.
-	 */
-	if (flogi->csp.port_type) {
-		/*
-		 * @todo: may need to send a LS_RJT
-		 */
-		bfa_trc(fabric->fcs, flogi->port_name);
-		fabric->stats.flogi_rejected++;
-		return;
-	}
-
-	fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred);
-	bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
-	bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
-
-	/*
-	 * Send a Flogi Acc
-	 */
-	bfa_fcs_fabric_send_flogi_acc(fabric);
-	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
-}
-
-static void
-bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
-{
-	struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg;
-	struct bfa_fcs_port_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
-	struct bfa_s   *bfa = fabric->fcs->bfa;
-	struct bfa_fcxp_s *fcxp;
-	u16        reqlen;
-	struct fchs_s          fchs;
-
-	fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
-	/**
-	 * Do not expect this failure -- expect remote node to retry
-	 */
-	if (!fcxp)
-		return;
-
-	reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-				    bfa_os_hton3b(FC_FABRIC_PORT),
-				    n2n_port->reply_oxid, pcfg->pwwn,
-				    pcfg->nwwn, bfa_fcport_get_maxfrsize(bfa),
-				    bfa_fcport_get_rx_bbcredit(bfa));
-
-	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps),
-			BFA_FALSE, FC_CLASS_3, reqlen, &fchs,
-			bfa_fcs_fabric_flogiacc_comp, fabric,
-			FC_MAX_PDUSZ, 0); /* Timeout 0 indicates no
-					   * response expected
-					   */
-}
-
-/**
- *   Flogi Acc completion callback.
- */
-static void
-bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t status, u32 rsp_len,
-			     u32 resid_len, struct fchs_s *rspfchs)
-{
-	struct bfa_fcs_fabric_s *fabric = cbarg;
-
-	bfa_trc(fabric->fcs, status);
-}
-
-/*
- *
- * @param[in] fabric - fabric
- * @param[in] result - 1
- *
- * @return - none
- */
-void
-bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, enum auth_status status)
-{
-	bfa_trc(fabric->fcs, status);
-
-	if (status == FC_AUTH_STATE_SUCCESS)
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_SUCCESS);
-	else
-		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_FAILED);
-}
-
-/**
- * Send AEN notification
- */
-static void
-bfa_fcs_fabric_aen_post(struct bfa_fcs_port_s *port,
-			enum bfa_port_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = port->fcs->logm;
-	wwn_t           pwwn = bfa_fcs_port_get_pwwn(port);
-	wwn_t           fwwn = bfa_fcs_port_get_fabric_name(port);
-	char            pwwn_ptr[BFA_STRING_32];
-	char            fwwn_ptr[BFA_STRING_32];
-
-	wwn2str(pwwn_ptr, pwwn);
-	wwn2str(fwwn_ptr, fwwn);
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, event),
-		pwwn_ptr, fwwn_ptr);
-
-	aen_data.port.pwwn = pwwn;
-	aen_data.port.fwwn = fwwn;
-}
-
-/*
- *
- * @param[in] fabric - fabric
- * @param[in] wwn_t - new fabric name
- *
- * @return - none
- */
-void
-bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
-			       wwn_t fabric_name)
-{
-	bfa_trc(fabric->fcs, fabric_name);
-
-	if (fabric->fabric_name == 0) {
-		/*
-		 * With BRCD switches, we don't get Fabric Name in FLOGI.
-		 * Don't generate a fabric name change event in this case.
-		 */
-		fabric->fabric_name = fabric_name;
-	} else {
-		fabric->fabric_name = fabric_name;
-		/*
-		 * Generate a Event
-		 */
-		bfa_fcs_fabric_aen_post(&fabric->bport,
-					BFA_PORT_AEN_FABRIC_NAME_CHANGE);
-	}
-
-}
-
-/**
- *
- * @param[in] fabric - fabric
- * @param[in] node_symname -
- *              Caller allocated buffer to receive the symbolic name
- *
- * @return - none
- */
-void
-bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname)
-{
-	bfa_os_memcpy(node_symname,
-			fcs->fabric.bport.port_cfg.sym_name.symname,
-			BFA_SYMNAME_MAXLEN);
-}
-
-/**
- * Not used by FCS.
- */
-void
-bfa_cb_lps_flogo_comp(void *bfad, void *uarg)
-{
-}
-
-
diff --git a/drivers/scsi/bfa/fcbuild.h b/drivers/scsi/bfa/fcbuild.h
deleted file mode 100644
index 981d98d..0000000
--- a/drivers/scsi/bfa/fcbuild.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * fcbuild.h - FC link service frame building and parsing routines
- */
-
-#ifndef __FCBUILD_H__
-#define __FCBUILD_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/fc.h>
-#include <protocol/fcp.h>
-#include <protocol/ct.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_pport.h>
-
-/*
- * Utility Macros/functions
- */
-
-#define fcif_sof_set(_ifhdr, _sof)	((_ifhdr)->sof = FC_ ## _sof)
-#define fcif_eof_set(_ifhdr, _eof)	((_ifhdr)->eof = FC_ ## _eof)
-
-#define wwn_is_equal(_wwn1, _wwn2)		\
-	(memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0)
-
-#define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1))
-
-/*
- * Given the fc response length, this routine will return
- * the length of the actual payload bytes following the CT header.
- *
- * Assumes the input response length does not include the crc, eof, etc.
- */
-static inline   u32
-fc_get_ctresp_pyld_len(u32 resp_len)
-{
-	return resp_len - sizeof(struct ct_hdr_s);
-}
-
-/*
- * Convert bfa speed to rpsc speed value.
- */
-static inline enum bfa_pport_speed
-fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed_s speed)
-{
-	switch (speed) {
-
-	case RPSC_OP_SPEED_1G:
-		return BFA_PPORT_SPEED_1GBPS;
-
-	case RPSC_OP_SPEED_2G:
-		return BFA_PPORT_SPEED_2GBPS;
-
-	case RPSC_OP_SPEED_4G:
-		return BFA_PPORT_SPEED_4GBPS;
-
-	case RPSC_OP_SPEED_8G:
-		return BFA_PPORT_SPEED_8GBPS;
-
-	case RPSC_OP_SPEED_10G:
-		return BFA_PPORT_SPEED_10GBPS;
-
-	default:
-		return BFA_PPORT_SPEED_UNKNOWN;
-	}
-}
-
-/*
- * Convert RPSC speed to bfa speed value.
- */
-static inline   enum fc_rpsc_op_speed_s
-fc_bfa_speed_to_rpsc_operspeed(enum bfa_pport_speed op_speed)
-{
-	switch (op_speed) {
-
-	case BFA_PPORT_SPEED_1GBPS:
-		return RPSC_OP_SPEED_1G;
-
-	case BFA_PPORT_SPEED_2GBPS:
-		return RPSC_OP_SPEED_2G;
-
-	case BFA_PPORT_SPEED_4GBPS:
-		return RPSC_OP_SPEED_4G;
-
-	case BFA_PPORT_SPEED_8GBPS:
-		return RPSC_OP_SPEED_8G;
-
-	case BFA_PPORT_SPEED_10GBPS:
-		return RPSC_OP_SPEED_10G;
-
-	default:
-		return RPSC_OP_SPEED_NOT_EST;
-	}
-}
-enum fc_parse_status {
-	FC_PARSE_OK = 0,
-	FC_PARSE_FAILURE = 1,
-	FC_PARSE_BUSY = 2,
-	FC_PARSE_LEN_INVAL,
-	FC_PARSE_ACC_INVAL,
-	FC_PARSE_PWWN_NOT_EQUAL,
-	FC_PARSE_NWWN_NOT_EQUAL,
-	FC_PARSE_RXSZ_INVAL,
-	FC_PARSE_NOT_FCP,
-	FC_PARSE_OPAFLAG_INVAL,
-	FC_PARSE_RPAFLAG_INVAL,
-	FC_PARSE_OPA_INVAL,
-	FC_PARSE_RPA_INVAL,
-
-};
-
-struct fc_templates_s {
-	struct fchs_s          fc_els_req;
-	struct fchs_s          fc_bls_req;
-	struct fc_logi_s      plogi;
-	struct fc_rrq_s        rrq;
-};
-
-void fcbuild_init(void);
-
-u16 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
-			u32 s_id, u16 ox_id, wwn_t port_name,
-			wwn_t node_name, u16 pdu_size, u8 set_npiv,
-			u8 set_auth, u16 local_bb_credits);
-u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi,
-			u32 s_id, u16 ox_id, wwn_t port_name,
-			wwn_t node_name, u16 pdu_size);
-u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
-			u32 s_id, u16 ox_id, wwn_t port_name,
-			wwn_t node_name, u16 pdu_size,
-			u16 local_bb_credits);
-u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id, wwn_t port_name,
-			wwn_t node_name, u16 pdu_size);
-enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
-u16 fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
-			u16 ox_id);
-enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
-u16 fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
-			u32 s_id, u16 ox_id, u16 rrq_oxid);
-enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len);
-u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
-			u16 ox_id, u8 *name);
-u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
-			u16 ox_id, enum bfa_port_role role);
-u16 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, u8 *fc4_bitmap,
-			u32 bitmap_size);
-u16 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
-u16 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, wwn_t port_name);
-u16 fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
-			u16 ox_id, u32 port_id);
-u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
-			u8 set_br_reg, u32 s_id, u16 ox_id);
-u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id,
-			wwn_t port_name, wwn_t node_name, u16 pdu_size);
-
-u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			wwn_t port_name, wwn_t node_name);
-enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
-			u32 host_dap,
-			wwn_t node_name, wwn_t port_name);
-enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
-			wwn_t port_name, wwn_t node_name);
-u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			wwn_t port_name, wwn_t node_name);
-u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u8 reason_code, u8 reason_code_expl);
-u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd,
-			u32 d_id, u32 s_id, u16 ox_id);
-u16 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id);
-enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len);
-
-u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id,
-			enum bfa_port_role role);
-u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u32 data_format);
-u16 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u32 data_format,
-			struct fc_rnid_common_id_data_s *common_id_data,
-			struct fc_rnid_general_topology_data_s *
-			gen_topo_data);
-u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
-			u32 d_id, u32 s_id,
-			u32 *pid_list, u16 npids);
-u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
-			u32 d_id, u32 s_id, u16 ox_id);
-u16 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			struct fc_rpsc_speed_info_s *oper_speed);
-u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
-			u8 fc4_type);
-u16 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id, wwn_t port_name);
-u16 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id, wwn_t node_name);
-u16 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id, u32 cos);
-u16 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id, u8 port_type);
-u16 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u32 port_id);
-u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo,
-			u32 d_id, u32 s_id, u16 ox_id,
-			wwn_t port_name);
-u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
-			u32 s_id, u16 ox_id);
-u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 cmd_code);
-u16 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			wwn_t wwn);
-u16 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			wwn_t wwn);
-void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
-void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id);
-enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len);
-enum fc_parse_status fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
-			 wwn_t port_name);
-enum fc_parse_status fc_prli_parse(struct fc_prli_s *prli);
-enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
-			wwn_t port_name);
-u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			u16 rx_id);
-int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
-u16 fc_tprlo_acc_build(struct fchs_s *fchs,
-			struct fc_tprlo_acc_s *tprlo_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			int num_pages);
-u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
-			u32 d_id, u32 s_id, u16 ox_id,
-			int num_pages);
-u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len);
-u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, wwn_t port_name, wwn_t node_name,
-			u16 pdu_size);
-u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
-u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, int num_pages);
-u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len);
-u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, int num_pages,
-			enum fc_tprlo_type tprlo_type, u32 tpr_id);
-u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len);
-u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
-			u16 ox_id, u32 reason_code,
-			u32 reason_expl);
-u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
-			u16 ox_id, u32 port_id);
-u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
-u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
-			u32 s_id, u16 ox_id);
-#endif
diff --git a/drivers/scsi/bfa/fcptm.c b/drivers/scsi/bfa/fcptm.c
deleted file mode 100644
index 8c8b08c..0000000
--- a/drivers/scsi/bfa/fcptm.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- * This file contains dummy FCPTM routines to aid in Initiator Mode only
- * compilation of OS driver.
- *
- */
-
-#include "bfa_os_inc.h"
-#include "fcs_rport.h"
-#include "fcs_fcptm.h"
-#include "fcs/bfa_fcs_rport.h"
-
-struct bfa_fcs_tin_s *
-bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport)
-{
-	return NULL;
-}
-
-void
-bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
-{
-}
-
-void
-bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len)
-{
-}
-
-void
-bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin)
-{
-}
-
-void
-bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin)
-{
-}
diff --git a/drivers/scsi/bfa/fcs.h b/drivers/scsi/bfa/fcs.h
deleted file mode 100644
index 8d08230..0000000
--- a/drivers/scsi/bfa/fcs.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs.h FCS module functions
- */
-
-
-#ifndef __FCS_H__
-#define __FCS_H__
-
-#define __fcs_min_cfg(__fcs)       ((__fcs)->min_cfg)
-
-void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs);
-
-#endif /* __FCS_H__ */
diff --git a/drivers/scsi/bfa/fcs_auth.h b/drivers/scsi/bfa/fcs_auth.h
deleted file mode 100644
index 65d155f..0000000
--- a/drivers/scsi/bfa/fcs_auth.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs_uf.h FCS unsolicited frame receive
- */
-
-
-#ifndef __FCS_AUTH_H__
-#define __FCS_AUTH_H__
-
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <fcs/bfa_fcs_lport.h>
-
-/*
- * fcs friend functions: only between fcs modules
- */
-void bfa_fcs_auth_uf_recv(struct bfa_fcs_fabric_s *fabric, int len);
-void bfa_fcs_auth_start(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_auth_stop(struct bfa_fcs_fabric_s *fabric);
-
-#endif /* __FCS_UF_H__ */
diff --git a/drivers/scsi/bfa/fcs_fabric.h b/drivers/scsi/bfa/fcs_fabric.h
deleted file mode 100644
index 432ab8a..0000000
--- a/drivers/scsi/bfa/fcs_fabric.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs_lport.h FCS logical port interfaces
- */
-
-#ifndef __FCS_FABRIC_H__
-#define __FCS_FABRIC_H__
-
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <fcs/bfa_fcs_lport.h>
-
-#define BFA_FCS_BRCD_SWITCH_OUI  0x051e
-
-/*
-* fcs friend functions: only between fcs modules
- */
-void		bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
-void            bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
-void            bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
-					struct bfa_fcs_vport_s *vport);
-void            bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
-					struct bfa_fcs_vport_s *vport);
-int             bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric);
-struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup(
-			struct bfa_fcs_fabric_s *fabric, wwn_t pwwn);
-void            bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs);
-void            bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric,
-			struct fchs_s *fchs, u16 len);
-u16        bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric);
-bfa_boolean_t   bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric);
-bfa_boolean_t	bfa_fcs_fabric_is_auth_failed(struct bfa_fcs_fabric_s *fabric);
-enum bfa_pport_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric);
-void     	bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric);
-
-bfa_status_t bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf,
-			struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg,
-			struct bfad_vf_s *vf_drv);
-void bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric,
-			enum auth_status status);
-
-void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
-			wwn_t fabric_name);
-u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
-void bfa_fcs_get_sym_name(const struct bfa_fcs_s *fcs, char *node_symname);
-
-#endif /* __FCS_FABRIC_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcpim.h b/drivers/scsi/bfa/fcs_fcpim.h
deleted file mode 100644
index 11e6e7b..0000000
--- a/drivers/scsi/bfa/fcs_fcpim.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __FCS_FCPIM_H__
-#define __FCS_FCPIM_H__
-
-#include <defs/bfa_defs_port.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-
-/*
- * Following routines are from FCPIM and will be called by rport.
- */
-struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim);
-bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim);
-
-void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim);
-void bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim);
-
-void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs,
-			u16 len);
-#endif /* __FCS_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcptm.h b/drivers/scsi/bfa/fcs_fcptm.h
deleted file mode 100644
index ffff082..0000000
--- a/drivers/scsi/bfa/fcs_fcptm.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __FCS_FCPTM_H__
-#define __FCS_FCPTM_H__
-
-#include <defs/bfa_defs_port.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-
-/*
- * Following routines are from FCPTM and will be called by rport.
- */
-struct bfa_fcs_tin_s *bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
-			u16 len);
-void bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin);
-void bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin);
-
-/*
- * Modudle init/cleanup routines.
- */
-void bfa_fcs_fcptm_modinit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fcptm_modexit(struct bfa_fcs_s *fcs);
-void bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs,
-			u16 len);
-
-#endif /* __FCS_FCPTM_H__ */
diff --git a/drivers/scsi/bfa/fcs_fcxp.h b/drivers/scsi/bfa/fcs_fcxp.h
deleted file mode 100644
index 8277fe9..0000000
--- a/drivers/scsi/bfa/fcs_fcxp.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs_fcxp.h FCXP helper macros for FCS
- */
-
-
-#ifndef __FCS_FCXP_H__
-#define __FCS_FCXP_H__
-
-#define bfa_fcs_fcxp_alloc(__fcs)	\
-	bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL)
-
-#endif /* __FCS_FCXP_H__ */
diff --git a/drivers/scsi/bfa/fcs_lport.h b/drivers/scsi/bfa/fcs_lport.h
deleted file mode 100644
index a6508c8..0000000
--- a/drivers/scsi/bfa/fcs_lport.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs_lport.h FCS logical port interfaces
- */
-
-#ifndef __FCS_LPORT_H__
-#define __FCS_LPORT_H__
-
-#define __VPORT_H__
-#include <defs/bfa_defs_port.h>
-#include <bfa_svc.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <fcs_fabric.h>
-#include <fcs_ms.h>
-#include <cs/bfa_q.h>
-#include <fcbuild.h>
-
-/*
- * PID used in P2P/N2N ( In Big Endian)
- */
-#define N2N_LOCAL_PID	    0x010000
-#define N2N_REMOTE_PID		0x020000
-
-/*
- * Misc Timeouts
- */
-/*
- * To be used when spawning a timer before retrying a failed command. Milli
- * Secs.
- */
-#define	BFA_FCS_RETRY_TIMEOUT 2000
-
-/*
- * Check for Port/Vport Mode/Role
- */
-#define	BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \
-		(port->port_cfg.roles & BFA_PORT_ROLE_FCP_IM)
-
-#define	BFA_FCS_VPORT_IS_TARGET_MODE(port) \
-		(port->port_cfg.roles & BFA_PORT_ROLE_FCP_TM)
-
-#define	BFA_FCS_VPORT_IS_IPFC_MODE(port) \
-		(port->port_cfg.roles & BFA_PORT_ROLE_FCP_IPFC)
-
-/*
- * Is this a Well Known Address
- */
-#define BFA_FCS_PID_IS_WKA(pid)  ((bfa_os_ntoh3b(pid) > 0xFFF000) ?  1 : 0)
-
-/*
- * Pointer to elements within Port
- */
-#define BFA_FCS_GET_HAL_FROM_PORT(port)  (port->fcs->bfa)
-#define BFA_FCS_GET_NS_FROM_PORT(port)  (&port->port_topo.pfab.ns)
-#define BFA_FCS_GET_SCN_FROM_PORT(port)  (&port->port_topo.pfab.scn)
-#define BFA_FCS_GET_MS_FROM_PORT(port)  (&port->port_topo.pfab.ms)
-#define BFA_FCS_GET_FDMI_FROM_PORT(port)  (&port->port_topo.pfab.ms.fdmi)
-
-/*
- * handler for unsolicied frames
- */
-void bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs,
-			u16 len);
-
-/*
- * Following routines will be called by Fabric to indicate port
- * online/offline to vport.
- */
-void bfa_fcs_lport_attach(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs,
-			uint16_t vf_id, struct bfa_fcs_vport_s *vport);
-void bfa_fcs_lport_init(struct bfa_fcs_port_s *lport,
-			struct bfa_port_cfg_s *port_cfg);
-void bfa_fcs_port_online(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_offline(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_delete(struct bfa_fcs_port_s *port);
-bfa_boolean_t   bfa_fcs_port_is_online(struct bfa_fcs_port_s *port);
-
-/*
- * Lookup rport based on PID
- */
-struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pid(
-			struct bfa_fcs_port_s *port, u32 pid);
-
-/*
- * Lookup rport based on PWWN
- */
-struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pwwn(
-			struct bfa_fcs_port_s *port, wwn_t pwwn);
-struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_nwwn(
-			struct bfa_fcs_port_s *port, wwn_t nwwn);
-void bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port,
-			struct bfa_fcs_rport_s *rport);
-void bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port,
-			struct bfa_fcs_rport_s *rport);
-
-void bfa_fcs_port_modinit(struct bfa_fcs_s *fcs);
-void bfa_fcs_port_modexit(struct bfa_fcs_s *fcs);
-void bfa_fcs_port_lip(struct bfa_fcs_port_s *port);
-
-#endif /* __FCS_LPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_ms.h b/drivers/scsi/bfa/fcs_ms.h
deleted file mode 100644
index b6a8c12..0000000
--- a/drivers/scsi/bfa/fcs_ms.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs_ms.h FCS ms interfaces
- */
-#ifndef __FCS_MS_H__
-#define __FCS_MS_H__
-
-/* MS FCS routines */
-void bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port);
-void bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port);
-
-/* FDMI FCS routines */
-void bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms);
-void bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms);
-void bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms);
-
-#endif
diff --git a/drivers/scsi/bfa/fcs_port.h b/drivers/scsi/bfa/fcs_port.h
deleted file mode 100644
index 408c06a..0000000
--- a/drivers/scsi/bfa/fcs_port.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs_pport.h FCS physical port interfaces
- */
-
-
-#ifndef __FCS_PPORT_H__
-#define __FCS_PPORT_H__
-
-/*
- * fcs friend functions: only between fcs modules
- */
-void bfa_fcs_pport_attach(struct bfa_fcs_s *fcs);
-
-#endif /* __FCS_PPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_rport.h b/drivers/scsi/bfa/fcs_rport.h
deleted file mode 100644
index e634fb7..0000000
--- a/drivers/scsi/bfa/fcs_rport.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs_rport.h FCS rport interfaces and defines
- */
-
-#ifndef __FCS_RPORT_H__
-#define __FCS_RPORT_H__
-
-#include <fcs/bfa_fcs_rport.h>
-
-#define BFA_FCS_RPORT_MAX_RETRIES               (5)
-
-void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
-			u16 len);
-void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport);
-
-struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_port_s *port,
-			u32 pid);
-void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs,
-			struct fc_logi_s *plogi_rsp);
-void bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port,
-			struct fchs_s *rx_fchs,
-			struct fc_logi_s *plogi);
-void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
-			struct fc_logi_s *plogi);
-void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id);
-void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport);
-int  bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport);
-struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port,
-			wwn_t wwn);
-
-
-/* Rport Features */
-void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport);
-void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport);
-void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport);
-
-#endif /* __FCS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/fcs_trcmod.h b/drivers/scsi/bfa/fcs_trcmod.h
deleted file mode 100644
index 41b5ae8..0000000
--- a/drivers/scsi/bfa/fcs_trcmod.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs_trcmod.h BFA FCS trace modules
- */
-
-#ifndef __FCS_TRCMOD_H__
-#define __FCS_TRCMOD_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
-	BFA_TRC_FCS_FABRIC		= 1,
-	BFA_TRC_FCS_VFAPI		= 2,
-	BFA_TRC_FCS_PORT		= 3,
-	BFA_TRC_FCS_VPORT		= 4,
-	BFA_TRC_FCS_VP_API		= 5,
-	BFA_TRC_FCS_VPS			= 6,
-	BFA_TRC_FCS_RPORT		= 7,
-	BFA_TRC_FCS_FCPIM		= 8,
-	BFA_TRC_FCS_FCPTM		= 9,
-	BFA_TRC_FCS_NS			= 10,
-	BFA_TRC_FCS_SCN			= 11,
-	BFA_TRC_FCS_LOOP		= 12,
-	BFA_TRC_FCS_UF			= 13,
-	BFA_TRC_FCS_PPORT		= 14,
-	BFA_TRC_FCS_FCPIP		= 15,
-	BFA_TRC_FCS_PORT_API	= 16,
-	BFA_TRC_FCS_RPORT_API	= 17,
-	BFA_TRC_FCS_AUTH		= 18,
-	BFA_TRC_FCS_N2N			= 19,
-	BFA_TRC_FCS_MS			= 20,
-	BFA_TRC_FCS_FDMI		= 21,
-	BFA_TRC_FCS_RPORT_FTRS	= 22,
-};
-
-#endif /* __FCS_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/fcs_uf.h b/drivers/scsi/bfa/fcs_uf.h
deleted file mode 100644
index f591072..0000000
--- a/drivers/scsi/bfa/fcs_uf.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  fcs_uf.h FCS unsolicited frame receive
- */
-
-
-#ifndef __FCS_UF_H__
-#define __FCS_UF_H__
-
-/*
- * fcs friend functions: only between fcs modules
- */
-void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
-
-#endif /* __FCS_UF_H__ */
diff --git a/drivers/scsi/bfa/fcs_vport.h b/drivers/scsi/bfa/fcs_vport.h
deleted file mode 100644
index bb647a4..0000000
--- a/drivers/scsi/bfa/fcs_vport.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __FCS_VPORT_H__
-#define __FCS_VPORT_H__
-
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_vport.h>
-#include <defs/bfa_defs_pci.h>
-
-void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport);
-
-#endif /* __FCS_VPORT_H__ */
-
diff --git a/drivers/scsi/bfa/fdmi.c b/drivers/scsi/bfa/fdmi.c
deleted file mode 100644
index 2b50eabf..0000000
--- a/drivers/scsi/bfa/fdmi.c
+++ /dev/null
@@ -1,1230 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  port_api.c BFA FCS port
- */
-
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "lport_priv.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include <fcs/bfa_fcs_fdmi.h>
-
-BFA_TRC_FILE(FCS, FDMI);
-
-#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
-
-/*
- * forward declarations
- */
-static void     bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg,
-					   struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_fdmi_rhba_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_fdmi_rprt_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_fdmi_rpa_response(void *fcsarg,
-					       struct bfa_fcxp_s *fcxp,
-					       void *cbarg,
-					       bfa_status_t req_status,
-					       u32 rsp_len,
-					       u32 resid_len,
-					       struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_fdmi_timeout(void *arg);
-static u16 bfa_fcs_port_fdmi_build_rhba_pyld(
-			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static u16 bfa_fcs_port_fdmi_build_rprt_pyld(
-			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static u16 bfa_fcs_port_fdmi_build_rpa_pyld(
-			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static u16 bfa_fcs_port_fdmi_build_portattr_block(
-			struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld);
-static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
-			struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
-static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
-			struct bfa_fcs_fdmi_port_attr_s *port_attr);
-/**
- *  fcs_fdmi_sm FCS FDMI state machine
- */
-
-/**
- *  FDMI State Machine events
- */
-enum port_fdmi_event {
-	FDMISM_EVENT_PORT_ONLINE = 1,
-	FDMISM_EVENT_PORT_OFFLINE = 2,
-	FDMISM_EVENT_RSP_OK = 4,
-	FDMISM_EVENT_RSP_ERROR = 5,
-	FDMISM_EVENT_TIMEOUT = 6,
-	FDMISM_EVENT_RHBA_SENT = 7,
-	FDMISM_EVENT_RPRT_SENT = 8,
-	FDMISM_EVENT_RPA_SENT = 9,
-};
-
-static void bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void     bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void     bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void     bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-static void	bfa_fcs_port_fdmi_sm_disabled(struct bfa_fcs_port_fdmi_s *fdmi,
-			enum port_fdmi_event event);
-
-/**
- * 		Start in offline state - awaiting MS to send start.
- */
-static void
-bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi,
-			     enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	fdmi->retry_cnt = 0;
-
-	switch (event) {
-	case FDMISM_EVENT_PORT_ONLINE:
-		if (port->vport) {
-			/*
-			 * For Vports, register a new port.
-			 */
-			bfa_sm_set_state(fdmi,
-					 bfa_fcs_port_fdmi_sm_sending_rprt);
-			bfa_fcs_port_fdmi_send_rprt(fdmi, NULL);
-		} else {
-			/*
-			 * For a base port, we should first register the HBA
-			 * atribute. The HBA attribute also contains the base
-			 *  port registration.
-			 */
-			bfa_sm_set_state(fdmi,
-					 bfa_fcs_port_fdmi_sm_sending_rhba);
-			bfa_fcs_port_fdmi_send_rhba(fdmi, NULL);
-		}
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
-				  enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RHBA_SENT:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
-				       &fdmi->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi,
-			  enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RSP_ERROR:
-		/*
-		 * if max retries have not been reached, start timer for a
-		 * delayed retry
-		 */
-		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba_retry);
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
-					&fdmi->timer, bfa_fcs_port_fdmi_timeout,
-					fdmi, BFA_FCS_RETRY_TIMEOUT);
-		} else {
-			/*
-			 * set state to offline
-			 */
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		}
-		break;
-
-	case FDMISM_EVENT_RSP_OK:
-		/*
-		 * Initiate Register Port Attributes
-		 */
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa);
-		fdmi->retry_cnt = 0;
-		bfa_fcs_port_fdmi_send_rpa(fdmi, NULL);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_fcxp_discard(fdmi->fcxp);
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-				enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rhba);
-		bfa_fcs_port_fdmi_send_rhba(fdmi, NULL);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_timer_stop(&fdmi->timer);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-/*
-* RPRT : Register Port
- */
-static void
-bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
-				  enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RPRT_SENT:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
-				       &fdmi->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi,
-			  enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RSP_ERROR:
-		/*
-		 * if max retries have not been reached, start timer for a
-		 * delayed retry
-		 */
-		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt_retry);
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
-					&fdmi->timer, bfa_fcs_port_fdmi_timeout,
-					fdmi, BFA_FCS_RETRY_TIMEOUT);
-
-		} else {
-			/*
-			 * set state to offline
-			 */
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-			fdmi->retry_cnt = 0;
-		}
-		break;
-
-	case FDMISM_EVENT_RSP_OK:
-		fdmi->retry_cnt = 0;
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_fcxp_discard(fdmi->fcxp);
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-				enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rprt);
-		bfa_fcs_port_fdmi_send_rprt(fdmi, NULL);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_timer_stop(&fdmi->timer);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-/*
- * Register Port Attributes
- */
-static void
-bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
-				 enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RPA_SENT:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
-				       &fdmi->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi,
-			 enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_RSP_ERROR:
-		/*
-		 * if max retries have not been reached, start timer for a
-		 * delayed retry
-		 */
-		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa_retry);
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
-					&fdmi->timer, bfa_fcs_port_fdmi_timeout,
-					fdmi, BFA_FCS_RETRY_TIMEOUT);
-		} else {
-			/*
-			 * set state to offline
-			 */
-			bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-			fdmi->retry_cnt = 0;
-		}
-		break;
-
-	case FDMISM_EVENT_RSP_OK:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online);
-		fdmi->retry_cnt = 0;
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_fcxp_discard(fdmi->fcxp);
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi,
-			       enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa);
-		bfa_fcs_port_fdmi_send_rpa(fdmi, NULL);
-		break;
-
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		bfa_timer_stop(&fdmi->timer);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi,
-			    enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	switch (event) {
-	case FDMISM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(port->fcs, event);
-	}
-}
-
-/**
- *  FDMI is disabled state.
- */
-static void
-bfa_fcs_port_fdmi_sm_disabled(struct bfa_fcs_port_fdmi_s *fdmi,
-				enum port_fdmi_event event)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-	bfa_trc(port->fcs, event);
-
-	/* No op State. It can only be enabled at Driver Init. */
-}
-
-/**
-*   RHBA : Register HBA Attributes.
- */
-static void
-bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fchs_s          fchs;
-	int             len, attr_len;
-	struct bfa_fcxp_s *fcxp;
-	u8        *pyld;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-				    bfa_fcs_port_fdmi_send_rhba, fdmi);
-		return;
-	}
-	fdmi->fcxp = fcxp;
-
-	pyld = bfa_fcxp_get_reqbuf(fcxp);
-	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
-
-	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
-				   FDMI_RHBA);
-
-	attr_len = bfa_fcs_port_fdmi_build_rhba_pyld(fdmi,
-			(u8 *) ((struct ct_hdr_s *) pyld + 1));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, (len + attr_len), &fchs,
-		      bfa_fcs_port_fdmi_rhba_response, (void *)fdmi,
-		      FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
-}
-
-static          u16
-bfa_fcs_port_fdmi_build_rhba_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
-				  u8 *pyld)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct bfa_fcs_fdmi_hba_attr_s hba_attr;	/* @todo */
-	struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr; /* @todo */
-	struct fdmi_rhba_s    *rhba = (struct fdmi_rhba_s *) pyld;
-	struct fdmi_attr_s    *attr;
-	u8        *curr_ptr;
-	u16        len, count;
-
-	/*
-	 * get hba attributes
-	 */
-	bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
-
-	rhba->hba_id = bfa_fcs_port_get_pwwn(port);
-	rhba->port_list.num_ports = bfa_os_htonl(1);
-	rhba->port_list.port_entry = bfa_fcs_port_get_pwwn(port);
-
-	len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
-
-	count = 0;
-	len += sizeof(rhba->hba_attr_blk.attr_count);
-
-	/*
-	 * fill out the invididual entries of the HBA attrib Block
-	 */
-	curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
-
-	/*
-	 * Node Name
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME);
-	attr->len = sizeof(wwn_t);
-	memcpy(attr->value, &bfa_fcs_port_get_nwwn(port), attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Manufacturer
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER);
-	attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
-	memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Serial Number
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM);
-	attr->len = (u16) strlen(fcs_hba_attr->serial_num);
-	memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Model
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL);
-	attr->len = (u16) strlen(fcs_hba_attr->model);
-	memcpy(attr->value, fcs_hba_attr->model, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Model Desc
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC);
-	attr->len = (u16) strlen(fcs_hba_attr->model_desc);
-	memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * H/W Version
-	 */
-	if (fcs_hba_attr->hw_version[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION);
-		attr->len = (u16) strlen(fcs_hba_attr->hw_version);
-		memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		count++;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-	}
-
-	/*
-	 * Driver Version
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION);
-	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
-	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Option Rom Version
-	 */
-	if (fcs_hba_attr->option_rom_ver[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION);
-		attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
-		memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		count++;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-	}
-
-	/*
-	 * f/w Version = driver version
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION);
-	attr->len = (u16) strlen(fcs_hba_attr->driver_version);
-	memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
-	/* variable fields need to be 4 byte aligned */
-	attr->len = fc_roundup(attr->len, sizeof(u32));
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * OS Name
-	 */
-	if (fcs_hba_attr->os_name[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME);
-		attr->len = (u16) strlen(fcs_hba_attr->os_name);
-		memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		count++;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-	}
-
-	/*
-	 * MAX_CT_PAYLOAD
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT);
-	attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
-	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
-	len += attr->len;
-	count++;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Update size of payload
-	 */
-	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
-
-	rhba->hba_attr_blk.attr_count = bfa_os_htonl(count);
-	return len;
-}
-
-static void
-bfa_fcs_port_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-}
-
-/**
-*   RPRT : Register Port
- */
-static void
-bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fchs_s          fchs;
-	u16        len, attr_len;
-	struct bfa_fcxp_s *fcxp;
-	u8        *pyld;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-				    bfa_fcs_port_fdmi_send_rprt, fdmi);
-		return;
-	}
-	fdmi->fcxp = fcxp;
-
-	pyld = bfa_fcxp_get_reqbuf(fcxp);
-	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
-
-	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
-				   FDMI_RPRT);
-
-	attr_len = bfa_fcs_port_fdmi_build_rprt_pyld(fdmi,
-			(u8 *) ((struct ct_hdr_s *) pyld + 1));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len + attr_len, &fchs,
-		      bfa_fcs_port_fdmi_rprt_response, (void *)fdmi,
-		      FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
-}
-
-/**
- * This routine builds Port Attribute Block that used in RPA, RPRT commands.
- */
-static          u16
-bfa_fcs_port_fdmi_build_portattr_block(struct bfa_fcs_port_fdmi_s *fdmi,
-				       u8 *pyld)
-{
-	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
-	struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
-	struct fdmi_attr_s    *attr;
-	u8        *curr_ptr;
-	u16        len;
-	u8         count = 0;
-
-	/*
-	 * get port attributes
-	 */
-	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
-
-	len = sizeof(port_attrib->attr_count);
-
-	/*
-	 * fill out the invididual entries
-	 */
-	curr_ptr = (u8 *) &port_attrib->port_attr;
-
-	/*
-	 * FC4 Types
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES);
-	attr->len = sizeof(fcs_port_attr.supp_fc4_types);
-	memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	++count;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * Supported Speed
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED);
-	attr->len = sizeof(fcs_port_attr.supp_speed);
-	memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	++count;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * current Port Speed
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED);
-	attr->len = sizeof(fcs_port_attr.curr_speed);
-	memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	++count;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * max frame size
-	 */
-	attr = (struct fdmi_attr_s *) curr_ptr;
-	attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE);
-	attr->len = sizeof(fcs_port_attr.max_frm_size);
-	memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
-	curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-	len += attr->len;
-	++count;
-	attr->len =
-		bfa_os_htons(attr->len + sizeof(attr->type) +
-			     sizeof(attr->len));
-
-	/*
-	 * OS Device Name
-	 */
-	if (fcs_port_attr.os_device_name[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME);
-		attr->len = (u16) strlen(fcs_port_attr.os_device_name);
-		memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		++count;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-
-	}
-	/*
-	 * Host Name
-	 */
-	if (fcs_port_attr.host_name[0] != '\0') {
-		attr = (struct fdmi_attr_s *) curr_ptr;
-		attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME);
-		attr->len = (u16) strlen(fcs_port_attr.host_name);
-		memcpy(attr->value, fcs_port_attr.host_name, attr->len);
-		/* variable fields need to be 4 byte aligned */
-		attr->len = fc_roundup(attr->len, sizeof(u32));
-		curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
-		len += attr->len;
-		++count;
-		attr->len =
-			bfa_os_htons(attr->len + sizeof(attr->type) +
-				     sizeof(attr->len));
-
-	}
-
-	/*
-	 * Update size of payload
-	 */
-	port_attrib->attr_count = bfa_os_htonl(count);
-	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
-	return len;
-}
-
-static          u16
-bfa_fcs_port_fdmi_build_rprt_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
-				  u8 *pyld)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fdmi_rprt_s    *rprt = (struct fdmi_rprt_s *) pyld;
-	u16        len;
-
-	rprt->hba_id = bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
-	rprt->port_name = bfa_fcs_port_get_pwwn(port);
-
-	len = bfa_fcs_port_fdmi_build_portattr_block(fdmi,
-			(u8 *) &rprt->port_attr_blk);
-
-	len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
-
-	return len;
-}
-
-static void
-bfa_fcs_port_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-}
-
-/**
-*   RPA : Register Port Attributes.
- */
-static void
-bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fchs_s          fchs;
-	u16        len, attr_len;
-	struct bfa_fcxp_s *fcxp;
-	u8        *pyld;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
-				    bfa_fcs_port_fdmi_send_rpa, fdmi);
-		return;
-	}
-	fdmi->fcxp = fcxp;
-
-	pyld = bfa_fcxp_get_reqbuf(fcxp);
-	bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
-
-	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port),
-				   FDMI_RPA);
-
-	attr_len = bfa_fcs_port_fdmi_build_rpa_pyld(fdmi,
-			(u8 *) ((struct ct_hdr_s *) pyld + 1));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len + attr_len, &fchs,
-		      bfa_fcs_port_fdmi_rpa_response, (void *)fdmi,
-		      FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
-}
-
-static          u16
-bfa_fcs_port_fdmi_build_rpa_pyld(struct bfa_fcs_port_fdmi_s *fdmi,
-				 u8 *pyld)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct fdmi_rpa_s     *rpa = (struct fdmi_rpa_s *) pyld;
-	u16        len;
-
-	rpa->port_name = bfa_fcs_port_get_pwwn(port);
-
-	len = bfa_fcs_port_fdmi_build_portattr_block(fdmi,
-			(u8 *) &rpa->port_attr_blk);
-
-	len += sizeof(rpa->port_name);
-
-	return len;
-}
-
-static void
-bfa_fcs_port_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			       void *cbarg, bfa_status_t req_status,
-			       u32 rsp_len, u32 resid_len,
-			       struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg;
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
-}
-
-static void
-bfa_fcs_port_fdmi_timeout(void *arg)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)arg;
-
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
-}
-
-static void
-bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi,
-			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
-
-	bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
-
-	bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
-		hba_attr->manufacturer);
-	bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
-						hba_attr->serial_num);
-	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, hba_attr->model);
-	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc, hba_attr->model_desc);
-	bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc, hba_attr->hw_version);
-	bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
-		hba_attr->option_rom_ver);
-	bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc, hba_attr->fw_version);
-
-	strncpy(hba_attr->driver_version, (char *)driver_info->version,
-		sizeof(hba_attr->driver_version));
-
-	strncpy(hba_attr->os_name, driver_info->host_os_name,
-		sizeof(hba_attr->os_name));
-
-	/*
-	 * If there is a patch level, append it to the os name along with a
-	 * separator
-	 */
-	if (driver_info->host_os_patch[0] != '\0') {
-		strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
-		strncat(hba_attr->os_name, driver_info->host_os_patch,
-			sizeof(driver_info->host_os_patch));
-	}
-
-	hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ);
-
-}
-
-static void
-bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi,
-			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
-{
-	struct bfa_fcs_port_s *port = fdmi->ms->port;
-	struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
-	struct bfa_pport_attr_s pport_attr;
-
-	bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
-
-	/*
-	 * get pport attributes from hal
-	 */
-	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
-
-	/*
-	 * get FC4 type Bitmask
-	 */
-	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
-
-	/*
-	 * Supported Speeds
-	 */
-	port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS);
-
-	/*
-	 * Current Speed
-	 */
-	port_attr->curr_speed = bfa_os_htonl(pport_attr.speed);
-
-	/*
-	 * Max PDU Size.
-	 */
-	port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ);
-
-	/*
-	 * OS device Name
-	 */
-	strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
-		sizeof(port_attr->os_device_name));
-
-	/*
-	 * Host name
-	 */
-	strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
-		sizeof(port_attr->host_name));
-
-}
-
-
-void
-bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
-
-	fdmi->ms = ms;
-	if (ms->port->fcs->fdmi_enabled)
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline);
-	else
-		bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_disabled);
-}
-
-void
-bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
-
-	fdmi->ms = ms;
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
-}
-
-void
-bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms)
-{
-	struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi;
-
-	fdmi->ms = ms;
-	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
-}
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen.h b/drivers/scsi/bfa/include/aen/bfa_aen.h
deleted file mode 100644
index 6abbab0..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_AEN_H__
-#define __BFA_AEN_H__
-
-#include "defs/bfa_defs_aen.h"
-#include "defs/bfa_defs_status.h"
-#include "cs/bfa_debug.h"
-
-#define BFA_AEN_MAX_ENTRY	512
-
-extern int bfa_aen_max_cfg_entry;
-struct bfa_aen_s {
-	void		*bfad;
-	int		max_entry;
-	int		write_index;
-	int		read_index;
-	int		bfad_num;
-	int		seq_num;
-	void		(*aen_cb_notify)(void *bfad);
-	void		(*gettimeofday)(struct bfa_timeval_s *tv);
-	struct bfa_trc_mod_s *trcmod;
-	int		app_ri[BFA_AEN_MAX_APP]; /* For multiclient support */
-	struct bfa_aen_entry_s list[BFA_AEN_MAX_ENTRY]; /* Must be the last */
-};
-
-
-/**
- * Public APIs
- */
-static inline void
-bfa_aen_set_max_cfg_entry(int max_entry)
-{
-	bfa_aen_max_cfg_entry = max_entry;
-}
-
-static inline int
-bfa_aen_get_max_cfg_entry(void)
-{
-	return bfa_aen_max_cfg_entry;
-}
-
-static inline int
-bfa_aen_get_meminfo(void)
-{
-	return sizeof(struct bfa_aen_entry_s) * bfa_aen_get_max_cfg_entry();
-}
-
-static inline int
-bfa_aen_get_wi(struct bfa_aen_s *aen)
-{
-	return aen->write_index;
-}
-
-static inline int
-bfa_aen_get_ri(struct bfa_aen_s *aen)
-{
-	return aen->read_index;
-}
-
-static inline int
-bfa_aen_fetch_count(struct bfa_aen_s *aen, enum bfa_aen_app  app_id)
-{
-	bfa_assert((app_id < BFA_AEN_MAX_APP) && (app_id >= bfa_aen_app_bcu));
-	return ((aen->write_index + aen->max_entry) - aen->app_ri[app_id])
-		% aen->max_entry;
-}
-
-int bfa_aen_init(struct bfa_aen_s *aen, struct bfa_trc_mod_s *trcmod,
-		void *bfad, int bfad_num, void (*aen_cb_notify)(void *),
-		void (*gettimeofday)(struct bfa_timeval_s *));
-
-void bfa_aen_post(struct bfa_aen_s *aen, enum bfa_aen_category aen_category,
-		     int aen_type, union bfa_aen_data_u *aen_data);
-
-bfa_status_t bfa_aen_fetch(struct bfa_aen_s *aen,
-			struct bfa_aen_entry_s *aen_entry,
-			int entry_req, enum bfa_aen_app app_id, int *entry_ret);
-
-int bfa_aen_get_inst(struct bfa_aen_s *aen);
-
-#endif /* __BFA_AEN_H__ */
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h b/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h
deleted file mode 100644
index 260d3ea..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for BFA_AEN_CAT_ADAPTER Module */
-#ifndef	__bfa_aen_adapter_h__
-#define	__bfa_aen_adapter_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_ADAPTER_ADD \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_ADD)
-#define BFA_AEN_ADAPTER_REMOVE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_REMOVE)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_audit.h b/drivers/scsi/bfa/include/aen/bfa_aen_audit.h
deleted file mode 100644
index 12cd7aa..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_audit.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for BFA_AEN_CAT_AUDIT Module */
-#ifndef	__bfa_aen_audit_h__
-#define	__bfa_aen_audit_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_AUDIT_AUTH_ENABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_ENABLE)
-#define BFA_AEN_AUDIT_AUTH_DISABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_DISABLE)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h b/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h
deleted file mode 100644
index 507d0b5..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for BFA_AEN_CAT_ETHPORT Module */
-#ifndef	__bfa_aen_ethport_h__
-#define	__bfa_aen_ethport_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_ETHPORT_LINKUP \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKUP)
-#define BFA_AEN_ETHPORT_LINKDOWN \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKDOWN)
-#define BFA_AEN_ETHPORT_ENABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_ENABLE)
-#define BFA_AEN_ETHPORT_DISABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_DISABLE)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h b/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h
deleted file mode 100644
index 4daf96f..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for BFA_AEN_CAT_IOC Module */
-#ifndef	__bfa_aen_ioc_h__
-#define	__bfa_aen_ioc_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_IOC_HBGOOD \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBGOOD)
-#define BFA_AEN_IOC_HBFAIL \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBFAIL)
-#define BFA_AEN_IOC_ENABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_ENABLE)
-#define BFA_AEN_IOC_DISABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_DISABLE)
-#define BFA_AEN_IOC_FWMISMATCH \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWMISMATCH)
-#define BFA_AEN_IOC_FWCFG_ERROR \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWCFG_ERROR)
-#define BFA_AEN_IOC_INVALID_VENDOR      \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_VENDOR)
-#define BFA_AEN_IOC_INVALID_NWWN        \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_NWWN)
-#define BFA_AEN_IOC_INVALID_PWWN        \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_INVALID_PWWN)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h b/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h
deleted file mode 100644
index a7d8ddc..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for BFA_AEN_CAT_ITNIM Module */
-#ifndef	__bfa_aen_itnim_h__
-#define	__bfa_aen_itnim_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_ITNIM_ONLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_ONLINE)
-#define BFA_AEN_ITNIM_OFFLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_OFFLINE)
-#define BFA_AEN_ITNIM_DISCONNECT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_DISCONNECT)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_lport.h b/drivers/scsi/bfa/include/aen/bfa_aen_lport.h
deleted file mode 100644
index 5a8ebb6..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_lport.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for BFA_AEN_CAT_LPORT Module */
-#ifndef	__bfa_aen_lport_h__
-#define	__bfa_aen_lport_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_LPORT_NEW \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW)
-#define BFA_AEN_LPORT_DELETE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE)
-#define BFA_AEN_LPORT_ONLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_ONLINE)
-#define BFA_AEN_LPORT_OFFLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_OFFLINE)
-#define BFA_AEN_LPORT_DISCONNECT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DISCONNECT)
-#define BFA_AEN_LPORT_NEW_PROP \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_PROP)
-#define BFA_AEN_LPORT_DELETE_PROP \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_PROP)
-#define BFA_AEN_LPORT_NEW_STANDARD \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_STANDARD)
-#define BFA_AEN_LPORT_DELETE_STANDARD \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_STANDARD)
-#define BFA_AEN_LPORT_NPIV_DUP_WWN \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_DUP_WWN)
-#define BFA_AEN_LPORT_NPIV_FABRIC_MAX \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_FABRIC_MAX)
-#define BFA_AEN_LPORT_NPIV_UNKNOWN \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_UNKNOWN)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_port.h b/drivers/scsi/bfa/include/aen/bfa_aen_port.h
deleted file mode 100644
index 9add905..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_port.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for BFA_AEN_CAT_PORT Module */
-#ifndef	__bfa_aen_port_h__
-#define	__bfa_aen_port_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_PORT_ONLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ONLINE)
-#define BFA_AEN_PORT_OFFLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_OFFLINE)
-#define BFA_AEN_PORT_RLIR \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_RLIR)
-#define BFA_AEN_PORT_SFP_INSERT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_INSERT)
-#define BFA_AEN_PORT_SFP_REMOVE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_REMOVE)
-#define BFA_AEN_PORT_SFP_POM \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_POM)
-#define BFA_AEN_PORT_ENABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ENABLE)
-#define BFA_AEN_PORT_DISABLE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISABLE)
-#define BFA_AEN_PORT_AUTH_ON \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_ON)
-#define BFA_AEN_PORT_AUTH_OFF \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_OFF)
-#define BFA_AEN_PORT_DISCONNECT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISCONNECT)
-#define BFA_AEN_PORT_QOS_NEG \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_QOS_NEG)
-#define BFA_AEN_PORT_FABRIC_NAME_CHANGE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_FABRIC_NAME_CHANGE)
-#define BFA_AEN_PORT_SFP_ACCESS_ERROR \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_ACCESS_ERROR)
-#define BFA_AEN_PORT_SFP_UNSUPPORT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_UNSUPPORT)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_rport.h b/drivers/scsi/bfa/include/aen/bfa_aen_rport.h
deleted file mode 100644
index 7e4be1f..0000000
--- a/drivers/scsi/bfa/include/aen/bfa_aen_rport.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for BFA_AEN_CAT_RPORT Module */
-#ifndef	__bfa_aen_rport_h__
-#define	__bfa_aen_rport_h__
-
-#include  <cs/bfa_log.h>
-#include  <defs/bfa_defs_aen.h>
-
-#define BFA_AEN_RPORT_ONLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_ONLINE)
-#define BFA_AEN_RPORT_OFFLINE \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_OFFLINE)
-#define BFA_AEN_RPORT_DISCONNECT \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_DISCONNECT)
-#define BFA_AEN_RPORT_QOS_PRIO \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_PRIO)
-#define BFA_AEN_RPORT_QOS_FLOWID \
-	BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_FLOWID)
-
-#endif
-
diff --git a/drivers/scsi/bfa/include/bfa.h b/drivers/scsi/bfa/include/bfa.h
deleted file mode 100644
index d52b32f..0000000
--- a/drivers/scsi/bfa/include/bfa.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_H__
-#define __BFA_H__
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_debug.h>
-#include <cs/bfa_q.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-#include <cs/bfa_plog.h>
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_ioc.h>
-#include <defs/bfa_defs_iocfc.h>
-#include <aen/bfa_aen.h>
-#include <bfi/bfi.h>
-
-struct bfa_s;
-#include <bfa_intr_priv.h>
-
-struct bfa_pcidev_s;
-
-/**
- * PCI devices supported by the current BFA
- */
-struct bfa_pciid_s {
-	u16        device_id;
-	u16        vendor_id;
-};
-
-extern char     bfa_version[];
-
-/**
- * BFA Power Mgmt Commands
- */
-enum bfa_pm_cmd {
-	BFA_PM_CTL_D0 = 0,
-	BFA_PM_CTL_D1 = 1,
-	BFA_PM_CTL_D2 = 2,
-	BFA_PM_CTL_D3 = 3,
-};
-
-/**
- * BFA memory resources
- */
-enum bfa_mem_type {
-	BFA_MEM_TYPE_KVA = 1,	/*! Kernel Virtual Memory *(non-dma-able) */
-	BFA_MEM_TYPE_DMA = 2,	/*! DMA-able memory */
-	BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA,
-};
-
-struct bfa_mem_elem_s {
-	enum bfa_mem_type mem_type;	/*  see enum bfa_mem_type 	*/
-	u32        mem_len;	/*  Total Length in Bytes	*/
-	u8       	*kva;		/*  kernel virtual address	*/
-	u64        dma;		/*  dma address if DMA memory	*/
-	u8       	*kva_curp;	/*  kva allocation cursor	*/
-	u64        dma_curp;	/*  dma allocation cursor	*/
-};
-
-struct bfa_meminfo_s {
-	struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX];
-};
-#define bfa_meminfo_kva(_m)	\
-	((_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp)
-#define bfa_meminfo_dma_virt(_m)	\
-	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp)
-#define bfa_meminfo_dma_phys(_m)	\
-	((_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp)
-
-/**
- * Generic Scatter Gather Element used by driver
- */
-struct bfa_sge_s {
-	u32        sg_len;
-	void           *sg_addr;
-};
-
-#define bfa_sge_to_be(__sge) do {                                          \
-	((u32 *)(__sge))[0] = bfa_os_htonl(((u32 *)(__sge))[0]);      \
-	((u32 *)(__sge))[1] = bfa_os_htonl(((u32 *)(__sge))[1]);      \
-	((u32 *)(__sge))[2] = bfa_os_htonl(((u32 *)(__sge))[2]);      \
-} while (0)
-
-
-/*
- * bfa stats interfaces
- */
-#define bfa_stats(_mod, _stats)	((_mod)->stats._stats++)
-
-#define bfa_ioc_get_stats(__bfa, __ioc_stats)	\
-	bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats)
-#define bfa_ioc_clear_stats(__bfa)	\
-	bfa_ioc_clr_stats(&(__bfa)->ioc)
-#define bfa_get_nports(__bfa)   \
-	bfa_ioc_get_nports(&(__bfa)->ioc)
-#define bfa_get_adapter_manufacturer(__bfa, __manufacturer) \
-	bfa_ioc_get_adapter_manufacturer(&(__bfa)->ioc, __manufacturer)
-#define bfa_get_adapter_model(__bfa, __model)   \
-	bfa_ioc_get_adapter_model(&(__bfa)->ioc, __model)
-#define bfa_get_adapter_serial_num(__bfa, __serial_num) \
-	bfa_ioc_get_adapter_serial_num(&(__bfa)->ioc, __serial_num)
-#define bfa_get_adapter_fw_ver(__bfa, __fw_ver) \
-	bfa_ioc_get_adapter_fw_ver(&(__bfa)->ioc, __fw_ver)
-#define bfa_get_adapter_optrom_ver(__bfa, __optrom_ver) \
-	bfa_ioc_get_adapter_optrom_ver(&(__bfa)->ioc, __optrom_ver)
-#define bfa_get_pci_chip_rev(__bfa, __chip_rev) \
-	bfa_ioc_get_pci_chip_rev(&(__bfa)->ioc, __chip_rev)
-#define bfa_get_ioc_state(__bfa)    \
-	bfa_ioc_get_state(&(__bfa)->ioc)
-#define bfa_get_type(__bfa) \
-	bfa_ioc_get_type(&(__bfa)->ioc)
-#define bfa_get_mac(__bfa)  \
-	bfa_ioc_get_mac(&(__bfa)->ioc)
-#define bfa_get_mfg_mac(__bfa)  \
-	bfa_ioc_get_mfg_mac(&(__bfa)->ioc)
-#define bfa_get_fw_clock_res(__bfa)    \
-	((__bfa)->iocfc.cfgrsp->fwcfg.fw_tick_res)
-
-/*
- * bfa API functions
- */
-void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids);
-void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg);
-void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg);
-void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg,
-			struct bfa_meminfo_s *meminfo);
-void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
-			struct bfa_meminfo_s *meminfo,
-			struct bfa_pcidev_s *pcidev);
-void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod);
-void bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod);
-void bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen);
-void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog);
-void bfa_detach(struct bfa_s *bfa);
-void bfa_init(struct bfa_s *bfa);
-void bfa_start(struct bfa_s *bfa);
-void bfa_stop(struct bfa_s *bfa);
-void bfa_attach_fcs(struct bfa_s *bfa);
-void bfa_cb_init(void *bfad, bfa_status_t status);
-void bfa_cb_stop(void *bfad, bfa_status_t status);
-void bfa_cb_updateq(void *bfad, bfa_status_t status);
-
-bfa_boolean_t bfa_intx(struct bfa_s *bfa);
-void bfa_isr_enable(struct bfa_s *bfa);
-void bfa_isr_disable(struct bfa_s *bfa);
-void bfa_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap,
-			u32 *num_vecs, u32 *max_vec_bit);
-#define bfa_msix(__bfa, __vec) ((__bfa)->msix.handler[__vec](__bfa, __vec))
-
-void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q);
-void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q);
-void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q);
-
-typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status);
-void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr);
-bfa_status_t bfa_iocfc_get_stats(struct bfa_s *bfa,
-			struct bfa_iocfc_stats_s *stats,
-			bfa_cb_ioc_t cbfn, void *cbarg);
-bfa_status_t bfa_iocfc_clear_stats(struct bfa_s *bfa,
-			bfa_cb_ioc_t cbfn, void *cbarg);
-void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr);
-
-void bfa_adapter_get_attr(struct bfa_s *bfa,
-			struct bfa_adapter_attr_s *ad_attr);
-u64 bfa_adapter_get_id(struct bfa_s *bfa);
-
-bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa,
-			struct bfa_iocfc_intr_attr_s *attr);
-
-void bfa_iocfc_enable(struct bfa_s *bfa);
-void bfa_iocfc_disable(struct bfa_s *bfa);
-void bfa_ioc_auto_recover(bfa_boolean_t auto_recover);
-void bfa_chip_reset(struct bfa_s *bfa);
-void bfa_cb_ioc_disable(void *bfad);
-void bfa_timer_tick(struct bfa_s *bfa);
-#define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout)	\
-	bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout)
-
-/*
- * BFA debug API functions
- */
-bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen);
-bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen);
-void bfa_debug_fwsave_clear(struct bfa_s *bfa);
-
-#include "bfa_priv.h"
-
-#endif /* __BFA_H__ */
diff --git a/drivers/scsi/bfa/include/bfa_fcpim.h b/drivers/scsi/bfa/include/bfa_fcpim.h
deleted file mode 100644
index 4bc9453..0000000
--- a/drivers/scsi/bfa/include/bfa_fcpim.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_FCPIM_H__
-#define __BFA_FCPIM_H__
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_fcpim.h>
-#include <defs/bfa_defs_fcpim.h>
-
-/*
- * forward declarations
- */
-struct bfa_itnim_s;
-struct bfa_ioim_s;
-struct bfa_tskim_s;
-struct bfad_ioim_s;
-struct bfad_tskim_s;
-
-/*
- * bfa fcpim module API functions
- */
-void		bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov);
-u16	bfa_fcpim_path_tov_get(struct bfa_s *bfa);
-void		bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth);
-u16	bfa_fcpim_qdepth_get(struct bfa_s *bfa);
-bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa,
-			struct bfa_fcpim_stats_s *modstats);
-bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa);
-void bfa_fcpim_set_ioredirect(struct bfa_s *bfa, bfa_boolean_t state);
-void bfa_fcpim_update_ioredirect(struct bfa_s *bfa);
-void bfa_cb_ioredirect_state_change(void *hcb_bfad, bfa_boolean_t ioredirect);
-
-#define bfa_fcpim_ioredirect_enabled(__bfa)                             \
-	(((struct bfa_fcpim_mod_s *)(BFA_FCPIM_MOD(__bfa)))->ioredirect)
-
-#define bfa_fcpim_get_next_reqq(__bfa, __qid)                           \
-{                                                                       \
-	struct bfa_fcpim_mod_s *__fcpim = BFA_FCPIM_MOD(__bfa);         \
-	__fcpim->reqq++;                                                \
-	__fcpim->reqq &= (BFI_IOC_MAX_CQS - 1);                          \
-	*(__qid) = __fcpim->reqq;                                       \
-}
-
-#define bfa_iocfc_map_msg_to_qid(__msg, __qid)                          \
-	*(__qid) = (u8)((__msg) & (BFI_IOC_MAX_CQS - 1));
-
-
-/*
- * bfa itnim API functions
- */
-struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa,
-					struct bfa_rport_s *rport, void *itnim);
-void		bfa_itnim_delete(struct bfa_itnim_s *itnim);
-void		bfa_itnim_online(struct bfa_itnim_s *itnim,
-				 bfa_boolean_t seq_rec);
-void		bfa_itnim_offline(struct bfa_itnim_s *itnim);
-void		bfa_itnim_get_stats(struct bfa_itnim_s *itnim,
-			struct bfa_itnim_hal_stats_s *stats);
-void		bfa_itnim_clear_stats(struct bfa_itnim_s *itnim);
-
-#define bfa_itnim_get_reqq(__ioim) (((struct bfa_ioim_s *)__ioim)->itnim->reqq)
-
-/**
- * 		BFA completion callback for bfa_itnim_online().
- *
- * @param[in]		itnim		FCS or driver itnim instance
- *
- * return None
- */
-void            bfa_cb_itnim_online(void *itnim);
-
-/**
- * 		BFA completion callback for bfa_itnim_offline().
- *
- * @param[in]		itnim		FCS or driver itnim instance
- *
- * return None
- */
-void            bfa_cb_itnim_offline(void *itnim);
-void            bfa_cb_itnim_tov_begin(void *itnim);
-void            bfa_cb_itnim_tov(void *itnim);
-
-/**
- * 		BFA notification to FCS/driver for second level error recovery.
- *
- * Atleast one I/O request has timedout and target is unresponsive to
- * repeated abort requests. Second level error recovery should be initiated
- * by starting implicit logout and recovery procedures.
- *
- * @param[in]		itnim		FCS or driver itnim instance
- *
- * return None
- */
-void            bfa_cb_itnim_sler(void *itnim);
-
-/*
- * bfa ioim API functions
- */
-struct bfa_ioim_s	*bfa_ioim_alloc(struct bfa_s *bfa,
-					struct bfad_ioim_s *dio,
-					struct bfa_itnim_s *itnim,
-					u16 nsgles);
-
-void		bfa_ioim_free(struct bfa_ioim_s *ioim);
-void		bfa_ioim_start(struct bfa_ioim_s *ioim);
-void		bfa_ioim_abort(struct bfa_ioim_s *ioim);
-void 		bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim,
-				      bfa_boolean_t iotov);
-
-
-/**
- * 		I/O completion notification.
- *
- * @param[in]		dio			driver IO structure
- * @param[in]		io_status		IO completion status
- * @param[in]		scsi_status		SCSI status returned by target
- * @param[in]		sns_len			SCSI sense length, 0 if none
- * @param[in]		sns_info		SCSI sense data, if any
- * @param[in]		residue			Residual length
- *
- * @return None
- */
-void            bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio,
-				  enum bfi_ioim_status io_status,
-				  u8 scsi_status, int sns_len,
-				  u8 *sns_info, s32 residue);
-
-/**
- * 		I/O good completion notification.
- *
- * @param[in]		dio			driver IO structure
- *
- * @return None
- */
-void            bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio);
-
-/**
- * 		I/O abort completion notification
- *
- * @param[in]		dio			driver IO that was aborted
- *
- * @return None
- */
-void            bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio);
-void		bfa_cb_ioim_resfree(void *hcb_bfad);
-
-void 			bfa_cb_ioim_resfree(void *hcb_bfad);
-
-/*
- * bfa tskim API functions
- */
-struct bfa_tskim_s	*bfa_tskim_alloc(struct bfa_s *bfa,
-					struct bfad_tskim_s *dtsk);
-void		bfa_tskim_free(struct bfa_tskim_s *tskim);
-void		bfa_tskim_start(struct bfa_tskim_s *tskim,
-				struct bfa_itnim_s *itnim, lun_t lun,
-				enum fcp_tm_cmnd tm, u8 t_secs);
-void		bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk,
-				  enum bfi_tskim_status tsk_status);
-
-#endif /* __BFA_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/bfa_fcptm.h b/drivers/scsi/bfa/include/bfa_fcptm.h
deleted file mode 100644
index 5f5ffe0..0000000
--- a/drivers/scsi/bfa/include/bfa_fcptm.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_FCPTM_H__
-#define __BFA_FCPTM_H__
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfi/bfi_fcptm.h>
-
-/*
- * forward declarations
- */
-struct bfa_tin_s;
-struct bfa_iotm_s;
-struct bfa_tsktm_s;
-
-/*
- * bfa fcptm module API functions
- */
-void bfa_fcptm_path_tov_set(struct bfa_s *bfa, u16 path_tov);
-u16 bfa_fcptm_path_tov_get(struct bfa_s *bfa);
-void bfa_fcptm_qdepth_set(struct bfa_s *bfa, u16 q_depth);
-u16 bfa_fcptm_qdepth_get(struct bfa_s *bfa);
-
-/*
- * bfa tin API functions
- */
-void bfa_tin_get_stats(struct bfa_tin_s *tin, struct bfa_tin_stats_s *stats);
-void bfa_tin_clear_stats(struct bfa_tin_s *tin);
-
-#endif /* __BFA_FCPTM_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfa_svc.h b/drivers/scsi/bfa/include/bfa_svc.h
deleted file mode 100644
index 7840943..0000000
--- a/drivers/scsi/bfa/include/bfa_svc.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_SVC_H__
-#define __BFA_SVC_H__
-
-/*
- * forward declarations
- */
-struct bfa_fcxp_s;
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_rport.h>
-#include <defs/bfa_defs_qos.h>
-#include <defs/bfa_defs_fcport.h>
-#include <cs/bfa_sm.h>
-#include <bfa.h>
-
-/**
- * 		BFA rport information.
- */
-struct bfa_rport_info_s {
-	u16        max_frmsz;	/*  max rcv pdu size               */
-	u32        pid:24,		/*  remote port ID                 */
-			lp_tag:8;	/*  tag                     */
-	u32        local_pid:24,	/*  local port ID		    */
-			cisc:8;		/*  CIRO supported		    */
-	u8         fc_class;	/*  supported FC classes. enum fc_cos */
-	u8         vf_en;		/*  virtual fabric enable          */
-	u16        vf_id;		/*  virtual fabric ID              */
-	enum bfa_pport_speed speed;	/*  Rport's current speed	    */
-};
-
-/**
- * BFA rport data structure
- */
-struct bfa_rport_s {
-	struct list_head        qe;	  /*  queue element */
-	bfa_sm_t	      sm; 	  /*  state machine */
-	struct bfa_s          *bfa;	  /*  backpointer to BFA */
-	void                  *rport_drv; /*  fcs/driver rport object */
-	u16              fw_handle; /*  firmware rport handle */
-	u16              rport_tag; /*  BFA rport tag */
-	struct bfa_rport_info_s rport_info; /*  rport info from fcs/driver */
-	struct bfa_reqq_wait_s reqq_wait; /*  to wait for room in reqq */
-	struct bfa_cb_qe_s    hcb_qe;	 /*  BFA callback qelem */
-	struct bfa_rport_hal_stats_s stats; /*  BFA rport statistics  */
-	struct bfa_rport_qos_attr_s  qos_attr;
-	union a {
-		bfa_status_t    status;	 /*  f/w status */
-		void            *fw_msg; /*  QoS scn event */
-	} event_arg;
-};
-#define BFA_RPORT_FC_COS(_rport)	((_rport)->rport_info.fc_class)
-
-/**
- * Send completion callback.
- */
-typedef void (*bfa_cb_fcxp_send_t) (void *bfad_fcxp, struct bfa_fcxp_s *fcxp,
-			void *cbarg, enum bfa_status req_status,
-			u32 rsp_len, u32 resid_len,
-			struct fchs_s *rsp_fchs);
-
-/**
- * BFA fcxp allocation (asynchronous)
- */
-typedef void (*bfa_fcxp_alloc_cbfn_t) (void *cbarg, struct bfa_fcxp_s *fcxp);
-
-struct bfa_fcxp_wqe_s {
-	struct list_head         qe;
-	bfa_fcxp_alloc_cbfn_t  alloc_cbfn;
-	void           *alloc_cbarg;
-};
-
-typedef u64 (*bfa_fcxp_get_sgaddr_t) (void *bfad_fcxp, int sgeid);
-typedef u32 (*bfa_fcxp_get_sglen_t) (void *bfad_fcxp, int sgeid);
-
-#define BFA_UF_BUFSZ	(2 * 1024 + 256)
-
-/**
- * @todo private
- */
-struct bfa_uf_buf_s {
-	u8         d[BFA_UF_BUFSZ];
-};
-
-
-struct bfa_uf_s {
-	struct list_head	qe;		/*  queue element	  */
-	struct bfa_s	*bfa;		/*  bfa instance	  */
-	u16        uf_tag;		/*  identifying tag fw msgs     */
-	u16        vf_id;
-	u16        src_rport_handle;
-	u16        rsvd;
-	u8        	*data_ptr;
-	u16        data_len;	/*  actual receive length	  */
-	u16        pb_len;		/*  posted buffer length	  */
-	void           	*buf_kva;	/*  buffer virtual address	  */
-	u64        buf_pa;		/*  buffer physical address	  */
-	struct bfa_cb_qe_s    hcb_qe;	/*  comp: BFA comp qelem	  */
-	struct bfa_sge_s   	sges[BFI_SGE_INLINE_MAX];
-};
-
-typedef void (*bfa_cb_pport_t) (void *cbarg, enum bfa_status status);
-
-/**
- * bfa lport login/logout service interface
- */
-struct bfa_lps_s {
-	struct list_head	qe;		/*  queue element */
-	struct bfa_s	*bfa;		/*  parent bfa instance	*/
-	bfa_sm_t	sm;		/*  finite state machine	*/
-	u8		lp_tag;		/*  lport tag			*/
-	u8		reqq;		/*  lport request queue	*/
-	u8		alpa;		/*  ALPA for loop topologies	*/
-	u32	lp_pid;		/*  lport port ID		*/
-	bfa_boolean_t	fdisc;		/*  send FDISC instead of FLOGI  */
-	bfa_boolean_t	auth_en;	/*  enable authentication	*/
-	bfa_boolean_t	auth_req;	/*  authentication required	*/
-	bfa_boolean_t	npiv_en;	/*  NPIV is allowed by peer	*/
-	bfa_boolean_t	fport;		/*  attached peer is F_PORT	*/
-	bfa_boolean_t	brcd_switch;/*  attached peer is brcd switch	*/
-	bfa_status_t	status;		/*  login status		*/
-	u16	pdusz;		/*  max receive PDU size 	*/
-	u16	pr_bbcred;	/*  BB_CREDIT from peer 	*/
-	u8		lsrjt_rsn;	/*  LSRJT reason		*/
-	u8		lsrjt_expl;	/*  LSRJT explanation		*/
-	wwn_t		pwwn;		/*  port wwn of lport		*/
-	wwn_t		nwwn;		/*  node wwn of lport		*/
-	wwn_t		pr_pwwn;	/*  port wwn of lport peer	*/
-	wwn_t		pr_nwwn;	/*  node wwn of lport peer	*/
-	mac_t		lp_mac;		/*  fpma/spma MAC for lport	*/
-	mac_t		fcf_mac;	/*  FCF MAC of lport		*/
-	struct bfa_reqq_wait_s	wqe;	/*  request wait queue element	*/
-	void		*uarg;		/*  user callback arg		*/
-	struct bfa_cb_qe_s hcb_qe;	/*  comp: callback qelem	*/
-	struct bfi_lps_login_rsp_s *loginrsp;
-	bfa_eproto_status_t	ext_status;
-};
-
-#define BFA_FCPORT(_bfa)        (&((_bfa)->modules.port))
-
-/*
- * bfa pport API functions
- */
-bfa_status_t bfa_fcport_enable(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_disable(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_speed(struct bfa_s *bfa,
-			enum bfa_pport_speed speed);
-enum bfa_pport_speed bfa_fcport_get_speed(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_topology(struct bfa_s *bfa,
-			enum bfa_pport_topology topo);
-enum bfa_pport_topology bfa_fcport_get_topology(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa);
-bfa_boolean_t bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa);
-u8 bfa_fcport_get_myalpa(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_clr_hardalpa(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxsize);
-u16 bfa_fcport_get_maxfrsize(struct bfa_s *bfa);
-u32 bfa_fcport_mypid(struct bfa_s *bfa);
-u8 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_trunk_enable(struct bfa_s *bfa, u8 bitmap);
-bfa_status_t bfa_fcport_trunk_disable(struct bfa_s *bfa);
-bfa_boolean_t bfa_fcport_trunk_query(struct bfa_s *bfa, u32 *bitmap);
-void bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr);
-wwn_t bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node);
-void bfa_fcport_event_register(struct bfa_s *bfa,
-			void (*event_cbfn) (void *cbarg,
-			bfa_pport_event_t event), void *event_cbarg);
-bfa_boolean_t bfa_fcport_is_disabled(struct bfa_s *bfa);
-void bfa_fcport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off);
-void bfa_fcport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off);
-bfa_status_t bfa_fcport_cfg_ratelim_speed(struct bfa_s *bfa,
-			enum bfa_pport_speed speed);
-enum bfa_pport_speed bfa_fcport_get_ratelim_speed(struct bfa_s *bfa);
-
-void bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit);
-void bfa_fcport_busy(struct bfa_s *bfa, bfa_boolean_t status);
-void bfa_fcport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon,
-			bfa_boolean_t link_e2e_beacon);
-void bfa_cb_pport_event(void *cbarg, bfa_pport_event_t event);
-void bfa_fcport_qos_get_attr(struct bfa_s *bfa,
-			struct bfa_qos_attr_s *qos_attr);
-void bfa_fcport_qos_get_vc_attr(struct bfa_s *bfa,
-			struct bfa_qos_vc_attr_s *qos_vc_attr);
-bfa_status_t bfa_fcport_get_qos_stats(struct bfa_s *bfa,
-			union bfa_fcport_stats_u *stats,
-			bfa_cb_pport_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
-			void *cbarg);
-bfa_status_t bfa_fcport_get_fcoe_stats(struct bfa_s *bfa,
-			union bfa_fcport_stats_u *stats,
-			bfa_cb_pport_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_fcoe_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
-			void *cbarg);
-
-bfa_boolean_t     bfa_fcport_is_ratelim(struct bfa_s *bfa);
-bfa_boolean_t	bfa_fcport_is_linkup(struct bfa_s *bfa);
-bfa_status_t bfa_fcport_get_stats(struct bfa_s *bfa,
-		union bfa_fcport_stats_u *stats,
-		bfa_cb_pport_t cbfn, void *cbarg);
-bfa_status_t bfa_fcport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn,
-		void *cbarg);
-bfa_boolean_t bfa_fcport_is_qos_enabled(struct bfa_s *bfa);
-
-/*
- * bfa rport API functions
- */
-struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv);
-void bfa_rport_delete(struct bfa_rport_s *rport);
-void bfa_rport_online(struct bfa_rport_s *rport,
-			struct bfa_rport_info_s *rport_info);
-void bfa_rport_offline(struct bfa_rport_s *rport);
-void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed);
-void bfa_rport_get_stats(struct bfa_rport_s *rport,
-			struct bfa_rport_hal_stats_s *stats);
-void bfa_rport_clear_stats(struct bfa_rport_s *rport);
-void bfa_cb_rport_online(void *rport);
-void bfa_cb_rport_offline(void *rport);
-void bfa_cb_rport_qos_scn_flowid(void *rport,
-			struct bfa_rport_qos_attr_s old_qos_attr,
-			struct bfa_rport_qos_attr_s new_qos_attr);
-void bfa_cb_rport_qos_scn_prio(void *rport,
-			struct bfa_rport_qos_attr_s old_qos_attr,
-			struct bfa_rport_qos_attr_s new_qos_attr);
-void bfa_rport_get_qos_attr(struct bfa_rport_s *rport,
-			struct bfa_rport_qos_attr_s *qos_attr);
-
-/*
- * bfa fcxp API functions
- */
-struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa,
-			int nreq_sgles, int nrsp_sgles,
-			bfa_fcxp_get_sgaddr_t get_req_sga,
-			bfa_fcxp_get_sglen_t get_req_sglen,
-			bfa_fcxp_get_sgaddr_t get_rsp_sga,
-			bfa_fcxp_get_sglen_t get_rsp_sglen);
-void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
-			bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *cbarg);
-void bfa_fcxp_walloc_cancel(struct bfa_s *bfa,
-			struct bfa_fcxp_wqe_s *wqe);
-void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp);
-
-void *bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp);
-void *bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp);
-
-void bfa_fcxp_free(struct bfa_fcxp_s *fcxp);
-
-void bfa_fcxp_send(struct bfa_fcxp_s *fcxp,
-			struct bfa_rport_s *rport, u16 vf_id, u8 lp_tag,
-			bfa_boolean_t cts, enum fc_cos cos,
-			u32 reqlen, struct fchs_s *fchs,
-			bfa_cb_fcxp_send_t cbfn,
-			void *cbarg,
-			u32 rsp_maxlen, u8 rsp_timeout);
-bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp);
-u32        bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp);
-u32	bfa_fcxp_get_maxrsp(struct bfa_s *bfa);
-
-static inline void *
-bfa_uf_get_frmbuf(struct bfa_uf_s *uf)
-{
-	return uf->data_ptr;
-}
-
-static inline   u16
-bfa_uf_get_frmlen(struct bfa_uf_s *uf)
-{
-	return uf->data_len;
-}
-
-/**
- *      Callback prototype for unsolicited frame receive handler.
- *
- * @param[in]           cbarg           callback arg for receive handler
- * @param[in]           uf              unsolicited frame descriptor
- *
- * @return None
- */
-typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf);
-
-/*
- * bfa uf API functions
- */
-void bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv,
-			void *cbarg);
-void bfa_uf_free(struct bfa_uf_s *uf);
-
-/**
- * bfa lport service api
- */
-
-u32	bfa_lps_get_max_vport(struct bfa_s *bfa);
-struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa);
-void bfa_lps_delete(struct bfa_lps_s *lps);
-void bfa_lps_discard(struct bfa_lps_s *lps);
-void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
-		   wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en);
-void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
-		   wwn_t nwwn);
-void bfa_lps_flogo(struct bfa_lps_s *lps);
-void bfa_lps_fdisclogo(struct bfa_lps_s *lps);
-u8 bfa_lps_get_tag(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps);
-bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps);
-bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps);
-u32 bfa_lps_get_pid(struct bfa_lps_s *lps);
-u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid);
-u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps);
-wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps);
-u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps);
-mac_t bfa_lps_get_lp_mac(struct bfa_lps_s *lps);
-void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status);
-void bfa_cb_lps_flogo_comp(void *bfad, void *uarg);
-void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status);
-void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg);
-void bfa_cb_lps_cvl_event(void *bfad, void *uarg);
-
-#endif /* __BFA_SVC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfa_timer.h b/drivers/scsi/bfa/include/bfa_timer.h
deleted file mode 100644
index f710874..0000000
--- a/drivers/scsi/bfa/include/bfa_timer.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_TIMER_H__
-#define __BFA_TIMER_H__
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_q.h>
-
-struct bfa_s;
-
-typedef void (*bfa_timer_cbfn_t)(void *);
-
-/**
- * BFA timer data structure
- */
-struct bfa_timer_s {
-	struct list_head	qe;
-	bfa_timer_cbfn_t timercb;
-	void            *arg;
-	int             timeout;	/**< in millisecs. */
-};
-
-/**
- * Timer module structure
- */
-struct bfa_timer_mod_s {
-	struct list_head timer_q;
-};
-
-#define BFA_TIMER_FREQ 200 /**< specified in millisecs */
-
-void bfa_timer_beat(struct bfa_timer_mod_s *mod);
-void bfa_timer_init(struct bfa_timer_mod_s *mod);
-void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
-			bfa_timer_cbfn_t timercb, void *arg,
-			unsigned int timeout);
-void bfa_timer_stop(struct bfa_timer_s *timer);
-
-#endif /* __BFA_TIMER_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi.h b/drivers/scsi/bfa/include/bfi/bfi.h
deleted file mode 100644
index a550e80..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_H__
-#define __BFI_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_status.h>
-
-#pragma pack(1)
-
-/**
- * Msg header common to all msgs
- */
-struct bfi_mhdr_s {
-	u8         msg_class;	/*  @ref bfi_mclass_t	    */
-	u8         msg_id;		/*  msg opcode with in the class   */
-	union {
-		struct {
-			u8         rsvd;
-			u8         lpu_id;	/*  msg destination	    */
-		} h2i;
-		u16        i2htok;	/*  token in msgs to host	    */
-	} mtag;
-};
-
-#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do {		\
-	(_mh).msg_class 		= (_mc);      \
-	(_mh).msg_id			= (_op);      \
-	(_mh).mtag.h2i.lpu_id	= (_lpuid);      \
-} while (0)
-
-#define bfi_i2h_set(_mh, _mc, _op, _i2htok) do {		\
-	(_mh).msg_class 		= (_mc);      \
-	(_mh).msg_id			= (_op);      \
-	(_mh).mtag.i2htok		= (_i2htok);      \
-} while (0)
-
-/*
- * Message opcodes: 0-127 to firmware, 128-255 to host
- */
-#define BFI_I2H_OPCODE_BASE	128
-#define BFA_I2HM(_x) 			((_x) + BFI_I2H_OPCODE_BASE)
-
-/**
- ****************************************************************************
- *
- * Scatter Gather Element and Page definition
- *
- ****************************************************************************
- */
-
-#define BFI_SGE_INLINE	1
-#define BFI_SGE_INLINE_MAX	(BFI_SGE_INLINE + 1)
-
-/**
- * SG Flags
- */
-enum {
-	BFI_SGE_DATA	= 0,	/*  data address, not last	     */
-	BFI_SGE_DATA_CPL	= 1,	/*  data addr, last in current page */
-	BFI_SGE_DATA_LAST	= 3,	/*  data address, last		     */
-	BFI_SGE_LINK	= 2,	/*  link address		     */
-	BFI_SGE_PGDLEN	= 2,	/*  cumulative data length for page */
-};
-
-/**
- * DMA addresses
- */
-union bfi_addr_u {
-	struct {
-		u32        addr_lo;
-		u32        addr_hi;
-	} a32;
-};
-
-/**
- * Scatter Gather Element
- */
-struct bfi_sge_s {
-#ifdef __BIGENDIAN
-	u32        flags:2,
-			rsvd:2,
-			sg_len:28;
-#else
-	u32        sg_len:28,
-			rsvd:2,
-			flags:2;
-#endif
-	union bfi_addr_u sga;
-};
-
-/**
- * Scatter Gather Page
- */
-#define BFI_SGPG_DATA_SGES		7
-#define BFI_SGPG_SGES_MAX		(BFI_SGPG_DATA_SGES + 1)
-#define BFI_SGPG_RSVD_WD_LEN	8
-struct bfi_sgpg_s {
-	struct bfi_sge_s sges[BFI_SGPG_SGES_MAX];
-	u32	rsvd[BFI_SGPG_RSVD_WD_LEN];
-};
-
-/*
- * Large Message structure - 128 Bytes size Msgs
- */
-#define BFI_LMSG_SZ		128
-#define BFI_LMSG_PL_WSZ	\
-			((BFI_LMSG_SZ - sizeof(struct bfi_mhdr_s)) / 4)
-
-struct bfi_msg_s {
-	struct bfi_mhdr_s mhdr;
-	u32	pl[BFI_LMSG_PL_WSZ];
-};
-
-/**
- * Mailbox message structure
- */
-#define BFI_MBMSG_SZ		7
-struct bfi_mbmsg_s {
-	struct bfi_mhdr_s	mh;
-	u32		pl[BFI_MBMSG_SZ];
-};
-
-/**
- * Message Classes
- */
-enum bfi_mclass {
-	BFI_MC_IOC		= 1,	/*  IO Controller (IOC)	    */
-	BFI_MC_DIAG		= 2,	/*  Diagnostic Msgs		    */
-	BFI_MC_FLASH		= 3,	/*  Flash message class	    */
-	BFI_MC_CEE		= 4,	/*  CEE                     */
-	BFI_MC_FCPORT		= 5,	/*  FC port		   	    */
-	BFI_MC_IOCFC		= 6,	/*  FC - IO Controller (IOC)	    */
-	BFI_MC_LL		= 7,	/*  Link Layer		 	    */
-	BFI_MC_UF		= 8,	/*  Unsolicited frame receive	    */
-	BFI_MC_FCXP		= 9,	/*  FC Transport		    */
-	BFI_MC_LPS		= 10,	/*  lport fc login services	    */
-	BFI_MC_RPORT		= 11,	/*  Remote port		    */
-	BFI_MC_ITNIM		= 12,	/*  I-T nexus (Initiator mode)	    */
-	BFI_MC_IOIM_READ	= 13,	/*  read IO (Initiator mode)	    */
-	BFI_MC_IOIM_WRITE	= 14,	/*  write IO (Initiator mode)	    */
-	BFI_MC_IOIM_IO		= 15,	/*  IO (Initiator mode)	    */
-	BFI_MC_IOIM		= 16,	/*  IO (Initiator mode)	    */
-	BFI_MC_IOIM_IOCOM	= 17,	/*  good IO completion		    */
-	BFI_MC_TSKIM		= 18,	/*  Initiator Task management	    */
-	BFI_MC_SBOOT		= 19,	/*  SAN boot services		    */
-	BFI_MC_IPFC		= 20,	/*  IP over FC Msgs		    */
-	BFI_MC_PORT		= 21,	/*  Physical port		    */
-	BFI_MC_MAX		= 32
-};
-
-#define BFI_IOC_MAX_CQS		4
-#define BFI_IOC_MAX_CQS_ASIC	8
-#define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */
-
-#pragma pack()
-
-#endif /* __BFI_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_boot.h b/drivers/scsi/bfa/include/bfi/bfi_boot.h
deleted file mode 100644
index 5955afe..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_boot.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/*
- * bfi_boot.h
- */
-
-#ifndef __BFI_BOOT_H__
-#define __BFI_BOOT_H__
-
-#define BFI_BOOT_TYPE_OFF		8
-#define BFI_BOOT_PARAM_OFF		12
-
-#define BFI_BOOT_TYPE_NORMAL 		0	/* param is device id */
-#define	BFI_BOOT_TYPE_FLASH		1
-#define	BFI_BOOT_TYPE_MEMTEST		2
-
-#define BFI_BOOT_MEMTEST_RES_ADDR   0x900
-#define BFI_BOOT_MEMTEST_RES_SIG    0xA0A1A2A3
-
-#endif
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cee.h b/drivers/scsi/bfa/include/bfi/bfi_cee.h
deleted file mode 100644
index 09705965..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_cee.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-/**
- *  Copyright (c) 2006-2009 Brocade Communications Systems, Inc.
- *  All rights reserved.
- *
- *  bfi_dcbx.h BFI Interface (Mailbox commands and related structures)
- * between host driver and DCBX/LLDP firmware module.
- *
-**/
-
-#ifndef __BFI_CEE_H__
-#define __BFI_CEE_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-
-enum bfi_cee_h2i_msgs_e {
-	BFI_CEE_H2I_GET_CFG_REQ = 1,
-	BFI_CEE_H2I_RESET_STATS = 2,
-	BFI_CEE_H2I_GET_STATS_REQ = 3,
-};
-
-
-enum bfi_cee_i2h_msgs_e {
-	BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1),
-	BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2),
-	BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3),
-};
-
-
-/* Data structures */
-
-/*
- * BFI_CEE_H2I_RESET_STATS
- */
-struct bfi_lldp_reset_stats_s {
-	struct bfi_mhdr_s  mh;
-};
-
-/*
- * BFI_CEE_H2I_RESET_STATS
- */
-struct bfi_cee_reset_stats_s {
-	struct bfi_mhdr_s  mh;
-};
-
-/*
- * BFI_CEE_H2I_GET_CFG_REQ
- */
-struct bfi_cee_get_req_s {
-	struct bfi_mhdr_s  mh;
-	union bfi_addr_u   dma_addr;
-};
-
-
-/*
- * BFI_CEE_I2H_GET_CFG_RSP
- */
-struct bfi_cee_get_rsp_s {
-	struct bfi_mhdr_s  mh;
-	u8            cmd_status;
-	u8            rsvd[3];
-};
-
-/*
- * BFI_CEE_H2I_GET_STATS_REQ
- */
-struct bfi_cee_stats_req_s {
-	struct bfi_mhdr_s  mh;
-	union bfi_addr_u   dma_addr;
-};
-
-
-/*
- * BFI_CEE_I2H_GET_STATS_RSP
- */
-struct bfi_cee_stats_rsp_s {
-	struct bfi_mhdr_s  mh;
-	u8 		   cmd_status;
-	u8 		   rsvd[3];
-};
-
-
-
-union bfi_cee_h2i_msg_u {
-	struct bfi_mhdr_s           mh;
-	struct bfi_cee_get_req_s   get_req;
-	struct bfi_cee_stats_req_s stats_req;
-};
-
-
-union bfi_cee_i2h_msg_u {
-	struct bfi_mhdr_s         mh;
-	struct bfi_cee_get_rsp_s  get_rsp;
-	struct bfi_cee_stats_rsp_s stats_rsp;
-};
-
-#pragma pack()
-
-
-#endif /* __BFI_CEE_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h b/drivers/scsi/bfa/include/bfi/bfi_ctreg.h
deleted file mode 100644
index c0ef5a9..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/*
- * bfi_ctreg.h catapult host block register definitions
- *
- * !!! Do not edit. Auto generated. !!!
- */
-
-#ifndef __BFI_CTREG_H__
-#define __BFI_CTREG_H__
-
-
-#define HOSTFN0_LPU_MBOX0_0              0x00019200
-#define HOSTFN1_LPU_MBOX0_8              0x00019260
-#define LPU_HOSTFN0_MBOX0_0              0x00019280
-#define LPU_HOSTFN1_MBOX0_8              0x000192e0
-#define HOSTFN2_LPU_MBOX0_0              0x00019400
-#define HOSTFN3_LPU_MBOX0_8              0x00019460
-#define LPU_HOSTFN2_MBOX0_0              0x00019480
-#define LPU_HOSTFN3_MBOX0_8              0x000194e0
-#define HOSTFN0_INT_STATUS               0x00014000
-#define __HOSTFN0_HALT_OCCURRED          0x01000000
-#define __HOSTFN0_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN0_INT_STATUS_LVL_SH      20
-#define __HOSTFN0_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN0_INT_STATUS_LVL_SH)
-#define __HOSTFN0_INT_STATUS_P_MK        0x000f0000
-#define __HOSTFN0_INT_STATUS_P_SH        16
-#define __HOSTFN0_INT_STATUS_P(_v)       ((_v) << __HOSTFN0_INT_STATUS_P_SH)
-#define __HOSTFN0_INT_STATUS_F           0x0000ffff
-#define HOSTFN0_INT_MSK                  0x00014004
-#define HOST_PAGE_NUM_FN0                0x00014008
-#define __HOST_PAGE_NUM_FN               0x000001ff
-#define HOST_MSIX_ERR_INDEX_FN0          0x0001400c
-#define __MSIX_ERR_INDEX_FN              0x000001ff
-#define HOSTFN1_INT_STATUS               0x00014100
-#define __HOSTFN1_HALT_OCCURRED          0x01000000
-#define __HOSTFN1_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN1_INT_STATUS_LVL_SH      20
-#define __HOSTFN1_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN1_INT_STATUS_LVL_SH)
-#define __HOSTFN1_INT_STATUS_P_MK        0x000f0000
-#define __HOSTFN1_INT_STATUS_P_SH        16
-#define __HOSTFN1_INT_STATUS_P(_v)       ((_v) << __HOSTFN1_INT_STATUS_P_SH)
-#define __HOSTFN1_INT_STATUS_F           0x0000ffff
-#define HOSTFN1_INT_MSK                  0x00014104
-#define HOST_PAGE_NUM_FN1                0x00014108
-#define HOST_MSIX_ERR_INDEX_FN1          0x0001410c
-#define APP_PLL_425_CTL_REG              0x00014204
-#define __P_425_PLL_LOCK                 0x80000000
-#define __APP_PLL_425_SRAM_USE_100MHZ    0x00100000
-#define __APP_PLL_425_RESET_TIMER_MK     0x000e0000
-#define __APP_PLL_425_RESET_TIMER_SH     17
-#define __APP_PLL_425_RESET_TIMER(_v)    ((_v) << __APP_PLL_425_RESET_TIMER_SH)
-#define __APP_PLL_425_LOGIC_SOFT_RESET   0x00010000
-#define __APP_PLL_425_CNTLMT0_1_MK       0x0000c000
-#define __APP_PLL_425_CNTLMT0_1_SH       14
-#define __APP_PLL_425_CNTLMT0_1(_v)      ((_v) << __APP_PLL_425_CNTLMT0_1_SH)
-#define __APP_PLL_425_JITLMT0_1_MK       0x00003000
-#define __APP_PLL_425_JITLMT0_1_SH       12
-#define __APP_PLL_425_JITLMT0_1(_v)      ((_v) << __APP_PLL_425_JITLMT0_1_SH)
-#define __APP_PLL_425_HREF               0x00000800
-#define __APP_PLL_425_HDIV               0x00000400
-#define __APP_PLL_425_P0_1_MK            0x00000300
-#define __APP_PLL_425_P0_1_SH            8
-#define __APP_PLL_425_P0_1(_v)           ((_v) << __APP_PLL_425_P0_1_SH)
-#define __APP_PLL_425_Z0_2_MK            0x000000e0
-#define __APP_PLL_425_Z0_2_SH            5
-#define __APP_PLL_425_Z0_2(_v)           ((_v) << __APP_PLL_425_Z0_2_SH)
-#define __APP_PLL_425_RSEL200500         0x00000010
-#define __APP_PLL_425_ENARST             0x00000008
-#define __APP_PLL_425_BYPASS             0x00000004
-#define __APP_PLL_425_LRESETN            0x00000002
-#define __APP_PLL_425_ENABLE             0x00000001
-#define APP_PLL_312_CTL_REG              0x00014208
-#define __P_312_PLL_LOCK                 0x80000000
-#define __ENABLE_MAC_AHB_1               0x00800000
-#define __ENABLE_MAC_AHB_0               0x00400000
-#define __ENABLE_MAC_1                   0x00200000
-#define __ENABLE_MAC_0                   0x00100000
-#define __APP_PLL_312_RESET_TIMER_MK     0x000e0000
-#define __APP_PLL_312_RESET_TIMER_SH     17
-#define __APP_PLL_312_RESET_TIMER(_v)    ((_v) << __APP_PLL_312_RESET_TIMER_SH)
-#define __APP_PLL_312_LOGIC_SOFT_RESET   0x00010000
-#define __APP_PLL_312_CNTLMT0_1_MK       0x0000c000
-#define __APP_PLL_312_CNTLMT0_1_SH       14
-#define __APP_PLL_312_CNTLMT0_1(_v)      ((_v) << __APP_PLL_312_CNTLMT0_1_SH)
-#define __APP_PLL_312_JITLMT0_1_MK       0x00003000
-#define __APP_PLL_312_JITLMT0_1_SH       12
-#define __APP_PLL_312_JITLMT0_1(_v)      ((_v) << __APP_PLL_312_JITLMT0_1_SH)
-#define __APP_PLL_312_HREF               0x00000800
-#define __APP_PLL_312_HDIV               0x00000400
-#define __APP_PLL_312_P0_1_MK            0x00000300
-#define __APP_PLL_312_P0_1_SH            8
-#define __APP_PLL_312_P0_1(_v)           ((_v) << __APP_PLL_312_P0_1_SH)
-#define __APP_PLL_312_Z0_2_MK            0x000000e0
-#define __APP_PLL_312_Z0_2_SH            5
-#define __APP_PLL_312_Z0_2(_v)           ((_v) << __APP_PLL_312_Z0_2_SH)
-#define __APP_PLL_312_RSEL200500         0x00000010
-#define __APP_PLL_312_ENARST             0x00000008
-#define __APP_PLL_312_BYPASS             0x00000004
-#define __APP_PLL_312_LRESETN            0x00000002
-#define __APP_PLL_312_ENABLE             0x00000001
-#define MBIST_CTL_REG                    0x00014220
-#define __EDRAM_BISTR_START              0x00000004
-#define __MBIST_RESET                    0x00000002
-#define __MBIST_START                    0x00000001
-#define MBIST_STAT_REG                   0x00014224
-#define __EDRAM_BISTR_STATUS             0x00000008
-#define __EDRAM_BISTR_DONE               0x00000004
-#define __MEM_BIT_STATUS                 0x00000002
-#define __MBIST_DONE                     0x00000001
-#define HOST_SEM0_REG                    0x00014230
-#define __HOST_SEMAPHORE                 0x00000001
-#define HOST_SEM1_REG                    0x00014234
-#define HOST_SEM2_REG                    0x00014238
-#define HOST_SEM3_REG                    0x0001423c
-#define HOST_SEM0_INFO_REG               0x00014240
-#define HOST_SEM1_INFO_REG               0x00014244
-#define HOST_SEM2_INFO_REG               0x00014248
-#define HOST_SEM3_INFO_REG               0x0001424c
-#define ETH_MAC_SER_REG                  0x00014288
-#define __APP_EMS_CKBUFAMPIN             0x00000020
-#define __APP_EMS_REFCLKSEL              0x00000010
-#define __APP_EMS_CMLCKSEL               0x00000008
-#define __APP_EMS_REFCKBUFEN2            0x00000004
-#define __APP_EMS_REFCKBUFEN1            0x00000002
-#define __APP_EMS_CHANNEL_SEL            0x00000001
-#define HOSTFN2_INT_STATUS               0x00014300
-#define __HOSTFN2_HALT_OCCURRED          0x01000000
-#define __HOSTFN2_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN2_INT_STATUS_LVL_SH      20
-#define __HOSTFN2_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN2_INT_STATUS_LVL_SH)
-#define __HOSTFN2_INT_STATUS_P_MK        0x000f0000
-#define __HOSTFN2_INT_STATUS_P_SH        16
-#define __HOSTFN2_INT_STATUS_P(_v)       ((_v) << __HOSTFN2_INT_STATUS_P_SH)
-#define __HOSTFN2_INT_STATUS_F           0x0000ffff
-#define HOSTFN2_INT_MSK                  0x00014304
-#define HOST_PAGE_NUM_FN2                0x00014308
-#define HOST_MSIX_ERR_INDEX_FN2          0x0001430c
-#define HOSTFN3_INT_STATUS               0x00014400
-#define __HALT_OCCURRED                  0x01000000
-#define __HOSTFN3_INT_STATUS_LVL_MK      0x00f00000
-#define __HOSTFN3_INT_STATUS_LVL_SH      20
-#define __HOSTFN3_INT_STATUS_LVL(_v)     ((_v) << __HOSTFN3_INT_STATUS_LVL_SH)
-#define __HOSTFN3_INT_STATUS_P_MK        0x000f0000
-#define __HOSTFN3_INT_STATUS_P_SH        16
-#define __HOSTFN3_INT_STATUS_P(_v)       ((_v) << __HOSTFN3_INT_STATUS_P_SH)
-#define __HOSTFN3_INT_STATUS_F           0x0000ffff
-#define HOSTFN3_INT_MSK                  0x00014404
-#define HOST_PAGE_NUM_FN3                0x00014408
-#define HOST_MSIX_ERR_INDEX_FN3          0x0001440c
-#define FNC_ID_REG                       0x00014600
-#define __FUNCTION_NUMBER                0x00000007
-#define FNC_PERS_REG                     0x00014604
-#define __F3_FUNCTION_ACTIVE             0x80000000
-#define __F3_FUNCTION_MODE               0x40000000
-#define __F3_PORT_MAP_MK                 0x30000000
-#define __F3_PORT_MAP_SH                 28
-#define __F3_PORT_MAP(_v)                ((_v) << __F3_PORT_MAP_SH)
-#define __F3_VM_MODE                     0x08000000
-#define __F3_INTX_STATUS_MK              0x07000000
-#define __F3_INTX_STATUS_SH              24
-#define __F3_INTX_STATUS(_v)             ((_v) << __F3_INTX_STATUS_SH)
-#define __F2_FUNCTION_ACTIVE             0x00800000
-#define __F2_FUNCTION_MODE               0x00400000
-#define __F2_PORT_MAP_MK                 0x00300000
-#define __F2_PORT_MAP_SH                 20
-#define __F2_PORT_MAP(_v)                ((_v) << __F2_PORT_MAP_SH)
-#define __F2_VM_MODE                     0x00080000
-#define __F2_INTX_STATUS_MK              0x00070000
-#define __F2_INTX_STATUS_SH              16
-#define __F2_INTX_STATUS(_v)             ((_v) << __F2_INTX_STATUS_SH)
-#define __F1_FUNCTION_ACTIVE             0x00008000
-#define __F1_FUNCTION_MODE               0x00004000
-#define __F1_PORT_MAP_MK                 0x00003000
-#define __F1_PORT_MAP_SH                 12
-#define __F1_PORT_MAP(_v)                ((_v) << __F1_PORT_MAP_SH)
-#define __F1_VM_MODE                     0x00000800
-#define __F1_INTX_STATUS_MK              0x00000700
-#define __F1_INTX_STATUS_SH              8
-#define __F1_INTX_STATUS(_v)             ((_v) << __F1_INTX_STATUS_SH)
-#define __F0_FUNCTION_ACTIVE             0x00000080
-#define __F0_FUNCTION_MODE               0x00000040
-#define __F0_PORT_MAP_MK                 0x00000030
-#define __F0_PORT_MAP_SH                 4
-#define __F0_PORT_MAP(_v)                ((_v) << __F0_PORT_MAP_SH)
-#define __F0_VM_MODE                     0x00000008
-#define __F0_INTX_STATUS                 0x00000007
-enum {
-    __F0_INTX_STATUS_MSIX            = 0x0,
-    __F0_INTX_STATUS_INTA            = 0x1,
-    __F0_INTX_STATUS_INTB            = 0x2,
-    __F0_INTX_STATUS_INTC            = 0x3,
-    __F0_INTX_STATUS_INTD            = 0x4,
-};
-#define OP_MODE                          0x0001460c
-#define __APP_ETH_CLK_LOWSPEED           0x00000004
-#define __GLOBAL_CORECLK_HALFSPEED       0x00000002
-#define __GLOBAL_FCOE_MODE               0x00000001
-#define HOST_SEM4_REG                    0x00014610
-#define HOST_SEM5_REG                    0x00014614
-#define HOST_SEM6_REG                    0x00014618
-#define HOST_SEM7_REG                    0x0001461c
-#define HOST_SEM4_INFO_REG               0x00014620
-#define HOST_SEM5_INFO_REG               0x00014624
-#define HOST_SEM6_INFO_REG               0x00014628
-#define HOST_SEM7_INFO_REG               0x0001462c
-#define HOSTFN0_LPU0_MBOX0_CMD_STAT      0x00019000
-#define __HOSTFN0_LPU0_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN0_LPU0_MBOX0_INFO_SH     1
-#define __HOSTFN0_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN0_LPU1_MBOX0_CMD_STAT      0x00019004
-#define __HOSTFN0_LPU1_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN0_LPU1_MBOX0_INFO_SH     1
-#define __HOSTFN0_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN0_LPU1_MBOX0_CMD_STATUS  0x00000001
-#define LPU0_HOSTFN0_MBOX0_CMD_STAT      0x00019008
-#define __LPU0_HOSTFN0_MBOX0_INFO_MK     0xfffffffe
-#define __LPU0_HOSTFN0_MBOX0_INFO_SH     1
-#define __LPU0_HOSTFN0_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN0_MBOX0_CMD_STATUS  0x00000001
-#define LPU1_HOSTFN0_MBOX0_CMD_STAT      0x0001900c
-#define __LPU1_HOSTFN0_MBOX0_INFO_MK     0xfffffffe
-#define __LPU1_HOSTFN0_MBOX0_INFO_SH     1
-#define __LPU1_HOSTFN0_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN1_LPU0_MBOX0_CMD_STAT      0x00019010
-#define __HOSTFN1_LPU0_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN1_LPU0_MBOX0_INFO_SH     1
-#define __HOSTFN1_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN1_LPU1_MBOX0_CMD_STAT      0x00019014
-#define __HOSTFN1_LPU1_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN1_LPU1_MBOX0_INFO_SH     1
-#define __HOSTFN1_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN1_LPU1_MBOX0_CMD_STATUS  0x00000001
-#define LPU0_HOSTFN1_MBOX0_CMD_STAT      0x00019018
-#define __LPU0_HOSTFN1_MBOX0_INFO_MK     0xfffffffe
-#define __LPU0_HOSTFN1_MBOX0_INFO_SH     1
-#define __LPU0_HOSTFN1_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN1_MBOX0_CMD_STATUS  0x00000001
-#define LPU1_HOSTFN1_MBOX0_CMD_STAT      0x0001901c
-#define __LPU1_HOSTFN1_MBOX0_INFO_MK     0xfffffffe
-#define __LPU1_HOSTFN1_MBOX0_INFO_SH     1
-#define __LPU1_HOSTFN1_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN1_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN2_LPU0_MBOX0_CMD_STAT      0x00019150
-#define __HOSTFN2_LPU0_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN2_LPU0_MBOX0_INFO_SH     1
-#define __HOSTFN2_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN2_LPU1_MBOX0_CMD_STAT      0x00019154
-#define __HOSTFN2_LPU1_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN2_LPU1_MBOX0_INFO_SH     1
-#define __HOSTFN2_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001
-#define LPU0_HOSTFN2_MBOX0_CMD_STAT      0x00019158
-#define __LPU0_HOSTFN2_MBOX0_INFO_MK     0xfffffffe
-#define __LPU0_HOSTFN2_MBOX0_INFO_SH     1
-#define __LPU0_HOSTFN2_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN2_MBOX0_CMD_STATUS  0x00000001
-#define LPU1_HOSTFN2_MBOX0_CMD_STAT      0x0001915c
-#define __LPU1_HOSTFN2_MBOX0_INFO_MK     0xfffffffe
-#define __LPU1_HOSTFN2_MBOX0_INFO_SH     1
-#define __LPU1_HOSTFN2_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN2_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN3_LPU0_MBOX0_CMD_STAT      0x00019160
-#define __HOSTFN3_LPU0_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN3_LPU0_MBOX0_INFO_SH     1
-#define __HOSTFN3_LPU0_MBOX0_INFO(_v)    ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU0_MBOX0_CMD_STATUS  0x00000001
-#define HOSTFN3_LPU1_MBOX0_CMD_STAT      0x00019164
-#define __HOSTFN3_LPU1_MBOX0_INFO_MK     0xfffffffe
-#define __HOSTFN3_LPU1_MBOX0_INFO_SH     1
-#define __HOSTFN3_LPU1_MBOX0_INFO(_v)    ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH)
-#define __HOSTFN3_LPU1_MBOX0_CMD_STATUS  0x00000001
-#define LPU0_HOSTFN3_MBOX0_CMD_STAT      0x00019168
-#define __LPU0_HOSTFN3_MBOX0_INFO_MK     0xfffffffe
-#define __LPU0_HOSTFN3_MBOX0_INFO_SH     1
-#define __LPU0_HOSTFN3_MBOX0_INFO(_v)    ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU0_HOSTFN3_MBOX0_CMD_STATUS  0x00000001
-#define LPU1_HOSTFN3_MBOX0_CMD_STAT      0x0001916c
-#define __LPU1_HOSTFN3_MBOX0_INFO_MK     0xfffffffe
-#define __LPU1_HOSTFN3_MBOX0_INFO_SH     1
-#define __LPU1_HOSTFN3_MBOX0_INFO(_v)    ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH)
-#define __LPU1_HOSTFN3_MBOX0_CMD_STATUS  0x00000001
-#define FW_INIT_HALT_P0                  0x000191ac
-#define __FW_INIT_HALT_P                 0x00000001
-#define FW_INIT_HALT_P1                  0x000191bc
-#define CPE_PI_PTR_Q0                    0x00038000
-#define __CPE_PI_UNUSED_MK               0xffff0000
-#define __CPE_PI_UNUSED_SH               16
-#define __CPE_PI_UNUSED(_v)              ((_v) << __CPE_PI_UNUSED_SH)
-#define __CPE_PI_PTR                     0x0000ffff
-#define CPE_PI_PTR_Q1                    0x00038040
-#define CPE_CI_PTR_Q0                    0x00038004
-#define __CPE_CI_UNUSED_MK               0xffff0000
-#define __CPE_CI_UNUSED_SH               16
-#define __CPE_CI_UNUSED(_v)              ((_v) << __CPE_CI_UNUSED_SH)
-#define __CPE_CI_PTR                     0x0000ffff
-#define CPE_CI_PTR_Q1                    0x00038044
-#define CPE_DEPTH_Q0                     0x00038008
-#define __CPE_DEPTH_UNUSED_MK            0xf8000000
-#define __CPE_DEPTH_UNUSED_SH            27
-#define __CPE_DEPTH_UNUSED(_v)           ((_v) << __CPE_DEPTH_UNUSED_SH)
-#define __CPE_MSIX_VEC_INDEX_MK          0x07ff0000
-#define __CPE_MSIX_VEC_INDEX_SH          16
-#define __CPE_MSIX_VEC_INDEX(_v)         ((_v) << __CPE_MSIX_VEC_INDEX_SH)
-#define __CPE_DEPTH                      0x0000ffff
-#define CPE_DEPTH_Q1                     0x00038048
-#define CPE_QCTRL_Q0                     0x0003800c
-#define __CPE_CTRL_UNUSED30_MK           0xfc000000
-#define __CPE_CTRL_UNUSED30_SH           26
-#define __CPE_CTRL_UNUSED30(_v)          ((_v) << __CPE_CTRL_UNUSED30_SH)
-#define __CPE_FUNC_INT_CTRL_MK           0x03000000
-#define __CPE_FUNC_INT_CTRL_SH           24
-#define __CPE_FUNC_INT_CTRL(_v)          ((_v) << __CPE_FUNC_INT_CTRL_SH)
-enum {
-    __CPE_FUNC_INT_CTRL_DISABLE      = 0x0,
-    __CPE_FUNC_INT_CTRL_F2NF         = 0x1,
-    __CPE_FUNC_INT_CTRL_3QUART       = 0x2,
-    __CPE_FUNC_INT_CTRL_HALF         = 0x3,
-};
-#define __CPE_CTRL_UNUSED20_MK           0x00f00000
-#define __CPE_CTRL_UNUSED20_SH           20
-#define __CPE_CTRL_UNUSED20(_v)          ((_v) << __CPE_CTRL_UNUSED20_SH)
-#define __CPE_SCI_TH_MK                  0x000f0000
-#define __CPE_SCI_TH_SH                  16
-#define __CPE_SCI_TH(_v)                 ((_v) << __CPE_SCI_TH_SH)
-#define __CPE_CTRL_UNUSED10_MK           0x0000c000
-#define __CPE_CTRL_UNUSED10_SH           14
-#define __CPE_CTRL_UNUSED10(_v)          ((_v) << __CPE_CTRL_UNUSED10_SH)
-#define __CPE_ACK_PENDING                0x00002000
-#define __CPE_CTRL_UNUSED40_MK           0x00001c00
-#define __CPE_CTRL_UNUSED40_SH           10
-#define __CPE_CTRL_UNUSED40(_v)          ((_v) << __CPE_CTRL_UNUSED40_SH)
-#define __CPE_PCIEID_MK                  0x00000300
-#define __CPE_PCIEID_SH                  8
-#define __CPE_PCIEID(_v)                 ((_v) << __CPE_PCIEID_SH)
-#define __CPE_CTRL_UNUSED00_MK           0x000000fe
-#define __CPE_CTRL_UNUSED00_SH           1
-#define __CPE_CTRL_UNUSED00(_v)          ((_v) << __CPE_CTRL_UNUSED00_SH)
-#define __CPE_ESIZE                      0x00000001
-#define CPE_QCTRL_Q1                     0x0003804c
-#define __CPE_CTRL_UNUSED31_MK           0xfc000000
-#define __CPE_CTRL_UNUSED31_SH           26
-#define __CPE_CTRL_UNUSED31(_v)          ((_v) << __CPE_CTRL_UNUSED31_SH)
-#define __CPE_CTRL_UNUSED21_MK           0x00f00000
-#define __CPE_CTRL_UNUSED21_SH           20
-#define __CPE_CTRL_UNUSED21(_v)          ((_v) << __CPE_CTRL_UNUSED21_SH)
-#define __CPE_CTRL_UNUSED11_MK           0x0000c000
-#define __CPE_CTRL_UNUSED11_SH           14
-#define __CPE_CTRL_UNUSED11(_v)          ((_v) << __CPE_CTRL_UNUSED11_SH)
-#define __CPE_CTRL_UNUSED41_MK           0x00001c00
-#define __CPE_CTRL_UNUSED41_SH           10
-#define __CPE_CTRL_UNUSED41(_v)          ((_v) << __CPE_CTRL_UNUSED41_SH)
-#define __CPE_CTRL_UNUSED01_MK           0x000000fe
-#define __CPE_CTRL_UNUSED01_SH           1
-#define __CPE_CTRL_UNUSED01(_v)          ((_v) << __CPE_CTRL_UNUSED01_SH)
-#define RME_PI_PTR_Q0                    0x00038020
-#define __LATENCY_TIME_STAMP_MK          0xffff0000
-#define __LATENCY_TIME_STAMP_SH          16
-#define __LATENCY_TIME_STAMP(_v)         ((_v) << __LATENCY_TIME_STAMP_SH)
-#define __RME_PI_PTR                     0x0000ffff
-#define RME_PI_PTR_Q1                    0x00038060
-#define RME_CI_PTR_Q0                    0x00038024
-#define __DELAY_TIME_STAMP_MK            0xffff0000
-#define __DELAY_TIME_STAMP_SH            16
-#define __DELAY_TIME_STAMP(_v)           ((_v) << __DELAY_TIME_STAMP_SH)
-#define __RME_CI_PTR                     0x0000ffff
-#define RME_CI_PTR_Q1                    0x00038064
-#define RME_DEPTH_Q0                     0x00038028
-#define __RME_DEPTH_UNUSED_MK            0xf8000000
-#define __RME_DEPTH_UNUSED_SH            27
-#define __RME_DEPTH_UNUSED(_v)           ((_v) << __RME_DEPTH_UNUSED_SH)
-#define __RME_MSIX_VEC_INDEX_MK          0x07ff0000
-#define __RME_MSIX_VEC_INDEX_SH          16
-#define __RME_MSIX_VEC_INDEX(_v)         ((_v) << __RME_MSIX_VEC_INDEX_SH)
-#define __RME_DEPTH                      0x0000ffff
-#define RME_DEPTH_Q1                     0x00038068
-#define RME_QCTRL_Q0                     0x0003802c
-#define __RME_INT_LATENCY_TIMER_MK       0xff000000
-#define __RME_INT_LATENCY_TIMER_SH       24
-#define __RME_INT_LATENCY_TIMER(_v)      ((_v) << __RME_INT_LATENCY_TIMER_SH)
-#define __RME_INT_DELAY_TIMER_MK         0x00ff0000
-#define __RME_INT_DELAY_TIMER_SH         16
-#define __RME_INT_DELAY_TIMER(_v)        ((_v) << __RME_INT_DELAY_TIMER_SH)
-#define __RME_INT_DELAY_DISABLE          0x00008000
-#define __RME_DLY_DELAY_DISABLE          0x00004000
-#define __RME_ACK_PENDING                0x00002000
-#define __RME_FULL_INTERRUPT_DISABLE     0x00001000
-#define __RME_CTRL_UNUSED10_MK           0x00000c00
-#define __RME_CTRL_UNUSED10_SH           10
-#define __RME_CTRL_UNUSED10(_v)          ((_v) << __RME_CTRL_UNUSED10_SH)
-#define __RME_PCIEID_MK                  0x00000300
-#define __RME_PCIEID_SH                  8
-#define __RME_PCIEID(_v)                 ((_v) << __RME_PCIEID_SH)
-#define __RME_CTRL_UNUSED00_MK           0x000000fe
-#define __RME_CTRL_UNUSED00_SH           1
-#define __RME_CTRL_UNUSED00(_v)          ((_v) << __RME_CTRL_UNUSED00_SH)
-#define __RME_ESIZE                      0x00000001
-#define RME_QCTRL_Q1                     0x0003806c
-#define __RME_CTRL_UNUSED11_MK           0x00000c00
-#define __RME_CTRL_UNUSED11_SH           10
-#define __RME_CTRL_UNUSED11(_v)          ((_v) << __RME_CTRL_UNUSED11_SH)
-#define __RME_CTRL_UNUSED01_MK           0x000000fe
-#define __RME_CTRL_UNUSED01_SH           1
-#define __RME_CTRL_UNUSED01(_v)          ((_v) << __RME_CTRL_UNUSED01_SH)
-#define PSS_CTL_REG                      0x00018800
-#define __PSS_I2C_CLK_DIV_MK             0x007f0000
-#define __PSS_I2C_CLK_DIV_SH             16
-#define __PSS_I2C_CLK_DIV(_v)            ((_v) << __PSS_I2C_CLK_DIV_SH)
-#define __PSS_LMEM_INIT_DONE             0x00001000
-#define __PSS_LMEM_RESET                 0x00000200
-#define __PSS_LMEM_INIT_EN               0x00000100
-#define __PSS_LPU1_RESET                 0x00000002
-#define __PSS_LPU0_RESET                 0x00000001
-#define PSS_ERR_STATUS_REG               0x00018810
-#define __PSS_LPU1_TCM_READ_ERR          0x00200000
-#define __PSS_LPU0_TCM_READ_ERR          0x00100000
-#define __PSS_LMEM5_CORR_ERR             0x00080000
-#define __PSS_LMEM4_CORR_ERR             0x00040000
-#define __PSS_LMEM3_CORR_ERR             0x00020000
-#define __PSS_LMEM2_CORR_ERR             0x00010000
-#define __PSS_LMEM1_CORR_ERR             0x00008000
-#define __PSS_LMEM0_CORR_ERR             0x00004000
-#define __PSS_LMEM5_UNCORR_ERR           0x00002000
-#define __PSS_LMEM4_UNCORR_ERR           0x00001000
-#define __PSS_LMEM3_UNCORR_ERR           0x00000800
-#define __PSS_LMEM2_UNCORR_ERR           0x00000400
-#define __PSS_LMEM1_UNCORR_ERR           0x00000200
-#define __PSS_LMEM0_UNCORR_ERR           0x00000100
-#define __PSS_BAL_PERR                   0x00000080
-#define __PSS_DIP_IF_ERR                 0x00000040
-#define __PSS_IOH_IF_ERR                 0x00000020
-#define __PSS_TDS_IF_ERR                 0x00000010
-#define __PSS_RDS_IF_ERR                 0x00000008
-#define __PSS_SGM_IF_ERR                 0x00000004
-#define __PSS_LPU1_RAM_ERR               0x00000002
-#define __PSS_LPU0_RAM_ERR               0x00000001
-#define ERR_SET_REG			 0x00018818
-#define __PSS_ERR_STATUS_SET		 0x003fffff
-#define PMM_1T_RESET_REG_P0              0x0002381c
-#define __PMM_1T_RESET_P                 0x00000001
-#define PMM_1T_RESET_REG_P1              0x00023c1c
-#define HQM_QSET0_RXQ_DRBL_P0            0x00038000
-#define __RXQ0_ADD_VECTORS_P             0x80000000
-#define __RXQ0_STOP_P                    0x40000000
-#define __RXQ0_PRD_PTR_P                 0x0000ffff
-#define HQM_QSET1_RXQ_DRBL_P0            0x00038080
-#define __RXQ1_ADD_VECTORS_P             0x80000000
-#define __RXQ1_STOP_P                    0x40000000
-#define __RXQ1_PRD_PTR_P                 0x0000ffff
-#define HQM_QSET0_RXQ_DRBL_P1            0x0003c000
-#define HQM_QSET1_RXQ_DRBL_P1            0x0003c080
-#define HQM_QSET0_TXQ_DRBL_P0            0x00038020
-#define __TXQ0_ADD_VECTORS_P             0x80000000
-#define __TXQ0_STOP_P                    0x40000000
-#define __TXQ0_PRD_PTR_P                 0x0000ffff
-#define HQM_QSET1_TXQ_DRBL_P0            0x000380a0
-#define __TXQ1_ADD_VECTORS_P             0x80000000
-#define __TXQ1_STOP_P                    0x40000000
-#define __TXQ1_PRD_PTR_P                 0x0000ffff
-#define HQM_QSET0_TXQ_DRBL_P1            0x0003c020
-#define HQM_QSET1_TXQ_DRBL_P1            0x0003c0a0
-#define HQM_QSET0_IB_DRBL_1_P0           0x00038040
-#define __IB1_0_ACK_P                    0x80000000
-#define __IB1_0_DISABLE_P                0x40000000
-#define __IB1_0_NUM_OF_ACKED_EVENTS_P    0x0000ffff
-#define HQM_QSET1_IB_DRBL_1_P0           0x000380c0
-#define __IB1_1_ACK_P                    0x80000000
-#define __IB1_1_DISABLE_P                0x40000000
-#define __IB1_1_NUM_OF_ACKED_EVENTS_P    0x0000ffff
-#define HQM_QSET0_IB_DRBL_1_P1           0x0003c040
-#define HQM_QSET1_IB_DRBL_1_P1           0x0003c0c0
-#define HQM_QSET0_IB_DRBL_2_P0           0x00038060
-#define __IB2_0_ACK_P                    0x80000000
-#define __IB2_0_DISABLE_P                0x40000000
-#define __IB2_0_NUM_OF_ACKED_EVENTS_P    0x0000ffff
-#define HQM_QSET1_IB_DRBL_2_P0           0x000380e0
-#define __IB2_1_ACK_P                    0x80000000
-#define __IB2_1_DISABLE_P                0x40000000
-#define __IB2_1_NUM_OF_ACKED_EVENTS_P    0x0000ffff
-#define HQM_QSET0_IB_DRBL_2_P1           0x0003c060
-#define HQM_QSET1_IB_DRBL_2_P1           0x0003c0e0
-
-
-/*
- * These definitions are either in error/missing in spec. Its auto-generated
- * from hard coded values in regparse.pl.
- */
-#define __EMPHPOST_AT_4G_MK_FIX          0x0000001c
-#define __EMPHPOST_AT_4G_SH_FIX          0x00000002
-#define __EMPHPRE_AT_4G_FIX              0x00000003
-#define __SFP_TXRATE_EN_FIX              0x00000100
-#define __SFP_RXRATE_EN_FIX              0x00000080
-
-
-/*
- * These register definitions are auto-generated from hard coded values
- * in regparse.pl.
- */
-
-
-/*
- * These register mapping definitions are auto-generated from mapping tables
- * in regparse.pl.
- */
-#define BFA_IOC0_HBEAT_REG               HOST_SEM0_INFO_REG
-#define BFA_IOC0_STATE_REG               HOST_SEM1_INFO_REG
-#define BFA_IOC1_HBEAT_REG               HOST_SEM2_INFO_REG
-#define BFA_IOC1_STATE_REG               HOST_SEM3_INFO_REG
-#define BFA_FW_USE_COUNT                 HOST_SEM4_INFO_REG
-
-#define CPE_DEPTH_Q(__n) \
-	(CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0))
-#define CPE_QCTRL_Q(__n) \
-	(CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0))
-#define CPE_PI_PTR_Q(__n) \
-	(CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0))
-#define CPE_CI_PTR_Q(__n) \
-	(CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0))
-#define RME_DEPTH_Q(__n) \
-	(RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0))
-#define RME_QCTRL_Q(__n) \
-	(RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0))
-#define RME_PI_PTR_Q(__n) \
-	(RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0))
-#define RME_CI_PTR_Q(__n) \
-	(RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0))
-#define HQM_QSET_RXQ_DRBL_P0(__n) \
-	(HQM_QSET0_RXQ_DRBL_P0 + (__n) * (HQM_QSET1_RXQ_DRBL_P0 - \
-	HQM_QSET0_RXQ_DRBL_P0))
-#define HQM_QSET_TXQ_DRBL_P0(__n) \
-	(HQM_QSET0_TXQ_DRBL_P0 + (__n) * (HQM_QSET1_TXQ_DRBL_P0 - \
-	HQM_QSET0_TXQ_DRBL_P0))
-#define HQM_QSET_IB_DRBL_1_P0(__n) \
-	(HQM_QSET0_IB_DRBL_1_P0 + (__n) * (HQM_QSET1_IB_DRBL_1_P0 - \
-	HQM_QSET0_IB_DRBL_1_P0))
-#define HQM_QSET_IB_DRBL_2_P0(__n) \
-	(HQM_QSET0_IB_DRBL_2_P0 + (__n) * (HQM_QSET1_IB_DRBL_2_P0 - \
-	HQM_QSET0_IB_DRBL_2_P0))
-#define HQM_QSET_RXQ_DRBL_P1(__n) \
-	(HQM_QSET0_RXQ_DRBL_P1 + (__n) * (HQM_QSET1_RXQ_DRBL_P1 - \
-	HQM_QSET0_RXQ_DRBL_P1))
-#define HQM_QSET_TXQ_DRBL_P1(__n) \
-	(HQM_QSET0_TXQ_DRBL_P1 + (__n) * (HQM_QSET1_TXQ_DRBL_P1 - \
-	HQM_QSET0_TXQ_DRBL_P1))
-#define HQM_QSET_IB_DRBL_1_P1(__n) \
-	(HQM_QSET0_IB_DRBL_1_P1 + (__n) * (HQM_QSET1_IB_DRBL_1_P1 - \
-	HQM_QSET0_IB_DRBL_1_P1))
-#define HQM_QSET_IB_DRBL_2_P1(__n) \
-	(HQM_QSET0_IB_DRBL_2_P1 + (__n) * (HQM_QSET1_IB_DRBL_2_P1 - \
-	HQM_QSET0_IB_DRBL_2_P1))
-
-#define CPE_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
-#define RME_Q_NUM(__fn, __q)  (((__fn) << 2) + (__q))
-#define CPE_Q_MASK(__q)  ((__q) & 0x3)
-#define RME_Q_MASK(__q)  ((__q) & 0x3)
-
-
-/*
- * PCI MSI-X vector defines
- */
-enum {
-    BFA_MSIX_CPE_Q0 = 0,
-    BFA_MSIX_CPE_Q1 = 1,
-    BFA_MSIX_CPE_Q2 = 2,
-    BFA_MSIX_CPE_Q3 = 3,
-    BFA_MSIX_RME_Q0 = 4,
-    BFA_MSIX_RME_Q1 = 5,
-    BFA_MSIX_RME_Q2 = 6,
-    BFA_MSIX_RME_Q3 = 7,
-    BFA_MSIX_LPU_ERR = 8,
-    BFA_MSIX_CT_MAX = 9,
-};
-
-/*
- * And corresponding host interrupt status bit field defines
- */
-#define __HFN_INT_CPE_Q0                   0x00000001U
-#define __HFN_INT_CPE_Q1                   0x00000002U
-#define __HFN_INT_CPE_Q2                   0x00000004U
-#define __HFN_INT_CPE_Q3                   0x00000008U
-#define __HFN_INT_CPE_Q4                   0x00000010U
-#define __HFN_INT_CPE_Q5                   0x00000020U
-#define __HFN_INT_CPE_Q6                   0x00000040U
-#define __HFN_INT_CPE_Q7                   0x00000080U
-#define __HFN_INT_RME_Q0                   0x00000100U
-#define __HFN_INT_RME_Q1                   0x00000200U
-#define __HFN_INT_RME_Q2                   0x00000400U
-#define __HFN_INT_RME_Q3                   0x00000800U
-#define __HFN_INT_RME_Q4                   0x00001000U
-#define __HFN_INT_RME_Q5                   0x00002000U
-#define __HFN_INT_RME_Q6                   0x00004000U
-#define __HFN_INT_RME_Q7                   0x00008000U
-#define __HFN_INT_ERR_EMC                  0x00010000U
-#define __HFN_INT_ERR_LPU0                 0x00020000U
-#define __HFN_INT_ERR_LPU1                 0x00040000U
-#define __HFN_INT_ERR_PSS                  0x00080000U
-#define __HFN_INT_MBOX_LPU0                0x00100000U
-#define __HFN_INT_MBOX_LPU1                0x00200000U
-#define __HFN_INT_MBOX1_LPU0               0x00400000U
-#define __HFN_INT_MBOX1_LPU1               0x00800000U
-#define __HFN_INT_LL_HALT		   0x01000000U
-#define __HFN_INT_CPE_MASK                 0x000000ffU
-#define __HFN_INT_RME_MASK                 0x0000ff00U
-
-
-/*
- * catapult memory map.
- */
-#define LL_PGN_HQM0                      0x0096
-#define LL_PGN_HQM1                      0x0097
-#define PSS_SMEM_PAGE_START	0x8000
-#define PSS_SMEM_PGNUM(_pg0, _ma)	((_pg0) + ((_ma) >> 15))
-#define PSS_SMEM_PGOFF(_ma)	((_ma) & 0x7fff)
-
-/*
- * End of catapult memory map
- */
-
-
-#endif /* __BFI_CTREG_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fabric.h b/drivers/scsi/bfa/include/bfi/bfi_fabric.h
deleted file mode 100644
index c0669ed..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_fabric.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_FABRIC_H__
-#define __BFI_FABRIC_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_fabric_h2i_msgs {
-	BFI_FABRIC_H2I_CREATE_REQ	= 1,
-	BFI_FABRIC_H2I_DELETE_REQ	= 2,
-	BFI_FABRIC_H2I_SETAUTH		= 3,
-};
-
-enum bfi_fabric_i2h_msgs {
-	BFI_FABRIC_I2H_CREATE_RSP	= BFA_I2HM(1),
-	BFI_FABRIC_I2H_DELETE_RSP	= BFA_I2HM(2),
-	BFI_FABRIC_I2H_SETAUTH_RSP	= BFA_I2HM(3),
-	BFI_FABRIC_I2H_ONLINE		= BFA_I2HM(4),
-	BFI_FABRIC_I2H_OFFLINE		= BFA_I2HM(5),
-};
-
-struct bfi_fabric_create_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u8         vf_en;		/*  virtual fabric enable	*/
-	u8         rsvd;
-	u16        vf_id;		/*  virtual fabric ID		*/
-	wwn_t		pwwn;		/*  port name			*/
-	wwn_t		nwwn;		/*  node name			*/
-};
-
-struct bfi_fabric_create_rsp_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host fabric handle		*/
-	u8         status;		/*  fabric create status	*/
-	u8         rsvd;
-};
-
-struct bfi_fabric_delete_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  firmware fabric handle	*/
-	u16        rsvd;
-};
-
-struct bfi_fabric_delete_rsp_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host fabric handle		*/
-	u8         status;		/*  fabric deletion status	*/
-	u8         rsvd;
-};
-
-#define BFI_FABRIC_AUTHSECRET_LEN	64
-struct bfi_fabric_setauth_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  f/w handle of fabric	*/
-	u8		algorithm;
-	u8		group;
-	u8		secret[BFI_FABRIC_AUTHSECRET_LEN];
-};
-
-union bfi_fabric_h2i_msg_u {
-	bfi_msg_t		*msg;
-	struct bfi_fabric_create_req_s	*create_req;
-	struct bfi_fabric_delete_req_s	*delete_req;
-};
-
-union bfi_fabric_i2h_msg_u {
-	bfi_msg_t		*msg;
-	struct bfi_fabric_create_rsp_s	*create_rsp;
-	struct bfi_fabric_delete_rsp_s	*delete_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_FABRIC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcpim.h b/drivers/scsi/bfa/include/bfi/bfi_fcpim.h
deleted file mode 100644
index 52c059f..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_fcpim.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_FCPIM_H__
-#define __BFI_FCPIM_H__
-
-#include "bfi.h"
-#include <protocol/fcp.h>
-
-#pragma pack(1)
-
-/*
- * Initiator mode I-T nexus interface defines.
- */
-
-enum bfi_itnim_h2i {
-	BFI_ITNIM_H2I_CREATE_REQ = 1,	/*  i-t nexus creation */
-	BFI_ITNIM_H2I_DELETE_REQ = 2,	/*  i-t nexus deletion */
-};
-
-enum bfi_itnim_i2h {
-	BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1),
-	BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2),
-	BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3),
-};
-
-struct bfi_itnim_create_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        fw_handle;	/*  f/w handle for itnim	 */
-	u8         class;		/*  FC class for IO		 */
-	u8         seq_rec;	/*  sequence recovery support	 */
-	u8         msg_no;		/*  seq id of the msg		 */
-};
-
-struct bfi_itnim_create_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        bfa_handle;	/*  bfa handle for itnim	 */
-	u8         status;		/*  fcp request status		 */
-	u8         seq_id;		/*  seq id of the msg		 */
-};
-
-struct bfi_itnim_delete_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        fw_handle;	/*  f/w itnim handle		 */
-	u8         seq_id;		/*  seq id of the msg		 */
-	u8         rsvd;
-};
-
-struct bfi_itnim_delete_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        bfa_handle;	/*  bfa handle for itnim	 */
-	u8         status;		/*  fcp request status		 */
-	u8         seq_id;		/*  seq id of the msg		 */
-};
-
-struct bfi_itnim_sler_event_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		 */
-	u16        bfa_handle;	/*  bfa handle for itnim	 */
-	u16        rsvd;
-};
-
-union bfi_itnim_h2i_msg_u {
-	struct bfi_itnim_create_req_s *create_req;
-	struct bfi_itnim_delete_req_s *delete_req;
-	struct bfi_msg_s      *msg;
-};
-
-union bfi_itnim_i2h_msg_u {
-	struct bfi_itnim_create_rsp_s *create_rsp;
-	struct bfi_itnim_delete_rsp_s *delete_rsp;
-	struct bfi_itnim_sler_event_s *sler_event;
-	struct bfi_msg_s      *msg;
-};
-
-/*
- * Initiator mode IO interface defines.
- */
-
-enum bfi_ioim_h2i {
-	BFI_IOIM_H2I_IOABORT_REQ = 1,	/*  IO abort request	 */
-	BFI_IOIM_H2I_IOCLEANUP_REQ = 2,	/*  IO cleanup request	 */
-};
-
-enum bfi_ioim_i2h {
-	BFI_IOIM_I2H_IO_RSP = BFA_I2HM(1),	/*  non-fp IO response	 */
-	BFI_IOIM_I2H_IOABORT_RSP = BFA_I2HM(2),/*  ABORT rsp	 */
-};
-
-/**
- * IO command DIF info
- */
-struct bfi_ioim_dif_s {
-	u32	dif_info[4];
-};
-
-/**
- * FCP IO messages overview
- *
- * @note
- * - Max CDB length supported is 64 bytes.
- * - SCSI Linked commands and SCSI bi-directional Commands not
- * 	 supported.
- *
- */
-struct bfi_ioim_req_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
-	u16        io_tag;		/*  I/O tag			 */
-	u16        rport_hdl;	/*  itnim/rport firmware handle */
-	struct fcp_cmnd_s cmnd;		/*  IO request info		 */
-
-	/**
-	 * SG elements array within the IO request must be double word
-	 * aligned. This aligment is required to optimize SGM setup for the IO.
-	 */
-	struct bfi_sge_s   sges[BFI_SGE_INLINE_MAX];
-	u8         io_timeout;
-	u8         dif_en;
-	u8         rsvd_a[2];
-	struct bfi_ioim_dif_s  dif;
-};
-
-/**
- * 	This table shows various IO status codes from firmware and their
- *	meaning. Host driver can use these status codes to further process
- *	IO completions.
- *
- * 	BFI_IOIM_STS_OK		: IO completed with error free SCSI &
- *					   transport status.
- * 					   - io-tag can be reused.
- *
- * 	BFA_IOIM_STS_SCSI_ERR		: IO completed with scsi error.
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_HOST_ABORTED	: IO was aborted successfully due to
- *					   host request.
- * 					   - io-tag cannot be reused yet.
- *
- * 	BFI_IOIM_STS_ABORTED		: IO was aborted successfully
- *					   internally by f/w.
- * 					   - io-tag cannot be reused yet.
- *
- * 	BFI_IOIM_STS_TIMEDOUT	: IO timedout and ABTS/RRQ is happening
- *					   in the firmware and
- * 					   - io-tag cannot be reused yet.
- *
- * 	BFI_IOIM_STS_SQER_NEEDED	: Firmware could not recover the IO
- *					  with sequence level error
- * 					  logic and hence host needs to retry
- *					  this IO with a different IO tag
- * 					  - io-tag cannot be used yet.
- *
- * 	BFI_IOIM_STS_NEXUS_ABORT	: Second Level Error Recovery from host
- *					  is required because 2 consecutive ABTS
- *					  timedout and host needs logout and
- *					  re-login with the target
- * 					  - io-tag cannot be used yet.
- *
- * 	BFI_IOIM_STS_UNDERRUN	: IO completed with SCSI status good,
- *					  but the data tranferred is less than
- *					  the fcp data length in the command.
- *					  ex. SCSI INQUIRY where transferred
- *					  data length and residue count in FCP
- *					  response accounts for total fcp-dl
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_OVERRUN	: IO completed with SCSI status good,
- *					  but the data transerred is more than
- *					  fcp data length in the command. ex.
- *					  TAPE IOs where blocks can of unequal
- *					  lengths.
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_RES_FREE	: Firmware has completed using io-tag
- *					  during abort process
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_PROTO_ERR	: Firmware detected a protocol error.
- *					  ex target sent more data than
- *					  requested, or there was data frame
- *					  loss and other reasons
- * 					  - io-tag cannot be used yet.
- *
- * 	BFI_IOIM_STS_DIF_ERR	: Firwmare detected DIF error. ex: DIF
- * 					  CRC err or Ref Tag err or App tag err.
- * 					  - io-tag can be reused.
- *
- * 	BFA_IOIM_STS_TSK_MGT_ABORT	: IO was aborted because of Task
- *					  Management command from the host
- * 					  - io-tag can be reused.
- *
- * 	BFI_IOIM_STS_UTAG		: Firmware does not know about this
- *					  io_tag.
- * 					  - io-tag can be reused.
- */
-enum bfi_ioim_status {
-	BFI_IOIM_STS_OK = 0,
-	BFI_IOIM_STS_HOST_ABORTED = 1,
-	BFI_IOIM_STS_ABORTED = 2,
-	BFI_IOIM_STS_TIMEDOUT = 3,
-	BFI_IOIM_STS_RES_FREE = 4,
-	BFI_IOIM_STS_SQER_NEEDED = 5,
-	BFI_IOIM_STS_PROTO_ERR = 6,
-	BFI_IOIM_STS_UTAG = 7,
-	BFI_IOIM_STS_PATHTOV = 8,
-};
-
-#define BFI_IOIM_SNSLEN	(256)
-/**
- * I/O response message
- */
-struct bfi_ioim_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header	 	 */
-	u16        io_tag;		/*  completed IO tag		 */
-	u16        bfa_rport_hndl;	/*  releated rport handle	 */
-	u8         io_status;	/*  IO completion status	 */
-	u8         reuse_io_tag;	/*  IO tag can be reused        */
-	u16	abort_tag;	/*  host abort request tag      */
-	u8		scsi_status;	/*  scsi status from target	 */
-	u8		sns_len;	/*  scsi sense length		 */
-	u8		resid_flags;	/*  IO residue flags		 */
-	u8		rsvd_a;
-	u32	residue;	/*  IO residual length in bytes */
-	u32	rsvd_b[3];
-};
-
-struct bfi_ioim_abort_req_s {
-	struct bfi_mhdr_s  mh;          /*  Common msg header  */
-	u16        io_tag;         /*  I/O tag            */
-	u16        abort_tag;      /*  unique request tag */
-};
-
-/*
- * Initiator mode task management command interface defines.
- */
-
-enum bfi_tskim_h2i {
-	BFI_TSKIM_H2I_TM_REQ    = 1, /*  task-mgmt command         */
-	BFI_TSKIM_H2I_ABORT_REQ = 2, /*  task-mgmt command         */
-};
-
-enum bfi_tskim_i2h {
-	BFI_TSKIM_I2H_TM_RSP = BFA_I2HM(1),
-};
-
-struct bfi_tskim_req_s {
-	struct bfi_mhdr_s  mh;             /*  Common msg header          */
-	u16        tsk_tag;        /*  task management tag        */
-	u16        itn_fhdl;       /*  itn firmware handle        */
-	lun_t           lun;            /*  LU number                  */
-	u8         tm_flags;       /*  see fcp_tm_cmnd_t          */
-	u8         t_secs;         /*  Timeout value in seconds   */
-	u8         rsvd[2];
-};
-
-struct bfi_tskim_abortreq_s {
-	struct bfi_mhdr_s  mh;             /*  Common msg header          */
-	u16        tsk_tag;        /*  task management tag        */
-	u16        rsvd;
-};
-
-enum bfi_tskim_status {
-	/*
-	 * Following are FCP-4 spec defined status codes,
-	 * **DO NOT CHANGE THEM **
-	 */
-	BFI_TSKIM_STS_OK       = 0,
-	BFI_TSKIM_STS_NOT_SUPP = 4,
-	BFI_TSKIM_STS_FAILED   = 5,
-
-	/**
-	 * Defined by BFA
-	 */
-	BFI_TSKIM_STS_TIMEOUT  = 10,    /*  TM request timedout     */
-	BFI_TSKIM_STS_ABORTED  = 11,    /*  Aborted on host request */
-};
-
-struct bfi_tskim_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		 */
-	u16        tsk_tag;	/*  task mgmt cmnd tag		 */
-	u8         tsk_status;	/*  @ref bfi_tskim_status */
-	u8         rsvd;
-};
-
-#pragma pack()
-
-#endif /* __BFI_FCPIM_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcxp.h b/drivers/scsi/bfa/include/bfi/bfi_fcxp.h
deleted file mode 100644
index e0e995a..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_fcxp.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_FCXP_H__
-#define __BFI_FCXP_H__
-
-#include "bfi.h"
-
-#pragma pack(1)
-
-enum bfi_fcxp_h2i {
-	BFI_FCXP_H2I_SEND_REQ = 1,
-};
-
-enum bfi_fcxp_i2h {
-	BFI_FCXP_I2H_SEND_RSP = BFA_I2HM(1),
-};
-
-#define BFA_FCXP_MAX_SGES	2
-
-/**
- * FCXP send request structure
- */
-struct bfi_fcxp_send_req_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
-	u16        fcxp_tag;	/*  driver request tag		    */
-	u16        max_frmsz;	/*  max send frame size	    */
-	u16        vf_id;		/*  vsan tag if applicable	    */
-	u16        rport_fw_hndl;	/*  FW Handle for the remote port  */
-	u8         class;		/*  FC class used for req/rsp	    */
-	u8         rsp_timeout;	/*  timeout in secs, 0-no response */
-	u8         cts;		/*  continue sequence		    */
-	u8         lp_tag;		/*  lport tag			    */
-	struct fchs_s   fchs;		/*  request FC header structure    */
-	u32        req_len;	/*  request payload length	    */
-	u32        rsp_maxlen;	/*  max response length expected   */
-	struct bfi_sge_s   req_sge[BFA_FCXP_MAX_SGES];	/*  request buf    */
-	struct bfi_sge_s   rsp_sge[BFA_FCXP_MAX_SGES];	/*  response buf   */
-};
-
-/**
- * FCXP send response structure
- */
-struct bfi_fcxp_send_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		    */
-	u16        fcxp_tag;	/*  send request tag		    */
-	u8         req_status;	/*  request status		    */
-	u8         rsvd;
-	u32        rsp_len;	/*  actual response length	    */
-	u32        residue_len;	/*  residual response length	    */
-	struct fchs_s   fchs;		/*  response FC header structure   */
-};
-
-#pragma pack()
-
-#endif /* __BFI_FCXP_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ioc.h b/drivers/scsi/bfa/include/bfi/bfi_ioc.h
deleted file mode 100644
index 450ded6..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_ioc.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_IOC_H__
-#define __BFI_IOC_H__
-
-#include "bfi.h"
-#include <defs/bfa_defs_ioc.h>
-
-#pragma pack(1)
-
-enum bfi_ioc_h2i_msgs {
-	BFI_IOC_H2I_ENABLE_REQ 		= 1,
-	BFI_IOC_H2I_DISABLE_REQ 	= 2,
-	BFI_IOC_H2I_GETATTR_REQ 	= 3,
-	BFI_IOC_H2I_DBG_SYNC	 	= 4,
-	BFI_IOC_H2I_DBG_DUMP	 	= 5,
-};
-
-enum bfi_ioc_i2h_msgs {
-	BFI_IOC_I2H_ENABLE_REPLY	= BFA_I2HM(1),
-	BFI_IOC_I2H_DISABLE_REPLY 	= BFA_I2HM(2),
-	BFI_IOC_I2H_GETATTR_REPLY 	= BFA_I2HM(3),
-	BFI_IOC_I2H_READY_EVENT 	= BFA_I2HM(4),
-	BFI_IOC_I2H_HBEAT		= BFA_I2HM(5),
-};
-
-/**
- * BFI_IOC_H2I_GETATTR_REQ message
- */
-struct bfi_ioc_getattr_req_s {
-	struct bfi_mhdr_s	mh;
-	union bfi_addr_u	attr_addr;
-};
-
-struct bfi_ioc_attr_s {
-	wwn_t           mfg_pwwn;       /* Mfg port wwn */
-	wwn_t           mfg_nwwn;       /* Mfg node wwn */
-	mac_t		mfg_mac;	/* Mfg mac      */
-	u16		rsvd_a;
-	wwn_t           pwwn;
-	wwn_t           nwwn;
-	mac_t           mac;            /* PBC or Mfg mac */
-	u16        	rsvd_b;
-	char            brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
-	u8         pcie_gen;
-	u8         pcie_lanes_orig;
-	u8         pcie_lanes;
-	u8         rx_bbcredit;	/*  receive buffer credits */
-	u32        adapter_prop;	/*  adapter properties     */
-	u16        maxfrsize;	/*  max receive frame size */
-	char       asic_rev;
-	u8         rsvd_c;
-	char       fw_version[BFA_VERSION_LEN];
-	char       optrom_version[BFA_VERSION_LEN];
-	struct bfa_mfg_vpd_s	vpd;
-	u32        card_type;	/* card type */
-};
-
-/**
- * BFI_IOC_I2H_GETATTR_REPLY message
- */
-struct bfi_ioc_getattr_reply_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header          */
-	u8		status;	/*  cfg reply status           */
-	u8		rsvd[3];
-};
-
-/**
- * Firmware memory page offsets
- */
-#define BFI_IOC_SMEM_PG0_CB	(0x40)
-#define BFI_IOC_SMEM_PG0_CT	(0x180)
-
-/**
- * Firmware trace offset
- */
-#define BFI_IOC_TRC_OFF		(0x4b00)
-#define BFI_IOC_TRC_ENTS	256
-
-#define BFI_IOC_FW_SIGNATURE	(0xbfadbfad)
-#define BFI_IOC_MD5SUM_SZ	4
-struct bfi_ioc_image_hdr_s {
-	u32        signature;	/*  constant signature */
-	u32        rsvd_a;
-	u32        exec;		/*  exec vector        */
-	u32        param;		/*  parameters         */
-	u32        rsvd_b[4];
-	u32        md5sum[BFI_IOC_MD5SUM_SZ];
-};
-
-/**
- *  BFI_IOC_I2H_READY_EVENT message
- */
-struct bfi_ioc_rdy_event_s {
-	struct bfi_mhdr_s  mh;			/*  common msg header */
-	u8         init_status;	/*  init event status */
-	u8         rsvd[3];
-};
-
-struct bfi_ioc_hbeat_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u32	   hb_count;	/*  current heart beat count	*/
-};
-
-/**
- * IOC hardware/firmware state
- */
-enum bfi_ioc_state {
-	BFI_IOC_UNINIT 	 = 0,		/*  not initialized                 */
-	BFI_IOC_INITING 	 = 1,	/*  h/w is being initialized        */
-	BFI_IOC_HWINIT 	 = 2,		/*  h/w is initialized              */
-	BFI_IOC_CFG 	 = 3,		/*  IOC configuration in progress   */
-	BFI_IOC_OP 		 = 4,	/*  IOC is operational              */
-	BFI_IOC_DISABLING 	 = 5,	/*  IOC is being disabled           */
-	BFI_IOC_DISABLED 	 = 6,	/*  IOC is disabled                 */
-	BFI_IOC_CFG_DISABLED = 7,	/*  IOC is being disabled;transient */
-	BFI_IOC_FAIL       = 8,		/*  IOC heart-beat failure          */
-	BFI_IOC_MEMTEST      = 9,	/*  IOC is doing memtest            */
-};
-
-#define BFI_IOC_ENDIAN_SIG  0x12345678
-
-enum {
-	BFI_ADAPTER_TYPE_FC   = 0x01,		/*  FC adapters           */
-	BFI_ADAPTER_TYPE_MK   = 0x0f0000,	/*  adapter type mask     */
-	BFI_ADAPTER_TYPE_SH   = 16,	        /*  adapter type shift    */
-	BFI_ADAPTER_NPORTS_MK = 0xff00,		/*  number of ports mask  */
-	BFI_ADAPTER_NPORTS_SH = 8,	        /*  number of ports shift */
-	BFI_ADAPTER_SPEED_MK  = 0xff,		/*  adapter speed mask    */
-	BFI_ADAPTER_SPEED_SH  = 0,	        /*  adapter speed shift   */
-	BFI_ADAPTER_PROTO     = 0x100000,	/*  prototype adapaters   */
-	BFI_ADAPTER_TTV       = 0x200000,	/*  TTV debug capable     */
-	BFI_ADAPTER_UNSUPP    = 0x400000,	/*  unknown adapter type  */
-};
-
-#define BFI_ADAPTER_GETP(__prop, __adap_prop)          		\
-    (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >>         \
-     BFI_ADAPTER_ ## __prop ## _SH)
-#define BFI_ADAPTER_SETP(__prop, __val)         		\
-    ((__val) << BFI_ADAPTER_ ## __prop ## _SH)
-#define BFI_ADAPTER_IS_PROTO(__adap_type)   			\
-    ((__adap_type) & BFI_ADAPTER_PROTO)
-#define BFI_ADAPTER_IS_TTV(__adap_type)     			\
-    ((__adap_type) & BFI_ADAPTER_TTV)
-#define BFI_ADAPTER_IS_UNSUPP(__adap_type)  			\
-    ((__adap_type) & BFI_ADAPTER_UNSUPP)
-#define BFI_ADAPTER_IS_SPECIAL(__adap_type)                     \
-    ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO |     \
-			BFI_ADAPTER_UNSUPP))
-
-/**
- * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages
- */
-struct bfi_ioc_ctrl_req_s {
-	struct bfi_mhdr_s	mh;
-	u8			ioc_class;
-	u8         	rsvd[3];
-};
-
-/**
- * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages
- */
-struct bfi_ioc_ctrl_reply_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header     */
-	u8         status;		/*  enable/disable status */
-	u8         rsvd[3];
-};
-
-#define BFI_IOC_MSGSZ   8
-/**
- * H2I Messages
- */
-union bfi_ioc_h2i_msg_u {
-	struct bfi_mhdr_s 	mh;
-	struct bfi_ioc_ctrl_req_s enable_req;
-	struct bfi_ioc_ctrl_req_s disable_req;
-	struct bfi_ioc_getattr_req_s getattr_req;
-	u32       		mboxmsg[BFI_IOC_MSGSZ];
-};
-
-/**
- * I2H Messages
- */
-union bfi_ioc_i2h_msg_u {
-	struct bfi_mhdr_s      	mh;
-	struct bfi_ioc_rdy_event_s 	rdy_event;
-	u32       		mboxmsg[BFI_IOC_MSGSZ];
-};
-
-#pragma pack()
-
-#endif /* __BFI_IOC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h b/drivers/scsi/bfa/include/bfi/bfi_iocfc.h
deleted file mode 100644
index ccdfcc5..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_IOCFC_H__
-#define __BFI_IOCFC_H__
-
-#include "bfi.h"
-#include <bfi/bfi_pbc.h>
-#include <defs/bfa_defs_ioc.h>
-#include <defs/bfa_defs_iocfc.h>
-#include <defs/bfa_defs_boot.h>
-
-#pragma pack(1)
-
-enum bfi_iocfc_h2i_msgs {
-	BFI_IOCFC_H2I_CFG_REQ 		= 1,
-	BFI_IOCFC_H2I_GET_STATS_REQ 	= 2,
-	BFI_IOCFC_H2I_CLEAR_STATS_REQ	= 3,
-	BFI_IOCFC_H2I_SET_INTR_REQ 	= 4,
-	BFI_IOCFC_H2I_UPDATEQ_REQ = 5,
-};
-
-enum bfi_iocfc_i2h_msgs {
-	BFI_IOCFC_I2H_CFG_REPLY		= BFA_I2HM(1),
-	BFI_IOCFC_I2H_GET_STATS_RSP 	= BFA_I2HM(2),
-	BFI_IOCFC_I2H_CLEAR_STATS_RSP	= BFA_I2HM(3),
-	BFI_IOCFC_I2H_UPDATEQ_RSP = BFA_I2HM(5),
-};
-
-struct bfi_iocfc_cfg_s {
-	u8         num_cqs; 	/*  Number of CQs to be used     */
-	u8         sense_buf_len;	/*  SCSI sense length            */
-	u8         trunk_enabled;	/*  port trunking enabled        */
-	u8         trunk_ports;	/*  trunk ports bit map          */
-	u32        endian_sig;	/*  endian signature of host     */
-
-	/**
-	 * Request and response circular queue base addresses, size and
-	 * shadow index pointers.
-	 */
-	union bfi_addr_u  req_cq_ba[BFI_IOC_MAX_CQS];
-	union bfi_addr_u  req_shadow_ci[BFI_IOC_MAX_CQS];
-	u16    req_cq_elems[BFI_IOC_MAX_CQS];
-	union bfi_addr_u  rsp_cq_ba[BFI_IOC_MAX_CQS];
-	union bfi_addr_u  rsp_shadow_pi[BFI_IOC_MAX_CQS];
-	u16    rsp_cq_elems[BFI_IOC_MAX_CQS];
-
-	union bfi_addr_u  stats_addr;	/*  DMA-able address for stats	  */
-	union bfi_addr_u  cfgrsp_addr;	/*  config response dma address  */
-	union bfi_addr_u  ioim_snsbase;  /*  IO sense buffer base address */
-	struct bfa_iocfc_intr_attr_s intr_attr; /*  IOC interrupt attributes */
-};
-
-/**
- * Boot target wwn information for this port. This contains either the stored
- * or discovered boot target port wwns for the port.
- */
-struct bfi_iocfc_bootwwns {
-	wwn_t		wwn[BFA_BOOT_BOOTLUN_MAX];
-	u8		nwwns;
-	u8		rsvd[7];
-};
-
-struct bfi_iocfc_cfgrsp_s {
-	struct bfa_iocfc_fwcfg_s	fwcfg;
-	struct bfa_iocfc_intr_attr_s	intr_attr;
-	struct bfi_iocfc_bootwwns	bootwwns;
-	struct bfi_pbc_s                pbc_cfg;
-};
-
-/**
- * BFI_IOCFC_H2I_CFG_REQ message
- */
-struct bfi_iocfc_cfg_req_s {
-	struct bfi_mhdr_s      mh;
-	union bfi_addr_u      ioc_cfg_dma_addr;
-};
-
-/**
- * BFI_IOCFC_I2H_CFG_REPLY message
- */
-struct bfi_iocfc_cfg_reply_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header          */
-	u8         cfg_success;	/*  cfg reply status           */
-	u8         lpu_bm;		/*  LPUs assigned for this IOC */
-	u8         rsvd[2];
-};
-
-/**
- *  BFI_IOCFC_H2I_GET_STATS_REQ & BFI_IOCFC_H2I_CLEAR_STATS_REQ messages
- */
-struct bfi_iocfc_stats_req_s {
-	struct bfi_mhdr_s mh;		/*  msg header            */
-	u32        msgtag;		/*  msgtag for reply      */
-};
-
-/**
- * BFI_IOCFC_I2H_GET_STATS_RSP & BFI_IOCFC_I2H_CLEAR_STATS_RSP messages
- */
-struct bfi_iocfc_stats_rsp_s {
-	struct bfi_mhdr_s mh;		/*  common msg header     */
-	u8         status;		/*  reply status          */
-	u8         rsvd[3];
-	u32        msgtag;		/*  msgtag for reply      */
-};
-
-/**
- * BFI_IOCFC_H2I_SET_INTR_REQ message
- */
-struct bfi_iocfc_set_intr_req_s {
-	struct bfi_mhdr_s mh;		/*  common msg header     */
-	u8		coalesce;	/*  enable intr coalescing*/
-	u8         rsvd[3];
-	u16	delay;		/*  delay timer 0..1125us  */
-	u16	latency;	/*  latency timer 0..225us */
-};
-
-/**
- * BFI_IOCFC_H2I_UPDATEQ_REQ message
- */
-struct bfi_iocfc_updateq_req_s {
-	struct bfi_mhdr_s mh;		/*  common msg header     */
-	u32 reqq_ba;			/*  reqq base addr        */
-	u32 rspq_ba;			/*  rspq base addr        */
-	u32 reqq_sci;			/*  reqq shadow ci        */
-	u32 rspq_spi;			/*  rspq shadow pi        */
-};
-
-/**
- * BFI_IOCFC_I2H_UPDATEQ_RSP message
- */
-struct bfi_iocfc_updateq_rsp_s {
-	struct bfi_mhdr_s mh;		/*  common msg header     */
-	u8         status;		/*  updateq  status       */
-	u8         rsvd[3];
-};
-
-/**
- * H2I Messages
- */
-union bfi_iocfc_h2i_msg_u {
-	struct bfi_mhdr_s 		mh;
-	struct bfi_iocfc_cfg_req_s 	cfg_req;
-	struct bfi_iocfc_stats_req_s stats_get;
-	struct bfi_iocfc_stats_req_s stats_clr;
-	struct bfi_iocfc_updateq_req_s updateq_req;
-	u32       			mboxmsg[BFI_IOC_MSGSZ];
-};
-
-/**
- * I2H Messages
- */
-union bfi_iocfc_i2h_msg_u {
-	struct bfi_mhdr_s      		mh;
-	struct bfi_iocfc_cfg_reply_s 		cfg_reply;
-	struct bfi_iocfc_stats_rsp_s stats_get_rsp;
-	struct bfi_iocfc_stats_rsp_s stats_clr_rsp;
-	struct bfi_iocfc_updateq_rsp_s updateq_rsp;
-	u32       			mboxmsg[BFI_IOC_MSGSZ];
-};
-
-#pragma pack()
-
-#endif /* __BFI_IOCFC_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lport.h b/drivers/scsi/bfa/include/bfi/bfi_lport.h
deleted file mode 100644
index 2901061..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_lport.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_LPORT_H__
-#define __BFI_LPORT_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_lport_h2i_msgs {
-	BFI_LPORT_H2I_CREATE_REQ = 1,
-	BFI_LPORT_H2I_DELETE_REQ = 2,
-};
-
-enum bfi_lport_i2h_msgs {
-	BFI_LPORT_I2H_CREATE_RSP = BFA_I2HM(1),
-	BFI_LPORT_I2H_DELETE_RSP = BFA_I2HM(2),
-	BFI_LPORT_I2H_ONLINE	  = BFA_I2HM(3),
-	BFI_LPORT_I2H_OFFLINE	  = BFA_I2HM(4),
-};
-
-#define BFI_LPORT_MAX_SYNNAME	64
-
-enum bfi_lport_role_e {
-	BFI_LPORT_ROLE_FCPIM	= 1,
-	BFI_LPORT_ROLE_FCPTM	= 2,
-	BFI_LPORT_ROLE_IPFC	= 4,
-};
-
-struct bfi_lport_create_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16	fabric_fwhdl;	/*  parent fabric instance	*/
-	u8		roles;		/*  lport FC-4 roles		*/
-	u8		rsvd;
-	wwn_t		pwwn;		/*  port name			*/
-	wwn_t		nwwn;		/*  node name			*/
-	u8		symname[BFI_LPORT_MAX_SYNNAME];
-};
-
-struct bfi_lport_create_rsp_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u8         status;		/*  lport creation status	*/
-	u8         rsvd[3];
-};
-
-struct bfi_lport_delete_req_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  firmware lport handle	*/
-	u16        rsvd;
-};
-
-struct bfi_lport_delete_rsp_s {
-	bfi_mhdr_t	mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host lport handle		*/
-	u8         status;		/*  lport deletion status	*/
-	u8         rsvd;
-};
-
-union bfi_lport_h2i_msg_u {
-	bfi_msg_t		*msg;
-	struct bfi_lport_create_req_s	*create_req;
-	struct bfi_lport_delete_req_s	*delete_req;
-};
-
-union bfi_lport_i2h_msg_u {
-	bfi_msg_t		*msg;
-	struct bfi_lport_create_rsp_s	*create_rsp;
-	struct bfi_lport_delete_rsp_s	*delete_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_LPORT_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lps.h b/drivers/scsi/bfa/include/bfi/bfi_lps.h
deleted file mode 100644
index 7ed31bb..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_lps.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_LPS_H__
-#define __BFI_LPS_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_lps_h2i_msgs {
-	BFI_LPS_H2I_LOGIN_REQ	= 1,
-	BFI_LPS_H2I_LOGOUT_REQ	= 2,
-};
-
-enum bfi_lps_i2h_msgs {
-	BFI_LPS_H2I_LOGIN_RSP	= BFA_I2HM(1),
-	BFI_LPS_H2I_LOGOUT_RSP	= BFA_I2HM(2),
-	BFI_LPS_H2I_CVL_EVENT   = BFA_I2HM(3),
-};
-
-struct bfi_lps_login_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
-	u8		alpa;
-	u16	pdu_size;
-	wwn_t		pwwn;
-	wwn_t		nwwn;
-	u8		fdisc;
-	u8		auth_en;
-	u8		rsvd[2];
-};
-
-struct bfi_lps_login_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
-	u8		status;
-	u8		lsrjt_rsn;
-	u8		lsrjt_expl;
-	wwn_t		port_name;
-	wwn_t		node_name;
-	u16	bb_credit;
-	u8		f_port;
-	u8		npiv_en;
-	u32	lp_pid:24;
-	u32	auth_req:8;
-	mac_t		lp_mac;
-	mac_t		fcf_mac;
-	u8		ext_status;
-	u8  	brcd_switch;/*  attached peer is brcd switch	*/
-};
-
-struct bfi_lps_logout_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
-	u8		rsvd[3];
-	wwn_t		port_name;
-};
-
-struct bfi_lps_logout_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8		lp_tag;
-	u8		status;
-	u8		rsvd[2];
-};
-
-struct bfi_lps_cvl_event_s {
-	struct bfi_mhdr_s  mh;      /* common msg header      */
-	u8		lp_tag;
-	u8		rsvd[3];
-};
-
-union bfi_lps_h2i_msg_u {
-	struct bfi_mhdr_s		*msg;
-	struct bfi_lps_login_req_s	*login_req;
-	struct bfi_lps_logout_req_s	*logout_req;
-};
-
-union bfi_lps_i2h_msg_u {
-	struct bfi_msg_s		*msg;
-	struct bfi_lps_login_rsp_s	*login_rsp;
-	struct bfi_lps_logout_rsp_s	*logout_rsp;
-	struct bfi_lps_cvl_event_s	*cvl_event;
-};
-
-#pragma pack()
-
-#endif /* __BFI_LPS_H__ */
-
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_pbc.h b/drivers/scsi/bfa/include/bfi/bfi_pbc.h
deleted file mode 100644
index 88a4154..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_pbc.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_PBC_H__
-#define __BFI_PBC_H__
-
-#pragma pack(1)
-
-#define BFI_PBC_MAX_BLUNS	8
-#define BFI_PBC_MAX_VPORTS	16
-
-#define BFI_PBC_PORT_DISABLED	 2
-/**
- * PBC boot lun configuration
- */
-struct bfi_pbc_blun_s {
-	wwn_t		tgt_pwwn;
-	lun_t		tgt_lun;
-};
-
-/**
- * PBC virtual port configuration
- */
-struct bfi_pbc_vport_s {
-	wwn_t		vp_pwwn;
-	wwn_t		vp_nwwn;
-};
-
-/**
- * BFI pre-boot configuration information
- */
-struct bfi_pbc_s {
-	u8		port_enabled;
-	u8		boot_enabled;
-	u8		nbluns;
-	u8		nvports;
-	u8		port_speed;
-	u8		rsvd_a;
-	u16		hss;
-	wwn_t		pbc_pwwn;
-	wwn_t		pbc_nwwn;
-	struct bfi_pbc_blun_s blun[BFI_PBC_MAX_BLUNS];
-	struct bfi_pbc_vport_s vport[BFI_PBC_MAX_VPORTS];
-};
-
-#pragma pack()
-
-#endif /* __BFI_PBC_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi_port.h b/drivers/scsi/bfa/include/bfi/bfi_port.h
deleted file mode 100644
index 3ec3bea..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_port.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFI_PORT_H__
-#define __BFI_PORT_H__
-
-#include <bfi/bfi.h>
-#include <defs/bfa_defs_pport.h>
-
-#pragma pack(1)
-
-enum bfi_port_h2i {
-	BFI_PORT_H2I_ENABLE_REQ		= (1),
-	BFI_PORT_H2I_DISABLE_REQ	= (2),
-	BFI_PORT_H2I_GET_STATS_REQ	= (3),
-	BFI_PORT_H2I_CLEAR_STATS_REQ	= (4),
-};
-
-enum bfi_port_i2h {
-	BFI_PORT_I2H_ENABLE_RSP		= BFA_I2HM(1),
-	BFI_PORT_I2H_DISABLE_RSP	= BFA_I2HM(2),
-	BFI_PORT_I2H_GET_STATS_RSP	= BFA_I2HM(3),
-	BFI_PORT_I2H_CLEAR_STATS_RSP	= BFA_I2HM(4),
-};
-
-/**
- * Generic REQ type
- */
-struct bfi_port_generic_req_s {
-	struct bfi_mhdr_s  mh;		/*  msg header			    */
-	u32        msgtag;		/*  msgtag for reply		    */
-	u32	rsvd;
-};
-
-/**
- * Generic RSP type
- */
-struct bfi_port_generic_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		    */
-	u8         status;		/*  port enable status		    */
-	u8         rsvd[3];
-	u32        msgtag;		/*  msgtag for reply		    */
-};
-
-/**
- * @todo
- * BFI_PORT_H2I_ENABLE_REQ
- */
-
-/**
- * @todo
- * BFI_PORT_I2H_ENABLE_RSP
- */
-
-/**
- * BFI_PORT_H2I_DISABLE_REQ
- */
-
-/**
- * BFI_PORT_I2H_DISABLE_RSP
- */
-
-/**
- * BFI_PORT_H2I_GET_STATS_REQ
- */
-struct bfi_port_get_stats_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		    */
-	union bfi_addr_u   dma_addr;
-};
-
-/**
- * BFI_PORT_I2H_GET_STATS_RSP
- */
-
-/**
- * BFI_PORT_H2I_CLEAR_STATS_REQ
- */
-
-/**
- * BFI_PORT_I2H_CLEAR_STATS_RSP
- */
-
-union bfi_port_h2i_msg_u {
-	struct bfi_mhdr_s		mh;
-	struct bfi_port_generic_req_s	enable_req;
-	struct bfi_port_generic_req_s	disable_req;
-	struct bfi_port_get_stats_req_s	getstats_req;
-	struct bfi_port_generic_req_s	clearstats_req;
-};
-
-union bfi_port_i2h_msg_u {
-	struct bfi_mhdr_s         	mh;
-	struct bfi_port_generic_rsp_s	enable_rsp;
-	struct bfi_port_generic_rsp_s	disable_rsp;
-	struct bfi_port_generic_rsp_s	getstats_rsp;
-	struct bfi_port_generic_rsp_s	clearstats_rsp;
-};
-
-#pragma pack()
-
-#endif /* __BFI_PORT_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_pport.h b/drivers/scsi/bfa/include/bfi/bfi_pport.h
deleted file mode 100644
index 50dcf45..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_pport.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFI_PPORT_H__
-#define __BFI_PPORT_H__
-
-#include <bfi/bfi.h>
-#include <defs/bfa_defs_pport.h>
-
-#pragma pack(1)
-
-enum bfi_fcport_h2i {
-	BFI_FCPORT_H2I_ENABLE_REQ		= (1),
-	BFI_FCPORT_H2I_DISABLE_REQ		= (2),
-	BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ	= (3),
-	BFI_FCPORT_H2I_STATS_GET_REQ		= (4),
-	BFI_FCPORT_H2I_STATS_CLEAR_REQ		= (5),
-};
-
-enum bfi_fcport_i2h {
-	BFI_FCPORT_I2H_ENABLE_RSP		= BFA_I2HM(1),
-	BFI_FCPORT_I2H_DISABLE_RSP		= BFA_I2HM(2),
-	BFI_FCPORT_I2H_SET_SVC_PARAMS_RSP	= BFA_I2HM(3),
-	BFI_FCPORT_I2H_STATS_GET_RSP		= BFA_I2HM(4),
-	BFI_FCPORT_I2H_STATS_CLEAR_RSP		= BFA_I2HM(5),
-	BFI_FCPORT_I2H_EVENT			= BFA_I2HM(6),
-};
-
-/**
- * Generic REQ type
- */
-struct bfi_fcport_req_s {
-	struct bfi_mhdr_s  mh;		/*  msg header			    */
-	u32	   msgtag;	/*  msgtag for reply		    */
-};
-
-/**
- * Generic RSP type
- */
-struct bfi_fcport_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		    */
-	u8		   status;	/*  port enable status		    */
-	u8		   rsvd[3];
-	u32	   msgtag;	/*  msgtag for reply		    */
-};
-
-/**
- * BFI_FCPORT_H2I_ENABLE_REQ
- */
-struct bfi_fcport_enable_req_s {
-	struct bfi_mhdr_s  mh;		/*  msg header			    */
-	u32	   rsvd1;
-	wwn_t		   nwwn;	/*  node wwn of physical port	    */
-	wwn_t		   pwwn;	/*  port wwn of physical port	    */
-	struct bfa_pport_cfg_s port_cfg; /*  port configuration	    */
-	union bfi_addr_u   stats_dma_addr; /*  DMA address for stats	    */
-	u32	   msgtag;	/*  msgtag for reply		    */
-	u32	   rsvd2;
-};
-
-/**
- * BFI_FCPORT_H2I_SET_SVC_PARAMS_REQ
- */
-struct bfi_fcport_set_svc_params_req_s {
-	struct bfi_mhdr_s  mh;		/*  msg header */
-	u16	   tx_bbcredit;	/*  Tx credits */
-	u16	   rsvd;
-};
-
-/**
- * BFI_FCPORT_I2H_EVENT
- */
-struct bfi_fcport_event_s {
-	struct bfi_mhdr_s 	mh;	/*  common msg header */
-	struct bfa_pport_link_s	link_state;
-};
-
-/**
- * fcport H2I message
- */
-union bfi_fcport_h2i_msg_u {
-	struct bfi_mhdr_s			*mhdr;
-	struct bfi_fcport_enable_req_s		*penable;
-	struct bfi_fcport_req_s			*pdisable;
-	struct bfi_fcport_set_svc_params_req_s	*psetsvcparams;
-	struct bfi_fcport_req_s			*pstatsget;
-	struct bfi_fcport_req_s			*pstatsclear;
-};
-
-/**
- * fcport I2H message
- */
-union bfi_fcport_i2h_msg_u {
-	struct bfi_msg_s			*msg;
-	struct bfi_fcport_rsp_s			*penable_rsp;
-	struct bfi_fcport_rsp_s			*pdisable_rsp;
-	struct bfi_fcport_rsp_s			*psetsvcparams_rsp;
-	struct bfi_fcport_rsp_s			*pstatsget_rsp;
-	struct bfi_fcport_rsp_s			*pstatsclear_rsp;
-	struct bfi_fcport_event_s		*event;
-};
-
-#pragma pack()
-
-#endif /* __BFI_PPORT_H__ */
diff --git a/drivers/scsi/bfa/include/bfi/bfi_rport.h b/drivers/scsi/bfa/include/bfi/bfi_rport.h
deleted file mode 100644
index e1cd83b..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_rport.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_RPORT_H__
-#define __BFI_RPORT_H__
-
-#include <bfi/bfi.h>
-
-#pragma pack(1)
-
-enum bfi_rport_h2i_msgs {
-	BFI_RPORT_H2I_CREATE_REQ = 1,
-	BFI_RPORT_H2I_DELETE_REQ = 2,
-	BFI_RPORT_H2I_SET_SPEED_REQ  = 3,
-};
-
-enum bfi_rport_i2h_msgs {
-	BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1),
-	BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2),
-	BFI_RPORT_I2H_QOS_SCN    = BFA_I2HM(3),
-};
-
-struct bfi_rport_create_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host rport handle		*/
-	u16        max_frmsz;	/*  max rcv pdu size		*/
-	u32        pid:24,		/*  remote port ID		*/
-			lp_tag:8;	/*  local port tag		*/
-	u32        local_pid:24,	/*  local port ID		*/
-			cisc:8;
-	u8         fc_class;	/*  supported FC classes	*/
-	u8         vf_en;		/*  virtual fabric enable	*/
-	u16        vf_id;		/*  virtual fabric ID		*/
-};
-
-struct bfi_rport_create_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u8         status;		/*  rport creation status	*/
-	u8         rsvd[3];
-	u16        bfa_handle;	/*  host rport handle		*/
-	u16        fw_handle;	/*  firmware rport handle	*/
-	struct bfa_rport_qos_attr_s qos_attr;  /* QoS Attributes */
-};
-
-struct bfa_rport_speed_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  firmware rport handle	*/
-	u8		speed;		/*! rport's speed via RPSC  */
-	u8		rsvd;
-};
-
-struct bfi_rport_delete_req_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        fw_handle;	/*  firmware rport handle	*/
-	u16        rsvd;
-};
-
-struct bfi_rport_delete_rsp_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host rport handle		*/
-	u8         status;		/*  rport deletion status	*/
-	u8         rsvd;
-};
-
-struct bfi_rport_qos_scn_s {
-	struct bfi_mhdr_s  mh;		/*  common msg header		*/
-	u16        bfa_handle;	/*  host rport handle		*/
-	u16        rsvd;
-	struct bfa_rport_qos_attr_s old_qos_attr;  /* Old QoS Attributes */
-	struct bfa_rport_qos_attr_s new_qos_attr;  /* New QoS Attributes */
-};
-
-union bfi_rport_h2i_msg_u {
-	struct bfi_msg_s 		*msg;
-	struct bfi_rport_create_req_s	*create_req;
-	struct bfi_rport_delete_req_s	*delete_req;
-	struct bfi_rport_speed_req_s	*speed_req;
-};
-
-union bfi_rport_i2h_msg_u {
-	struct bfi_msg_s 		*msg;
-	struct bfi_rport_create_rsp_s	*create_rsp;
-	struct bfi_rport_delete_rsp_s	*delete_rsp;
-	struct bfi_rport_qos_scn_s	*qos_scn_evt;
-};
-
-#pragma pack()
-
-#endif /* __BFI_RPORT_H__ */
-
diff --git a/drivers/scsi/bfa/include/bfi/bfi_uf.h b/drivers/scsi/bfa/include/bfi/bfi_uf.h
deleted file mode 100644
index f328a9e..0000000
--- a/drivers/scsi/bfa/include/bfi/bfi_uf.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFI_UF_H__
-#define __BFI_UF_H__
-
-#include "bfi.h"
-
-#pragma pack(1)
-
-enum bfi_uf_h2i {
-	BFI_UF_H2I_BUF_POST = 1,
-};
-
-enum bfi_uf_i2h {
-	BFI_UF_I2H_FRM_RCVD = BFA_I2HM(1),
-};
-
-#define BFA_UF_MAX_SGES	2
-
-struct bfi_uf_buf_post_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
-	u16        buf_tag;	/*  buffer tag			*/
-	u16        buf_len;	/*  total buffer length	*/
-	struct bfi_sge_s   sge[BFA_UF_MAX_SGES]; /*  buffer DMA SGEs	*/
-};
-
-struct bfi_uf_frm_rcvd_s {
-	struct bfi_mhdr_s  mh;		/*  Common msg header		*/
-	u16        buf_tag;	/*  buffer tag			*/
-	u16        rsvd;
-	u16        frm_len;	/*  received frame length 	*/
-	u16        xfr_len;	/*  tranferred length		*/
-};
-
-#pragma pack()
-
-#endif /* __BFI_UF_H__ */
diff --git a/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h b/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h
deleted file mode 100644
index a75a1f3..0000000
--- a/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_cna_trcmod.h CNA trace modules
- */
-
-#ifndef __BFA_CNA_TRCMOD_H__
-#define __BFA_CNA_TRCMOD_H__
-
-#include <cs/bfa_trc.h>
-
-/*
- * !!! Only append to the enums defined here to avoid any versioning
- * !!! needed between trace utility and driver version
- */
-enum {
-	BFA_TRC_CNA_CEE		= 1,
-	BFA_TRC_CNA_PORT	= 2,
-	BFA_TRC_CNA_IOC     = 3,
-	BFA_TRC_CNA_DIAG    = 4,
-	BFA_TRC_CNA_IOC_CB  = 5,
-	BFA_TRC_CNA_IOC_CT  = 6,
-};
-
-#endif /* __BFA_CNA_TRCMOD_H__ */
diff --git a/drivers/scsi/bfa/include/cna/cee/bfa_cee.h b/drivers/scsi/bfa/include/cna/cee/bfa_cee.h
deleted file mode 100644
index 77f297f..0000000
--- a/drivers/scsi/bfa/include/cna/cee/bfa_cee.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_CEE_H__
-#define __BFA_CEE_H__
-
-#include <defs/bfa_defs_cee.h>
-#include <bfa_ioc.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-
-typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, bfa_status_t status);
-typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, bfa_status_t status);
-
-struct bfa_cee_cbfn_s {
-	bfa_cee_get_attr_cbfn_t    get_attr_cbfn;
-	void *get_attr_cbarg;
-	bfa_cee_get_stats_cbfn_t   get_stats_cbfn;
-	void *get_stats_cbarg;
-	bfa_cee_reset_stats_cbfn_t reset_stats_cbfn;
-	void *reset_stats_cbarg;
-};
-
-struct bfa_cee_s {
-	void *dev;
-	bfa_boolean_t get_attr_pending;
-	bfa_boolean_t get_stats_pending;
-	bfa_boolean_t reset_stats_pending;
-	bfa_status_t get_attr_status;
-	bfa_status_t get_stats_status;
-	bfa_status_t reset_stats_status;
-	struct bfa_cee_cbfn_s cbfn;
-	struct bfa_ioc_hbfail_notify_s hbfail;
-	struct bfa_trc_mod_s *trcmod;
-	struct bfa_log_mod_s *logmod;
-	struct bfa_cee_attr_s *attr;
-	struct bfa_cee_stats_s *stats;
-	struct bfa_dma_s attr_dma;
-	struct bfa_dma_s stats_dma;
-	struct bfa_ioc_s *ioc;
-	struct bfa_mbox_cmd_s get_cfg_mb;
-	struct bfa_mbox_cmd_s get_stats_mb;
-	struct bfa_mbox_cmd_s reset_stats_mb;
-};
-
-u32 bfa_cee_meminfo(void);
-void bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva,
-			 u64 dma_pa);
-void bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev,
-			struct bfa_trc_mod_s *trcmod,
-			struct bfa_log_mod_s *logmod);
-void bfa_cee_detach(struct bfa_cee_s *cee);
-bfa_status_t bfa_cee_get_attr(struct bfa_cee_s *cee,
-			 struct bfa_cee_attr_s *attr,
-			bfa_cee_get_attr_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_cee_get_stats(struct bfa_cee_s *cee,
-			struct bfa_cee_stats_s *stats,
-			bfa_cee_get_stats_cbfn_t cbfn, void *cbarg);
-bfa_status_t bfa_cee_reset_stats(struct bfa_cee_s *cee,
-			bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg);
-#endif /* __BFA_CEE_H__ */
diff --git a/drivers/scsi/bfa/include/cna/port/bfa_port.h b/drivers/scsi/bfa/include/cna/port/bfa_port.h
deleted file mode 100644
index d7babaf..0000000
--- a/drivers/scsi/bfa/include/cna/port/bfa_port.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_PORT_H__
-#define __BFA_PORT_H__
-
-#include <defs/bfa_defs_port.h>
-#include <bfa_ioc.h>
-#include <cs/bfa_trc.h>
-#include <cs/bfa_log.h>
-
-typedef void    (*bfa_port_stats_cbfn_t) (void *dev, bfa_status_t status);
-typedef void    (*bfa_port_endis_cbfn_t) (void *dev, bfa_status_t status);
-
-struct bfa_port_s {
-	void           *dev;
-	struct bfa_ioc_s *ioc;
-	struct bfa_trc_mod_s *trcmod;
-	struct bfa_log_mod_s *logmod;
-	u32        msgtag;
-	bfa_boolean_t   stats_busy;
-	struct bfa_mbox_cmd_s stats_mb;
-	bfa_port_stats_cbfn_t stats_cbfn;
-	void           *stats_cbarg;
-	bfa_status_t    stats_status;
-	u32             stats_reset_time;
-	union bfa_pport_stats_u *stats;
-	struct bfa_dma_s stats_dma;
-	bfa_boolean_t   endis_pending;
-	struct bfa_mbox_cmd_s endis_mb;
-	bfa_port_endis_cbfn_t endis_cbfn;
-	void           *endis_cbarg;
-	bfa_status_t    endis_status;
-	struct bfa_ioc_hbfail_notify_s hbfail;
-};
-
-void            bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc,
-				void *dev, struct bfa_trc_mod_s *trcmod,
-				struct bfa_log_mod_s *logmod);
-void            bfa_port_detach(struct bfa_port_s *port);
-void            bfa_port_hbfail(void *arg);
-
-bfa_status_t    bfa_port_get_stats(struct bfa_port_s *port,
-				   union bfa_pport_stats_u *stats,
-				   bfa_port_stats_cbfn_t cbfn, void *cbarg);
-bfa_status_t    bfa_port_clear_stats(struct bfa_port_s *port,
-				     bfa_port_stats_cbfn_t cbfn, void *cbarg);
-bfa_status_t    bfa_port_enable(struct bfa_port_s *port,
-				bfa_port_endis_cbfn_t cbfn, void *cbarg);
-bfa_status_t    bfa_port_disable(struct bfa_port_s *port,
-				 bfa_port_endis_cbfn_t cbfn, void *cbarg);
-u32        bfa_port_meminfo(void);
-void            bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva,
-				   u64 dma_pa);
-
-#endif /* __BFA_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h b/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h
deleted file mode 100644
index 1563ee5..0000000
--- a/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved.
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __ETHPORT_DEFS_H__
-#define __ETHPORT_DEFS_H__
-
-struct bnad_drv_stats {
-	u64 netif_queue_stop;
-	u64 netif_queue_wakeup;
-	u64 tso4;
-	u64 tso6;
-	u64 tso_err;
-	u64 tcpcsum_offload;
-	u64 udpcsum_offload;
-	u64 csum_help;
-	u64 csum_help_err;
-
-	u64 hw_stats_updates;
-	u64 netif_rx_schedule;
-	u64 netif_rx_complete;
-	u64 netif_rx_dropped;
-};
-#endif
diff --git a/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h b/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h
deleted file mode 100644
index eb75480..0000000
--- a/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved.
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __PHYPORT_DEFS_H__
-#define __PHYPORT_DEFS_H__
-
-#define BNA_TXF_ID_MAX  	64
-#define BNA_RXF_ID_MAX  	64
-
-/*
- * Statistics
- */
-
-/*
- * TxF Frame Statistics
- */
-struct bna_stats_txf {
-	u64        ucast_octets;
-	u64        ucast;
-	u64        ucast_vlan;
-
-	u64        mcast_octets;
-	u64        mcast;
-	u64        mcast_vlan;
-
-	u64        bcast_octets;
-	u64        bcast;
-	u64        bcast_vlan;
-
-	u64        errors;
-	u64        filter_vlan;	/* frames filtered due to VLAN */
-	u64        filter_mac_sa;	/* frames filtered due to SA check */
-};
-
-/*
- * RxF Frame Statistics
- */
-struct bna_stats_rxf {
-	u64        ucast_octets;
-	u64        ucast;
-	u64        ucast_vlan;
-
-	u64        mcast_octets;
-	u64        mcast;
-	u64        mcast_vlan;
-
-	u64        bcast_octets;
-	u64        bcast;
-	u64        bcast_vlan;
-	u64        frame_drops;
-};
-
-/*
- * FC Tx Frame Statistics
- */
-struct bna_stats_fc_tx {
-	u64        txf_ucast_octets;
-	u64        txf_ucast;
-	u64        txf_ucast_vlan;
-
-	u64        txf_mcast_octets;
-	u64        txf_mcast;
-	u64        txf_mcast_vlan;
-
-	u64        txf_bcast_octets;
-	u64        txf_bcast;
-	u64        txf_bcast_vlan;
-
-	u64        txf_parity_errors;
-	u64        txf_timeout;
-	u64        txf_fid_parity_errors;
-};
-
-/*
- * FC Rx Frame Statistics
- */
-struct bna_stats_fc_rx {
-	u64        rxf_ucast_octets;
-	u64        rxf_ucast;
-	u64        rxf_ucast_vlan;
-
-	u64        rxf_mcast_octets;
-	u64        rxf_mcast;
-	u64        rxf_mcast_vlan;
-
-	u64        rxf_bcast_octets;
-	u64        rxf_bcast;
-	u64        rxf_bcast_vlan;
-};
-
-/*
- * RAD Frame Statistics
- */
-struct cna_stats_rad {
-	u64        rx_frames;
-	u64        rx_octets;
-	u64        rx_vlan_frames;
-
-	u64        rx_ucast;
-	u64        rx_ucast_octets;
-	u64        rx_ucast_vlan;
-
-	u64        rx_mcast;
-	u64        rx_mcast_octets;
-	u64        rx_mcast_vlan;
-
-	u64        rx_bcast;
-	u64        rx_bcast_octets;
-	u64        rx_bcast_vlan;
-
-	u64        rx_drops;
-};
-
-/*
- * BPC Tx Registers
- */
-struct cna_stats_bpc_tx {
-	u64        tx_pause[8];
-	u64        tx_zero_pause[8];	/*  Pause cancellation */
-	u64        tx_first_pause[8];	/*  Pause initiation rather
-						 *than retention */
-};
-
-/*
- * BPC Rx Registers
- */
-struct cna_stats_bpc_rx {
-	u64        rx_pause[8];
-	u64        rx_zero_pause[8];	/*  Pause cancellation */
-	u64        rx_first_pause[8];	/*  Pause initiation rather
-						 *than retention */
-};
-
-/*
- * MAC Rx Statistics
- */
-struct cna_stats_mac_rx {
-	u64        frame_64;	/* both rx and tx counter */
-	u64        frame_65_127;	/* both rx and tx counter */
-	u64        frame_128_255;	/* both rx and tx counter */
-	u64        frame_256_511;	/* both rx and tx counter */
-	u64        frame_512_1023;	/* both rx and tx counter */
-	u64        frame_1024_1518;	/* both rx and tx counter */
-	u64        frame_1518_1522;	/* both rx and tx counter */
-	u64        rx_bytes;
-	u64        rx_packets;
-	u64        rx_fcs_error;
-	u64        rx_multicast;
-	u64        rx_broadcast;
-	u64        rx_control_frames;
-	u64        rx_pause;
-	u64        rx_unknown_opcode;
-	u64        rx_alignment_error;
-	u64        rx_frame_length_error;
-	u64        rx_code_error;
-	u64        rx_carrier_sense_error;
-	u64        rx_undersize;
-	u64        rx_oversize;
-	u64        rx_fragments;
-	u64        rx_jabber;
-	u64        rx_drop;
-};
-
-/*
- * MAC Tx Statistics
- */
-struct cna_stats_mac_tx {
-	u64        tx_bytes;
-	u64        tx_packets;
-	u64        tx_multicast;
-	u64        tx_broadcast;
-	u64        tx_pause;
-	u64        tx_deferral;
-	u64        tx_excessive_deferral;
-	u64        tx_single_collision;
-	u64        tx_muliple_collision;
-	u64        tx_late_collision;
-	u64        tx_excessive_collision;
-	u64        tx_total_collision;
-	u64        tx_pause_honored;
-	u64        tx_drop;
-	u64        tx_jabber;
-	u64        tx_fcs_error;
-	u64        tx_control_frame;
-	u64        tx_oversize;
-	u64        tx_undersize;
-	u64        tx_fragments;
-};
-
-/*
- * Complete statistics
- */
-struct bna_stats {
-	struct cna_stats_mac_rx mac_rx_stats;
-	struct cna_stats_bpc_rx bpc_rx_stats;
-	struct cna_stats_rad rad_stats;
-	struct bna_stats_fc_rx fc_rx_stats;
-	struct cna_stats_mac_tx mac_tx_stats;
-	struct cna_stats_bpc_tx bpc_tx_stats;
-	struct bna_stats_fc_tx fc_tx_stats;
-	struct bna_stats_rxf rxf_stats[BNA_TXF_ID_MAX];
-	struct bna_stats_txf txf_stats[BNA_RXF_ID_MAX];
-};
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_checksum.h b/drivers/scsi/bfa/include/cs/bfa_checksum.h
deleted file mode 100644
index 650f8d0..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_checksum.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_checksum.h BFA checksum utilities
- */
-
-#ifndef __BFA_CHECKSUM_H__
-#define __BFA_CHECKSUM_H__
-
-static inline u32
-bfa_checksum_u32(u32 *buf, int sz)
-{
-	int		i, m = sz >> 2;
-	u32	sum = 0;
-
-	for (i = 0; i < m; i++)
-		sum ^= buf[i];
-
-	return sum;
-}
-
-static inline u16
-bfa_checksum_u16(u16 *buf, int sz)
-{
-	int             i, m = sz >> 1;
-	u16        sum = 0;
-
-	for (i = 0; i < m; i++)
-		sum ^= buf[i];
-
-	return sum;
-}
-
-static inline u8
-bfa_checksum_u8(u8 *buf, int sz)
-{
-	int             i;
-	u8         sum = 0;
-
-	for (i = 0; i < sz; i++)
-		sum ^= buf[i];
-
-	return sum;
-}
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_debug.h b/drivers/scsi/bfa/include/cs/bfa_debug.h
deleted file mode 100644
index 75a911e..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_debug.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_debug.h BFA debug interfaces
- */
-
-#ifndef __BFA_DEBUG_H__
-#define __BFA_DEBUG_H__
-
-#define bfa_assert(__cond)	do {					\
-	if (!(__cond)) 							\
-		bfa_panic(__LINE__, __FILE__, #__cond);      \
-} while (0)
-
-#define bfa_sm_fault(__mod, __event)	do {				\
-	bfa_trc(__mod, (((uint32_t)0xDEAD << 16) | __event));		\
-	bfa_sm_panic((__mod)->logm, __LINE__, __FILE__, __event); 	\
-} while (0)
-
-#ifndef BFA_PERF_BUILD
-#define bfa_assert_fp(__cond)	bfa_assert(__cond)
-#else
-#define bfa_assert_fp(__cond)
-#endif
-
-struct bfa_log_mod_s;
-void bfa_panic(int line, char *file, char *panicstr);
-void bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event);
-
-#endif /* __BFA_DEBUG_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_log.h b/drivers/scsi/bfa/include/cs/bfa_log.h
deleted file mode 100644
index bc334e0..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_log.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_log.h BFA log library data structure and function definition
- */
-
-#ifndef __BFA_LOG_H__
-#define __BFA_LOG_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_aen.h>
-
-/*
- * BFA log module definition
- *
- * To create a new module id:
- * Add a #define at the end of the list below. Select a value for your
- * definition so that it is one (1) greater than the previous
- * definition. Modify the definition of BFA_LOG_MODULE_ID_MAX to become
- * your new definition.
- * Should have no gaps in between the values because this is used in arrays.
- * IMPORTANT: AEN_IDs must be at the begining, otherwise update bfa_defs_aen.h
- */
-
-enum bfa_log_module_id {
-	BFA_LOG_UNUSED_ID	= 0,
-
-	/* AEN defs begin */
-	BFA_LOG_AEN_MIN		= BFA_LOG_UNUSED_ID,
-
-	BFA_LOG_AEN_ID_ADAPTER 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_ADAPTER,/* 1 */
-	BFA_LOG_AEN_ID_PORT 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_PORT,	/* 2 */
-	BFA_LOG_AEN_ID_LPORT 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_LPORT,	/* 3 */
-	BFA_LOG_AEN_ID_RPORT 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_RPORT,	/* 4 */
-	BFA_LOG_AEN_ID_ITNIM 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_ITNIM,	/* 5 */
-	BFA_LOG_AEN_ID_TIN 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_TIN,	/* 6 */
-	BFA_LOG_AEN_ID_IPFC 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_IPFC,	/* 7 */
-	BFA_LOG_AEN_ID_AUDIT 	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_AUDIT,	/* 8 */
-	BFA_LOG_AEN_ID_IOC	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_IOC,	/* 9 */
-	BFA_LOG_AEN_ID_ETHPORT	= BFA_LOG_AEN_MIN + BFA_AEN_CAT_ETHPORT,/* 10 */
-
-	BFA_LOG_AEN_MAX		= BFA_LOG_AEN_ID_ETHPORT,
-	/* AEN defs end */
-
-	BFA_LOG_MODULE_ID_MIN	= BFA_LOG_AEN_MAX,
-
-	BFA_LOG_FW_ID		= BFA_LOG_MODULE_ID_MIN + 1,
-	BFA_LOG_HAL_ID		= BFA_LOG_MODULE_ID_MIN + 2,
-	BFA_LOG_FCS_ID		= BFA_LOG_MODULE_ID_MIN + 3,
-	BFA_LOG_WDRV_ID		= BFA_LOG_MODULE_ID_MIN + 4,
-	BFA_LOG_LINUX_ID	= BFA_LOG_MODULE_ID_MIN + 5,
-	BFA_LOG_SOLARIS_ID	= BFA_LOG_MODULE_ID_MIN + 6,
-
-	BFA_LOG_MODULE_ID_MAX 	= BFA_LOG_SOLARIS_ID,
-
-	/* Not part of any arrays */
-	BFA_LOG_MODULE_ID_ALL 	= BFA_LOG_MODULE_ID_MAX + 1,
-	BFA_LOG_AEN_ALL 	= BFA_LOG_MODULE_ID_MAX + 2,
-	BFA_LOG_DRV_ALL		= BFA_LOG_MODULE_ID_MAX + 3,
-};
-
-/*
- * BFA log catalog name
- */
-#define BFA_LOG_CAT_NAME	"BFA"
-
-/*
- * bfa log severity values
- */
-enum bfa_log_severity {
-	BFA_LOG_INVALID = 0,
-	BFA_LOG_CRITICAL = 1,
-	BFA_LOG_ERROR = 2,
-	BFA_LOG_WARNING = 3,
-	BFA_LOG_INFO = 4,
-	BFA_LOG_NONE = 5,
-	BFA_LOG_LEVEL_MAX = BFA_LOG_NONE
-};
-
-#define BFA_LOG_MODID_OFFSET		16
-
-
-struct bfa_log_msgdef_s {
-	u32	msg_id;		/*  message id */
-	int		attributes;	/*  attributes */
-	int		severity;	/*  severity level */
-	char		*msg_value;
-					/*  msg string */
-	char		*message;
-					/*  msg format string */
-	int		arg_type;	/*  argument type */
-	int		arg_num;	/*  number of argument */
-};
-
-/*
- * supported argument type
- */
-enum bfa_log_arg_type {
-	BFA_LOG_S = 0,		/*  string */
-	BFA_LOG_D,		/*  decimal */
-	BFA_LOG_I,		/*  integer */
-	BFA_LOG_O,		/*  oct number */
-	BFA_LOG_U,		/*  unsigned integer */
-	BFA_LOG_X,		/*  hex number */
-	BFA_LOG_F,		/*  floating */
-	BFA_LOG_C,		/*  character */
-	BFA_LOG_L,		/*  double */
-	BFA_LOG_P		/*  pointer */
-};
-
-#define BFA_LOG_ARG_TYPE	2
-#define BFA_LOG_ARG0		(0 * BFA_LOG_ARG_TYPE)
-#define BFA_LOG_ARG1		(1 * BFA_LOG_ARG_TYPE)
-#define BFA_LOG_ARG2		(2 * BFA_LOG_ARG_TYPE)
-#define BFA_LOG_ARG3		(3 * BFA_LOG_ARG_TYPE)
-
-#define BFA_LOG_GET_MOD_ID(msgid) ((msgid >> BFA_LOG_MODID_OFFSET) & 0xff)
-#define BFA_LOG_GET_MSG_IDX(msgid) (msgid & 0xffff)
-#define BFA_LOG_GET_MSG_ID(msgdef) ((msgdef)->msg_id)
-#define BFA_LOG_GET_MSG_FMT_STRING(msgdef) ((msgdef)->message)
-#define BFA_LOG_GET_SEVERITY(msgdef) ((msgdef)->severity)
-
-/*
- * Event attributes
- */
-#define BFA_LOG_ATTR_NONE	0
-#define BFA_LOG_ATTR_AUDIT	1
-#define BFA_LOG_ATTR_LOG	2
-#define BFA_LOG_ATTR_FFDC	4
-
-#define BFA_LOG_CREATE_ID(msw, lsw) \
-	(((u32)msw << BFA_LOG_MODID_OFFSET) | lsw)
-
-struct bfa_log_mod_s;
-
-/**
- * callback function
- */
-typedef void (*bfa_log_cb_t)(struct bfa_log_mod_s *log_mod, u32 msg_id,
-			const char *format, ...);
-
-
-struct bfa_log_mod_s {
-	char		instance_info[BFA_STRING_32];	/*  instance info */
-	int		log_level[BFA_LOG_MODULE_ID_MAX + 1];
-						/*  log level for modules */
-	bfa_log_cb_t	cbfn; 			/*  callback function */
-};
-
-extern int bfa_log_init(struct bfa_log_mod_s *log_mod,
-			char *instance_name, bfa_log_cb_t cbfn);
-extern int bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...);
-extern bfa_status_t bfa_log_set_level(struct bfa_log_mod_s *log_mod,
-			int mod_id, enum bfa_log_severity log_level);
-extern bfa_status_t bfa_log_set_level_all(struct bfa_log_mod_s *log_mod,
-			enum bfa_log_severity log_level);
-extern bfa_status_t bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod,
-			enum bfa_log_severity log_level);
-extern enum bfa_log_severity bfa_log_get_level(struct bfa_log_mod_s *log_mod,
-			int mod_id);
-extern enum bfa_log_severity bfa_log_get_msg_level(
-			struct bfa_log_mod_s *log_mod, u32 msg_id);
-/*
- * array of messages generated from xml files
- */
-extern struct bfa_log_msgdef_s bfa_log_msg_array[];
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_perf.h b/drivers/scsi/bfa/include/cs/bfa_perf.h
deleted file mode 100644
index 45aa5f9..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_perf.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFAD_PERF_H__
-#define __BFAD_PERF_H__
-
-#ifdef BFAD_PERF_BUILD
-
-#undef bfa_trc
-#undef bfa_trc32
-#undef bfa_assert
-#undef BFA_TRC_FILE
-
-#define bfa_trc(_trcp, _data)
-#define bfa_trc32(_trcp, _data)
-#define bfa_assert(__cond)
-#define BFA_TRC_FILE(__mod, __submod)
-
-#endif
-
-#endif /* __BFAD_PERF_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_plog.h b/drivers/scsi/bfa/include/cs/bfa_plog.h
deleted file mode 100644
index f5bef63..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_plog.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_PORTLOG_H__
-#define __BFA_PORTLOG_H__
-
-#include "protocol/fc.h"
-#include <defs/bfa_defs_types.h>
-
-#define BFA_PL_NLOG_ENTS 256
-#define BFA_PL_LOG_REC_INCR(_x) ((_x)++, (_x) %= BFA_PL_NLOG_ENTS)
-
-#define BFA_PL_STRING_LOG_SZ   32   /* number of chars in string log */
-#define BFA_PL_INT_LOG_SZ      8    /* number of integers in the integer log */
-
-enum bfa_plog_log_type {
-	BFA_PL_LOG_TYPE_INVALID = 0,
-	BFA_PL_LOG_TYPE_INT 	= 1,
-	BFA_PL_LOG_TYPE_STRING 	= 2,
-};
-
-/*
- * the (fixed size) record format for each entry in the portlog
- */
-struct bfa_plog_rec_s {
-	u32        tv;	/* Filled by the portlog driver when the *
-				 * entry is added to the circular log.   */
-	u8         port;	/* Source port that logged this entry. CM
-				 * entities will use 0xFF */
-	u8         mid;	/* Integer value to be used by all entities *
-				 * while logging. The module id to string   *
-				 * conversion will be done by BFAL. See
-				 * enum bfa_plog_mid */
-	u8         eid;	/* indicates Rx, Tx, IOCTL, etc. See
-				 * enum bfa_plog_eid */
-	u8         log_type; /* indicates string log or integer log.
-				   * see bfa_plog_log_type_t */
-	u8         log_num_ints;
-	/*
-	 * interpreted only if log_type is INT_LOG. indicates number of
-	 * integers in the int_log[] (0-PL_INT_LOG_SZ).
-	 */
-	u8         rsvd;
-	u16        misc;	/* can be used to indicate fc frame length,
-				 *etc.. */
-	union {
-		char            string_log[BFA_PL_STRING_LOG_SZ];
-		u32        int_log[BFA_PL_INT_LOG_SZ];
-	} log_entry;
-
-};
-
-/*
- * the following #defines will be used by the logging entities to indicate
- * their module id. BFAL will convert the integer value to string format
- *
-* process to be used while changing the following #defines:
- *  - Always add new entries at the end
- *  - define corresponding string in BFAL
- *  - Do not remove any entry or rearrange the order.
- */
-enum bfa_plog_mid {
-	BFA_PL_MID_INVALID 	= 0,
-	BFA_PL_MID_DEBUG 	= 1,
-	BFA_PL_MID_DRVR 	= 2,
-	BFA_PL_MID_HAL 		= 3,
-	BFA_PL_MID_HAL_FCXP 	= 4,
-	BFA_PL_MID_HAL_UF 	= 5,
-	BFA_PL_MID_FCS 		= 6,
-	BFA_PL_MID_LPS		= 7,
-	BFA_PL_MID_MAX 		= 8
-};
-
-#define BFA_PL_MID_STRLEN    8
-struct bfa_plog_mid_strings_s {
-	char            m_str[BFA_PL_MID_STRLEN];
-};
-
-/*
- * the following #defines will be used by the logging entities to indicate
- * their event type. BFAL will convert the integer value to string format
- *
-* process to be used while changing the following #defines:
- *  - Always add new entries at the end
- *  - define corresponding string in BFAL
- *  - Do not remove any entry or rearrange the order.
- */
-enum bfa_plog_eid {
-	BFA_PL_EID_INVALID 		= 0,
-	BFA_PL_EID_IOC_DISABLE 		= 1,
-	BFA_PL_EID_IOC_ENABLE 		= 2,
-	BFA_PL_EID_PORT_DISABLE 	= 3,
-	BFA_PL_EID_PORT_ENABLE 		= 4,
-	BFA_PL_EID_PORT_ST_CHANGE 	= 5,
-	BFA_PL_EID_TX 			= 6,
-	BFA_PL_EID_TX_ACK1 		= 7,
-	BFA_PL_EID_TX_RJT 		= 8,
-	BFA_PL_EID_TX_BSY 		= 9,
-	BFA_PL_EID_RX 			= 10,
-	BFA_PL_EID_RX_ACK1 		= 11,
-	BFA_PL_EID_RX_RJT 		= 12,
-	BFA_PL_EID_RX_BSY 		= 13,
-	BFA_PL_EID_CT_IN 		= 14,
-	BFA_PL_EID_CT_OUT 		= 15,
-	BFA_PL_EID_DRIVER_START 	= 16,
-	BFA_PL_EID_RSCN 		= 17,
-	BFA_PL_EID_DEBUG 		= 18,
-	BFA_PL_EID_MISC 		= 19,
-	BFA_PL_EID_FIP_FCF_DISC		= 20,
-	BFA_PL_EID_FIP_FCF_CVL		= 21,
-	BFA_PL_EID_LOGIN		= 22,
-	BFA_PL_EID_LOGO			= 23,
-	BFA_PL_EID_MAX			= 24
-};
-
-#define BFA_PL_ENAME_STRLEN    	8
-struct bfa_plog_eid_strings_s {
-	char            e_str[BFA_PL_ENAME_STRLEN];
-};
-
-#define BFA_PL_SIG_LEN	8
-#define BFA_PL_SIG_STR  "12pl123"
-
-/*
- * per port circular log buffer
- */
-struct bfa_plog_s {
-	char            plog_sig[BFA_PL_SIG_LEN];	/* Start signature */
-	u8         plog_enabled;
-	u8         rsvd[7];
-	u32        ticks;
-	u16        head;
-	u16        tail;
-	struct bfa_plog_rec_s  plog_recs[BFA_PL_NLOG_ENTS];
-};
-
-void bfa_plog_init(struct bfa_plog_s *plog);
-void bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event, u16 misc, char *log_str);
-void bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event, u16 misc,
-			u32 *intarr, u32 num_ints);
-void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event, u16 misc,
-			struct fchs_s *fchdr);
-void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event, u16 misc,
-			struct fchs_s *fchdr, u32 pld_w0);
-void bfa_plog_clear(struct bfa_plog_s *plog);
-void bfa_plog_enable(struct bfa_plog_s *plog);
-void bfa_plog_disable(struct bfa_plog_s *plog);
-bfa_boolean_t	bfa_plog_get_setting(struct bfa_plog_s *plog);
-
-#endif /* __BFA_PORTLOG_H__ */
diff --git a/drivers/scsi/bfa/include/cs/bfa_q.h b/drivers/scsi/bfa/include/cs/bfa_q.h
deleted file mode 100644
index ea895fa..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_q.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_q.h Circular queue definitions.
- */
-
-#ifndef __BFA_Q_H__
-#define __BFA_Q_H__
-
-#define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next))
-#define bfa_q_next(_qe)	(((struct list_head *) (_qe))->next)
-#define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev)
-
-/*
- * bfa_q_qe_init - to initialize a queue element
- */
-#define bfa_q_qe_init(_qe) {						\
-	bfa_q_next(_qe) = (struct list_head *) NULL;			\
-	bfa_q_prev(_qe) = (struct list_head *) NULL;			\
-}
-
-/*
- * bfa_q_deq - dequeue an element from head of the queue
- */
-#define bfa_q_deq(_q, _qe) {						\
-	if (!list_empty(_q)) {					\
-		(*((struct list_head **) (_qe))) = bfa_q_next(_q);	\
-		bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) =	\
-						(struct list_head *) (_q); \
-		bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \
-		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		\
-	} else {							\
-		*((struct list_head **) (_qe)) = (struct list_head *) NULL; \
-	}								\
-}
-
-/*
- * bfa_q_deq_tail - dequeue an element from tail of the queue
- */
-#define bfa_q_deq_tail(_q, _qe) {					    \
-	if (!list_empty(_q)) {					            \
-		*((struct list_head **) (_qe)) = bfa_q_prev(_q);	    \
-		bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = 	    \
-						(struct list_head *) (_q);  \
-		bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);    \
-		BFA_Q_DBG_INIT(*((struct list_head **) _qe));		    \
-	} else {							    \
-		*((struct list_head **) (_qe)) = (struct list_head *) NULL; \
-	}								    \
-}
-
-/*
- * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not
- * consistent across modules)
- */
-#ifndef BFA_PERF_BUILD
-#define BFA_Q_DBG_INIT(_qe)	bfa_q_qe_init(_qe)
-#else
-#define BFA_Q_DBG_INIT(_qe)
-#endif
-
-#define bfa_q_is_on_q(_q, _qe)		\
-	bfa_q_is_on_q_func(_q, (struct list_head *)(_qe))
-extern int bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe);
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_sm.h b/drivers/scsi/bfa/include/cs/bfa_sm.h
deleted file mode 100644
index 11fba90..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_sm.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfasm.h State machine defines
- */
-
-#ifndef __BFA_SM_H__
-#define __BFA_SM_H__
-
-typedef void (*bfa_sm_t)(void *sm, int event);
-/**
- * oc - object class eg. bfa_ioc
- * st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc_s
- * etype - object type, eg. enum ioc_event
- */
-#define bfa_sm_state_decl(oc, st, otype, etype)         \
-	static void oc ## _sm_ ## st(otype * fsm, etype event)
-
-#define bfa_sm_set_state(_sm, _state)	((_sm)->sm = (bfa_sm_t)(_state))
-#define bfa_sm_send_event(_sm, _event)	((_sm)->sm((_sm), (_event)))
-#define bfa_sm_get_state(_sm)		((_sm)->sm)
-#define bfa_sm_cmp_state(_sm, _state)	((_sm)->sm == (bfa_sm_t)(_state))
-
-/**
- * For converting from state machine function to state encoding.
- */
-struct bfa_sm_table_s {
-	bfa_sm_t	sm;	/*  state machine function	*/
-	int		state;	/*  state machine encoding	*/
-	char		*name;	/*  state name for display	*/
-};
-#define BFA_SM(_sm)	((bfa_sm_t)(_sm))
-
-int bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm);
-
-/**
- * State machine with entry actions.
- */
-typedef void (*bfa_fsm_t)(void *fsm, int event);
-
-/**
- * oc - object class eg. bfa_ioc
- * st - state, eg. reset
- * otype - object type, eg. struct bfa_ioc_s
- * etype - object type, eg. enum ioc_event
- */
-#define bfa_fsm_state_decl(oc, st, otype, etype)		\
-	static void oc ## _sm_ ## st(otype * fsm, etype event);      \
-	static void oc ## _sm_ ## st ## _entry(otype * fsm)
-
-#define bfa_fsm_set_state(_fsm, _state) do {	\
-	(_fsm)->fsm = (bfa_fsm_t)(_state);      \
-	_state ## _entry(_fsm);      \
-} while (0)
-
-#define bfa_fsm_send_event(_fsm, _event)	\
-	((_fsm)->fsm((_fsm), (_event)))
-#define bfa_fsm_cmp_state(_fsm, _state)		\
-	((_fsm)->fsm == (bfa_fsm_t)(_state))
-
-#endif
diff --git a/drivers/scsi/bfa/include/cs/bfa_trc.h b/drivers/scsi/bfa/include/cs/bfa_trc.h
deleted file mode 100644
index 310771c..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_trc.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_TRC_H__
-#define __BFA_TRC_H__
-
-#include <bfa_os_inc.h>
-
-#ifndef BFA_TRC_MAX
-#define BFA_TRC_MAX	(4 * 1024)
-#endif
-
-#ifndef BFA_TRC_TS
-#define BFA_TRC_TS(_trcm)	((_trcm)->ticks++)
-#endif
-
-struct bfa_trc_s {
-#ifdef __BIGENDIAN
-	u16	fileno;
-	u16	line;
-#else
-	u16	line;
-	u16	fileno;
-#endif
-	u32	timestamp;
-	union {
-		struct {
-			u32	rsvd;
-			u32	u32;
-		} u32;
-		u64	u64;
-	} data;
-};
-
-
-struct bfa_trc_mod_s {
-	u32	head;
-	u32	tail;
-	u32	ntrc;
-	u32	stopped;
-	u32	ticks;
-	u32	rsvd[3];
-	struct bfa_trc_s trc[BFA_TRC_MAX];
-};
-
-
-enum {
-	BFA_TRC_FW   = 1,	/*  firmware modules */
-	BFA_TRC_HAL  = 2,	/*  BFA modules */
-	BFA_TRC_FCS  = 3,	/*  BFA FCS modules */
-	BFA_TRC_LDRV = 4,	/*  Linux driver modules */
-	BFA_TRC_SDRV = 5,	/*  Solaris driver modules */
-	BFA_TRC_VDRV = 6,	/*  vmware driver modules */
-	BFA_TRC_WDRV = 7,	/*  windows driver modules */
-	BFA_TRC_AEN  = 8,	/*  AEN module */
-	BFA_TRC_BIOS = 9,	/*  bios driver modules */
-	BFA_TRC_EFI  = 10,	/*  EFI driver modules */
-	BNA_TRC_WDRV = 11,	/*  BNA windows driver modules */
-	BNA_TRC_VDRV = 12,	/*  BNA vmware driver modules */
-	BNA_TRC_SDRV = 13,	/*  BNA Solaris driver modules */
-	BNA_TRC_LDRV = 14,	/*  BNA Linux driver modules */
-	BNA_TRC_HAL  = 15,	/*  BNA modules */
-	BFA_TRC_CNA  = 16,	/*  Common modules */
-	BNA_TRC_IMDRV = 17	/*  BNA windows intermediate driver modules */
-};
-#define BFA_TRC_MOD_SH	10
-#define BFA_TRC_MOD(__mod)	((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH)
-
-/**
- * Define a new tracing file (module). Module should match one defined above.
- */
-#define BFA_TRC_FILE(__mod, __submod)					\
-	static int __trc_fileno = ((BFA_TRC_ ## __mod ## _ ## __submod) | \
-						 BFA_TRC_MOD(__mod))
-
-
-#define bfa_trc32(_trcp, _data)	\
-	__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
-
-
-#ifndef BFA_BOOT_BUILD
-#define bfa_trc(_trcp, _data)	\
-	__bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data)
-#else
-void bfa_boot_trc(struct bfa_trc_mod_s *trcmod, u16 fileno,
-			u16 line, u32 data);
-#define bfa_trc(_trcp, _data)	\
-	bfa_boot_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data)
-#endif
-
-
-static inline void
-bfa_trc_init(struct bfa_trc_mod_s *trcm)
-{
-	trcm->head = trcm->tail = trcm->stopped = 0;
-	trcm->ntrc = BFA_TRC_MAX;
-}
-
-
-static inline void
-bfa_trc_stop(struct bfa_trc_mod_s *trcm)
-{
-	trcm->stopped = 1;
-}
-
-#ifdef FWTRC
-extern void dc_flush(void *data);
-#else
-#define dc_flush(data)
-#endif
-
-
-static inline void
-__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
-{
-	int		tail = trcm->tail;
-	struct bfa_trc_s 	*trc = &trcm->trc[tail];
-
-	if (trcm->stopped)
-		return;
-
-	trc->fileno = (u16) fileno;
-	trc->line = (u16) line;
-	trc->data.u64 = data;
-	trc->timestamp = BFA_TRC_TS(trcm);
-	dc_flush(trc);
-
-	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
-	if (trcm->tail == trcm->head)
-		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
-	dc_flush(trcm);
-}
-
-
-static inline void
-__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
-{
-	int		tail = trcm->tail;
-	struct bfa_trc_s *trc = &trcm->trc[tail];
-
-	if (trcm->stopped)
-		return;
-
-	trc->fileno = (u16) fileno;
-	trc->line = (u16) line;
-	trc->data.u32.u32 = data;
-	trc->timestamp = BFA_TRC_TS(trcm);
-	dc_flush(trc);
-
-	trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
-	if (trcm->tail == trcm->head)
-		trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
-	dc_flush(trcm);
-}
-
-#ifndef BFA_PERF_BUILD
-#define bfa_trc_fp(_trcp, _data)	bfa_trc(_trcp, _data)
-#else
-#define bfa_trc_fp(_trcp, _data)
-#endif
-
-#endif /* __BFA_TRC_H__ */
-
diff --git a/drivers/scsi/bfa/include/cs/bfa_wc.h b/drivers/scsi/bfa/include/cs/bfa_wc.h
deleted file mode 100644
index 0460bd4..0000000
--- a/drivers/scsi/bfa/include/cs/bfa_wc.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_wc.h Generic wait counter.
- */
-
-#ifndef __BFA_WC_H__
-#define __BFA_WC_H__
-
-typedef void (*bfa_wc_resume_t) (void *cbarg);
-
-struct bfa_wc_s {
-	bfa_wc_resume_t wc_resume;
-	void		*wc_cbarg;
-	int		wc_count;
-};
-
-static inline void
-bfa_wc_up(struct bfa_wc_s *wc)
-{
-	wc->wc_count++;
-}
-
-static inline void
-bfa_wc_down(struct bfa_wc_s *wc)
-{
-	wc->wc_count--;
-	if (wc->wc_count == 0)
-		wc->wc_resume(wc->wc_cbarg);
-}
-
-/**
- * Initialize a waiting counter.
- */
-static inline void
-bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg)
-{
-	wc->wc_resume = wc_resume;
-	wc->wc_cbarg = wc_cbarg;
-	wc->wc_count = 0;
-	bfa_wc_up(wc);
-}
-
-/**
- * Wait for counter to reach zero
- */
-static inline void
-bfa_wc_wait(struct bfa_wc_s *wc)
-{
-	bfa_wc_down(wc);
-}
-
-#endif
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h b/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h
deleted file mode 100644
index aea0360..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_ADAPTER_H__
-#define __BFA_DEFS_ADAPTER_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_version.h>
-#include <defs/bfa_defs_mfg.h>
-
-/**
- * BFA adapter level attributes.
- */
-enum {
-	BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE),
-					/*
-					 *!< adapter serial num length
-					 */
-	BFA_ADAPTER_MODEL_NAME_LEN  = 16,  /*  model name length */
-	BFA_ADAPTER_MODEL_DESCR_LEN = 128, /*  model description length */
-	BFA_ADAPTER_MFG_NAME_LEN    = 8,   /*  manufacturer name length */
-	BFA_ADAPTER_SYM_NAME_LEN    = 64,  /*  adapter symbolic name length */
-	BFA_ADAPTER_OS_TYPE_LEN	    = 64,  /*  adapter os type length */
-};
-
-struct bfa_adapter_attr_s {
-	char            manufacturer[BFA_ADAPTER_MFG_NAME_LEN];
-	char            serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
-	u32		card_type;
-	char            model[BFA_ADAPTER_MODEL_NAME_LEN];
-	char            model_descr[BFA_ADAPTER_MODEL_DESCR_LEN];
-	wwn_t           pwwn;
-	char            node_symname[FC_SYMNAME_MAX];
-	char            hw_ver[BFA_VERSION_LEN];
-	char            fw_ver[BFA_VERSION_LEN];
-	char            optrom_ver[BFA_VERSION_LEN];
-	char            os_type[BFA_ADAPTER_OS_TYPE_LEN];
-	struct bfa_mfg_vpd_s	vpd;
-	struct mac_s	mac;
-
-	u8		nports;
-	u8		max_speed;
-	u8		prototype;
-	char	        asic_rev;
-
-	u8         pcie_gen;
-	u8         pcie_lanes_orig;
-	u8         pcie_lanes;
-	u8	        cna_capable;
-	u8         is_mezz;
-};
-
-/**
- * BFA adapter level events
- * Arguments below are in BFAL context from Mgmt
- * BFA_PORT_AEN_ADD:        [in]: None     [out]: serial_num, pwwn, nports
- * BFA_PORT_AEN_REMOVE:     [in]: pwwn     [out]: serial_num, pwwn, nports
- */
-enum bfa_adapter_aen_event {
-	BFA_ADAPTER_AEN_ADD 	= 1,	/*  New Adapter found event */
-	BFA_ADAPTER_AEN_REMOVE 	= 2,	/*  Adapter removed event */
-};
-
-struct bfa_adapter_aen_data_s {
-	char            serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
-	u32        nports;	/*  Number of NPorts */
-	wwn_t           pwwn;	/*  WWN of one of its physical port */
-};
-
-#endif /* __BFA_DEFS_ADAPTER_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_aen.h b/drivers/scsi/bfa/include/defs/bfa_defs_aen.h
deleted file mode 100644
index 3524469..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_aen.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_AEN_H__
-#define __BFA_DEFS_AEN_H__
-
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_ioc.h>
-#include <defs/bfa_defs_adapter.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_lport.h>
-#include <defs/bfa_defs_rport.h>
-#include <defs/bfa_defs_itnim.h>
-#include <defs/bfa_defs_tin.h>
-#include <defs/bfa_defs_ipfc.h>
-#include <defs/bfa_defs_audit.h>
-#include <defs/bfa_defs_ethport.h>
-
-#define BFA_AEN_MAX_APP         5
-
-enum bfa_aen_app {
-	bfa_aen_app_bcu = 0,    /* No thread for bcu */
-	bfa_aen_app_hcm = 1,
-	bfa_aen_app_cim = 2,
-	bfa_aen_app_snia = 3,
-	bfa_aen_app_test = 4,   /* To be removed after unit test */
-};
-
-enum bfa_aen_category {
-	BFA_AEN_CAT_ADAPTER 	= 1,
-	BFA_AEN_CAT_PORT 	= 2,
-	BFA_AEN_CAT_LPORT 	= 3,
-	BFA_AEN_CAT_RPORT 	= 4,
-	BFA_AEN_CAT_ITNIM 	= 5,
-	BFA_AEN_CAT_TIN 	= 6,
-	BFA_AEN_CAT_IPFC 	= 7,
-	BFA_AEN_CAT_AUDIT 	= 8,
-	BFA_AEN_CAT_IOC 	= 9,
-	BFA_AEN_CAT_ETHPORT	= 10,
-	BFA_AEN_MAX_CAT 	= 10
-};
-
-#pragma pack(1)
-union bfa_aen_data_u {
-	struct bfa_adapter_aen_data_s 	adapter;
-	struct bfa_port_aen_data_s 	port;
-	struct bfa_lport_aen_data_s 	lport;
-	struct bfa_rport_aen_data_s 	rport;
-	struct bfa_itnim_aen_data_s 	itnim;
-	struct bfa_audit_aen_data_s 	audit;
-	struct bfa_ioc_aen_data_s 	ioc;
-	struct bfa_ethport_aen_data_s 	ethport;
-};
-
-struct bfa_aen_entry_s {
-	enum bfa_aen_category 	aen_category;
-	int			aen_type;
-	union bfa_aen_data_u  	aen_data;
-	struct bfa_timeval_s   	aen_tv;
-	s32         	seq_num;
-	s32         	bfad_num;
-	s32         	rsvd[1];
-};
-
-#pragma pack()
-
-#define bfa_aen_event_t int
-
-#endif /* __BFA_DEFS_AEN_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_audit.h b/drivers/scsi/bfa/include/defs/bfa_defs_audit.h
deleted file mode 100644
index 8e3a962..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_audit.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_AUDIT_H__
-#define __BFA_DEFS_AUDIT_H__
-
-#include <bfa_os_inc.h>
-
-/**
- * BFA audit events
- */
-enum bfa_audit_aen_event {
-	BFA_AUDIT_AEN_AUTH_ENABLE 	= 1,
-	BFA_AUDIT_AEN_AUTH_DISABLE 	= 2,
-};
-
-/**
- * audit event data
- */
-struct bfa_audit_aen_data_s {
-	wwn_t           pwwn;
-};
-
-#endif /* __BFA_DEFS_AUDIT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h b/drivers/scsi/bfa/include/defs/bfa_defs_auth.h
deleted file mode 100644
index f56ed87..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_AUTH_H__
-#define __BFA_DEFS_AUTH_H__
-
-#include <defs/bfa_defs_types.h>
-
-#define PUBLIC_KEY			15409
-#define PRIVATE_KEY			19009
-#define KEY_LEN				32399
-#define BFA_AUTH_SECRET_STRING_LEN	256
-#define BFA_AUTH_FAIL_NO_PASSWORD	0xFE
-#define BFA_AUTH_FAIL_TIMEOUT		0xFF
-
-/**
- * Authentication status
- */
-enum bfa_auth_status {
-	BFA_AUTH_STATUS_NONE 	= 0,	/*  no authentication */
-	BFA_AUTH_UNINIT 	= 1,	/*  state - uninit */
-	BFA_AUTH_NEG_SEND 	= 2,	/*  state - negotiate send */
-	BFA_AUTH_CHAL_WAIT 	= 3,	/*  state - challenge wait */
-	BFA_AUTH_NEG_RETRY 	= 4,	/*  state - negotiate retry */
-	BFA_AUTH_REPLY_SEND 	= 5,	/*  state - reply send */
-	BFA_AUTH_STATUS_WAIT 	= 6,	/*  state - status wait */
-	BFA_AUTH_SUCCESS 	= 7,	/*  state - success */
-	BFA_AUTH_FAILED 	= 8,	/*  state - failed */
-	BFA_AUTH_STATUS_UNKNOWN = 9,	/*  authentication status unknown */
-};
-
-enum bfa_auth_rej_code {
-	BFA_AUTH_RJT_CODE_AUTH_FAILURE   = 1, /* auth failure */
-	BFA_AUTH_RJT_CODE_LOGICAL_ERR    = 2, /* logical error */
-};
-
-/**
- * Authentication reject codes
- */
-enum bfa_auth_rej_code_exp {
-	BFA_AUTH_MECH_NOT_USABLE        = 1, /* auth. mechanism not usable */
-	BFA_AUTH_DH_GROUP_NOT_USABLE    = 2, /* DH Group not usable */
-	BFA_AUTH_HASH_FUNC_NOT_USABLE   = 3, /* hash Function not usable */
-	BFA_AUTH_AUTH_XACT_STARTED      = 4, /* auth xact started */
-	BFA_AUTH_AUTH_FAILED            = 5, /* auth failed */
-	BFA_AUTH_INCORRECT_PLD          = 6, /* incorrect payload */
-	BFA_AUTH_INCORRECT_PROTO_MSG    = 7, /* incorrect proto msg */
-	BFA_AUTH_RESTART_AUTH_PROTO     = 8, /* restart auth protocol */
-	BFA_AUTH_AUTH_CONCAT_NOT_SUPP   = 9, /* auth concat not supported */
-	BFA_AUTH_PROTO_VER_NOT_SUPP     = 10,/* proto version not supported */
-};
-
-struct auth_proto_stats_s {
-	u32        auth_rjts;
-	u32        auth_negs;
-	u32        auth_dones;
-
-	u32        dhchap_challenges;
-	u32        dhchap_replies;
-	u32        dhchap_successes;
-};
-
-/**
- * Authentication related statistics
- */
-struct bfa_auth_stats_s {
-	u32           auth_failures;	/*  authentication failures */
-	u32           auth_successes;	/*  authentication successes*/
-	struct auth_proto_stats_s auth_rx_stats; /*  Rx protocol stats */
-	struct auth_proto_stats_s auth_tx_stats; /*  Tx protocol stats */
-};
-
-/**
- * Authentication hash function algorithms
- */
-enum bfa_auth_algo {
-	BFA_AUTH_ALGO_MD5 	= 1,	/*  Message-Digest algorithm 5 */
-	BFA_AUTH_ALGO_SHA1 	= 2,	/*  Secure Hash Algorithm 1 */
-	BFA_AUTH_ALGO_MS 	= 3,	/*  MD5, then SHA-1 */
-	BFA_AUTH_ALGO_SM 	= 4,	/*  SHA-1, then MD5 */
-};
-
-/**
- * DH Groups
- *
- * Current value could be combination of one or more of the following values
- */
-enum bfa_auth_group {
-	BFA_AUTH_GROUP_DHNULL 	= 0,	/*  DH NULL (value == 0) */
-	BFA_AUTH_GROUP_DH768 	= 1,	/*  DH group 768 (value == 1) */
-	BFA_AUTH_GROUP_DH1024 	= 2,	/*  DH group 1024 (value == 2) */
-	BFA_AUTH_GROUP_DH1280 	= 4,	/*  DH group 1280 (value == 3) */
-	BFA_AUTH_GROUP_DH1536 	= 8,	/*  DH group 1536 (value == 4) */
-
-	BFA_AUTH_GROUP_ALL 	= 256	/*  Use default DH group order
-					 *    0, 1, 2, 3, 4 */
-};
-
-/**
- * Authentication secret sources
- */
-enum bfa_auth_secretsource {
-	BFA_AUTH_SECSRC_LOCAL 	= 1,	/*  locally configured */
-	BFA_AUTH_SECSRC_RADIUS 	= 2,	/*  use radius server */
-	BFA_AUTH_SECSRC_TACACS 	= 3,	/*  TACACS server */
-};
-
-/**
- * Authentication attributes
- */
-struct bfa_auth_attr_s {
-	enum bfa_auth_status 	status;
-	enum bfa_auth_algo 	algo;
-	enum bfa_auth_group 	dh_grp;
-	enum bfa_auth_rej_code  rjt_code;
-	enum bfa_auth_rej_code_exp rjt_code_exp;
-	u8			secret_set;
-	u8			resv[3];
-};
-
-#endif /* __BFA_DEFS_AUTH_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h b/drivers/scsi/bfa/include/defs/bfa_defs_boot.h
deleted file mode 100644
index 0fca10b..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_BOOT_H__
-#define __BFA_DEFS_BOOT_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_pport.h>
-
-enum {
-	BFA_BOOT_BOOTLUN_MAX = 4,	/*  maximum boot lun per IOC */
-	BFA_PREBOOT_BOOTLUN_MAX = 8,    /*  maximum preboot lun per IOC */
-
-};
-
-#define BOOT_CFG_REV1	1
-
-/**
- *      Boot options setting. Boot options setting determines from where
- *      to get the boot lun information
- */
-enum bfa_boot_bootopt {
-    BFA_BOOT_AUTO_DISCOVER = 0,    /*  Boot from blun provided by fabric */
-    BFA_BOOT_STORED_BLUN   = 1,    /*  Boot from bluns stored in flash   */
-    BFA_BOOT_FIRST_LUN     = 2,    /*  Boot from first discovered blun   */
-};
-
-/**
- * Boot lun information.
- */
-struct bfa_boot_bootlun_s {
-	wwn_t           pwwn;	/*  port wwn of target */
-	lun_t           lun;	/*  64-bit lun */
-};
-
-/**
- * BOOT boot configuraton
- */
-struct bfa_boot_cfg_s {
-	u8         version;
-	u8         rsvd1;
-	u16        chksum;
-
-	u8         enable;		/*  enable/disable SAN boot */
-	u8         speed;		/*  boot speed settings */
-	u8         topology;	/*  boot topology setting */
-	u8         bootopt;	/*  bfa_boot_bootopt_t */
-
-	u32        nbluns;		/*  number of boot luns */
-
-	u32        rsvd2;
-
-	struct bfa_boot_bootlun_s blun[BFA_BOOT_BOOTLUN_MAX];
-	struct bfa_boot_bootlun_s blun_disc[BFA_BOOT_BOOTLUN_MAX];
-};
-
-struct bfa_boot_pbc_s {
-	u8         enable;         /* enable/disable SAN boot */
-	u8         speed;          /* boot speed settings */
-	u8         topology;       /* boot topology setting */
-	u8         rsvd1;
-	u32        nbluns;         /* number of boot luns */
-	struct bfa_boot_bootlun_s pblun[BFA_PREBOOT_BOOTLUN_MAX];
-};
-
-#endif /* __BFA_DEFS_BOOT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_cee.h b/drivers/scsi/bfa/include/defs/bfa_defs_cee.h
deleted file mode 100644
index 6eaf519..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_cee.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- *  bfa_defs_cee.h Interface declarations between host based
- *	BFAL and DCBX/LLDP module in Firmware
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_CEE_H__
-#define __BFA_DEFS_CEE_H__
-
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_pport.h>
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-#define BFA_CEE_LLDP_MAX_STRING_LEN (128)
-
-#define BFA_CEE_LLDP_SYS_CAP_OTHER       0x0001
-#define BFA_CEE_LLDP_SYS_CAP_REPEATER    0x0002
-#define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE  0x0004
-#define BFA_CEE_LLDP_SYS_CAP_WLAN_AP     0x0008
-#define BFA_CEE_LLDP_SYS_CAP_ROUTER      0x0010
-#define BFA_CEE_LLDP_SYS_CAP_TELEPHONE 	 0x0020
-#define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD   0x0040
-#define BFA_CEE_LLDP_SYS_CAP_STATION     0x0080
-#define BFA_CEE_LLDP_SYS_CAP_CVLAN	     0x0100
-#define BFA_CEE_LLDP_SYS_CAP_SVLAN 	     0x0200
-#define BFA_CEE_LLDP_SYS_CAP_TPMR		 0x0400
-
-
-/* LLDP string type */
-struct bfa_cee_lldp_str_s {
-	u8 sub_type;
-	u8 len;
-	u8 rsvd[2];
-	u8 value[BFA_CEE_LLDP_MAX_STRING_LEN];
-};
-
-
-/* LLDP parameters */
-struct bfa_cee_lldp_cfg_s {
-	struct bfa_cee_lldp_str_s chassis_id;
-	struct bfa_cee_lldp_str_s port_id;
-	struct bfa_cee_lldp_str_s port_desc;
-	struct bfa_cee_lldp_str_s sys_name;
-	struct bfa_cee_lldp_str_s sys_desc;
-	struct bfa_cee_lldp_str_s mgmt_addr;
-	u16    time_to_interval;
-	u16    enabled_system_cap;
-};
-
-enum bfa_cee_dcbx_version_e {
-	DCBX_PROTOCOL_PRECEE = 1,
-	DCBX_PROTOCOL_CEE    = 2,
-};
-
-enum bfa_cee_lls_e {
-	CEE_LLS_DOWN_NO_TLV = 0, /* LLS is down because the TLV not sent by
-				  * the peer */
-	CEE_LLS_DOWN        = 1, /* LLS is down as advertised by the peer */
-	CEE_LLS_UP          = 2,
-};
-
-/* CEE/DCBX parameters */
-struct bfa_cee_dcbx_cfg_s {
-	u8 pgid[8];
-	u8 pg_percentage[8];
-	u8 pfc_enabled;          /* bitmap of priorties with PFC enabled */
-	u8 fcoe_user_priority;   /* bitmap of priorities used for FcoE
-				       * traffic */
-	u8 dcbx_version;	/* operating version:CEE or preCEE */
-	u8 lls_fcoe;	/* FCoE Logical Link Status */
-	u8 lls_lan;	/* LAN Logical Link Status */
-	u8 rsvd[3];
-};
-
-/* CEE status */
-/* Making this to tri-state for the benefit of port list command */
-enum bfa_cee_status_e {
-	CEE_UP = 0,
-	CEE_PHY_UP = 1,
-	CEE_LOOPBACK = 2,
-	CEE_PHY_DOWN = 3,
-};
-
-/* CEE Query */
-struct bfa_cee_attr_s {
-	u8                   cee_status;
-	u8                   error_reason;
-	struct bfa_cee_lldp_cfg_s lldp_remote;
-	struct bfa_cee_dcbx_cfg_s dcbx_remote;
-	mac_t src_mac;
-	u8 link_speed;
-	u8 nw_priority;
-	u8 filler[2];
-};
-
-
-
-
-/* LLDP/DCBX/CEE Statistics */
-
-struct bfa_cee_lldp_stats_s {
-	u32 frames_transmitted;
-	u32 frames_aged_out;
-	u32 frames_discarded;
-	u32 frames_in_error;
-	u32 frames_rcvd;
-	u32 tlvs_discarded;
-	u32 tlvs_unrecognized;
-};
-
-struct bfa_cee_dcbx_stats_s {
-	u32 subtlvs_unrecognized;
-	u32 negotiation_failed;
-	u32 remote_cfg_changed;
-	u32 tlvs_received;
-	u32 tlvs_invalid;
-	u32 seqno;
-	u32 ackno;
-	u32 recvd_seqno;
-	u32 recvd_ackno;
-};
-
-struct bfa_cee_cfg_stats_s {
-	u32 cee_status_down;
-	u32 cee_status_up;
-	u32 cee_hw_cfg_changed;
-	u32 recvd_invalid_cfg;
-};
-
-
-struct bfa_cee_stats_s {
-	struct bfa_cee_lldp_stats_s lldp_stats;
-	struct bfa_cee_dcbx_stats_s dcbx_stats;
-	struct bfa_cee_cfg_stats_s  cfg_stats;
-};
-
-#pragma pack()
-
-
-#endif	/* __BFA_DEFS_CEE_H__ */
-
-
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h b/drivers/scsi/bfa/include/defs/bfa_defs_driver.h
deleted file mode 100644
index 7d00d00..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_DRIVER_H__
-#define __BFA_DEFS_DRIVER_H__
-
-/**
- * Driver statistics
- */
-struct bfa_driver_stats_s {
-	u16    tm_io_abort;
-    u16    tm_io_abort_comp;
-    u16    tm_lun_reset;
-    u16    tm_lun_reset_comp;
-    u16    tm_target_reset;
-    u16    tm_bus_reset;
-    u16    ioc_restart;        /*  IOC restart count */
-    u16    rsvd;
-    u64    control_req;
-    u64    input_req;
-    u64    output_req;
-    u64    input_words;
-    u64    output_words;
-};
-
-
-#endif /* __BFA_DEFS_DRIVER_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h b/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h
deleted file mode 100644
index b4fa092..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_ETHPORT_H__
-#define __BFA_DEFS_ETHPORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_port.h>
-#include <protocol/types.h>
-#include <cna/pstats/phyport_defs.h>
-#include <cna/pstats/ethport_defs.h>
-
-struct bna_tx_info_s {
-	u32    miniport_state;
-	u32    adapter_state;
-	u64    tx_count;
-	u64    tx_wi;
-	u64    tx_sg;
-	u64    tx_tcp_chksum;
-	u64    tx_udp_chksum;
-	u64    tx_ip_chksum;
-	u64    tx_lsov1;
-	u64    tx_lsov2;
-	u64    tx_max_sg_len ;
-};
-
-struct bna_rx_queue_info_s {
-	u16    q_id ;
-	u16    buf_size ;
-	u16    buf_count ;
-	u16    rsvd ;
-	u64    rx_count ;
-	u64    rx_dropped ;
-	u64    rx_unsupported ;
-	u64    rx_internal_err ;
-	u64    rss_count ;
-	u64    vlan_count ;
-	u64    rx_tcp_chksum ;
-	u64    rx_udp_chksum ;
-	u64    rx_ip_chksum ;
-	u64    rx_hds ;
-};
-
-struct bna_rx_q_set_s {
-	u16    q_set_type;
-	u32    miniport_state;
-	u32    adapter_state;
-	struct bna_rx_queue_info_s    rx_queue[2];
-};
-
-struct bna_port_stats_s {
-	struct bna_tx_info_s   tx_stats;
-	u16        qset_count ;
-	struct bna_rx_q_set_s  rx_qset[8];
-};
-
-struct bfa_ethport_stats_s {
-	struct bna_stats_txf	txf_stats[1];
-	struct bna_stats_rxf	rxf_stats[1];
-	struct bnad_drv_stats drv_stats;
-};
-
-/**
- * Ethernet port events
- * Arguments below are in BFAL context from Mgmt
- * BFA_PORT_AEN_ETH_LINKUP:    [in]: mac [out]: mac
- * BFA_PORT_AEN_ETH_LINKDOWN:  [in]: mac [out]: mac
- * BFA_PORT_AEN_ETH_ENABLE:  [in]: mac [out]: mac
- * BFA_PORT_AEN_ETH_DISABLE:  [in]: mac [out]: mac
- *
- */
-enum bfa_ethport_aen_event {
-	BFA_ETHPORT_AEN_LINKUP = 1, /*  Base Port Ethernet link up event */
-	BFA_ETHPORT_AEN_LINKDOWN = 2, /*  Base Port Ethernet link down event */
-	BFA_ETHPORT_AEN_ENABLE = 3, /*  Base Port Ethernet link enable event */
-	BFA_ETHPORT_AEN_DISABLE = 4, /*  Base Port Ethernet link disable
-				      * event */
-};
-
-struct bfa_ethport_aen_data_s {
-	mac_t mac;	/*  MAC address of the physical port */
-};
-
-
-#endif /* __BFA_DEFS_ETHPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h b/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h
deleted file mode 100644
index c08f4f5..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_FCPIM_H__
-#define __BFA_DEFS_FCPIM_H__
-
-struct bfa_fcpim_stats_s {
-	u32        total_ios;	/*  Total IO count */
-	u32        qresumes;	/*  IO waiting for CQ space */
-	u32        no_iotags;	/*  NO IO contexts */
-	u32        io_aborts;	/*  IO abort requests */
-	u32        no_tskims;	/*  NO task management contexts */
-	u32        iocomp_ok;	/*  IO completions with OK status */
-	u32        iocomp_underrun;	/*  IO underrun (good) */
-	u32        iocomp_overrun;	/*  IO overrun (good) */
-	u32        iocomp_aborted;	/*  Aborted IO requests */
-	u32        iocomp_timedout;	/*  IO timeouts */
-	u32        iocom_nexus_abort;	/*  IO selection timeouts */
-	u32        iocom_proto_err;	/*  IO protocol errors */
-	u32        iocom_dif_err;	/*  IO SBC-3 protection errors */
-	u32        iocom_tm_abort;	/*  IO aborted by TM requests */
-	u32        iocom_sqer_needed;	/*  IO retry for SQ error
-						 *recovery */
-	u32        iocom_res_free;	/*  Delayed freeing of IO resources */
-	u32        iocomp_scsierr;	/*  IO with non-good SCSI status */
-	u32        iocom_hostabrts;	/*  Host IO abort requests */
-	u32        iocom_utags;	/*  IO comp with unknown tags */
-	u32        io_cleanups;	/*  IO implicitly aborted */
-	u32        io_tmaborts;	/*  IO aborted due to TM commands */
-	u32        rsvd;
-};
-#endif /*__BFA_DEFS_FCPIM_H__*/
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h b/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h
deleted file mode 100644
index af86a63..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_fcport.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- *  bfa_defs_fcport.h
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_FCPORT_H__
-#define __BFA_DEFS_FCPORT_H__
-
-#include <defs/bfa_defs_types.h>
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-/**
- * FCoE statistics
- */
-struct bfa_fcoe_stats_s {
-	u64	secs_reset;	/*  Seconds since stats reset	     */
-	u64	cee_linkups;	/*  CEE link up		     */
-	u64	cee_linkdns;	/*  CEE link down		     */
-	u64	fip_linkups;	/*  FIP link up		     */
-	u64	fip_linkdns;	/*  FIP link down		     */
-	u64	fip_fails;	/*  FIP failures		     */
-	u64	mac_invalids;	/*  Invalid mac assignments	     */
-	u64	vlan_req;	/*  Vlan requests		     */
-	u64	vlan_notify;	/*  Vlan notifications		     */
-	u64	vlan_err;	/*  Vlan notification errors	     */
-	u64	vlan_timeouts;	/*  Vlan request timeouts	     */
-	u64	vlan_invalids;	/*  Vlan invalids		     */
-	u64	disc_req;	/*  Discovery requests		     */
-	u64	disc_rsp;	/*  Discovery responses	     */
-	u64	disc_err;	/*  Discovery error frames	     */
-	u64	disc_unsol;	/*  Discovery unsolicited	     */
-	u64	disc_timeouts;	/*  Discovery timeouts		     */
-	u64	disc_fcf_unavail; /*  Discovery FCF not avail	     */
-	u64	linksvc_unsupp;	/*  FIP link service req unsupp.    */
-	u64	linksvc_err;	/*  FIP link service req errors     */
-	u64	logo_req;	/*  FIP logos received			     */
-	u64	clrvlink_req;	/*  Clear virtual link requests     */
-	u64	op_unsupp;	/*  FIP operation unsupp.	     */
-	u64	untagged;	/*  FIP untagged frames	     */
-	u64	txf_ucast;	/*  Tx FCoE unicast frames	     */
-	u64	txf_ucast_vlan;	/*  Tx FCoE unicast vlan frames     */
-	u64	txf_ucast_octets; /*  Tx FCoE unicast octets	     */
-	u64	txf_mcast;	/*  Tx FCoE mutlicast frames	     */
-	u64	txf_mcast_vlan;	/*  Tx FCoE mutlicast vlan frames   */
-	u64	txf_mcast_octets; /*  Tx FCoE multicast octets	     */
-	u64	txf_bcast;	/*  Tx FCoE broadcast frames	     */
-	u64	txf_bcast_vlan;	/*  Tx FCoE broadcast vlan frames   */
-	u64	txf_bcast_octets; /*  Tx FCoE broadcast octets	     */
-	u64	txf_timeout;	/*  Tx timeouts		     */
-	u64	txf_parity_errors; /*  Transmit parity err	     */
-	u64	txf_fid_parity_errors; /*  Transmit FID parity err  */
-	u64     rxf_ucast_octets; /* Rx FCoE unicast octets        */
-	u64     rxf_ucast;      /* Rx FCoE unicast frames          */
-	u64     rxf_ucast_vlan; /* Rx FCoE unicast vlan frames     */
-	u64     rxf_mcast_octets; /* Rx FCoE multicast octets      */
-	u64     rxf_mcast;      /* Rx FCoE multicast frames        */
-	u64     rxf_mcast_vlan; /* Rx FCoE multicast vlan frames   */
-	u64     rxf_bcast_octets; /* Rx FCoE broadcast octets      */
-	u64     rxf_bcast;      /* Rx FCoE broadcast frames        */
-	u64     rxf_bcast_vlan; /* Rx FCoE broadcast vlan frames   */
-};
-
-/**
- * QoS or FCoE stats (fcport stats excluding physical FC port stats)
- */
-union bfa_fcport_stats_u {
-	struct bfa_qos_stats_s	fcqos;
-	struct bfa_fcoe_stats_s	fcoe;
-};
-
-#pragma pack()
-
-#endif  /* __BFA_DEFS_FCPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h
deleted file mode 100644
index add0a05..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_IOC_H__
-#define __BFA_DEFS_IOC_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_version.h>
-#include <defs/bfa_defs_adapter.h>
-#include <defs/bfa_defs_pm.h>
-
-enum {
-	BFA_IOC_DRIVER_LEN	= 16,
-	BFA_IOC_CHIP_REV_LEN 	= 8,
-};
-
-/**
- * Driver and firmware versions.
- */
-struct bfa_ioc_driver_attr_s {
-	char            driver[BFA_IOC_DRIVER_LEN];	/*  driver name */
-	char            driver_ver[BFA_VERSION_LEN];	/*  driver version */
-	char            fw_ver[BFA_VERSION_LEN];	/*  firmware version*/
-	char            bios_ver[BFA_VERSION_LEN];	/*  bios version */
-	char            efi_ver[BFA_VERSION_LEN];	/*  EFI version */
-	char            ob_ver[BFA_VERSION_LEN];	/*  openboot version*/
-};
-
-/**
- * IOC PCI device attributes
- */
-struct bfa_ioc_pci_attr_s {
-	u16        vendor_id;	/*  PCI vendor ID */
-	u16        device_id;	/*  PCI device ID */
-	u16        ssid;		/*  subsystem ID */
-	u16        ssvid;		/*  subsystem vendor ID */
-	u32        pcifn;		/*  PCI device function */
-	u32        rsvd;		/* padding */
-	u8         chip_rev[BFA_IOC_CHIP_REV_LEN];	 /*  chip revision */
-};
-
-/**
- * IOC states
- */
-enum bfa_ioc_state {
-	BFA_IOC_RESET       = 1,  /*  IOC is in reset state */
-	BFA_IOC_SEMWAIT     = 2,  /*  Waiting for IOC hardware semaphore */
-	BFA_IOC_HWINIT 	    = 3,  /*  IOC hardware is being initialized */
-	BFA_IOC_GETATTR     = 4,  /*  IOC is being configured */
-	BFA_IOC_OPERATIONAL = 5,  /*  IOC is operational */
-	BFA_IOC_INITFAIL    = 6,  /*  IOC hardware failure */
-	BFA_IOC_HBFAIL      = 7,  /*  IOC heart-beat failure */
-	BFA_IOC_DISABLING   = 8,  /*  IOC is being disabled */
-	BFA_IOC_DISABLED    = 9,  /*  IOC is disabled */
-	BFA_IOC_FWMISMATCH  = 10, /*  IOC firmware different from drivers */
-};
-
-/**
- * IOC firmware stats
- */
-struct bfa_fw_ioc_stats_s {
-	u32        hb_count;
-	u32        cfg_reqs;
-	u32        enable_reqs;
-	u32        disable_reqs;
-	u32        stats_reqs;
-	u32        clrstats_reqs;
-	u32        unknown_reqs;
-	u32        ic_reqs;		/*  interrupt coalesce reqs */
-};
-
-/**
- * IOC driver stats
- */
-struct bfa_ioc_drv_stats_s {
-	u32	ioc_isrs;
-	u32	ioc_enables;
-	u32	ioc_disables;
-	u32	ioc_hbfails;
-	u32	ioc_boots;
-	u32	stats_tmos;
-	u32        hb_count;
-	u32        disable_reqs;
-	u32        enable_reqs;
-	u32        disable_replies;
-	u32        enable_replies;
-};
-
-/**
- * IOC statistics
- */
-struct bfa_ioc_stats_s {
-	struct bfa_ioc_drv_stats_s	drv_stats; /*  driver IOC stats */
-	struct bfa_fw_ioc_stats_s 	fw_stats;  /*  firmware IOC stats */
-};
-
-
-enum bfa_ioc_type_e {
-	BFA_IOC_TYPE_FC	  = 1,
-	BFA_IOC_TYPE_FCoE = 2,
-	BFA_IOC_TYPE_LL	  = 3,
-};
-
-/**
- * IOC attributes returned in queries
- */
-struct bfa_ioc_attr_s {
-	enum bfa_ioc_type_e		ioc_type;
-	enum bfa_ioc_state 		state;		/*  IOC state      */
-	struct bfa_adapter_attr_s	adapter_attr;	/*  HBA attributes */
-	struct bfa_ioc_driver_attr_s 	driver_attr;	/*  driver attr    */
-	struct bfa_ioc_pci_attr_s	pci_attr;
-	u8				port_id;	/*  port number    */
-	u8				rsvd[7];	/*  64bit align    */
-};
-
-/**
- * BFA IOC level events
- */
-enum bfa_ioc_aen_event {
-	BFA_IOC_AEN_HBGOOD	= 1,	/*  Heart Beat restore event	*/
-	BFA_IOC_AEN_HBFAIL	= 2,	/*  Heart Beat failure event	*/
-	BFA_IOC_AEN_ENABLE	= 3,	/*  IOC enabled event		*/
-	BFA_IOC_AEN_DISABLE	= 4,	/*  IOC disabled event		*/
-	BFA_IOC_AEN_FWMISMATCH	= 5,	/*  IOC firmware mismatch	*/
-	BFA_IOC_AEN_FWCFG_ERROR = 6,    /*  IOC firmware config error   */
-	BFA_IOC_AEN_INVALID_VENDOR = 7,
-	BFA_IOC_AEN_INVALID_NWWN = 8,   /*  Zero NWWN                   */
-	BFA_IOC_AEN_INVALID_PWWN = 9    /*  Zero PWWN                   */
-
-};
-
-/**
- * BFA IOC level event data, now just a place holder
- */
-struct bfa_ioc_aen_data_s {
-	wwn_t	pwwn;
-	s16 ioc_type;
-	mac_t	mac;
-};
-
-#endif /* __BFA_DEFS_IOC_H__ */
-
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h
deleted file mode 100644
index 31e728a..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_IOCFC_H__
-#define __BFA_DEFS_IOCFC_H__
-
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_version.h>
-#include <defs/bfa_defs_adapter.h>
-#include <defs/bfa_defs_pm.h>
-
-#define BFA_IOCFC_INTR_DELAY	1125
-#define BFA_IOCFC_INTR_LATENCY	225
-#define BFA_IOCFCOE_INTR_DELAY  25
-#define BFA_IOCFCOE_INTR_LATENCY 5
-
-/**
- * Interrupt coalescing configuration.
- */
-struct bfa_iocfc_intr_attr_s {
-	bfa_boolean_t	coalesce;	/*  enable/disable coalescing */
-	u16	latency;	/*  latency in microseconds   */
-	u16	delay;		/*  delay in microseconds     */
-};
-
-/**
- * IOC firmware configuraton
- */
-struct bfa_iocfc_fwcfg_s {
-	u16        num_fabrics;	/*  number of fabrics		*/
-	u16        num_lports;	/*  number of local lports	*/
-	u16        num_rports;	/*  number of remote ports	*/
-	u16        num_ioim_reqs;	/*  number of IO reqs		*/
-	u16        num_tskim_reqs;	/*  task management requests	*/
-	u16        num_iotm_reqs;	/*  number of TM IO reqs	*/
-	u16        num_tsktm_reqs;	/*  TM task management requests*/
-	u16        num_fcxp_reqs;	/*  unassisted FC exchanges	*/
-	u16        num_uf_bufs;	/*  unsolicited recv buffers	*/
-	u8	   num_cqs;
-	u8         fw_tick_res;    /*!< FW clock resolution in ms */
-	u8         rsvd[4];
-
-};
-
-struct bfa_iocfc_drvcfg_s {
-	u16        num_reqq_elems;	/*  number of req queue elements */
-	u16        num_rspq_elems;	/*  number of rsp queue elements */
-	u16        num_sgpgs;	/*  number of total SG pages	  */
-	u16        num_sboot_tgts;	/*  number of SAN boot targets	  */
-	u16        num_sboot_luns;	/*  number of SAN boot luns	  */
-	u16	    ioc_recover;	/*  IOC recovery mode		  */
-	u16	    min_cfg;	/*  minimum configuration	  */
-	u16        path_tov;	/*  device path timeout	  */
-	bfa_boolean_t   delay_comp; /*  delay completion of
-							failed inflight IOs */
-	u32		rsvd;
-};
-/**
- * IOC configuration
- */
-struct bfa_iocfc_cfg_s {
-	struct bfa_iocfc_fwcfg_s	fwcfg;	/*  firmware side config */
-	struct bfa_iocfc_drvcfg_s	drvcfg;	/*  driver side config	  */
-};
-
-/**
- * IOC firmware IO stats
- */
-struct bfa_fw_io_stats_s {
-	u32	host_abort;		/*  IO aborted by host driver*/
-	u32	host_cleanup;		/*  IO clean up by host driver */
-
-	u32	fw_io_timeout;		/*  IOs timedout */
-	u32	fw_frm_parse;		/*  frame parsed by f/w */
-	u32	fw_frm_data;		/*  fcp_data frame parsed by f/w */
-	u32	fw_frm_rsp;		/*  fcp_rsp frame parsed by f/w */
-	u32	fw_frm_xfer_rdy;	/*  xfer_rdy frame parsed by f/w */
-	u32	fw_frm_bls_acc;		/*  BLS ACC  frame parsed by f/w */
-	u32	fw_frm_tgt_abort;	/*  target ABTS parsed by f/w */
-	u32	fw_frm_unknown;		/*  unknown parsed by f/w */
-	u32	fw_data_dma;		/*  f/w DMA'ed the data frame */
-	u32	fw_frm_drop;		/*  f/w drop the frame */
-
-	u32	rec_timeout;		/*  FW rec timed out */
-	u32	error_rec;			/*  FW sending rec on
-							* an error condition*/
-	u32	wait_for_si;		/*  FW wait for SI */
-	u32	rec_rsp_inval;		/*  REC rsp invalid */
-	u32	seqr_io_abort;		/*  target does not know cmd so abort */
-	u32	seqr_io_retry;		/*  SEQR failed so retry IO */
-
-	u32	itn_cisc_upd_rsp;	/*  ITN cisc updated on fcp_rsp */
-	u32	itn_cisc_upd_data;	/*  ITN cisc updated on fcp_data */
-	u32	itn_cisc_upd_xfer_rdy;	/*  ITN cisc updated on fcp_data */
-
-	u32	fcp_data_lost;		/*  fcp data lost */
-
-	u32	ro_set_in_xfer_rdy;	/*  Target set RO in Xfer_rdy frame */
-	u32	xfer_rdy_ooo_err;	/*  Out of order Xfer_rdy received */
-	u32	xfer_rdy_unknown_err;	/*  unknown error in xfer_rdy frame */
-
-	u32	io_abort_timeout;	/*  ABTS timedout  */
-	u32	sler_initiated;		/*  SLER initiated */
-
-	u32	unexp_fcp_rsp;		/*  fcp response in wrong state */
-
-	u32	fcp_rsp_under_run;	/*  fcp rsp IO underrun */
-	u32        fcp_rsp_under_run_wr;   /*  fcp rsp IO underrun for write */
-	u32	fcp_rsp_under_run_err;	/*  fcp rsp IO underrun error */
-	u32        fcp_rsp_resid_inval;    /*  invalid residue */
-	u32	fcp_rsp_over_run;	/*  fcp rsp IO overrun */
-	u32	fcp_rsp_over_run_err;	/*  fcp rsp IO overrun error */
-	u32	fcp_rsp_proto_err;	/*  protocol error in fcp rsp */
-	u32	fcp_rsp_sense_err;	/*  error in sense info in fcp rsp */
-	u32	fcp_conf_req;		/*  FCP conf requested */
-
-	u32	tgt_aborted_io;		/*  target initiated abort */
-
-	u32	ioh_edtov_timeout_event;/*  IOH edtov timer popped */
-	u32	ioh_fcp_rsp_excp_event;	/*  IOH FCP_RSP exception */
-	u32	ioh_fcp_conf_event;	/*  IOH FCP_CONF */
-	u32	ioh_mult_frm_rsp_event;	/*  IOH multi_frame FCP_RSP */
-	u32	ioh_hit_class2_event;	/*  IOH hit class2 */
-	u32	ioh_miss_other_event;	/*  IOH miss other */
-	u32	ioh_seq_cnt_err_event;	/*  IOH seq cnt error */
-	u32	ioh_len_err_event;		/*  IOH len error - fcp_dl !=
-							* bytes xfered */
-	u32	ioh_seq_len_err_event;	/*  IOH seq len error */
-	u32	ioh_data_oor_event;	/*  Data out of range */
-	u32	ioh_ro_ooo_event;	/*  Relative offset out of range */
-	u32	ioh_cpu_owned_event;	/*  IOH hit -iost owned by f/w */
-	u32	ioh_unexp_frame_event;	/*  unexpected frame recieved
-						 *   count */
-	u32	ioh_err_int;		/*  IOH error int during data-phase
-						 *   for scsi write
-						 */
-};
-
-/**
- * IOC port firmware stats
- */
-
-struct bfa_fw_port_fpg_stats_s {
-    u32    intr_evt;
-    u32    intr;
-    u32    intr_excess;
-    u32    intr_cause0;
-    u32    intr_other;
-    u32    intr_other_ign;
-    u32    sig_lost;
-    u32    sig_regained;
-    u32    sync_lost;
-    u32    sync_to;
-    u32    sync_regained;
-    u32    div2_overflow;
-    u32    div2_underflow;
-    u32    efifo_overflow;
-    u32    efifo_underflow;
-    u32    idle_rx;
-    u32    lrr_rx;
-    u32    lr_rx;
-    u32    ols_rx;
-    u32    nos_rx;
-    u32    lip_rx;
-    u32    arbf0_rx;
-    u32    arb_rx;
-    u32    mrk_rx;
-    u32    const_mrk_rx;
-    u32    prim_unknown;
-};
-
-
-struct bfa_fw_port_lksm_stats_s {
-    u32    hwsm_success;       /*  hwsm state machine success          */
-    u32    hwsm_fails;         /*  hwsm fails                          */
-    u32    hwsm_wdtov;         /*  hwsm timed out                      */
-    u32    swsm_success;       /*  swsm success                        */
-    u32    swsm_fails;         /*  swsm fails                          */
-    u32    swsm_wdtov;         /*  swsm timed out                      */
-    u32    busybufs;           /*  link init failed due to busybuf     */
-    u32    buf_waits;          /*  bufwait state entries               */
-    u32    link_fails;         /*  link failures                       */
-    u32    psp_errors;         /*  primitive sequence protocol errors  */
-    u32    lr_unexp;           /*  No. of times LR rx-ed unexpectedly  */
-    u32    lrr_unexp;          /*  No. of times LRR rx-ed unexpectedly */
-    u32    lr_tx;              /*  No. of times LR tx started          */
-    u32    lrr_tx;             /*  No. of times LRR tx started         */
-    u32    ols_tx;             /*  No. of times OLS tx started         */
-    u32    nos_tx;             /*  No. of times NOS tx started         */
-    u32    hwsm_lrr_rx;        /*  No. of times LRR rx-ed by HWSM      */
-    u32    hwsm_lr_rx;         /* No. of times LR rx-ed by HWSM        */
-};
-
-
-struct bfa_fw_port_snsm_stats_s {
-    u32    hwsm_success;       /*  Successful hwsm terminations        */
-    u32    hwsm_fails;         /*  hwsm fail count                     */
-    u32    hwsm_wdtov;         /*  hwsm timed out                      */
-    u32    swsm_success;       /*  swsm success                        */
-    u32    swsm_wdtov;         /*  swsm timed out                      */
-    u32    error_resets;       /*  error resets initiated by upsm      */
-    u32    sync_lost;          /*  Sync loss count                     */
-    u32    sig_lost;           /*  Signal loss count                   */
-};
-
-
-struct bfa_fw_port_physm_stats_s {
-    u32    module_inserts;     /*  Module insert count                 */
-    u32    module_xtracts;     /*  Module extracts count               */
-    u32    module_invalids;    /*  Invalid module inserted count       */
-    u32    module_read_ign;    /*  Module validation status ignored    */
-    u32    laser_faults;       /*  Laser fault count                   */
-    u32    rsvd;
-};
-
-
-struct bfa_fw_fip_stats_s {
-    u32    vlan_req;           /*  vlan discovery requests             */
-    u32    vlan_notify;        /*  vlan notifications                  */
-    u32    vlan_err;           /*  vlan response error                 */
-    u32    vlan_timeouts;      /*  vlan disvoery timeouts              */
-    u32    vlan_invalids;      /*  invalid vlan in discovery advert.   */
-    u32    disc_req;           /*  Discovery solicit requests          */
-    u32    disc_rsp;           /*  Discovery solicit response          */
-    u32    disc_err;           /*  Discovery advt. parse errors        */
-    u32    disc_unsol;         /*  Discovery unsolicited               */
-    u32    disc_timeouts;      /*  Discovery timeouts                  */
-    u32    disc_fcf_unavail;   /*  Discovery FCF Not Avail.            */
-    u32    linksvc_unsupp;     /*  Unsupported link service req        */
-    u32    linksvc_err;        /*  Parse error in link service req     */
-    u32    logo_req;           /*  FIP logos received	               */
-    u32    clrvlink_req;       /*  Clear virtual link req              */
-    u32    op_unsupp;          /*  Unsupported FIP operation           */
-    u32    untagged;           /*  Untagged frames (ignored)           */
-    u32	   invalid_version;    /*!< Invalid FIP version           */
-};
-
-
-struct bfa_fw_lps_stats_s {
-    u32    mac_invalids;       /*  Invalid mac assigned                */
-    u32    rsvd;
-};
-
-
-struct bfa_fw_fcoe_stats_s {
-    u32    cee_linkups;        /*  CEE link up count                   */
-    u32    cee_linkdns;        /*  CEE link down count                 */
-    u32    fip_linkups;        /*  FIP link up count                   */
-    u32    fip_linkdns;        /*  FIP link up count                   */
-    u32    fip_fails;          /*  FIP fail count                      */
-    u32    mac_invalids;       /*  Invalid mac assigned                */
-};
-
-/**
- * IOC firmware FCoE port stats
- */
-struct bfa_fw_fcoe_port_stats_s {
-    struct bfa_fw_fcoe_stats_s  fcoe_stats;
-    struct bfa_fw_fip_stats_s   fip_stats;
-};
-
-/**
- * IOC firmware FC port stats
- */
-struct bfa_fw_fc_port_stats_s {
-	struct bfa_fw_port_fpg_stats_s		fpg_stats;
-	struct bfa_fw_port_physm_stats_s	physm_stats;
-	struct bfa_fw_port_snsm_stats_s		snsm_stats;
-	struct bfa_fw_port_lksm_stats_s		lksm_stats;
-};
-
-/**
- * IOC firmware FC port stats
- */
-union bfa_fw_port_stats_s {
-	struct bfa_fw_fc_port_stats_s	fc_stats;
-	struct bfa_fw_fcoe_port_stats_s	fcoe_stats;
-};
-
-/**
- * IOC firmware stats
- */
-struct bfa_fw_stats_s {
-	struct bfa_fw_ioc_stats_s	ioc_stats;
-	struct bfa_fw_io_stats_s	io_stats;
-	union  bfa_fw_port_stats_s	port_stats;
-};
-
-/**
- * IOC statistics
- */
-struct bfa_iocfc_stats_s {
-	struct bfa_fw_stats_s 	fw_stats;	/*  firmware IOC stats      */
-};
-
-/**
- * IOC attributes returned in queries
- */
-struct bfa_iocfc_attr_s {
-	struct bfa_iocfc_cfg_s		config;		/*  IOCFC config   */
-	struct bfa_iocfc_intr_attr_s	intr_attr;	/*  interrupt attr */
-};
-
-#define BFA_IOCFC_PATHTOV_MAX	60
-#define BFA_IOCFC_QDEPTH_MAX	2000
-
-#endif /* __BFA_DEFS_IOC_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h
deleted file mode 100644
index 7cb63ea..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_IPFC_H__
-#define __BFA_DEFS_IPFC_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-#include <defs/bfa_defs_types.h>
-
-/**
- * FCS ip remote port states
- */
-enum bfa_iprp_state {
-	BFA_IPRP_UNINIT  = 0,	/*  PORT is not yet initialized */
-	BFA_IPRP_ONLINE  = 1,	/*  process login is complete */
-	BFA_IPRP_OFFLINE = 2,	/*  iprp is offline */
-};
-
-/**
- * FCS remote port statistics
- */
-struct bfa_iprp_stats_s {
-	u32        offlines;
-	u32        onlines;
-	u32        rscns;
-	u32        plogis;
-	u32        logos;
-	u32        plogi_timeouts;
-	u32        plogi_rejects;
-};
-
-/**
- * FCS iprp attribute returned in queries
- */
-struct bfa_iprp_attr_s {
-	enum bfa_iprp_state state;
-};
-
-struct bfa_ipfc_stats_s {
-	u32 arp_sent;
-	u32 arp_recv;
-	u32 arp_reply_sent;
-	u32 arp_reply_recv;
-	u32 farp_sent;
-	u32 farp_recv;
-	u32 farp_reply_sent;
-	u32 farp_reply_recv;
-	u32 farp_reject_sent;
-	u32 farp_reject_recv;
-};
-
-struct bfa_ipfc_attr_s {
-	bfa_boolean_t enabled;
-};
-
-#endif /* __BFA_DEFS_IPFC_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h b/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h
deleted file mode 100644
index d77788b..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_ITNIM_H__
-#define __BFA_DEFS_ITNIM_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-
-/**
- * FCS itnim states
- */
-enum bfa_itnim_state {
-	BFA_ITNIM_OFFLINE 	= 0,	/*  offline */
-	BFA_ITNIM_PRLI_SEND 	= 1,	/*  prli send */
-	BFA_ITNIM_PRLI_SENT 	= 2,	/*  prli sent */
-	BFA_ITNIM_PRLI_RETRY 	= 3,	/*  prli retry */
-	BFA_ITNIM_HCB_ONLINE 	= 4,	/*  online callback */
-	BFA_ITNIM_ONLINE 	= 5,	/*  online */
-	BFA_ITNIM_HCB_OFFLINE 	= 6,	/*  offline callback */
-	BFA_ITNIM_INITIATIOR 	= 7,	/*  initiator */
-};
-
-struct bfa_itnim_latency_s {
-	u32	min;
-	u32	max;
-	u32	count;
-	u32	clock_res;
-	u32	avg;
-	u32	rsvd;
-};
-
-struct bfa_itnim_hal_stats_s {
-	u32	onlines;	/*  ITN nexus onlines (PRLI done) */
-	u32	offlines;	/*  ITN Nexus offlines 	*/
-	u32	creates;	/*  ITN create requests 	*/
-	u32	deletes;	/*  ITN delete requests 	*/
-	u32	create_comps;	/*  ITN create completions 	*/
-	u32	delete_comps;	/*  ITN delete completions 	*/
-	u32	sler_events;	/*  SLER (sequence level error
-					 * recovery) events */
-	u32	ioc_disabled;	/*  Num IOC disables		*/
-	u32	cleanup_comps;	/*  ITN cleanup completions */
-	u32	tm_cmnds;	/*  task management(TM) cmnds sent */
-	u32	tm_fw_rsps;	/*  TM cmds firmware responses */
-	u32	tm_success;	/*  TM successes */
-	u32	tm_failures;	/*  TM failures */
-	u32	tm_io_comps;	/*  TM IO completions */
-	u32	tm_qresumes;	/*  TM queue resumes (after waiting
-					 * for resources)
-					 */
-	u32	tm_iocdowns;	/*  TM cmnds affected by IOC down */
-	u32	tm_cleanups;	/*  TM cleanups */
-	u32	tm_cleanup_comps;
-					/*  TM cleanup completions */
-	u32	ios;		/*  IO requests */
-	u32	io_comps;	/*  IO completions */
-	u64	input_reqs;	/*  INPUT requests */
-	u64	output_reqs;	/*  OUTPUT requests */
-};
-
-/**
- * FCS remote port statistics
- */
-struct bfa_itnim_stats_s {
-	u32        onlines;	/*  num rport online */
-	u32        offlines;	/*  num rport offline */
-	u32        prli_sent;	/*  num prli sent out */
-	u32        fcxp_alloc_wait;/*  num fcxp alloc waits */
-	u32        prli_rsp_err;	/*  num prli rsp errors */
-	u32        prli_rsp_acc;	/*  num prli rsp accepts */
-	u32        initiator;	/*  rport is an initiator */
-	u32        prli_rsp_parse_err;	/*  prli rsp parsing errors */
-	u32        prli_rsp_rjt;	/*  num prli rsp rejects */
-	u32        timeout;	/*  num timeouts detected */
-	u32        sler;		/*  num sler notification from BFA */
-	u32	rsvd;
-	struct bfa_itnim_hal_stats_s	hal_stats;
-};
-
-/**
- * FCS itnim attributes returned in queries
- */
-struct bfa_itnim_attr_s {
-	enum bfa_itnim_state state; /*  FCS itnim state        */
-	u8 retry;		/*  data retransmision support */
-	u8	task_retry_id;  /*  task retry ident support   */
-	u8 rec_support;    /*  REC supported              */
-	u8 conf_comp;      /*  confirmed completion supp  */
-	struct bfa_itnim_latency_s  io_latency; /* IO latency  */
-};
-
-/**
- * BFA ITNIM events.
- * Arguments below are in BFAL context from Mgmt
- * BFA_ITNIM_AEN_NEW:       [in]: None  [out]: vf_id, lpwwn
- * BFA_ITNIM_AEN_DELETE:    [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- *				  [out]: vf_id, ppwwn, lpwwn, rpwwn
- * BFA_ITNIM_AEN_ONLINE:    [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- *				  [out]: vf_id, ppwwn, lpwwn, rpwwn
- * BFA_ITNIM_AEN_OFFLINE:   [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- *				  [out]: vf_id, ppwwn, lpwwn, rpwwn
- * BFA_ITNIM_AEN_DISCONNECT:[in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets),
- *				  [out]: vf_id, ppwwn, lpwwn, rpwwn
- */
-enum bfa_itnim_aen_event {
-	BFA_ITNIM_AEN_ONLINE 	= 1,	/*  Target online */
-	BFA_ITNIM_AEN_OFFLINE 	= 2,	/*  Target offline */
-	BFA_ITNIM_AEN_DISCONNECT = 3,	/*  Target disconnected */
-};
-
-/**
- * BFA ITNIM event data structure.
- */
-struct bfa_itnim_aen_data_s {
-	u16        vf_id;	/*  vf_id of the IT nexus */
-	u16        rsvd[3];
-	wwn_t           ppwwn;	/*  WWN of its physical port */
-	wwn_t           lpwwn;	/*  WWN of logical port */
-	wwn_t           rpwwn;	/*  WWN of remote(target) port */
-};
-
-#endif /* __BFA_DEFS_ITNIM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_led.h b/drivers/scsi/bfa/include/defs/bfa_defs_led.h
deleted file mode 100644
index 6203927..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_led.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_LED_H__
-#define __BFA_DEFS_LED_H__
-
-#define	BFA_LED_MAX_NUM		3
-
-enum bfa_led_op {
-	BFA_LED_OFF   = 0,
-	BFA_LED_ON    = 1,
-	BFA_LED_FLICK = 2,
-	BFA_LED_BLINK = 3,
-};
-
-enum bfa_led_color {
-	BFA_LED_GREEN = 0,
-	BFA_LED_AMBER = 1,
-};
-
-#endif /* __BFA_DEFS_LED_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_lport.h b/drivers/scsi/bfa/include/defs/bfa_defs_lport.h
deleted file mode 100644
index 0952a13..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_lport.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_LPORT_H__
-#define __BFA_DEFS_LPORT_H__
-
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_port.h>
-
-/**
- * BFA AEN logical port events.
- * Arguments below are in BFAL context from Mgmt
- * BFA_LPORT_AEN_NEW:       [in]: None         [out]: vf_id, ppwwn, lpwwn, roles
- * BFA_LPORT_AEN_DELETE:    [in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_ONLINE:    [in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_OFFLINE:   [in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_DISCONNECT:[in]: lpwwn        [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NEW_PROP:  [in]: None         [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_DELETE_PROP:     [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NEW_STANDARD:    [in]: None   [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_DELETE_STANDARD: [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NPIV_DUP_WWN:    [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NPIV_FABRIC_MAX: [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- * BFA_LPORT_AEN_NPIV_UNKNOWN:    [in]: lpwwn  [out]: vf_id, ppwwn. lpwwn, roles
- */
-enum bfa_lport_aen_event {
-	BFA_LPORT_AEN_NEW	= 1,	/*  LPort created event */
-	BFA_LPORT_AEN_DELETE	= 2,	/*  LPort deleted event */
-	BFA_LPORT_AEN_ONLINE	= 3,	/*  LPort online event */
-	BFA_LPORT_AEN_OFFLINE	= 4,	/*  LPort offline event */
-	BFA_LPORT_AEN_DISCONNECT = 5,	/*  LPort disconnect event */
-	BFA_LPORT_AEN_NEW_PROP	= 6,	/*  VPort created event */
-	BFA_LPORT_AEN_DELETE_PROP = 7,	/*  VPort deleted event */
-	BFA_LPORT_AEN_NEW_STANDARD = 8,	/*  VPort created event */
-	BFA_LPORT_AEN_DELETE_STANDARD = 9,  /*  VPort deleted event */
-	BFA_LPORT_AEN_NPIV_DUP_WWN = 10,    /*  VPort configured with
-					     *   duplicate WWN event
-						 */
-	BFA_LPORT_AEN_NPIV_FABRIC_MAX = 11, /*  Max NPIV in fabric/fport */
-	BFA_LPORT_AEN_NPIV_UNKNOWN = 12, /*  Unknown NPIV Error code event */
-};
-
-/**
- * BFA AEN event data structure
- */
-struct bfa_lport_aen_data_s {
-	u16        vf_id;	/*  vf_id of this logical port */
-	s16         roles;  /*  Logical port mode,IM/TM/IP etc */
-	u32        rsvd;
-	wwn_t           ppwwn;	/*  WWN of its physical port */
-	wwn_t           lpwwn;	/*  WWN of this logical port */
-};
-
-#endif /* __BFA_DEFS_LPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h
deleted file mode 100644
index d22fb79..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_MFG_H__
-#define __BFA_DEFS_MFG_H__
-
-#include <bfa_os_inc.h>
-
-/**
- * Manufacturing block version
- */
-#define BFA_MFG_VERSION				2
-
-/**
- * Manufacturing block encrypted version
- */
-#define BFA_MFG_ENC_VER				2
-
-/**
- * Manufacturing block version 1 length
- */
-#define BFA_MFG_VER1_LEN			128
-
-/**
- * Manufacturing block header length
- */
-#define BFA_MFG_HDR_LEN				4
-
-/**
- * Checksum size
- */
-#define BFA_MFG_CHKSUM_SIZE			16
-
-/**
- * Manufacturing block format
- */
-#define BFA_MFG_SERIALNUM_SIZE			11
-#define BFA_MFG_PARTNUM_SIZE			14
-#define BFA_MFG_SUPPLIER_ID_SIZE		10
-#define BFA_MFG_SUPPLIER_PARTNUM_SIZE		20
-#define BFA_MFG_SUPPLIER_SERIALNUM_SIZE		20
-#define BFA_MFG_SUPPLIER_REVISION_SIZE		4
-#define STRSZ(_n)	(((_n) + 4) & ~3)
-
-/**
- * Manufacturing card type
- */
-enum {
-	BFA_MFG_TYPE_CB_MAX  = 825,      /*  Crossbow card type max	*/
-	BFA_MFG_TYPE_FC8P2   = 825,      /*  8G 2port FC card		*/
-	BFA_MFG_TYPE_FC8P1   = 815,      /*  8G 1port FC card		*/
-	BFA_MFG_TYPE_FC4P2   = 425,      /*  4G 2port FC card		*/
-	BFA_MFG_TYPE_FC4P1   = 415,      /*  4G 1port FC card		*/
-	BFA_MFG_TYPE_CNA10P2 = 1020,     /*  10G 2port CNA card	*/
-	BFA_MFG_TYPE_CNA10P1 = 1010,     /*  10G 1port CNA card	*/
-	BFA_MFG_TYPE_JAYHAWK = 804,      /*  Jayhawk mezz card */
-	BFA_MFG_TYPE_WANCHESE = 1007,    /*  Wanchese mezz card */
-	BFA_MFG_TYPE_INVALID = 0,        /*  Invalid card type */
-};
-
-#pragma pack(1)
-
-/**
- * Card type to port number conversion
- */
-#define bfa_mfg_type2port_num(card_type) (((card_type) / 10) % 10)
-
-/**
- * Check if Mezz card
- */
-#define bfa_mfg_is_mezz(type) (( \
-	(type) == BFA_MFG_TYPE_JAYHAWK || \
-	(type) == BFA_MFG_TYPE_WANCHESE))
-
-/**
- * Check if card type valid
- */
-#define bfa_mfg_is_card_type_valid(type) (( \
-	(type) == BFA_MFG_TYPE_FC8P2 || \
-	(type) == BFA_MFG_TYPE_FC8P1 || \
-	(type) == BFA_MFG_TYPE_FC4P2 || \
-	(type) == BFA_MFG_TYPE_FC4P1 || \
-	(type) == BFA_MFG_TYPE_CNA10P2 || \
-	(type) == BFA_MFG_TYPE_CNA10P1 || \
-	bfa_mfg_is_mezz(type)))
-
-/**
- * All numerical fields are in big-endian format.
- */
-struct bfa_mfg_block_s {
-};
-
-/**
- * VPD data length
- */
-#define BFA_MFG_VPD_LEN		512
-
-#define BFA_MFG_VPD_PCI_HDR_OFF		137
-#define BFA_MFG_VPD_PCI_VER_MASK	0x07	/*  version mask 3 bits */
-#define BFA_MFG_VPD_PCI_VDR_MASK	0xf8	/*  vendor mask 5 bits */
-
-/**
- * VPD vendor tag
- */
-enum {
-	BFA_MFG_VPD_UNKNOWN	= 0,     /*  vendor unknown 		*/
-	BFA_MFG_VPD_IBM 	= 1,     /*  vendor IBM 		*/
-	BFA_MFG_VPD_HP  	= 2,     /*  vendor HP  		*/
-	BFA_MFG_VPD_DELL        = 3,	 /*  vendor DELL                */
-	BFA_MFG_VPD_PCI_IBM 	= 0x08,  /*  PCI VPD IBM     		*/
-	BFA_MFG_VPD_PCI_HP  	= 0x10,  /*  PCI VPD HP			*/
-	BFA_MFG_VPD_PCI_DELL    = 0x20,  /*  PCI VPD DELL           	*/
-	BFA_MFG_VPD_PCI_BRCD 	= 0xf8,  /*  PCI VPD Brocade 		*/
-};
-
-/**
- * All numerical fields are in big-endian format.
- */
-struct bfa_mfg_vpd_s {
-	u8		version;	/*  vpd data version */
-	u8		vpd_sig[3];	/*  characters 'V', 'P', 'D' */
-	u8		chksum;		/*  u8 checksum */
-	u8		vendor;		/*  vendor */
-	u8 	len;		/*  vpd data length excluding header */
-	u8 	rsv;
-	u8		data[BFA_MFG_VPD_LEN];	/*  vpd data */
-};
-
-#pragma pack()
-
-#endif /* __BFA_DEFS_MFG_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h b/drivers/scsi/bfa/include/defs/bfa_defs_pci.h
deleted file mode 100644
index ea7d89b..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_PCI_H__
-#define __BFA_DEFS_PCI_H__
-
-/**
- * PCI device and vendor ID information
- */
-enum {
-	BFA_PCI_VENDOR_ID_BROCADE	= 0x1657,
-	BFA_PCI_DEVICE_ID_FC_8G2P	= 0x13,
-	BFA_PCI_DEVICE_ID_FC_8G1P	= 0x17,
-	BFA_PCI_DEVICE_ID_CT		= 0x14,
-	BFA_PCI_DEVICE_ID_CT_FC         = 0x21,
-};
-
-#define bfa_asic_id_ct(devid)                   \
-	((devid) == BFA_PCI_DEVICE_ID_CT ||     \
-	 (devid) == BFA_PCI_DEVICE_ID_CT_FC)
-
-/**
- * PCI sub-system device and vendor ID information
- */
-enum {
-	BFA_PCI_FCOE_SSDEVICE_ID	= 0x14,
-};
-
-/**
- * Maximum number of device address ranges mapped through different BAR(s)
- */
-#define BFA_PCI_ACCESS_RANGES 1
-
-#endif /* __BFA_DEFS_PCI_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pm.h b/drivers/scsi/bfa/include/defs/bfa_defs_pm.h
deleted file mode 100644
index e8d6d95..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pm.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_PM_H__
-#define __BFA_DEFS_PM_H__
-
-#include <bfa_os_inc.h>
-
-/**
- * BFA power management device states
- */
-enum bfa_pm_ds {
-	BFA_PM_DS_D0 = 0,	/*  full power mode */
-	BFA_PM_DS_D1 = 1,	/*  power save state 1 */
-	BFA_PM_DS_D2 = 2,	/*  power save state 2 */
-	BFA_PM_DS_D3 = 3,	/*  power off state */
-};
-
-#endif /* __BFA_DEFS_PM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pom.h b/drivers/scsi/bfa/include/defs/bfa_defs_pom.h
deleted file mode 100644
index d9fa278..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pom.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_POM_H__
-#define __BFA_DEFS_POM_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_types.h>
-
-/**
- * POM health status levels for each attributes.
- */
-enum bfa_pom_entry_health {
-	BFA_POM_HEALTH_NOINFO  = 1,	/*  no information */
-	BFA_POM_HEALTH_NORMAL  = 2,	/*  health is normal */
-	BFA_POM_HEALTH_WARNING = 3,	/*  warning level */
-	BFA_POM_HEALTH_ALARM   = 4,	/*  alarming level */
-};
-
-/**
- * Reading of temperature/voltage/current/power
- */
-struct bfa_pom_entry_s {
-	enum bfa_pom_entry_health health;	/*  POM entry health */
-	u32        curr_value;	/*  current value */
-	u32        thr_warn_high;	/*  threshold warning high */
-	u32        thr_warn_low;	/*  threshold warning low */
-	u32        thr_alarm_low;	/*  threshold alaram low */
-	u32        thr_alarm_high;	/*  threshold alarm high */
-};
-
-/**
- * POM attributes
- */
-struct bfa_pom_attr_s {
-	struct bfa_pom_entry_s temperature;	/*  centigrade */
-	struct bfa_pom_entry_s voltage;	/*  volts */
-	struct bfa_pom_entry_s curr;	/*  milli amps */
-	struct bfa_pom_entry_s txpower;	/*  micro watts */
-	struct bfa_pom_entry_s rxpower;	/*  micro watts */
-};
-
-#endif /* __BFA_DEFS_POM_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_port.h b/drivers/scsi/bfa/include/defs/bfa_defs_port.h
deleted file mode 100644
index ebdf0d1..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_port.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_PORT_H__
-#define __BFA_DEFS_PORT_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_ioc.h>
-
-#define BFA_FCS_FABRIC_IPADDR_SZ  16
-
-/**
- * symbolic names for base port/virtual port
- */
-#define BFA_SYMNAME_MAXLEN	128	/* vmware/windows uses 128 bytes */
-struct bfa_port_symname_s {
-	char            symname[BFA_SYMNAME_MAXLEN];
-};
-
-/**
-* Roles of FCS port:
- *     - FCP IM and FCP TM roles cannot be enabled together for a FCS port
- *     - Create multiple ports if both IM and TM functions required.
- *     - Atleast one role must be specified.
- */
-enum bfa_port_role {
-	BFA_PORT_ROLE_FCP_IM 	= 0x01,	/*  FCP initiator role */
-	BFA_PORT_ROLE_FCP_TM 	= 0x02,	/*  FCP target role */
-	BFA_PORT_ROLE_FCP_IPFC 	= 0x04,	/*  IP over FC role */
-	BFA_PORT_ROLE_FCP_MAX 	= BFA_PORT_ROLE_FCP_IPFC | BFA_PORT_ROLE_FCP_IM
-};
-
-/**
- * FCS port configuration.
- */
-struct bfa_port_cfg_s {
-	wwn_t               pwwn;       /*  port wwn */
-	wwn_t               nwwn;       /*  node wwn */
-	struct bfa_port_symname_s  sym_name;   /*  vm port symbolic name */
-	bfa_boolean_t       preboot_vp;  /* vport created from PBC */
-	enum bfa_port_role     roles;      /*  FCS port roles */
-	u8             tag[16];	/*  opaque tag from application */
-};
-
-/**
- * FCS port states
- */
-enum bfa_port_state {
-	BFA_PORT_UNINIT  = 0,	/*  PORT is not yet initialized */
-	BFA_PORT_FDISC   = 1,	/*  FDISC is in progress */
-	BFA_PORT_ONLINE  = 2,	/*  login to fabric is complete */
-	BFA_PORT_OFFLINE = 3,	/*  No login to fabric */
-};
-
-/**
- * FCS port type. Required for VmWare.
- */
-enum bfa_port_type {
-	BFA_PORT_TYPE_PHYSICAL = 0,
-	BFA_PORT_TYPE_VIRTUAL,
-};
-
-/**
- * FCS port offline reason. Required for VmWare.
- */
-enum bfa_port_offline_reason {
-	BFA_PORT_OFFLINE_UNKNOWN = 0,
-	BFA_PORT_OFFLINE_LINKDOWN,
-	BFA_PORT_OFFLINE_FAB_UNSUPPORTED,	/*  NPIV not supported by the
-						 *    fabric */
-	BFA_PORT_OFFLINE_FAB_NORESOURCES,
-	BFA_PORT_OFFLINE_FAB_LOGOUT,
-};
-
-/**
- * FCS lport info. Required for VmWare.
- */
-struct bfa_port_info_s {
-	u8         port_type;	/* bfa_port_type_t : physical or
-					 * virtual */
-	u8         port_state;	/* one of bfa_port_state values */
-	u8         offline_reason;	/* one of bfa_port_offline_reason_t
-					 * values */
-	wwn_t           port_wwn;
-	wwn_t           node_wwn;
-
-	/*
-	 * following 4 feilds are valid for Physical Ports only
-	 */
-	u32        max_vports_supp;	/* Max supported vports */
-	u32        num_vports_inuse;	/* Num of in use vports */
-	u32        max_rports_supp;	/* Max supported rports */
-	u32        num_rports_inuse;	/* Num of doscovered rports */
-
-};
-
-/**
- * FCS port statistics
- */
-struct bfa_port_stats_s {
-	u32        ns_plogi_sent;
-	u32        ns_plogi_rsp_err;
-	u32        ns_plogi_acc_err;
-	u32        ns_plogi_accepts;
-	u32        ns_rejects;	/* NS command rejects */
-	u32        ns_plogi_unknown_rsp;
-	u32        ns_plogi_alloc_wait;
-
-	u32        ns_retries;	/* NS command retries */
-	u32        ns_timeouts;	/* NS command timeouts */
-
-	u32        ns_rspnid_sent;
-	u32        ns_rspnid_accepts;
-	u32        ns_rspnid_rsp_err;
-	u32        ns_rspnid_rejects;
-	u32        ns_rspnid_alloc_wait;
-
-	u32        ns_rftid_sent;
-	u32        ns_rftid_accepts;
-	u32        ns_rftid_rsp_err;
-	u32        ns_rftid_rejects;
-	u32        ns_rftid_alloc_wait;
-
-	u32	ns_rffid_sent;
-	u32	ns_rffid_accepts;
-	u32	ns_rffid_rsp_err;
-	u32	ns_rffid_rejects;
-	u32	ns_rffid_alloc_wait;
-
-	u32        ns_gidft_sent;
-	u32        ns_gidft_accepts;
-	u32        ns_gidft_rsp_err;
-	u32        ns_gidft_rejects;
-	u32        ns_gidft_unknown_rsp;
-	u32        ns_gidft_alloc_wait;
-
-	/*
-	 * Mgmt Server stats
-	 */
-	u32        ms_retries;	/* MS command retries */
-	u32        ms_timeouts;	/* MS command timeouts */
-	u32        ms_plogi_sent;
-	u32        ms_plogi_rsp_err;
-	u32        ms_plogi_acc_err;
-	u32        ms_plogi_accepts;
-	u32        ms_rejects;	/* MS command rejects */
-	u32        ms_plogi_unknown_rsp;
-	u32        ms_plogi_alloc_wait;
-
-	u32        num_rscn;	/* Num of RSCN received */
-	u32        num_portid_rscn;/* Num portid format RSCN
-								* received */
-
-	u32	uf_recvs; 	/* unsolicited recv frames      */
-	u32	uf_recv_drops; 	/* dropped received frames	*/
-
-	u32	rsvd; 		/* padding for 64 bit alignment */
-};
-
-/**
- * BFA port attribute returned in queries
- */
-struct bfa_port_attr_s {
-	enum bfa_port_state state;		/*  port state */
-	u32         pid;		/*  port ID */
-	struct bfa_port_cfg_s   port_cfg;	/*  port configuration */
-	enum bfa_pport_type port_type;	/*  current topology */
-	u32         loopback;	/*  cable is externally looped back */
-	wwn_t		fabric_name; /*  attached switch's nwwn */
-	u8		fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /*  attached
-							* fabric's ip addr */
-	struct mac_s    fpma_mac;	/*  Lport's FPMA Mac address */
-	u16     authfail;		/*  auth failed state */
-};
-
-/**
- * BFA physical port Level events
- * Arguments below are in BFAL context from Mgmt
- * BFA_PORT_AEN_ONLINE:     [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_OFFLINE:    [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_RLIR:       [in]: None	[out]: pwwn, rlir_data, rlir_len
- * BFA_PORT_AEN_SFP_INSERT: [in]: pwwn	[out]: port_id, pwwn
- * BFA_PORT_AEN_SFP_REMOVE: [in]: pwwn	[out]: port_id, pwwn
- * BFA_PORT_AEN_SFP_POM:    [in]: pwwn	[out]: level, port_id, pwwn
- * BFA_PORT_AEN_ENABLE:     [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_DISABLE:    [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_AUTH_ON:    [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_AUTH_OFF:   [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_DISCONNECT: [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_QOS_NEG:    [in]: pwwn	[out]: pwwn
- * BFA_PORT_AEN_FABRIC_NAME_CHANGE: [in]: pwwn, [out]: pwwn, fwwn
- *
- */
-enum bfa_port_aen_event {
-	BFA_PORT_AEN_ONLINE     = 1,	/*  Physical Port online event */
-	BFA_PORT_AEN_OFFLINE    = 2,	/*  Physical Port offline event */
-	BFA_PORT_AEN_RLIR       = 3,	/*  RLIR event, not supported */
-	BFA_PORT_AEN_SFP_INSERT = 4,	/*  SFP inserted event */
-	BFA_PORT_AEN_SFP_REMOVE = 5,	/*  SFP removed event */
-	BFA_PORT_AEN_SFP_POM    = 6,	/*  SFP POM event */
-	BFA_PORT_AEN_ENABLE     = 7,	/*  Physical Port enable event */
-	BFA_PORT_AEN_DISABLE    = 8,	/*  Physical Port disable event */
-	BFA_PORT_AEN_AUTH_ON    = 9,	/*  Physical Port auth success event */
-	BFA_PORT_AEN_AUTH_OFF   = 10,	/*  Physical Port auth fail event */
-	BFA_PORT_AEN_DISCONNECT = 11,	/*  Physical Port disconnect event */
-	BFA_PORT_AEN_QOS_NEG    = 12,  	/*  Base Port QOS negotiation event */
-	BFA_PORT_AEN_FABRIC_NAME_CHANGE = 13, /*  Fabric Name/WWN change
-					       * event */
-	BFA_PORT_AEN_SFP_ACCESS_ERROR = 14, /*  SFP read error event */
-	BFA_PORT_AEN_SFP_UNSUPPORT = 15, /*  Unsupported SFP event */
-};
-
-enum bfa_port_aen_sfp_pom {
-	BFA_PORT_AEN_SFP_POM_GREEN = 1,	/*  Normal */
-	BFA_PORT_AEN_SFP_POM_AMBER = 2,	/*  Warning */
-	BFA_PORT_AEN_SFP_POM_RED   = 3,	/*  Critical */
-	BFA_PORT_AEN_SFP_POM_MAX   = BFA_PORT_AEN_SFP_POM_RED
-};
-
-struct bfa_port_aen_data_s {
-	wwn_t           pwwn;         /*  WWN of the physical port */
-	wwn_t           fwwn;         /*  WWN of the fabric port */
-	s32         phy_port_num; /*! For SFP related events */
-	s16         ioc_type;
-	s16         level;        /*  Only transitions will
-					* be informed */
-	struct mac_s    mac;          /*  MAC address of the ethernet port,
-					* applicable to CNA port only */
-	s16         rsvd;
-};
-
-#endif /* __BFA_DEFS_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h
deleted file mode 100644
index 2de67583..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_PPORT_H__
-#define __BFA_DEFS_PPORT_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/fc.h>
-#include <defs/bfa_defs_types.h>
-#include <defs/bfa_defs_qos.h>
-#include <cna/pstats/phyport_defs.h>
-
-/* Modify char* port_stt[] in bfal_port.c if a new state was added */
-enum bfa_pport_states {
-	BFA_PPORT_ST_UNINIT 		= 1,
-	BFA_PPORT_ST_ENABLING_QWAIT 	= 2,
-	BFA_PPORT_ST_ENABLING 		= 3,
-	BFA_PPORT_ST_LINKDOWN 		= 4,
-	BFA_PPORT_ST_LINKUP 		= 5,
-	BFA_PPORT_ST_DISABLING_QWAIT 	= 6,
-	BFA_PPORT_ST_DISABLING		= 7,
-	BFA_PPORT_ST_DISABLED 		= 8,
-	BFA_PPORT_ST_STOPPED 		= 9,
-	BFA_PPORT_ST_IOCDOWN 		= 10,
-	BFA_PPORT_ST_IOCDIS 		= 11,
-	BFA_PPORT_ST_FWMISMATCH		= 12,
-	BFA_PPORT_ST_PREBOOT_DISABLED   = 13,
-	BFA_PPORT_ST_MAX_STATE,
-};
-
-/**
- * 	Port speed settings. Each specific speed is a bit field. Use multiple
- *      bits to specify speeds to be selected for auto-negotiation.
- */
-enum bfa_pport_speed {
-	BFA_PPORT_SPEED_UNKNOWN = 0,
-	BFA_PPORT_SPEED_1GBPS 	= 1,
-	BFA_PPORT_SPEED_2GBPS 	= 2,
-	BFA_PPORT_SPEED_4GBPS 	= 4,
-	BFA_PPORT_SPEED_8GBPS 	= 8,
-	BFA_PPORT_SPEED_10GBPS 	= 10,
-	BFA_PPORT_SPEED_AUTO =
-		(BFA_PPORT_SPEED_1GBPS | BFA_PPORT_SPEED_2GBPS |
-		 BFA_PPORT_SPEED_4GBPS | BFA_PPORT_SPEED_8GBPS),
-};
-
-/**
- * 		Port operational type (in sync with SNIA port type).
- */
-enum bfa_pport_type {
-	BFA_PPORT_TYPE_UNKNOWN = 1,	/*  port type is unknown */
-	BFA_PPORT_TYPE_TRUNKED = 2,	/*  Trunked mode */
-	BFA_PPORT_TYPE_NPORT   = 5,	/*  P2P with switched fabric */
-	BFA_PPORT_TYPE_NLPORT  = 6,	/*  public loop */
-	BFA_PPORT_TYPE_LPORT   = 20,	/*  private loop */
-	BFA_PPORT_TYPE_P2P     = 21,	/*  P2P with no switched fabric */
-	BFA_PPORT_TYPE_VPORT   = 22,	/*  NPIV - virtual port */
-};
-
-/**
- * 		Port topology setting. A port's topology and fabric login status
- * 		determine its operational type.
- */
-enum bfa_pport_topology {
-	BFA_PPORT_TOPOLOGY_NONE = 0,	/*  No valid topology */
-	BFA_PPORT_TOPOLOGY_P2P  = 1,	/*  P2P only */
-	BFA_PPORT_TOPOLOGY_LOOP = 2,	/*  LOOP topology */
-	BFA_PPORT_TOPOLOGY_AUTO = 3,	/*  auto topology selection */
-};
-
-/**
- * 		Physical port loopback types.
- */
-enum bfa_pport_opmode {
-	BFA_PPORT_OPMODE_NORMAL   = 0x00, /*  normal non-loopback mode */
-	BFA_PPORT_OPMODE_LB_INT   = 0x01, /*  internal loop back */
-	BFA_PPORT_OPMODE_LB_SLW   = 0x02, /*  serial link wrapback (serdes) */
-	BFA_PPORT_OPMODE_LB_EXT   = 0x04, /*  external loop back (serdes) */
-	BFA_PPORT_OPMODE_LB_CBL   = 0x08, /*  cabled loop back */
-	BFA_PPORT_OPMODE_LB_NLINT = 0x20, /*  NL_Port internal loopback */
-};
-
-#define BFA_PPORT_OPMODE_LB_HARD(_mode)			\
-	((_mode == BFA_PPORT_OPMODE_LB_INT) ||		\
-     (_mode == BFA_PPORT_OPMODE_LB_SLW) ||		\
-     (_mode == BFA_PPORT_OPMODE_LB_EXT))
-
-/**
-		Port State (in sync with SNIA port state).
- */
-enum bfa_pport_snia_state {
-	BFA_PPORT_STATE_UNKNOWN  = 1,	/*  port is not initialized */
-	BFA_PPORT_STATE_ONLINE   = 2,	/*  port is ONLINE */
-	BFA_PPORT_STATE_DISABLED = 3,	/*  port is disabled by user */
-	BFA_PPORT_STATE_BYPASSED = 4,	/*  port is bypassed (in LOOP) */
-	BFA_PPORT_STATE_DIAG     = 5,	/*  port diagnostics is active */
-	BFA_PPORT_STATE_LINKDOWN = 6,	/*  link is down */
-	BFA_PPORT_STATE_LOOPBACK = 8,	/*  port is looped back */
-};
-
-/**
- * 		Port link state
- */
-enum bfa_pport_linkstate {
-	BFA_PPORT_LINKUP 	 = 1,	/*  Physical port/Trunk link up */
-	BFA_PPORT_LINKDOWN 	 = 2,	/*  Physical port/Trunk link down */
-	BFA_PPORT_TRUNK_LINKDOWN = 3,	/*  Trunk link down (new tmaster) */
-};
-
-/**
- * 		Port link state event
- */
-#define bfa_pport_event_t enum bfa_pport_linkstate
-
-/**
- * 		Port link state reason code
- */
-enum bfa_pport_linkstate_rsn {
-	BFA_PPORT_LINKSTATE_RSN_NONE		= 0,
-	BFA_PPORT_LINKSTATE_RSN_DISABLED 	= 1,
-	BFA_PPORT_LINKSTATE_RSN_RX_NOS 		= 2,
-	BFA_PPORT_LINKSTATE_RSN_RX_OLS 		= 3,
-	BFA_PPORT_LINKSTATE_RSN_RX_LIP 		= 4,
-	BFA_PPORT_LINKSTATE_RSN_RX_LIPF7 	= 5,
-	BFA_PPORT_LINKSTATE_RSN_SFP_REMOVED 	= 6,
-	BFA_PPORT_LINKSTATE_RSN_PORT_FAULT 	= 7,
-	BFA_PPORT_LINKSTATE_RSN_RX_LOS 		= 8,
-	BFA_PPORT_LINKSTATE_RSN_LOCAL_FAULT 	= 9,
-	BFA_PPORT_LINKSTATE_RSN_REMOTE_FAULT 	= 10,
-	BFA_PPORT_LINKSTATE_RSN_TIMEOUT 	= 11,
-
-
-
-	/* CEE related reason codes/errors */
-	CEE_LLDP_INFO_AGED_OUT       = 20,
-	CEE_LLDP_SHUTDOWN_TLV_RCVD   = 21,
-	CEE_PEER_NOT_ADVERTISE_DCBX  = 22,
-	CEE_PEER_NOT_ADVERTISE_PG    = 23,
-	CEE_PEER_NOT_ADVERTISE_PFC   = 24,
-	CEE_PEER_NOT_ADVERTISE_FCOE  = 25,
-	CEE_PG_NOT_COMPATIBLE        = 26,
-	CEE_PFC_NOT_COMPATIBLE       = 27,
-	CEE_FCOE_NOT_COMPATIBLE      = 28,
-	CEE_BAD_PG_RCVD              = 29,
-	CEE_BAD_BW_RCVD              = 30,
-	CEE_BAD_PFC_RCVD             = 31,
-	CEE_BAD_FCOE_PRI_RCVD        = 32,
-	CEE_FCOE_PRI_PFC_OFF         = 33,
-	CEE_DUP_CONTROL_TLV_RCVD     = 34,
-	CEE_DUP_FEAT_TLV_RCVD        = 35,
-	CEE_APPLY_NEW_CFG            = 36,	/* reason, not an error */
-	CEE_PROTOCOL_INIT            = 37,  /* reason, not an error */
-	CEE_PHY_LINK_DOWN            = 38,
-	CEE_LLS_FCOE_ABSENT          = 39,
-	CEE_LLS_FCOE_DOWN            = 40
-};
-
-/**
- *      Default Target Rate Limiting Speed.
- */
-#define BFA_PPORT_DEF_TRL_SPEED  BFA_PPORT_SPEED_1GBPS
-
-/**
- *      Physical port configuration
- */
-struct bfa_pport_cfg_s {
-	u8         topology;	/*  bfa_pport_topology		*/
-	u8         speed;		/*  enum bfa_pport_speed	*/
-	u8         trunked;	/*  trunked or not		*/
-	u8         qos_enabled;	/*  qos enabled or not		*/
-	u8         trunk_ports;	/*  bitmap of trunked ports	*/
-	u8         cfg_hardalpa;	/*  is hard alpa configured	*/
-	u16        maxfrsize;	/*  maximum frame size		*/
-	u8         hardalpa;	/*  configured hard alpa	*/
-	u8         rx_bbcredit;	/*  receive buffer credits	*/
-	u8         tx_bbcredit;	/*  transmit buffer credits	*/
-	u8         ratelimit;	/*  ratelimit enabled or not	*/
-	u8         trl_def_speed;	/*  ratelimit default speed	*/
-	u8		rsvd[3];
-	u16   	path_tov;	/*  device path timeout	*/
-	u16   	q_depth;	/*  SCSI Queue depth		*/
-};
-
-/**
- * 		Port attribute values.
- */
-struct bfa_pport_attr_s {
-	/*
-	 * Static fields
-	 */
-	wwn_t           nwwn;		/*  node wwn */
-	wwn_t           pwwn;		/*  port wwn */
-	wwn_t           factorynwwn;    /*  factory node wwn */
-	wwn_t           factorypwwn;    /*  factory port wwn */
-	enum fc_cos     cos_supported;	/*  supported class of services */
-	u32        rsvd;
-	struct fc_symname_s    port_symname;	/*  port symbolic name */
-	enum bfa_pport_speed speed_supported; /*  supported speeds */
-	bfa_boolean_t   pbind_enabled;	/*  Will be set if Persistent binding
-					 *   enabled. Relevant only in Windows
-					 */
-
-	/*
-	 * Configured values
-	 */
-	struct bfa_pport_cfg_s pport_cfg;	/*  pport cfg */
-
-	/*
-	 * Dynamic field - info from BFA
-	 */
-	enum bfa_pport_states 	port_state;	/*  current port state */
-	enum bfa_pport_speed 	speed;		/*  current speed */
-	enum bfa_pport_topology 	topology;	/*  current topology */
-	bfa_boolean_t		beacon;		/*  current beacon status */
-	bfa_boolean_t		link_e2e_beacon;/*  set if link beacon on */
-	bfa_boolean_t		plog_enabled;	/*  set if portlog is enabled*/
-
-	/*
-	 * Dynamic field - info from FCS
-	 */
-	u32        	pid;		/*  port ID */
-	enum bfa_pport_type 	port_type;	/*  current topology */
-	u32        	loopback;	/*  external loopback */
-	u32		authfail;	/* auth fail state */
-	u32		rsvd2;		/*  padding for 64 bit */
-};
-
-/**
- * 		FC Port statistics.
- */
-struct bfa_pport_fc_stats_s {
-	u64    secs_reset; /* Seconds since stats is reset     */
-	u64    tx_frames;  /* Tx frames                */
-	u64    tx_words;   /* Tx words                 */
-	u64    tx_lip;     /* Tx LIP               */
-	u64    tx_nos;     /* Tx NOS               */
-	u64    tx_ols;     /* Tx OLS               */
-	u64    tx_lr;      /* Tx LR                */
-	u64    tx_lrr;     /* Tx LRR               */
-	u64    rx_frames;  /* Rx frames                */
-	u64    rx_words;   /* Rx words                 */
-	u64    lip_count;  /* Rx LIP                   */
-	u64    nos_count;  /* Rx NOS               */
-	u64    ols_count;  /* Rx OLS               */
-	u64    lr_count;   /* Rx LR                */
-	u64    lrr_count;  /* Rx LRR               */
-	u64    invalid_crcs;   /* Rx CRC err frames            */
-	u64    invalid_crc_gd_eof; /* Rx CRC err good EOF frames   */
-	u64    undersized_frm; /* Rx undersized frames         */
-	u64    oversized_frm;  /* Rx oversized frames          */
-	u64    bad_eof_frm;    /* Rx frames with bad EOF       */
-	u64    error_frames;   /* Errored frames           */
-	u64    dropped_frames; /* Dropped frames           */
-	u64    link_failures;  /* Link Failure (LF) count          */
-	u64    loss_of_syncs;  /* Loss of sync count           */
-	u64    loss_of_signals;/* Loss of signal count         */
-	u64    primseq_errs;   /* Primitive sequence protocol err. */
-	u64    bad_os_count;   /* Invalid ordered sets         */
-	u64    err_enc_out;    /* Encoding err nonframe_8b10b      */
-	u64    err_enc;    /* Encoding err frame_8b10b         */
-};
-
-/**
- * 		Eth Port statistics.
- */
-struct bfa_pport_eth_stats_s {
-	u64    secs_reset;   /* Seconds since stats is reset   */
-	u64    frame_64;     /* Frames 64 bytes            */
-	u64    frame_65_127;     /* Frames 65-127 bytes        */
-	u64    frame_128_255;    /* Frames 128-255 bytes       */
-	u64    frame_256_511;    /* Frames 256-511 bytes       */
-	u64    frame_512_1023;   /* Frames 512-1023 bytes          */
-	u64    frame_1024_1518;  /* Frames 1024-1518 bytes         */
-	u64    frame_1519_1522;  /* Frames 1519-1522 bytes         */
-	u64    tx_bytes;     /* Tx bytes               */
-	u64    tx_packets;   /* Tx packets             */
-	u64    tx_mcast_packets; /* Tx multicast packets       */
-	u64    tx_bcast_packets; /* Tx broadcast packets       */
-	u64    tx_control_frame; /* Tx control frame           */
-	u64    tx_drop;      /* Tx drops               */
-	u64    tx_jabber;    /* Tx jabber              */
-	u64    tx_fcs_error;     /* Tx FCS error           */
-	u64    tx_fragments;     /* Tx fragments           */
-	u64    rx_bytes;     /* Rx bytes               */
-	u64    rx_packets;   /* Rx packets             */
-	u64    rx_mcast_packets; /* Rx multicast packets       */
-	u64    rx_bcast_packets; /* Rx broadcast packets       */
-	u64    rx_control_frames; /* Rx control frames         */
-	u64    rx_unknown_opcode; /* Rx unknown opcode         */
-	u64    rx_drop;      /* Rx drops               */
-	u64    rx_jabber;    /* Rx jabber              */
-	u64    rx_fcs_error;     /* Rx FCS errors              */
-	u64    rx_alignment_error; /* Rx alignment errors          */
-	u64    rx_frame_length_error; /* Rx frame len errors       */
-	u64    rx_code_error;    /* Rx code errors             */
-	u64    rx_fragments;     /* Rx fragments           */
-	u64    rx_pause;     /* Rx pause               */
-	u64    rx_zero_pause;    /* Rx zero pause              */
-	u64    tx_pause;     /* Tx pause               */
-	u64    tx_zero_pause;    /* Tx zero pause              */
-	u64    rx_fcoe_pause;    /* Rx FCoE pause              */
-	u64    rx_fcoe_zero_pause; /* Rx FCoE zero pause       */
-	u64    tx_fcoe_pause;    /* Tx FCoE pause              */
-	u64    tx_fcoe_zero_pause; /* Tx FCoE zero pause       */
-};
-
-/**
- * 		Port statistics.
- */
-union bfa_pport_stats_u {
-	struct bfa_pport_fc_stats_s	fc;
-	struct bfa_pport_eth_stats_s 	eth;
-};
-
-/**
- *              Port FCP mappings.
- */
-struct bfa_pport_fcpmap_s {
-	char		osdevname[256];
-	u32	bus;
-	u32        target;
-	u32        oslun;
-	u32        fcid;
-	wwn_t           nwwn;
-	wwn_t           pwwn;
-	u64        fcplun;
-	char		luid[256];
-};
-
-/**
- *              Port RNI	 */
-struct bfa_pport_rnid_s {
-	wwn_t             wwn;
-	u32          unittype;
-	u32          portid;
-	u32          attached_nodes_num;
-	u16          ip_version;
-	u16          udp_port;
-	u8           ipaddr[16];
-	u16          rsvd;
-	u16          topologydiscoveryflags;
-};
-
-struct bfa_fcport_fcf_s {
-	wwn_t           name;           /* FCF name                 */
-	wwn_t           fabric_name;    /* Fabric Name              */
-	u8		fipenabled;     /* FIP enabled or not       */
-	u8		fipfailed;      /* FIP failed or not        */
-	u8         	resv[2];
-	u8         	pri;            /* FCF priority             */
-	u8         	version;        /* FIP version used         */
-	u8         	available;      /* Available  for  login    */
-	u8         	fka_disabled;   /* FKA is disabled          */
-	u8         	maxsz_verified; /* FCoE max size verified   */
-	u8         	fc_map[3];      /* FC map                   */
-	u16		vlan;           /* FCoE vlan tag/priority   */
-	u32        	fka_adv_per;    /* FIP  ka advert. period   */
-	struct mac_s	mac;            /* FCF mac                  */
-};
-
-/**
- * 		Link state information
- */
-struct bfa_pport_link_s {
-	u8         linkstate;	/*  Link state bfa_pport_linkstate */
-	u8         linkstate_rsn;	/*  bfa_pport_linkstate_rsn_t */
-	u8         topology;	/*  P2P/LOOP bfa_pport_topology */
-	u8         speed;		/*  Link speed (1/2/4/8 G) */
-	u32        linkstate_opt;	/*  Linkstate optional data (debug) */
-	u8         trunked;	/*  Trunked or not (1 or 0) */
-	u8         resvd[3];
-	struct bfa_qos_attr_s  qos_attr;   /* QoS Attributes */
-	union {
-		struct bfa_qos_vc_attr_s qos_vc_attr;  /* VC info from ELP */
-		struct bfa_fcport_fcf_s fcf;    /* FCF information (for FCoE) */
-	} vc_fcf;
-};
-
-#endif /* __BFA_DEFS_PPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_qos.h b/drivers/scsi/bfa/include/defs/bfa_defs_qos.h
deleted file mode 100644
index aadbacd..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_qos.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_QOS_H__
-#define __BFA_DEFS_QOS_H__
-
-/**
- * QoS states
- */
-enum bfa_qos_state {
-	BFA_QOS_ONLINE = 1,		/*  QoS is online */
-	BFA_QOS_OFFLINE = 2,		/*  QoS is offline */
-};
-
-
-/**
- * QoS  Priority levels.
- */
-enum bfa_qos_priority {
-	BFA_QOS_UNKNOWN = 0,
-	BFA_QOS_HIGH  = 1,	/*  QoS Priority Level High */
-	BFA_QOS_MED  =  2,	/*  QoS Priority Level Medium */
-	BFA_QOS_LOW  =  3,	/*  QoS Priority Level Low */
-};
-
-
-/**
- * QoS  bandwidth allocation for each priority level
- */
-enum bfa_qos_bw_alloc {
-	BFA_QOS_BW_HIGH  = 60,	/*  bandwidth allocation for High */
-	BFA_QOS_BW_MED  =  30,	/*  bandwidth allocation for Medium */
-	BFA_QOS_BW_LOW  =  10,	/*  bandwidth allocation for Low */
-};
-
-/**
- * QoS attribute returned in QoS Query
- */
-struct bfa_qos_attr_s {
-	enum bfa_qos_state state;		/*  QoS current state */
-	u32  total_bb_cr;  	 	/*  Total BB Credits */
-};
-
-/**
- * These fields should be displayed only from the CLI.
- * There will be a separate BFAL API (get_qos_vc_attr ?)
- * to retrieve this.
- *
- */
-#define  BFA_QOS_MAX_VC  16
-
-struct bfa_qos_vc_info_s {
-	u8 vc_credit;
-	u8 borrow_credit;
-	u8 priority;
-	u8 resvd;
-};
-
-struct bfa_qos_vc_attr_s {
-	u16  total_vc_count;                    /*  Total VC Count */
-	u16  shared_credit;
-	u32  elp_opmode_flags;
-	struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC];  /*   as many as
-							    * total_vc_count */
-};
-
-/**
- * QoS statistics
- */
-struct bfa_qos_stats_s {
-	u32	flogi_sent; 		/*  QoS Flogi sent */
-	u32	flogi_acc_recvd;	/*  QoS Flogi Acc received */
-	u32	flogi_rjt_recvd; /*  QoS Flogi rejects received */
-	u32	flogi_retries;		/*  QoS Flogi retries */
-
-	u32	elp_recvd; 	   	/*  QoS ELP received */
-	u32	elp_accepted;       /*  QoS ELP Accepted */
-	u32	elp_rejected;       /*  QoS ELP rejected */
-	u32	elp_dropped;        /*  QoS ELP dropped  */
-
-	u32	qos_rscn_recvd;     /*  QoS RSCN received */
-	u32	rsvd; 		/* padding for 64 bit alignment */
-};
-
-#endif /* __BFA_DEFS_QOS_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_rport.h b/drivers/scsi/bfa/include/defs/bfa_defs_rport.h
deleted file mode 100644
index e0af59d..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_rport.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_RPORT_H__
-#define __BFA_DEFS_RPORT_H__
-
-#include <bfa_os_inc.h>
-#include <protocol/types.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_qos.h>
-
-/**
- * FCS remote port states
- */
-enum bfa_rport_state {
-	BFA_RPORT_UNINIT 	= 0,	/*  PORT is not yet initialized */
-	BFA_RPORT_OFFLINE 	= 1,	/*  rport is offline */
-	BFA_RPORT_PLOGI 	= 2,	/*  PLOGI to rport is in progress */
-	BFA_RPORT_ONLINE 	= 3,	/*  login to rport is complete */
-	BFA_RPORT_PLOGI_RETRY 	= 4,	/*  retrying login to rport */
-	BFA_RPORT_NSQUERY 	= 5,	/*  nameserver query */
-	BFA_RPORT_ADISC 	= 6,	/*  ADISC authentication */
-	BFA_RPORT_LOGO 		= 7,	/*  logging out with rport */
-	BFA_RPORT_LOGORCV 	= 8,	/*  handling LOGO from rport */
-	BFA_RPORT_NSDISC 	= 9,	/*  re-discover rport */
-};
-
-/**
- *  Rport Scsi Function : Initiator/Target.
- */
-enum bfa_rport_function {
-	BFA_RPORT_INITIATOR 	= 0x01,	/*  SCSI Initiator	*/
-	BFA_RPORT_TARGET 	= 0x02,	/*  SCSI Target	*/
-};
-
-/**
- * port/node symbolic names for rport
- */
-#define BFA_RPORT_SYMNAME_MAXLEN	255
-struct bfa_rport_symname_s {
-	char            symname[BFA_RPORT_SYMNAME_MAXLEN];
-};
-
-struct bfa_rport_hal_stats_s {
-	u32        sm_un_cr;	    /*  uninit: create events      */
-	u32        sm_un_unexp;	    /*  uninit: exception events   */
-	u32        sm_cr_on;	    /*  created: online events     */
-	u32        sm_cr_del;	    /*  created: delete events     */
-	u32        sm_cr_hwf;	    /*  created: IOC down          */
-	u32        sm_cr_unexp;	    /*  created: exception events  */
-	u32        sm_fwc_rsp;	    /*  fw create: f/w responses   */
-	u32        sm_fwc_del;	    /*  fw create: delete events   */
-	u32        sm_fwc_off;	    /*  fw create: offline events  */
-	u32        sm_fwc_hwf;	    /*  fw create: IOC down        */
-	u32        sm_fwc_unexp;	    /*  fw create: exception events*/
-	u32        sm_on_off;	    /*  online: offline events     */
-	u32        sm_on_del;	    /*  online: delete events      */
-	u32        sm_on_hwf;	    /*  online: IOC down events    */
-	u32        sm_on_unexp;	    /*  online: exception events   */
-	u32        sm_fwd_rsp;	    /*  fw delete: fw responses    */
-	u32        sm_fwd_del;	    /*  fw delete: delete events   */
-	u32        sm_fwd_hwf;	    /*  fw delete: IOC down events */
-	u32        sm_fwd_unexp;	    /*  fw delete: exception events*/
-	u32        sm_off_del;	    /*  offline: delete events     */
-	u32        sm_off_on;	    /*  offline: online events     */
-	u32        sm_off_hwf;	    /*  offline: IOC down events   */
-	u32        sm_off_unexp;	    /*  offline: exception events  */
-	u32        sm_del_fwrsp;	    /*  delete: fw responses       */
-	u32        sm_del_hwf;	    /*  delete: IOC down events    */
-	u32        sm_del_unexp;	    /*  delete: exception events   */
-	u32        sm_delp_fwrsp;	    /*  delete pend: fw responses  */
-	u32        sm_delp_hwf;	    /*  delete pend: IOC downs     */
-	u32        sm_delp_unexp;	    /*  delete pend: exceptions    */
-	u32        sm_offp_fwrsp;	    /*  off-pending: fw responses  */
-	u32        sm_offp_del;	    /*  off-pending: deletes       */
-	u32        sm_offp_hwf;	    /*  off-pending: IOC downs     */
-	u32        sm_offp_unexp;	    /*  off-pending: exceptions    */
-	u32        sm_iocd_off;	    /*  IOC down: offline events   */
-	u32        sm_iocd_del;	    /*  IOC down: delete events    */
-	u32        sm_iocd_on;	    /*  IOC down: online events    */
-	u32        sm_iocd_unexp;	    /*  IOC down: exceptions       */
-	u32        rsvd;
-};
-
-/**
- * FCS remote port statistics
- */
-struct bfa_rport_stats_s {
-	u32        offlines;           /*  remote port offline count  */
-	u32        onlines;            /*  remote port online count   */
-	u32        rscns;              /*  RSCN affecting rport       */
-	u32        plogis;		    /*  plogis sent                */
-	u32        plogi_accs;	    /*  plogi accepts              */
-	u32        plogi_timeouts;	    /*  plogi timeouts             */
-	u32        plogi_rejects;	    /*  rcvd plogi rejects         */
-	u32        plogi_failed;	    /*  local failure              */
-	u32        plogi_rcvd;	    /*  plogis rcvd                */
-	u32        prli_rcvd;          /*  inbound PRLIs              */
-	u32        adisc_rcvd;         /*  ADISCs received            */
-	u32        adisc_rejects;      /*  recvd  ADISC rejects       */
-	u32        adisc_sent;         /*  ADISC requests sent        */
-	u32        adisc_accs;         /*  ADISC accepted by rport    */
-	u32        adisc_failed;       /*  ADISC failed (no response) */
-	u32        adisc_rejected;     /*  ADISC rejected by us    */
-	u32        logos;              /*  logos sent                 */
-	u32        logo_accs;          /*  LOGO accepts from rport    */
-	u32        logo_failed;        /*  LOGO failures              */
-	u32        logo_rejected;      /*  LOGO rejects from rport    */
-	u32        logo_rcvd;          /*  LOGO from remote port      */
-
-	u32        rpsc_rcvd;         /*  RPSC received            */
-	u32        rpsc_rejects;      /*  recvd  RPSC rejects       */
-	u32        rpsc_sent;         /*  RPSC requests sent        */
-	u32        rpsc_accs;         /*  RPSC accepted by rport    */
-	u32        rpsc_failed;       /*  RPSC failed (no response) */
-	u32        rpsc_rejected;     /*  RPSC rejected by us    */
-
-	u32        rsvd;
-	struct bfa_rport_hal_stats_s	hal_stats;  /*  BFA rport stats    */
-};
-
-/**
- *  Rport's QoS attributes
- */
-struct bfa_rport_qos_attr_s {
-	enum bfa_qos_priority qos_priority;  /*  rport's QoS priority   */
-	u32	       qos_flow_id;	  /*  QoS flow Id	 */
-};
-
-/**
- * FCS remote port attributes returned in queries
- */
-struct bfa_rport_attr_s {
-	wwn_t           	nwwn;	/*  node wwn */
-	wwn_t           	pwwn;	/*  port wwn */
-	enum fc_cos cos_supported;	/*  supported class of services */
-	u32        	pid;	/*  port ID */
-	u32        	df_sz;	/*  Max payload size */
-	enum bfa_rport_state 	state;	/*  Rport State machine state */
-	enum fc_cos        	fc_cos;	/*  FC classes of services */
-	bfa_boolean_t   	cisc;	/*  CISC capable device */
-	struct bfa_rport_symname_s symname; /*  Symbolic Name */
-	enum bfa_rport_function	scsi_function; /*  Initiator/Target */
-	struct bfa_rport_qos_attr_s qos_attr; /*  qos attributes  */
-	enum bfa_pport_speed curr_speed;   /*  operating speed got from
-					    * RPSC ELS. UNKNOWN, if RPSC
-					    * is not supported */
-	bfa_boolean_t 	trl_enforced;	/*  TRL enforced ? TRUE/FALSE */
-	enum bfa_pport_speed	assigned_speed;	/* Speed assigned by the user.
-						 * will be used if RPSC is not
-						 * supported by the rport */
-};
-
-#define bfa_rport_aen_qos_data_t struct bfa_rport_qos_attr_s
-
-/**
- * BFA remote port events
- * Arguments below are in BFAL context from Mgmt
- * BFA_RPORT_AEN_ONLINE:    [in]: lpwwn	[out]: vf_id, lpwwn, rpwwn
- * BFA_RPORT_AEN_OFFLINE:   [in]: lpwwn [out]: vf_id, lpwwn, rpwwn
- * BFA_RPORT_AEN_DISCONNECT:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn
- * BFA_RPORT_AEN_QOS_PRIO:  [in]: lpwwn [out]: vf_id, lpwwn, rpwwn, prio
- * BFA_RPORT_AEN_QOS_FLOWID:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn, flow_id
- */
-enum bfa_rport_aen_event {
-	BFA_RPORT_AEN_ONLINE      = 1,	/*  RPort online event */
-	BFA_RPORT_AEN_OFFLINE     = 2,	/*  RPort offline event */
-	BFA_RPORT_AEN_DISCONNECT  = 3,	/*  RPort disconnect event */
-	BFA_RPORT_AEN_QOS_PRIO    = 4,	/*  QOS priority change event */
-	BFA_RPORT_AEN_QOS_FLOWID  = 5,	/*  QOS flow Id change event */
-};
-
-struct bfa_rport_aen_data_s {
-	u16        vf_id;	/*  vf_id of this logical port */
-	u16        rsvd[3];
-	wwn_t           ppwwn;	/*  WWN of its physical port */
-	wwn_t           lpwwn;	/*  WWN of this logical port */
-	wwn_t           rpwwn;	/*  WWN of this remote port */
-	union {
-		bfa_rport_aen_qos_data_t qos;
-	} priv;
-};
-
-#endif /* __BFA_DEFS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_status.h b/drivers/scsi/bfa/include/defs/bfa_defs_status.h
deleted file mode 100644
index 6eb4e62..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_status.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_STATUS_H__
-#define __BFA_DEFS_STATUS_H__
-
-/**
- * API status return values
- *
- * NOTE: The error msgs are auto generated from the comments. Only singe line
- * comments are supported
- */
-enum bfa_status {
-	BFA_STATUS_OK 		= 0,	/*  Success */
-	BFA_STATUS_FAILED 	= 1,	/*  Operation failed */
-	BFA_STATUS_EINVAL 	= 2,	/*  Invalid params Check input
-					 * parameters */
-	BFA_STATUS_ENOMEM 	= 3,	/*  Out of resources */
-	BFA_STATUS_ENOSYS 	= 4,	/*  Function not implemented */
-	BFA_STATUS_ETIMER 	= 5,	/*  Timer expired - Retry, if
-					 * persists, contact support */
-	BFA_STATUS_EPROTOCOL 	= 6,	/*  Protocol error */
-	BFA_STATUS_ENOFCPORTS 	= 7,	/*  No FC ports resources */
-	BFA_STATUS_NOFLASH 	= 8,	/*  Flash not present */
-	BFA_STATUS_BADFLASH 	= 9,	/*  Flash is corrupted or bad */
-	BFA_STATUS_SFP_UNSUPP 	= 10,	/*  Unsupported SFP - Replace SFP */
-	BFA_STATUS_UNKNOWN_VFID = 11,	/*  VF_ID not found */
-	BFA_STATUS_DATACORRUPTED = 12,	/*  Diag returned data corrupted
-					 * contact support */
-	BFA_STATUS_DEVBUSY 	= 13,	/*  Device busy - Retry operation */
-	BFA_STATUS_ABORTED 	= 14,	/*  Operation aborted */
-	BFA_STATUS_NODEV 	= 15,	/*  Dev is not present */
-	BFA_STATUS_HDMA_FAILED 	= 16,	/*  Host dma failed contact support */
-	BFA_STATUS_FLASH_BAD_LEN = 17,	/*  Flash bad length */
-	BFA_STATUS_UNKNOWN_LWWN = 18,	/*  LPORT PWWN not found */
-	BFA_STATUS_UNKNOWN_RWWN = 19,	/*  RPORT PWWN not found */
-	BFA_STATUS_FCPT_LS_RJT 	= 20,	/*  Got LS_RJT for FC Pass
-					 * through Req */
-	BFA_STATUS_VPORT_EXISTS = 21,	/*  VPORT already exists */
-	BFA_STATUS_VPORT_MAX 	= 22,	/*  Reached max VPORT supported
-					 * limit */
-	BFA_STATUS_UNSUPP_SPEED = 23,	/*  Invalid Speed Check speed
-					 * setting */
-	BFA_STATUS_INVLD_DFSZ 	= 24,	/*  Invalid Max data field size */
-	BFA_STATUS_CNFG_FAILED 	= 25,	/*  Setting can not be persisted */
-	BFA_STATUS_CMD_NOTSUPP 	= 26,	/*  Command/API not supported */
-	BFA_STATUS_NO_ADAPTER 	= 27,	/*  No Brocade Adapter Found */
-	BFA_STATUS_LINKDOWN 	= 28,	/*  Link is down - Check or replace
-					 * SFP/cable */
-	BFA_STATUS_FABRIC_RJT 	= 29,	/*  Reject from attached fabric */
-	BFA_STATUS_UNKNOWN_VWWN = 30,	/*  VPORT PWWN not found */
-	BFA_STATUS_NSLOGIN_FAILED = 31,	/*  Nameserver login failed */
-	BFA_STATUS_NO_RPORTS 	= 32,	/*  No remote ports found */
-	BFA_STATUS_NSQUERY_FAILED = 33,	/*  Nameserver query failed */
-	BFA_STATUS_PORT_OFFLINE = 34,	/*  Port is not online */
-	BFA_STATUS_RPORT_OFFLINE = 35,	/*  RPORT is not online */
-	BFA_STATUS_TGTOPEN_FAILED = 36,	/*  Remote SCSI target open failed */
-	BFA_STATUS_BAD_LUNS 	= 37,	/*  No valid LUNs found */
-	BFA_STATUS_IO_FAILURE 	= 38,	/*  SCSI target IO failure */
-	BFA_STATUS_NO_FABRIC 	= 39,	/*  No switched fabric present */
-	BFA_STATUS_EBADF 	= 40,	/*  Bad file descriptor */
-	BFA_STATUS_EINTR 	= 41,	/*  A signal was caught during ioctl */
-	BFA_STATUS_EIO 		= 42,	/*  I/O error */
-	BFA_STATUS_ENOTTY 	= 43,	/*  Inappropriate I/O control
-					 * operation */
-	BFA_STATUS_ENXIO 	= 44,	/*  No such device or address */
-	BFA_STATUS_EFOPEN 	= 45,	/*  Failed to open file */
-	BFA_STATUS_VPORT_WWN_BP = 46,	/*  WWN is same as base port's WWN */
-	BFA_STATUS_PORT_NOT_DISABLED = 47, /*  Port not disabled disable port
-					    * first */
-	BFA_STATUS_BADFRMHDR 	= 48,	/*  Bad frame header */
-	BFA_STATUS_BADFRMSZ 	= 49,	/*  Bad frame size check and replace
-					 * SFP/cable */
-	BFA_STATUS_MISSINGFRM 	= 50,   /* Missing frame check and replace
-					 * SFP/cable or for Mezz card check and
-					 * replace pass through module */
-	BFA_STATUS_LINKTIMEOUT 	= 51,	/*  Link timeout check and replace
-					 * SFP/cable */
-	BFA_STATUS_NO_FCPIM_NEXUS = 52,	/*  No FCP Nexus exists with the
-					 * rport */
-	BFA_STATUS_CHECKSUM_FAIL = 53,	/*  checksum failure */
-	BFA_STATUS_GZME_FAILED 	= 54,	/*  Get zone member query failed */
-	BFA_STATUS_SCSISTART_REQD = 55,	/*  SCSI disk require START command */
-	BFA_STATUS_IOC_FAILURE 	= 56,	/*  IOC failure - Retry, if persists
-					 * contact support */
-	BFA_STATUS_INVALID_WWN 	= 57,	/*  Invalid WWN */
-	BFA_STATUS_MISMATCH 	= 58,	/*  Version mismatch */
-	BFA_STATUS_IOC_ENABLED 	= 59,	/*  IOC is already enabled */
-	BFA_STATUS_ADAPTER_ENABLED = 60, /*  Adapter is not disabled disable
-					  * adapter first */
-	BFA_STATUS_IOC_NON_OP 	= 61,	/*  IOC is not operational. Enable IOC
-					 * and if it still fails,
-					 * contact support */
-	BFA_STATUS_ADDR_MAP_FAILURE = 62, /*  PCI base address not mapped
-					   * in OS */
-	BFA_STATUS_SAME_NAME 	= 63,	/*  Name exists! use a different
-					 * name */
-	BFA_STATUS_PENDING      = 64,   /*  API completes asynchronously */
-	BFA_STATUS_8G_SPD	= 65,	/*  Speed setting not valid for
-					 * 8G HBA */
-	BFA_STATUS_4G_SPD	= 66,	/*  Speed setting not valid for
-					 * 4G HBA */
-	BFA_STATUS_AD_IS_ENABLE = 67,	/*  Adapter is already enabled */
-	BFA_STATUS_EINVAL_TOV 	= 68,	/*  Invalid path failover TOV */
-	BFA_STATUS_EINVAL_QDEPTH = 69,	/*  Invalid queue depth value */
-	BFA_STATUS_VERSION_FAIL = 70,	/*  Application/Driver version
-					 * mismatch */
-	BFA_STATUS_DIAG_BUSY    = 71,	/*  diag busy */
-	BFA_STATUS_BEACON_ON	= 72,	/*  Port Beacon already on */
-	BFA_STATUS_BEACON_OFF	= 73,	/*  Port Beacon already off */
-	BFA_STATUS_LBEACON_ON   = 74,	/*  Link End-to-End Beacon already
-					 * on */
-	BFA_STATUS_LBEACON_OFF	= 75,	/*  Link End-to-End Beacon already
-					 * off */
-	BFA_STATUS_PORT_NOT_INITED = 76, /*  Port not initialized */
-	BFA_STATUS_RPSC_ENABLED = 77, /*  Target has a valid speed */
-	BFA_STATUS_ENOFSAVE = 78,	/*  No saved firmware trace */
-	BFA_STATUS_BAD_FILE = 79,	/*  Not a valid Brocade Boot Code
-					 * file */
-	BFA_STATUS_RLIM_EN = 80,	/*  Target rate limiting is already
-					 * enabled */
-	BFA_STATUS_RLIM_DIS = 81,  /*  Target rate limiting is already
-				    * disabled */
-	BFA_STATUS_IOC_DISABLED = 82,   /*  IOC is already disabled */
-	BFA_STATUS_ADAPTER_DISABLED = 83,   /*  Adapter is already disabled */
-	BFA_STATUS_BIOS_DISABLED = 84,   /*  Bios is already disabled */
-	BFA_STATUS_AUTH_ENABLED = 85,   /*  Authentication is already
-					 * enabled */
-	BFA_STATUS_AUTH_DISABLED = 86,   /*  Authentication is already
-					 * disabled */
-	BFA_STATUS_ERROR_TRL_ENABLED = 87,   /*  Target rate limiting is
-					      * enabled */
-	BFA_STATUS_ERROR_QOS_ENABLED = 88,   /*  QoS is enabled */
-	BFA_STATUS_NO_SFP_DEV = 89, /*  No SFP device check or replace SFP */
-	BFA_STATUS_MEMTEST_FAILED = 90,	/*  Memory test failed contact
-					 * support */
-	BFA_STATUS_INVALID_DEVID = 91,	/*  Invalid device id provided */
-	BFA_STATUS_QOS_ENABLED = 92, /*  QOS is already enabled */
-	BFA_STATUS_QOS_DISABLED = 93, /*  QOS is already disabled */
-	BFA_STATUS_INCORRECT_DRV_CONFIG = 94, /*  Check configuration
-					       * key/value pair */
-	BFA_STATUS_REG_FAIL = 95, /*  Can't read windows registry */
-	BFA_STATUS_IM_INV_CODE = 96, /*  Invalid IOCTL code */
-	BFA_STATUS_IM_INV_VLAN = 97, /*  Invalid VLAN ID */
-	BFA_STATUS_IM_INV_ADAPT_NAME = 98, /*  Invalid adapter name */
-	BFA_STATUS_IM_LOW_RESOURCES = 99, /*  Memory allocation failure in
-					   * driver */
-	BFA_STATUS_IM_VLANID_IS_PVID = 100, /*  Given VLAN id same as PVID */
-	BFA_STATUS_IM_VLANID_EXISTS = 101, /*  Given VLAN id already exists */
-	BFA_STATUS_IM_FW_UPDATE_FAIL = 102, /*  Updating firmware with new
-					     * VLAN ID failed */
-	BFA_STATUS_PORTLOG_ENABLED = 103, /*  Port Log is already enabled */
-	BFA_STATUS_PORTLOG_DISABLED = 104, /*  Port Log is already disabled */
-	BFA_STATUS_FILE_NOT_FOUND = 105, /*  Specified file could not be
-					  * found */
-	BFA_STATUS_QOS_FC_ONLY = 106, /*  QOS can be enabled for FC mode
-				       * only */
-	BFA_STATUS_RLIM_FC_ONLY = 107, /*  RATELIM can be enabled for FC mode
-					* only */
-	BFA_STATUS_CT_SPD = 108, /*  Invalid speed selection for Catapult. */
-	BFA_STATUS_LEDTEST_OP = 109, /*  LED test is operating */
-	BFA_STATUS_CEE_NOT_DN = 110, /*  eth port is not at down state, please
-				      * bring down first */
-	BFA_STATUS_10G_SPD = 111, /*  Speed setting not valid for 10G CNA */
-	BFA_STATUS_IM_INV_TEAM_NAME = 112, /*  Invalid team name */
-	BFA_STATUS_IM_DUP_TEAM_NAME = 113, /*  Given team name already
-					    * exists */
-	BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114, /*  Given adapter is part
-						    * of another team */
-	BFA_STATUS_IM_ADAPT_HAS_VLANS = 115, /*  Adapter has VLANs configured.
-					      * Delete all VLANs to become
-					      * part of the team */
-	BFA_STATUS_IM_PVID_MISMATCH = 116, /*  Mismatching PVIDs configured
-					    * for adapters */
-	BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117, /*  Mismatching link speeds
-						  * configured for adapters */
-	BFA_STATUS_IM_MTU_MISMATCH = 118, /*  Mismatching MTUs configured for
-					   * adapters */
-	BFA_STATUS_IM_RSS_MISMATCH = 119, /*  Mismatching RSS parameters
-					   * configured for adapters */
-	BFA_STATUS_IM_HDS_MISMATCH = 120, /*  Mismatching HDS parameters
-					   * configured for adapters */
-	BFA_STATUS_IM_OFFLOAD_MISMATCH = 121, /*  Mismatching offload
-					       * parameters configured for
-					       * adapters */
-	BFA_STATUS_IM_PORT_PARAMS = 122, /*  Error setting port parameters */
-	BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123, /*  Port is not part of team */
-	BFA_STATUS_IM_CANNOT_REM_PRI = 124, /*  Primary adapter cannot be
-					     * removed. Change primary before
-					     * removing */
-	BFA_STATUS_IM_MAX_PORTS_REACHED = 125, /*  Exceeding maximum ports
-						* per team */
-	BFA_STATUS_IM_LAST_PORT_DELETE = 126, /*  Last port in team being
-					       * deleted */
-	BFA_STATUS_IM_NO_DRIVER = 127, /*  IM driver is not installed */
-	BFA_STATUS_IM_MAX_VLANS_REACHED = 128, /*  Exceeding maximum VLANs
-						* per port */
-	BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129, /* Bios speed config not
-						  * allowed for CNA */
-	BFA_STATUS_NO_MINPORT_DRIVER = 130, /*  Miniport driver is not
-					     * loaded */
-	BFA_STATUS_CARD_TYPE_MISMATCH = 131, /*  Card type mismatch */
-	BFA_STATUS_BAD_ASICBLK = 132, /*  Bad ASIC block */
-	BFA_STATUS_NO_DRIVER = 133, /*  Brocade adapter/driver not installed
-				     *  or loaded */
-	BFA_STATUS_INVALID_MAC = 134, /*  Invalid MAC address */
-	BFA_STATUS_IM_NO_VLAN = 135, /*  No VLANs configured on the adapter */
-	BFA_STATUS_IM_ETH_LB_FAILED = 136, /*  Ethernet loopback test failed */
-	BFA_STATUS_IM_PVID_REMOVE = 137, /* Cannot remove port VLAN (PVID) */
-	BFA_STATUS_IM_PVID_EDIT = 138, /* Cannot edit port VLAN (PVID) */
-	BFA_STATUS_CNA_NO_BOOT = 139, /*  Boot upload not allowed for CNA */
-	BFA_STATUS_IM_PVID_NON_ZERO = 140, /*  Port VLAN ID (PVID) is Set to
-					    * Non-Zero Value */
-	BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141, /*  Acquiring Network
-						  * Subsystem Lock Failed.Please
-						  * try after some time */
-	BFA_STATUS_IM_GET_INETCFG_FAILED = 142, /*  Acquiring Network Subsystem
-						 * handle Failed. Please try
-						 * after some time */
-	BFA_STATUS_IM_NOT_BOUND = 143, /*  IM driver is not active */
-	BFA_STATUS_INSUFFICIENT_PERMS = 144, /*  User doesn't have sufficient
-					      * permissions to execute the BCU
-					      * application */
-	BFA_STATUS_IM_INV_VLAN_NAME = 145, /* Invalid/Reserved VLAN name
-					    * string. The name is not allowed
-					    * for the normal VLAN */
-	BFA_STATUS_CMD_NOTSUPP_CNA = 146, /*  Command not supported for CNA */
-	BFA_STATUS_IM_PASSTHRU_EDIT = 147, /* Can not edit passthrough VLAN
-					    * id */
-	BFA_STATUS_IM_BIND_FAILED = 148, /* IM Driver bind operation
-					  * failed */
-	BFA_STATUS_IM_UNBIND_FAILED = 149, /* IM Driver unbind operation
-					    * failed */
-	BFA_STATUS_IM_PORT_IN_TEAM = 150, /*  Port is already part of the
-					   * team */
-	BFA_STATUS_IM_VLAN_NOT_FOUND = 151, /*  VLAN ID doesn't exists */
-	BFA_STATUS_IM_TEAM_NOT_FOUND = 152, /*  Teaming configuration doesn't
-					     * exists */
-	BFA_STATUS_IM_TEAM_CFG_NOT_ALLOWED = 153, /*  Given settings are not
-						* allowed for the current
-						* Teaming mode */
-	BFA_STATUS_PBC = 154, /* Operation not allowed for pre-boot
-			       * configuration */
-	BFA_STATUS_DEVID_MISSING = 155, /* Boot image is not for the adapter(s)
-					 * installed */
-	BFA_STATUS_BAD_FWCFG = 156, /* Bad firmware configuration */
-	BFA_STATUS_CREATE_FILE = 157, /* Failed to create temporary file */
-	BFA_STATUS_INVALID_VENDOR = 158, /* Invalid switch vendor */
-	BFA_STATUS_SFP_NOT_READY = 159, /* SFP info is not ready. Retry */
-	BFA_STATUS_NO_TOPOLOGY_FOR_CNA = 160, /* Topology command not
-					       * applicable to CNA */
-	BFA_STATUS_BOOT_CODE_UPDATED = 161, /* reboot -- -r is needed after
-					     * boot code updated */
-	BFA_STATUS_BOOT_VERSION = 162, /* Boot code version not compatible with
-					* the driver installed */
-	BFA_STATUS_CARDTYPE_MISSING = 163, /* Boot image is not for the
-					    * adapter(s) installed */
-	BFA_STATUS_INVALID_CARDTYPE = 164, /* Invalid card type provided */
-	BFA_STATUS_MAX_VAL              /* Unknown error code */
-};
-#define bfa_status_t enum bfa_status
-
-enum bfa_eproto_status {
-	BFA_EPROTO_BAD_ACCEPT = 0,
-	BFA_EPROTO_UNKNOWN_RSP = 1
-};
-#define bfa_eproto_status_t enum bfa_eproto_status
-
-#endif /* __BFA_DEFS_STATUS_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tin.h b/drivers/scsi/bfa/include/defs/bfa_defs_tin.h
deleted file mode 100644
index e05a2db..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_tin.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_TIN_H__
-#define __BFA_DEFS_TIN_H__
-
-#include <protocol/types.h>
-#include <protocol/fc.h>
-
-/**
- * FCS tin states
- */
-enum bfa_tin_state_e {
-	BFA_TIN_SM_OFFLINE = 0,		/*  tin is offline */
-	BFA_TIN_SM_WOS_LOGIN = 1,	/*  Waiting PRLI ACC/RJT from ULP */
-	BFA_TIN_SM_WFW_ONLINE = 2,	/*  Waiting ACK to PRLI ACC from FW */
-	BFA_TIN_SM_ONLINE = 3,		/*  tin login is complete */
-	BFA_TIN_SM_WIO_RELOGIN = 4,	/*  tin relogin is in progress */
-	BFA_TIN_SM_WIO_LOGOUT = 5,	/*  Processing of PRLO req from
-					 *   Initiator is in progress
-					 */
-	BFA_TIN_SM_WOS_LOGOUT = 6,	/*  Processing of PRLO req from
-					 *   Initiator is in progress
-					 */
-	BFA_TIN_SM_WIO_CLEAN = 7,	/*  Waiting for IO cleanup before tin
-					 *   is offline. This can be triggered
-					 *   by RPORT LOGO (rcvd/sent) or by
-					 *   PRLO (rcvd/sent)
-					 */
-};
-
-struct bfa_prli_req_s {
-	struct fchs_s fchs;
-	struct fc_prli_s prli_payload;
-};
-
-struct bfa_prlo_req_s {
-	struct fchs_s fchs;
-	struct fc_prlo_s prlo_payload;
-};
-
-void bfa_tin_send_login_rsp(void *bfa_tin, u32 login_rsp,
-				struct fc_ls_rjt_s rjt_payload);
-void bfa_tin_send_logout_rsp(void *bfa_tin, u32 logout_rsp,
-				struct fc_ls_rjt_s rjt_payload);
-/**
- * FCS target port statistics
- */
-struct bfa_tin_stats_s {
-	u32 onlines;	/*  ITN nexus onlines (PRLI done) */
-	u32 offlines;	/*  ITN Nexus offlines 	*/
-	u32 prli_req_parse_err;	/*  prli req parsing errors */
-	u32 prli_rsp_rjt;	/*  num prli rsp rejects sent */
-	u32 prli_rsp_acc;	/*  num prli rsp accepts sent */
-	u32 cleanup_comps;	/*  ITN cleanup completions */
-};
-
-/**
- * FCS tin attributes returned in queries
- */
-struct bfa_tin_attr_s {
-	enum bfa_tin_state_e state;
-	u8	seq_retry;    /*  Sequence retry supported      */
-	u8	rsvd[3];
-};
-
-/**
- * BFA TIN async event data structure for BFAL
- */
-enum bfa_tin_aen_event {
-	BFA_TIN_AEN_ONLINE 	= 1,	/*  Target online */
-	BFA_TIN_AEN_OFFLINE 	= 2,	/*  Target offline */
-	BFA_TIN_AEN_DISCONNECT	= 3,	/*  Target disconnected */
-};
-
-/**
- * BFA TIN event data structure.
- */
-struct bfa_tin_aen_data_s {
-	u16 vf_id;	/*  vf_id of the IT nexus */
-	u16 rsvd[3];
-	wwn_t lpwwn;	/*  WWN of logical port */
-	wwn_t rpwwn;	/*  WWN of remote(target) port */
-};
-
-/**
- * Below APIs are needed from BFA driver
- * Move these to BFA driver public header file?
- */
-/*  TIN rcvd new PRLI & gets bfad_tin_t ptr from driver this callback */
-void *bfad_tin_rcvd_login_req(void *bfad_tm_port, void *bfa_tin,
-				wwn_t rp_wwn, u32 rp_fcid,
-				struct bfa_prli_req_s prli_req);
-/*  TIN rcvd new PRLO */
-void bfad_tin_rcvd_logout_req(void *bfad_tin, wwn_t rp_wwn, u32 rp_fcid,
-				struct bfa_prlo_req_s prlo_req);
-/*  TIN is online and ready for IO */
-void bfad_tin_online(void *bfad_tin);
-/*  TIN is offline and BFA driver can shutdown its upper stack */
-void bfad_tin_offline(void *bfad_tin);
-/*  TIN does not need this BFA driver tin tag anymore, so can be freed */
-void bfad_tin_res_free(void *bfad_tin);
-
-#endif /* __BFA_DEFS_TIN_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h b/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h
deleted file mode 100644
index ade763db..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_TSENSOR_H__
-#define __BFA_DEFS_TSENSOR_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_types.h>
-
-/**
- * Temperature sensor status values
- */
-enum bfa_tsensor_status {
-	BFA_TSENSOR_STATUS_UNKNOWN   = 1,   /*  unknown status */
-	BFA_TSENSOR_STATUS_FAULTY    = 2,   /*  sensor is faulty */
-	BFA_TSENSOR_STATUS_BELOW_MIN = 3,   /*  temperature below mininum */
-	BFA_TSENSOR_STATUS_NOMINAL   = 4,   /*  normal temperature */
-	BFA_TSENSOR_STATUS_ABOVE_MAX = 5,   /*  temperature above maximum */
-};
-
-/**
- * Temperature sensor attribute
- */
-struct bfa_tsensor_attr_s {
-	enum bfa_tsensor_status status;	/*  temperature sensor status */
-	u32        	value;	/*  current temperature in celsius */
-};
-
-#endif /* __BFA_DEFS_TSENSOR_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_types.h b/drivers/scsi/bfa/include/defs/bfa_defs_types.h
deleted file mode 100644
index 4348332..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_types.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_TYPES_H__
-#define __BFA_DEFS_TYPES_H__
-
-#include <bfa_os_inc.h>
-
-enum bfa_boolean {
-	BFA_FALSE = 0,
-	BFA_TRUE  = 1
-};
-#define bfa_boolean_t enum bfa_boolean
-
-#define BFA_STRING_32	32
-
-#endif /* __BFA_DEFS_TYPES_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_version.h b/drivers/scsi/bfa/include/defs/bfa_defs_version.h
deleted file mode 100644
index f8902a2..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_version.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#ifndef __BFA_DEFS_VERSION_H__
-#define __BFA_DEFS_VERSION_H__
-
-#define BFA_VERSION_LEN		64
-
-#endif
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vf.h b/drivers/scsi/bfa/include/defs/bfa_defs_vf.h
deleted file mode 100644
index 3235be5..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_vf.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_VF_H__
-#define __BFA_DEFS_VF_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_port.h>
-#include <protocol/types.h>
-
-/**
- * VF states
- */
-enum bfa_vf_state {
-	BFA_VF_UNINIT    = 0,	/*  fabric is not yet initialized */
-	BFA_VF_LINK_DOWN = 1,	/*  link is down */
-	BFA_VF_FLOGI     = 2,	/*  flogi is in progress */
-	BFA_VF_AUTH      = 3,	/*  authentication in progress */
-	BFA_VF_NOFABRIC  = 4,	/*  fabric is not present */
-	BFA_VF_ONLINE    = 5,	/*  login to fabric is complete */
-	BFA_VF_EVFP      = 6,	/*  EVFP is in progress */
-	BFA_VF_ISOLATED  = 7,	/*  port isolated due to vf_id mismatch */
-};
-
-/**
- * VF statistics
- */
-struct bfa_vf_stats_s {
-	u32        flogi_sent;	/*  Num FLOGIs sent 		*/
-	u32        flogi_rsp_err;	/*  FLOGI response errors 	*/
-	u32        flogi_acc_err;	/*  FLOGI accept errors 	*/
-	u32        flogi_accepts;	/*  FLOGI accepts received 	*/
-	u32        flogi_rejects;	/*  FLOGI rejects received 	*/
-	u32        flogi_unknown_rsp; /*  Unknown responses for FLOGI */
-	u32        flogi_alloc_wait; /*  Allocation waits prior to
-					   * sending FLOGI
-					   */
-	u32        flogi_rcvd;	/*  FLOGIs received */
-	u32        flogi_rejected;	/*  Incoming FLOGIs rejected */
-	u32        fabric_onlines;	/*  Internal fabric online
-					 * notification sent to other
-					 * modules
-					 */
-	u32        fabric_offlines; /*  Internal fabric offline
-					  * notification sent to other
-					  * modules
-					  */
-	u32        resvd;
-};
-
-/**
- * VF attributes returned in queries
- */
-struct bfa_vf_attr_s {
-	enum bfa_vf_state  state;		/*  VF state */
-	u32        rsvd;
-	wwn_t           fabric_name;	/*  fabric name */
-};
-
-#endif /* __BFA_DEFS_VF_H__ */
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vport.h b/drivers/scsi/bfa/include/defs/bfa_defs_vport.h
deleted file mode 100644
index 9f021f4..0000000
--- a/drivers/scsi/bfa/include/defs/bfa_defs_vport.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_DEFS_VPORT_H__
-#define __BFA_DEFS_VPORT_H__
-
-#include <bfa_os_inc.h>
-#include <defs/bfa_defs_port.h>
-#include <protocol/types.h>
-
-/**
- * VPORT states
- */
-enum bfa_vport_state {
-	BFA_FCS_VPORT_UNINIT 		= 0,
-	BFA_FCS_VPORT_CREATED 		= 1,
-	BFA_FCS_VPORT_OFFLINE 		= 1,
-	BFA_FCS_VPORT_FDISC_SEND 	= 2,
-	BFA_FCS_VPORT_FDISC 		= 3,
-	BFA_FCS_VPORT_FDISC_RETRY 	= 4,
-	BFA_FCS_VPORT_ONLINE 		= 5,
-	BFA_FCS_VPORT_DELETING 		= 6,
-	BFA_FCS_VPORT_CLEANUP 		= 6,
-	BFA_FCS_VPORT_LOGO_SEND 	= 7,
-	BFA_FCS_VPORT_LOGO 			= 8,
-	BFA_FCS_VPORT_ERROR			= 9,
-	BFA_FCS_VPORT_MAX_STATE,
-};
-
-/**
- * vport statistics
- */
-struct bfa_vport_stats_s {
-	struct bfa_port_stats_s port_stats;	/*  base class (port) stats */
-	/*
-	 * TODO - remove
-	 */
-
-	u32        fdisc_sent;	/*  num fdisc sent */
-	u32        fdisc_accepts;	/*  fdisc accepts */
-	u32        fdisc_retries;	/*  fdisc retries */
-	u32        fdisc_timeouts;	/*  fdisc timeouts */
-	u32        fdisc_rsp_err;	/*  fdisc response error */
-	u32        fdisc_acc_bad;	/*  bad fdisc accepts */
-	u32        fdisc_rejects;	/*  fdisc rejects */
-	u32        fdisc_unknown_rsp;
-	/*
-	 *!< fdisc rsp unknown error
-	 */
-	u32        fdisc_alloc_wait;/*  fdisc req (fcxp)alloc wait */
-
-	u32        logo_alloc_wait;/*  logo req (fcxp) alloc wait */
-	u32        logo_sent;	/*  logo sent */
-	u32        logo_accepts;	/*  logo accepts */
-	u32        logo_rejects;	/*  logo rejects */
-	u32        logo_rsp_err;	/*  logo rsp errors */
-	u32        logo_unknown_rsp;
-			/*  logo rsp unknown errors */
-
-	u32        fab_no_npiv;	/*  fabric does not support npiv */
-
-	u32        fab_offline;	/*  offline events from fab SM */
-	u32        fab_online;	/*  online events from fab SM */
-	u32        fab_cleanup;	/*  cleanup request from fab SM */
-	u32        rsvd;
-};
-
-/**
- * BFA vport attribute returned in queries
- */
-struct bfa_vport_attr_s {
-	struct bfa_port_attr_s   port_attr; /*  base class (port) attributes */
-	enum bfa_vport_state vport_state; /*  vport state */
-	u32          rsvd;
-};
-
-#endif /* __BFA_DEFS_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb.h b/drivers/scsi/bfa/include/fcb/bfa_fcb.h
deleted file mode 100644
index 2963b0b..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcb.h BFA FCS callback interfaces
- */
-
-#ifndef __BFA_FCB_H__
-#define __BFA_FCB_H__
-
-/**
- *  fcb Main fcs callbacks
- */
-
-void bfa_fcb_exit(struct bfad_s *bfad);
-
-
-
-#endif /* __BFA_FCB_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h
deleted file mode 100644
index 52585d3..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
-* : bfad_fcpim.h - BFA FCS initiator mode remote port callbacks
- */
-
-#ifndef __BFAD_FCB_FCPIM_H__
-#define __BFAD_FCB_FCPIM_H__
-
-struct bfad_itnim_s;
-
-/*
- * RPIM callbacks
- */
-
-/**
- * 	Memory allocation for remote port instance. Called before PRLI is
- * 	initiated to the remote target port.
- *
- * @param[in] bfad		- driver instance
- * @param[out] itnim		- FCS remote port (IM) instance
- * @param[out] itnim_drv	- driver remote port (IM) instance
- *
- * @return None
- */
-void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim,
-				    struct bfad_itnim_s **itnim_drv);
-
-/**
- * 		Free remote port (IM) instance.
- *
- * @param[in] bfad	- driver instance
- * @param[in] itnim_drv	- driver remote port instance
- *
- * @return None
- */
-void            bfa_fcb_itnim_free(struct bfad_s *bfad,
-				   struct bfad_itnim_s *itnim_drv);
-
-/**
- * 	Notification of when login with a remote target device is complete.
- *
- * @param[in] itnim_drv	- driver remote port instance
- *
- * @return None
- */
-void            bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv);
-
-/**
- * 	Notification when login with the remote device is severed.
- *
- * @param[in] itnim_drv	- driver remote port instance
- *
- * @return None
- */
-void            bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv);
-
-void            bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim_drv);
-
-#endif /* __BFAD_FCB_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h
deleted file mode 100644
index 5fd7f98..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcb_port.h BFA FCS virtual port driver interfaces
- */
-
-#ifndef __BFA_FCB_PORT_H__
-#define __BFA_FCB_PORT_H__
-
-#include <fcb/bfa_fcb_vport.h>
-/**
- *  fcs_port_fcb FCS port driver interfaces
- */
-
-/*
- * Forward declarations
- */
-struct bfad_port_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * 	Call from FCS to driver module when a port is instantiated. The port
- * 	can be a base port or a virtual port with in the base fabric or
- * 	a virtual fabric.
- *
- *  On this callback, driver is supposed to create scsi_host, scsi_tgt or
- *  network interfaces bases on ports personality/roles.
- *
- *      base port of base fabric:	vf_drv == NULL && vp_drv == NULL
- *      vport of base fabric:		vf_drv == NULL && vp_drv != NULL
- *      base port of VF:		vf_drv != NULL && vp_drv == NULL
- *      vport of VF:			vf_drv != NULL && vp_drv != NULL
- *
- * @param[in] bfad   - driver instance
- * @param[in] port   - FCS port instance
- * @param[in] roles  - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-struct bfad_port_s *bfa_fcb_port_new(struct bfad_s *bfad,
-			struct bfa_fcs_port_s *port,
-			enum bfa_port_role roles, struct bfad_vf_s *vf_drv,
-			struct bfad_vport_s *vp_drv);
-
-/**
- * 	Call from FCS to driver module when a port is deleted. The port
- * 	can be a base port or a virtual port with in the base fabric or
- * 	a virtual fabric.
- *
- * @param[in] bfad   - driver instance
- * @param[in] roles  - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-void bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles,
-			struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
-
-/**
- * 	Notification when port transitions to ONLINE state.
- *
- * Online notification is a logical link up for the local port. This
- * notification is sent after a successfull FLOGI, or a successful
- * link initialization in proviate-loop or N2N topologies.
- *
- * @param[in] bfad   - driver instance
- * @param[in] roles  - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-void bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles,
-			struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
-
-/**
- * 	Notification when port transitions to OFFLINE state.
- *
- * Offline notification is a logical link down for the local port.
- *
- * @param[in] bfad   - driver instance
- * @param[in] roles  - port roles: IM, TM, IP
- * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF)
- * @param[in] vp_drv - vport driver instance, NULL if base port
- *
- * @return None
- */
-void bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles,
-			struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv);
-
-
-#endif /* __BFA_FCB_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h
deleted file mode 100644
index e0261bb..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcb_rport.h BFA FCS rport driver interfaces
- */
-
-#ifndef __BFA_FCB_RPORT_H__
-#define __BFA_FCB_RPORT_H__
-
-/**
- *  fcs_rport_fcb Remote port driver interfaces
- */
-
-
-struct bfad_rport_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * 	Completion callback for bfa_fcs_rport_add().
- *
- * @param[in] rport_drv - driver instance of rport
- *
- * @return None
- */
-void bfa_fcb_rport_add(struct bfad_rport_s *rport_drv);
-
-/**
- * 	Completion callback for bfa_fcs_rport_remove().
- *
- * @param[in] rport_drv - driver instance of rport
- *
- * @return None
- */
-void bfa_fcb_rport_remove(struct bfad_rport_s *rport_drv);
-
-/**
- * 		Call to allocate a rport instance.
- *
- * @param[in] bfad - driver instance
- * @param[out] rport - BFA FCS instance of rport
- * @param[out] rport_drv - driver instance of rport
- *
- * @retval BFA_STATUS_OK - successfully allocated
- * @retval BFA_STATUS_ENOMEM - cannot allocate
- */
-bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad,
-			struct bfa_fcs_rport_s **rport,
-			struct bfad_rport_s **rport_drv);
-
-/**
- * 	Call to free rport memory resources.
- *
- * @param[in] bfad - driver instance
- * @param[in] rport_drv - driver instance of rport
- *
- * @return None
- */
-void bfa_fcb_rport_free(struct bfad_s *bfad, struct bfad_rport_s **rport_drv);
-
-
-
-#endif /* __BFA_FCB_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h
deleted file mode 100644
index cfd3fac..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcb_vf.h BFA FCS virtual fabric driver interfaces
- */
-
-#ifndef __BFA_FCB_VF_H__
-#define __BFA_FCB_VF_H__
-
-/**
- *  fcs_vf_fcb Virtual fabric driver intrefaces
- */
-
-
-struct bfad_vf_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * 	Completion callback for bfa_fcs_vf_stop().
- *
- * @param[in] vf_drv - driver instance of vf
- *
- * @return None
- */
-void            bfa_fcb_vf_stop(struct bfad_vf_s *vf_drv);
-
-
-
-#endif /* __BFA_FCB_VF_H__ */
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h
deleted file mode 100644
index cfd6ba7..0000000
--- a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcb_vport.h BFA FCS virtual port driver interfaces
- */
-
-#ifndef __BFA_FCB_VPORT_H__
-#define __BFA_FCB_VPORT_H__
-
-/**
- *  fcs_vport_fcb Virtual port driver interfaces
- */
-
-
-struct bfad_vport_s;
-
-/*
- * Callback functions from BFA FCS to driver
- */
-
-/**
- * 	Completion callback for bfa_fcs_vport_delete().
- *
- * @param[in] vport_drv - driver instance of vport
- *
- * @return None
- */
-void bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv);
-void bfa_fcb_pbc_vport_create(struct bfad_s *bfad, struct bfi_pbc_vport_s);
-
-
-
-#endif /* __BFA_FCB_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs.h b/drivers/scsi/bfa/include/fcs/bfa_fcs.h
deleted file mode 100644
index 54e5b81..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_FCS_H__
-#define __BFA_FCS_H__
-
-#include <cs/bfa_debug.h>
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_version.h>
-#include <bfa.h>
-#include <fcs/bfa_fcs_fabric.h>
-
-#define BFA_FCS_OS_STR_LEN  		64
-
-struct bfa_fcs_stats_s {
-	struct {
-		u32        untagged; /*  untagged receive frames */
-		u32        tagged;	/*  tagged receive frames */
-		u32        vfid_unknown;	/*  VF id is unknown */
-	} uf;
-};
-
-struct bfa_fcs_driver_info_s {
-	u8  version[BFA_VERSION_LEN];		/*  Driver Version */
-	u8  host_machine_name[BFA_FCS_OS_STR_LEN];
-	u8  host_os_name[BFA_FCS_OS_STR_LEN]; /*  OS name and version */
-	u8  host_os_patch[BFA_FCS_OS_STR_LEN];/*  patch or service pack */
-	u8  os_device_name[BFA_FCS_OS_STR_LEN]; /*  Driver Device Name */
-};
-
-struct bfa_fcs_s {
-	struct bfa_s      *bfa;	/*  corresponding BFA bfa instance */
-	struct bfad_s         *bfad; /*  corresponding BDA driver instance */
-	struct bfa_log_mod_s  *logm;	/*  driver logging module instance */
-	struct bfa_trc_mod_s  *trcmod;	/*  tracing module */
-	struct bfa_aen_s      *aen;	/*  aen component */
-	bfa_boolean_t   vf_enabled;	/*  VF mode is enabled */
-	bfa_boolean_t   fdmi_enabled;   /*!< FDMI is enabled */
-	bfa_boolean_t min_cfg;		/* min cfg enabled/disabled */
-	u16        port_vfid;	/*  port default VF ID */
-	struct bfa_fcs_driver_info_s driver_info;
-	struct bfa_fcs_fabric_s fabric; /*  base fabric state machine */
-	struct bfa_fcs_stats_s	stats;	/*  FCS statistics */
-	struct bfa_wc_s       	wc;	/*  waiting counter */
-};
-
-/*
- * bfa fcs API functions
- */
-void bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa,
-			struct bfad_s *bfad, bfa_boolean_t min_cfg);
-void bfa_fcs_init(struct bfa_fcs_s *fcs);
-void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
-			struct bfa_fcs_driver_info_s *driver_info);
-void bfa_fcs_set_fdmi_param(struct bfa_fcs_s *fcs, bfa_boolean_t fdmi_enable);
-void bfa_fcs_exit(struct bfa_fcs_s *fcs);
-void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod);
-void bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod);
-void bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen);
-void 	  	bfa_fcs_start(struct bfa_fcs_s *fcs);
-
-#endif /* __BFA_FCS_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h
deleted file mode 100644
index 28c4c9f..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_FCS_AUTH_H__
-#define __BFA_FCS_AUTH_H__
-
-struct bfa_fcs_s;
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_auth.h>
-#include <defs/bfa_defs_vf.h>
-#include <cs/bfa_q.h>
-#include <cs/bfa_sm.h>
-#include <defs/bfa_defs_pport.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <protocol/fc_sp.h>
-
-struct bfa_fcs_fabric_s;
-
-
-
-struct bfa_fcs_auth_s {
-	bfa_sm_t	sm;	/*  state machine */
-	bfa_boolean_t   policy;	/*  authentication enabled/disabled */
-	enum bfa_auth_status status;	/*  authentication status */
-	enum auth_rjt_codes  rjt_code;	/*  auth reject status */
-	enum auth_rjt_code_exps  rjt_code_exp;	/*  auth reject reason */
-	enum bfa_auth_algo algo;	/*  Authentication algorithm */
-	struct bfa_auth_stats_s stats;	/*  Statistics */
-	enum auth_dh_gid   group;	/*  DH(diffie-hellman) Group */
-	enum bfa_auth_secretsource source;	/*  Secret source */
-	char            secret[BFA_AUTH_SECRET_STRING_LEN];
-				/*  secret string */
-	u8         secret_len;
-				/*  secret string length */
-	u8         nretries;
-				/*  number of retries */
-	struct bfa_fcs_fabric_s *fabric;/*  pointer to fabric */
-	u8         sentcode;	/*  pointer to response data */
-	u8        *response;	/*  pointer to response data */
-	struct bfa_timer_s delay_timer; 	/*  delay timer */
-	struct bfa_fcxp_s *fcxp;		/*  pointer to fcxp */
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-};
-
-/**
- * bfa fcs authentication public functions
- */
-bfa_status_t    bfa_fcs_auth_get_attr(struct bfa_fcs_s *port,
-				      struct bfa_auth_attr_s *attr);
-bfa_status_t    bfa_fcs_auth_set_policy(struct bfa_fcs_s *port,
-					bfa_boolean_t policy);
-enum bfa_auth_status bfa_fcs_auth_get_status(struct bfa_fcs_s *port);
-bfa_status_t    bfa_fcs_auth_set_algo(struct bfa_fcs_s *port,
-				      enum bfa_auth_algo algo);
-bfa_status_t    bfa_fcs_auth_get_stats(struct bfa_fcs_s *port,
-				       struct bfa_auth_stats_s *stats);
-bfa_status_t    bfa_fcs_auth_set_dh_group(struct bfa_fcs_s *port, int group);
-bfa_status_t    bfa_fcs_auth_set_secretstring(struct bfa_fcs_s *port,
-					      char *secret);
-bfa_status_t    bfa_fcs_auth_set_secretstring_encrypt(struct bfa_fcs_s *port,
-					      u32 secret[], u32 len);
-bfa_status_t    bfa_fcs_auth_set_secretsource(struct bfa_fcs_s *port,
-					      enum bfa_auth_secretsource src);
-bfa_status_t    bfa_fcs_auth_reset_stats(struct bfa_fcs_s *port);
-bfa_status_t    bfa_fcs_auth_reinit(struct bfa_fcs_s *port);
-
-#endif /* __BFA_FCS_AUTH_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h
deleted file mode 100644
index 08b79d5..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_FCS_FABRIC_H__
-#define __BFA_FCS_FABRIC_H__
-
-struct bfa_fcs_s;
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_vf.h>
-#include <cs/bfa_q.h>
-#include <cs/bfa_sm.h>
-#include <defs/bfa_defs_pport.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <protocol/fc_sp.h>
-#include <fcs/bfa_fcs_auth.h>
-
-/*
- * forward declaration
- */
-struct bfad_vf_s;
-
-enum bfa_fcs_fabric_type {
-	BFA_FCS_FABRIC_UNKNOWN = 0,
-	BFA_FCS_FABRIC_SWITCHED = 1,
-	BFA_FCS_FABRIC_PLOOP = 2,
-	BFA_FCS_FABRIC_N2N = 3,
-};
-
-
-struct bfa_fcs_fabric_s {
-	struct list_head   qe;		/*  queue element */
-	bfa_sm_t	 sm;		/*  state machine */
-	struct bfa_fcs_s *fcs;		/*  FCS instance */
-	struct bfa_fcs_port_s  bport;	/*  base logical port */
-	enum bfa_fcs_fabric_type fab_type; /*  fabric type */
-	enum bfa_pport_type oper_type;	/*  current link topology */
-	u8         is_vf;		/*  is virtual fabric? */
-	u8         is_npiv;	/*  is NPIV supported ? */
-	u8         is_auth;	/*  is Security/Auth supported ? */
-	u16        bb_credit;	/*  BB credit from fabric */
-	u16        vf_id;		/*  virtual fabric ID */
-	u16        num_vports;	/*  num vports */
-	u16        rsvd;
-	struct list_head         vport_q;	/*  queue of virtual ports */
-	struct list_head         vf_q;	/*  queue of virtual fabrics */
-	struct bfad_vf_s      *vf_drv;	/*  driver vf structure */
-	struct bfa_timer_s link_timer;	/*  Link Failure timer. Vport */
-	wwn_t           fabric_name;	/*  attached fabric name */
-	bfa_boolean_t   auth_reqd;	/*  authentication required	*/
-	struct bfa_timer_s delay_timer;	/*  delay timer		*/
-	union {
-		u16        swp_vfid;/*  switch port VF id		*/
-	} event_arg;
-	struct bfa_fcs_auth_s  auth;	/*  authentication config	*/
-	struct bfa_wc_s        wc;	/*  wait counter for delete	*/
-	struct bfa_vf_stats_s  stats; 	/*  fabric/vf stats		*/
-	struct bfa_lps_s	*lps;	/*  lport login services	*/
-	u8	fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ];  /*  attached
-							    * fabric's ip addr
-							    */
-};
-
-#define bfa_fcs_fabric_npiv_capable(__f)    ((__f)->is_npiv)
-#define bfa_fcs_fabric_is_switched(__f)			\
-	((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED)
-
-/**
- *   The design calls for a single implementation of base fabric and vf.
- */
-#define bfa_fcs_vf_t struct bfa_fcs_fabric_s
-
-struct bfa_vf_event_s {
-	u32        undefined;
-};
-
-/**
- * bfa fcs vf public functions
- */
-bfa_status_t bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id);
-bfa_status_t bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs);
-bfa_status_t bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs,
-			       u16 vf_id, struct bfa_port_cfg_s *port_cfg,
-			       struct bfad_vf_s *vf_drv);
-bfa_status_t bfa_fcs_vf_delete(bfa_fcs_vf_t *vf);
-void bfa_fcs_vf_start(bfa_fcs_vf_t *vf);
-bfa_status_t bfa_fcs_vf_stop(bfa_fcs_vf_t *vf);
-void bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
-void bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs);
-void bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr);
-void bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf,
-			  struct bfa_vf_stats_s *vf_stats);
-void bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf);
-void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
-bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id);
-struct bfad_vf_s *bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf);
-
-#endif /* __BFA_FCS_FABRIC_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h
deleted file mode 100644
index 9a35ecf..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcs_fcpim.h BFA FCS FCP Initiator Mode interfaces/defines.
- */
-
-#ifndef __BFA_FCS_FCPIM_H__
-#define __BFA_FCS_FCPIM_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_itnim.h>
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_rport.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <bfa_fcpim.h>
-
-/*
- * forward declarations
- */
-struct bfad_itnim_s;
-
-struct bfa_fcs_itnim_s {
-	bfa_sm_t		sm;		/*  state machine */
-	struct bfa_fcs_rport_s 	*rport;		/*  parent remote rport  */
-	struct bfad_itnim_s   	*itnim_drv;	/*  driver peer instance */
-	struct bfa_fcs_s      	*fcs;		/*  fcs instance         */
-	struct bfa_timer_s 	timer;		/*  timer functions      */
-	struct bfa_itnim_s 	*bfa_itnim;	/*  BFA itnim struct     */
-	u32                	prli_retries;   /*  max prli retry attempts */
-	bfa_boolean_t	 	seq_rec;	/*  seq recovery support */
-	bfa_boolean_t	 	rec_support;	/*  REC supported        */
-	bfa_boolean_t	 	conf_comp;	/*  FCP_CONF     support */
-	bfa_boolean_t	 	task_retry_id;	/*  task retry id supp   */
-	struct bfa_fcxp_wqe_s 	fcxp_wqe;	/*  wait qelem for fcxp  */
-	struct bfa_fcxp_s *fcxp;		/*  FCXP in use          */
-	struct bfa_itnim_stats_s 	stats;	/*  itn statistics       */
-};
-
-
-static inline struct bfad_port_s *
-bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->port->bfad_port;
-}
-
-
-static inline struct bfa_fcs_port_s *
-bfa_fcs_itnim_get_port(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->port;
-}
-
-
-static inline wwn_t
-bfa_fcs_itnim_get_nwwn(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->nwwn;
-}
-
-
-static inline wwn_t
-bfa_fcs_itnim_get_pwwn(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->pwwn;
-}
-
-
-static inline u32
-bfa_fcs_itnim_get_fcid(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->pid;
-}
-
-
-static inline   u32
-bfa_fcs_itnim_get_maxfrsize(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->maxfrsize;
-}
-
-
-static inline   enum fc_cos
-bfa_fcs_itnim_get_cos(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->rport->fc_cos;
-}
-
-
-static inline struct bfad_itnim_s *
-bfa_fcs_itnim_get_drvitn(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->itnim_drv;
-}
-
-
-static inline struct bfa_itnim_s *
-bfa_fcs_itnim_get_halitn(struct bfa_fcs_itnim_s *itnim)
-{
-	return itnim->bfa_itnim;
-}
-
-/**
- * bfa fcs FCP Initiator mode API functions
- */
-void bfa_fcs_itnim_get_attr(struct bfa_fcs_itnim_s *itnim,
-			struct bfa_itnim_attr_s *attr);
-void bfa_fcs_itnim_get_stats(struct bfa_fcs_itnim_s *itnim,
-			struct bfa_itnim_stats_s *stats);
-struct bfa_fcs_itnim_s *bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port,
-			wwn_t rpwwn);
-bfa_status_t bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
-			struct bfa_itnim_attr_s *attr);
-bfa_status_t bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn,
-			struct bfa_itnim_stats_s *stats);
-bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port,
-			wwn_t rpwwn);
-#endif /* __BFA_FCS_FCPIM_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h
deleted file mode 100644
index 4441fff..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcs_fdmi.h BFA fcs fdmi module public interface
- */
-
-#ifndef __BFA_FCS_FDMI_H__
-#define __BFA_FCS_FDMI_H__
-#include <bfa_os_inc.h>
-#include <protocol/fdmi.h>
-
-#define	BFA_FCS_FDMI_SUPORTED_SPEEDS  (FDMI_TRANS_SPEED_1G  | \
-					FDMI_TRANS_SPEED_2G | \
-					FDMI_TRANS_SPEED_4G | \
-					FDMI_TRANS_SPEED_8G)
-
-/*
-* HBA Attribute Block : BFA internal representation. Note : Some variable
-* sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based
- * on this the size has been reduced to 16 bytes from the standard's 64 bytes.
- */
-struct bfa_fcs_fdmi_hba_attr_s {
-	wwn_t           node_name;
-	u8         manufacturer[64];
-	u8         serial_num[64];
-	u8         model[16];
-	u8         model_desc[256];
-	u8         hw_version[8];
-	u8         driver_version[8];
-	u8         option_rom_ver[BFA_VERSION_LEN];
-	u8         fw_version[8];
-	u8         os_name[256];
-	u32        max_ct_pyld;
-};
-
-/*
- * Port Attribute Block
- */
-struct bfa_fcs_fdmi_port_attr_s {
-	u8         supp_fc4_types[32];	/* supported FC4 types */
-	u32        supp_speed;	/* supported speed */
-	u32        curr_speed;	/* current Speed */
-	u32        max_frm_size;	/* max frame size */
-	u8         os_device_name[256];	/* OS device Name */
-	u8         host_name[256];	/* host name */
-};
-
-#endif /* __BFA_FCS_FDMI_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h
deleted file mode 100644
index ceaefd3..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcs_port.h BFA fcs port module public interface
- */
-
-#ifndef __BFA_FCS_PORT_H__
-#define __BFA_FCS_PORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_pport.h>
-#include <defs/bfa_defs_rport.h>
-#include <cs/bfa_q.h>
-#include <bfa_svc.h>
-#include <cs/bfa_wc.h>
-
-struct bfa_fcs_s;
-struct bfa_fcs_fabric_s;
-
-/*
- * Maximum Rports supported per port (physical/logical).
- */
-#define BFA_FCS_MAX_RPORTS_SUPP  256	/* @todo : tentative value */
-
-
-struct bfa_fcs_port_ns_s {
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;
-	struct bfa_fcs_port_s *port;	/*  parent port */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-};
-
-
-struct bfa_fcs_port_scn_s {
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;
-	struct bfa_fcs_port_s *port;	/*  parent port */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-};
-
-
-struct bfa_fcs_port_fdmi_s {
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;
-	struct bfa_fcs_port_ms_s *ms;	/*  parent ms */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-	u8         retry_cnt;	/*  retry count */
-	u8	 	   rsvd[3];
-};
-
-
-struct bfa_fcs_port_ms_s {
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;
-	struct bfa_fcs_port_s *port;	/*  parent port */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-	struct bfa_fcs_port_fdmi_s fdmi;	/*  FDMI component of MS */
-	u8         retry_cnt;	/*  retry count */
-	u8	 	   rsvd[3];
-};
-
-
-struct bfa_fcs_port_fab_s {
-	struct bfa_fcs_port_ns_s ns;	/*  NS component of port */
-	struct bfa_fcs_port_scn_s scn;	/*  scn component of port */
-	struct bfa_fcs_port_ms_s ms;	/*  MS component of port */
-};
-
-
-
-#define 	MAX_ALPA_COUNT 		127
-
-struct bfa_fcs_port_loop_s {
-	u8         num_alpa;	/*  Num of ALPA entries in the map */
-	u8         alpa_pos_map[MAX_ALPA_COUNT];	/*  ALPA Positional
-							 *Map */
-	struct bfa_fcs_port_s *port;	/*  parent port */
-};
-
-
-
-struct bfa_fcs_port_n2n_s {
-	u32        rsvd;
-	u16        reply_oxid;	/*  ox_id from the req flogi to be
-					 *used in flogi acc */
-	wwn_t           rem_port_wwn;	/*  Attached port's wwn */
-};
-
-
-union bfa_fcs_port_topo_u {
-	struct bfa_fcs_port_fab_s pfab;
-	struct bfa_fcs_port_loop_s ploop;
-	struct bfa_fcs_port_n2n_s pn2n;
-};
-
-
-struct bfa_fcs_port_s {
-	struct list_head         qe;	/*  used by port/vport */
-	bfa_sm_t               sm;	/*  state machine */
-	struct bfa_fcs_fabric_s *fabric;/*  parent fabric */
-	struct bfa_port_cfg_s  port_cfg;/*  port configuration */
-	struct bfa_timer_s link_timer;	/*  timer for link offline */
-	u32 pid:24;	/*  FC address */
-	u8  lp_tag;	/*  lport tag */
-	u16 num_rports;	/*  Num of r-ports */
-	struct list_head rport_q;	/*  queue of discovered r-ports */
-	struct bfa_fcs_s *fcs;	/*  FCS instance */
-	union bfa_fcs_port_topo_u port_topo;	/*  fabric/loop/n2n details */
-	struct bfad_port_s *bfad_port;	/*  driver peer instance */
-	struct bfa_fcs_vport_s *vport;	/*  NULL for base ports */
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_fcxp_wqe_s fcxp_wqe;
-	struct bfa_port_stats_s stats;
-	struct bfa_wc_s        wc;	/*  waiting counter for events */
-};
-
-#define bfa_fcs_lport_t struct bfa_fcs_port_s
-
-/**
- * Symbolic Name related defines
- *  Total bytes 255.
- *  Physical Port's symbolic name 128 bytes.
- *  For Vports, Vport's symbolic name is appended to the Physical port's
- *  Symbolic Name.
- *
- *  Physical Port's symbolic name Format : (Total 128 bytes)
- *  Adapter Model number/name : 12 bytes
- *  Driver Version     : 10 bytes
- *  Host Machine Name  : 30 bytes
- * 	Host OS Info	   : 48 bytes
- * 	Host OS PATCH Info : 16 bytes
- *  ( remaining 12 bytes reserved to be used for separator)
- */
-#define BFA_FCS_PORT_SYMBNAME_SEPARATOR 		" | "
-
-#define BFA_FCS_PORT_SYMBNAME_MODEL_SZ			12
-#define BFA_FCS_PORT_SYMBNAME_VERSION_SZ 		10
-#define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ 	30
-#define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ			48
-#define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ		16
-
-/**
- * Get FC port ID for a logical port.
- */
-#define bfa_fcs_port_get_fcid(_lport)	((_lport)->pid)
-#define bfa_fcs_port_get_pwwn(_lport)	((_lport)->port_cfg.pwwn)
-#define bfa_fcs_port_get_nwwn(_lport)	((_lport)->port_cfg.nwwn)
-#define bfa_fcs_port_get_psym_name(_lport)	((_lport)->port_cfg.sym_name)
-#define bfa_fcs_port_is_initiator(_lport)	\
-			((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_IM)
-#define bfa_fcs_port_is_target(_lport)	\
-			((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_TM)
-#define bfa_fcs_port_get_nrports(_lport)	\
-			((_lport) ? (_lport)->num_rports : 0)
-
-static inline struct bfad_port_s *
-bfa_fcs_port_get_drvport(struct bfa_fcs_port_s *port)
-{
-	return port->bfad_port;
-}
-
-
-#define bfa_fcs_port_get_opertype(_lport)	((_lport)->fabric->oper_type)
-
-
-#define bfa_fcs_port_get_fabric_name(_lport)	((_lport)->fabric->fabric_name)
-
-
-#define bfa_fcs_port_get_fabric_ipaddr(_lport) \
-		((_lport)->fabric->fabric_ip_addr)
-
-/**
- * bfa fcs port public functions
- */
-void bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs,
-			struct bfa_port_cfg_s *port_cfg);
-struct bfa_fcs_port_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs);
-void bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port,
-			wwn_t rport_wwns[], int *nrports);
-
-wwn_t bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn,
-			int index, int nrports, bfa_boolean_t bwwn);
-
-struct bfa_fcs_port_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
-			u16 vf_id, wwn_t lpwwn);
-
-void bfa_fcs_port_get_info(struct bfa_fcs_port_s *port,
-			struct bfa_port_info_s *port_info);
-void bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port,
-			struct bfa_port_attr_s *port_attr);
-void bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port,
-			struct bfa_port_stats_s *port_stats);
-void bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port);
-enum bfa_pport_speed bfa_fcs_port_get_rport_max_speed(
-			struct bfa_fcs_port_s *port);
-void bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port);
-void bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port);
-
-#endif /* __BFA_FCS_PORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h
deleted file mode 100644
index 3027fc6..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __BFA_FCS_RPORT_H__
-#define __BFA_FCS_RPORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <cs/bfa_q.h>
-#include <fcs/bfa_fcs.h>
-#include <defs/bfa_defs_rport.h>
-
-#define BFA_FCS_RPORT_DEF_DEL_TIMEOUT 	90 	/* in secs */
-/*
- * forward declarations
- */
-struct bfad_rport_s;
-
-struct bfa_fcs_itnim_s;
-struct bfa_fcs_tin_s;
-struct bfa_fcs_iprp_s;
-
-/* Rport Features (RPF) */
-struct bfa_fcs_rpf_s {
-	bfa_sm_t               sm;	/*  state machine */
-	struct bfa_fcs_rport_s *rport;	/*  parent rport */
-	struct bfa_timer_s 	timer;	/*  general purpose timer */
-	struct bfa_fcxp_s 	*fcxp;	/*  FCXP needed for discarding */
-	struct bfa_fcxp_wqe_s 	fcxp_wqe;	/*  fcxp wait queue element */
-	int             	rpsc_retries;	/*  max RPSC retry attempts */
-	enum bfa_pport_speed 	rpsc_speed;	/* Current Speed from RPSC.
-						 * O if RPSC fails */
-	enum bfa_pport_speed	assigned_speed;	/* Speed assigned by the user.
-						 * will be used if RPSC is not
-						 * supported by the rport */
-};
-
-struct bfa_fcs_rport_s {
-	struct list_head         qe;	/*  used by port/vport */
-	struct bfa_fcs_port_s *port;	/*  parent FCS port */
-	struct bfa_fcs_s      *fcs;	/*  fcs instance */
-	struct bfad_rport_s   *rp_drv;	/*  driver peer instance */
-	u32        pid;	/*  port ID of rport */
-	u16        maxfrsize;	/*  maximum frame size */
-	u16        reply_oxid;	/*  OX_ID of inbound requests */
-	enum fc_cos        fc_cos;	/*  FC classes of service supp */
-	bfa_boolean_t   cisc;	/*  CISC capable device */
-	bfa_boolean_t   prlo;   /*  processing prlo or LOGO */
-	wwn_t           pwwn;	/*  port wwn of rport */
-	wwn_t           nwwn;	/*  node wwn of rport */
-	struct bfa_rport_symname_s psym_name; /*  port symbolic name  */
-	bfa_sm_t        sm;		/*  state machine */
-	struct bfa_timer_s timer;	/*  general purpose timer */
-	struct bfa_fcs_itnim_s *itnim;	/*  ITN initiator mode role */
-	struct bfa_fcs_tin_s *tin;	/*  ITN initiator mode role */
-	struct bfa_fcs_iprp_s *iprp;	/*  IP/FC role */
-	struct bfa_rport_s *bfa_rport;	/*  BFA Rport */
-	struct bfa_fcxp_s *fcxp;	/*  FCXP needed for discarding */
-	int             plogi_retries;	/*  max plogi retry attempts */
-	int             ns_retries;	/*  max NS query retry attempts */
-	struct bfa_fcxp_wqe_s 	fcxp_wqe; /*  fcxp wait queue element */
-	struct bfa_rport_stats_s stats;	/*  rport stats */
-	enum bfa_rport_function	scsi_function;  /*  Initiator/Target */
-	struct bfa_fcs_rpf_s rpf; 	/* Rport features module */
-};
-
-static inline struct bfa_rport_s *
-bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport)
-{
-	return rport->bfa_rport;
-}
-
-/**
- * bfa fcs rport API functions
- */
-bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn,
-			struct bfa_fcs_rport_s *rport,
-			struct bfad_rport_s *rport_drv);
-bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport);
-void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_attr_s *attr);
-void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_stats_s *stats);
-void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport);
-struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port,
-			wwn_t rpwwn);
-struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn(
-			struct bfa_fcs_port_s *port, wwn_t rnwwn);
-void bfa_fcs_rport_set_del_timeout(u8 rport_tmo);
-void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
-			enum bfa_pport_speed speed);
-#endif /* __BFA_FCS_RPORT_H__ */
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h
deleted file mode 100644
index 0af2624..0000000
--- a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcs_vport.h BFA fcs vport module public interface
- */
-
-#ifndef __BFA_FCS_VPORT_H__
-#define __BFA_FCS_VPORT_H__
-
-#include <defs/bfa_defs_status.h>
-#include <defs/bfa_defs_port.h>
-#include <defs/bfa_defs_vport.h>
-#include <fcs/bfa_fcs.h>
-#include <fcb/bfa_fcb_vport.h>
-
-struct bfa_fcs_vport_s {
-	struct list_head		qe;		/*  queue elem	 */
-	bfa_sm_t		sm;		/*  state machine	*/
-	bfa_fcs_lport_t		lport;		/*  logical port	*/
-	struct bfa_timer_s	timer;		/*  general purpose timer */
-	struct bfad_vport_s	*vport_drv;	/*  Driver private	*/
-	struct bfa_vport_stats_s vport_stats;	/*  vport statistics	*/
-	struct bfa_lps_s	*lps;		/*  Lport login service */
-	int			fdisc_retries;
-};
-
-#define bfa_fcs_vport_get_port(vport) \
-			((struct bfa_fcs_port_s  *)(&vport->port))
-
-/**
- * bfa fcs vport public functions
- */
-bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport,
-			struct bfa_fcs_s *fcs, u16 vf_id,
-			struct bfa_port_cfg_s *port_cfg,
-			struct bfad_vport_s *vport_drv);
-bfa_status_t bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport,
-			struct bfa_fcs_s *fcs, uint16_t vf_id,
-			struct bfa_port_cfg_s *port_cfg,
-			struct bfad_vport_s *vport_drv);
-bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport);
-bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport);
-bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport);
-void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
-			struct bfa_vport_attr_s *vport_attr);
-void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
-			struct bfa_vport_stats_s *vport_stats);
-void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport);
-struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs,
-			u16 vf_id, wwn_t vpwwn);
-
-#endif /* __BFA_FCS_VPORT_H__ */
diff --git a/drivers/scsi/bfa/include/log/bfa_log_fcs.h b/drivers/scsi/bfa/include/log/bfa_log_fcs.h
deleted file mode 100644
index b6f5df8..0000000
--- a/drivers/scsi/bfa/include/log/bfa_log_fcs.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/*
- * messages define for FCS Module
- */
-#ifndef	__BFA_LOG_FCS_H__
-#define	__BFA_LOG_FCS_H__
-#include  <cs/bfa_log.h>
-#define BFA_LOG_FCS_FABRIC_NOSWITCH 	\
-	(((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_FCS_FABRIC_ISOLATED 	\
-	(((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 2)
-#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_hal.h b/drivers/scsi/bfa/include/log/bfa_log_hal.h
deleted file mode 100644
index 5f8f5e3..0000000
--- a/drivers/scsi/bfa/include/log/bfa_log_hal.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for HAL Module */
-#ifndef	__BFA_LOG_HAL_H__
-#define	__BFA_LOG_HAL_H__
-#include  <cs/bfa_log.h>
-#define BFA_LOG_HAL_ASSERT \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_HAL_HEARTBEAT_FAILURE \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 2)
-#define BFA_LOG_HAL_FCPIM_PARM_INVALID \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 3)
-#define BFA_LOG_HAL_SM_ASSERT \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 4)
-#define BFA_LOG_HAL_DRIVER_ERROR \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 5)
-#define BFA_LOG_HAL_DRIVER_CONFIG_ERROR \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 6)
-#define BFA_LOG_HAL_MBOX_ERROR \
-	(((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 7)
-#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_linux.h b/drivers/scsi/bfa/include/log/bfa_log_linux.h
deleted file mode 100644
index 44bc897..0000000
--- a/drivers/scsi/bfa/include/log/bfa_log_linux.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/* messages define for LINUX Module */
-#ifndef	__BFA_LOG_LINUX_H__
-#define	__BFA_LOG_LINUX_H__
-#include  <cs/bfa_log.h>
-#define BFA_LOG_LINUX_DEVICE_CLAIMED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_LINUX_HASH_INIT_FAILED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 2)
-#define BFA_LOG_LINUX_SYSFS_FAILED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 3)
-#define BFA_LOG_LINUX_MEM_ALLOC_FAILED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 4)
-#define BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 5)
-#define BFA_LOG_LINUX_ITNIM_FREE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 6)
-#define BFA_LOG_LINUX_ITNIM_ONLINE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 7)
-#define BFA_LOG_LINUX_ITNIM_OFFLINE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 8)
-#define BFA_LOG_LINUX_SCSI_HOST_FREE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 9)
-#define BFA_LOG_LINUX_SCSI_ABORT \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 10)
-#define BFA_LOG_LINUX_SCSI_ABORT_COMP \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 11)
-#define BFA_LOG_LINUX_DRIVER_CONFIG_ERROR \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 12)
-#define BFA_LOG_LINUX_BNA_STATE_MACHINE \
-		(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 13)
-#define BFA_LOG_LINUX_IOC_ERROR \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 14)
-#define BFA_LOG_LINUX_RESOURCE_ALLOC_ERROR \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 15)
-#define BFA_LOG_LINUX_RING_BUFFER_ERROR \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 16)
-#define BFA_LOG_LINUX_DRIVER_ERROR \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 17)
-#define BFA_LOG_LINUX_DRIVER_INFO \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 18)
-#define BFA_LOG_LINUX_DRIVER_DIAG \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 19)
-#define BFA_LOG_LINUX_DRIVER_AEN \
-	(((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 20)
-#endif
diff --git a/drivers/scsi/bfa/include/log/bfa_log_wdrv.h b/drivers/scsi/bfa/include/log/bfa_log_wdrv.h
deleted file mode 100644
index 809a95f..0000000
--- a/drivers/scsi/bfa/include/log/bfa_log_wdrv.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/*
- * messages define for WDRV Module
- */
-#ifndef	__BFA_LOG_WDRV_H__
-#define	__BFA_LOG_WDRV_H__
-#include  <cs/bfa_log.h>
-#define BFA_LOG_WDRV_IOC_INIT_ERROR 	\
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 1)
-#define BFA_LOG_WDRV_IOC_INTERNAL_ERROR \
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 2)
-#define BFA_LOG_WDRV_IOC_START_ERROR 	\
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 3)
-#define BFA_LOG_WDRV_IOC_STOP_ERROR 	\
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 4)
-#define BFA_LOG_WDRV_INSUFFICIENT_RESOURCES \
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 5)
-#define BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR \
-	(((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 6)
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/ct.h b/drivers/scsi/bfa/include/protocol/ct.h
deleted file mode 100644
index b82540a..0000000
--- a/drivers/scsi/bfa/include/protocol/ct.h
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __CT_H__
-#define __CT_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-struct ct_hdr_s{
-	u32	rev_id:8;	/* Revision of the CT */
-	u32	in_id:24;	/* Initiator Id */
-	u32	gs_type:8;	/* Generic service Type */
-	u32	gs_sub_type:8;	/* Generic service sub type */
-	u32	options:8;	/* options */
-	u32	rsvrd:8;	/* reserved */
-	u32	cmd_rsp_code:16;/* ct command/response code */
-	u32	max_res_size:16;/* maximum/residual size */
-	u32	frag_id:8;	/* fragment ID */
-	u32	reason_code:8;	/* reason code */
-	u32	exp_code:8;	/* explanation code */
-	u32	vendor_unq:8;	/* vendor unique */
-};
-
-/*
- * defines for the Revision
- */
-enum {
-	CT_GS3_REVISION = 0x01,
-};
-
-/*
- * defines for gs_type
- */
-enum {
-	CT_GSTYPE_KEYSERVICE	= 0xF7,
-	CT_GSTYPE_ALIASSERVICE	= 0xF8,
-	CT_GSTYPE_MGMTSERVICE	= 0xFA,
-	CT_GSTYPE_TIMESERVICE	= 0xFB,
-	CT_GSTYPE_DIRSERVICE	= 0xFC,
-};
-
-/*
- * defines for gs_sub_type for gs type directory service
- */
-enum {
-	CT_GSSUBTYPE_NAMESERVER = 0x02,
-};
-
-/*
- * defines for gs_sub_type for gs type management service
- */
-enum {
-	CT_GSSUBTYPE_CFGSERVER	= 0x01,
-	CT_GSSUBTYPE_UNZONED_NS = 0x02,
-	CT_GSSUBTYPE_ZONESERVER = 0x03,
-	CT_GSSUBTYPE_LOCKSERVER = 0x04,
-	CT_GSSUBTYPE_HBA_MGMTSERVER = 0x10,	/* for FDMI */
-};
-
-/*
- * defines for CT response code field
- */
-enum {
-	CT_RSP_REJECT = 0x8001,
-	CT_RSP_ACCEPT = 0x8002,
-};
-
-/*
- * definitions for CT reason code
- */
-enum {
-	CT_RSN_INV_CMD		= 0x01,
-	CT_RSN_INV_VER		= 0x02,
-	CT_RSN_LOGIC_ERR	= 0x03,
-	CT_RSN_INV_SIZE		= 0x04,
-	CT_RSN_LOGICAL_BUSY	= 0x05,
-	CT_RSN_PROTO_ERR	= 0x07,
-	CT_RSN_UNABLE_TO_PERF	= 0x09,
-	CT_RSN_NOT_SUPP			= 0x0B,
-	CT_RSN_SERVER_NOT_AVBL  = 0x0D,
-	CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E,
-	CT_RSN_VENDOR_SPECIFIC  = 0xFF,
-
-};
-
-/*
- * definitions for explanations code for Name server
- */
-enum {
-	CT_NS_EXP_NOADDITIONAL	= 0x00,
-	CT_NS_EXP_ID_NOT_REG	= 0x01,
-	CT_NS_EXP_PN_NOT_REG	= 0x02,
-	CT_NS_EXP_NN_NOT_REG	= 0x03,
-	CT_NS_EXP_CS_NOT_REG	= 0x04,
-	CT_NS_EXP_IPN_NOT_REG	= 0x05,
-	CT_NS_EXP_IPA_NOT_REG	= 0x06,
-	CT_NS_EXP_FT_NOT_REG	= 0x07,
-	CT_NS_EXP_SPN_NOT_REG	= 0x08,
-	CT_NS_EXP_SNN_NOT_REG	= 0x09,
-	CT_NS_EXP_PT_NOT_REG	= 0x0A,
-	CT_NS_EXP_IPP_NOT_REG	= 0x0B,
-	CT_NS_EXP_FPN_NOT_REG	= 0x0C,
-	CT_NS_EXP_HA_NOT_REG	= 0x0D,
-	CT_NS_EXP_FD_NOT_REG	= 0x0E,
-	CT_NS_EXP_FF_NOT_REG	= 0x0F,
-	CT_NS_EXP_ACCESSDENIED	= 0x10,
-	CT_NS_EXP_UNACCEPTABLE_ID = 0x11,
-	CT_NS_EXP_DATABASEEMPTY			= 0x12,
-	CT_NS_EXP_NOT_REG_IN_SCOPE 		= 0x13,
-	CT_NS_EXP_DOM_ID_NOT_PRESENT 	= 0x14,
-	CT_NS_EXP_PORT_NUM_NOT_PRESENT  = 0x15,
-	CT_NS_EXP_NO_DEVICE_ATTACHED 	= 0x16
-};
-
-/*
- * definitions for the explanation code for all servers
- */
-enum {
-	CT_EXP_AUTH_EXCEPTION			= 0xF1,
-	CT_EXP_DB_FULL					= 0xF2,
-	CT_EXP_DB_EMPTY					= 0xF3,
-	CT_EXP_PROCESSING_REQ			= 0xF4,
-	CT_EXP_UNABLE_TO_VERIFY_CONN	= 0xF5,
-	CT_EXP_DEVICES_NOT_IN_CMN_ZONE  = 0xF6
-};
-
-/*
- * Command codes for Name server
- */
-enum {
-	GS_GID_PN	= 0x0121,	/* Get Id on port name */
-	GS_GPN_ID	= 0x0112,	/* Get port name on ID */
-	GS_GNN_ID	= 0x0113,	/* Get node name on ID */
-	GS_GID_FT	= 0x0171,	/* Get Id on FC4 type */
-	GS_GSPN_ID	= 0x0118,	/* Get symbolic PN on ID */
-	GS_RFT_ID	= 0x0217,	/* Register fc4type on ID */
-	GS_RSPN_ID	= 0x0218,	/* Register symbolic PN on ID */
-	GS_RPN_ID	= 0x0212,	/* Register port name */
-	GS_RNN_ID	= 0x0213,	/* Register node name */
-	GS_RCS_ID	= 0x0214,	/* Register class of service */
-	GS_RPT_ID	= 0x021A,	/* Register port type */
-	GS_GA_NXT	= 0x0100,	/* Get all next */
-	GS_RFF_ID	= 0x021F,	/* Register FC4 Feature		*/
-};
-
-struct fcgs_id_req_s{
-	u32	rsvd:8;
-	u32	dap:24;	/* port identifier */
-};
-#define fcgs_gpnid_req_t struct fcgs_id_req_s
-#define fcgs_gnnid_req_t struct fcgs_id_req_s
-#define fcgs_gspnid_req_t struct fcgs_id_req_s
-
-struct fcgs_gidpn_req_s{
-	wwn_t	port_name;	/* port wwn */
-};
-
-struct fcgs_gidpn_resp_s{
-	u32	rsvd:8;
-	u32	dap:24;	/* port identifier */
-};
-
-/**
- * RFT_ID
- */
-struct fcgs_rftid_req_s {
-	u32	rsvd:8;
-	u32	dap:24;		/* port identifier */
-	u32	fc4_type[8];	/* fc4 types */
-};
-
-/**
- * RFF_ID : Register FC4 features.
- */
-
-#define FC_GS_FCP_FC4_FEATURE_INITIATOR  0x02
-#define FC_GS_FCP_FC4_FEATURE_TARGET	 0x01
-
-struct fcgs_rffid_req_s{
-    u32    rsvd:8;
-    u32    dap:24;		/* port identifier	*/
-    u32    rsvd1:16;
-    u32    fc4ftr_bits:8;	/* fc4 feature bits	*/
-    u32    fc4_type:8;	/* corresponding FC4 Type */
-};
-
-/**
- * GID_FT Request
- */
-struct fcgs_gidft_req_s{
-	u8	reserved;
-	u8	domain_id;	/* domain, 0 - all fabric */
-	u8	area_id;	/* area, 0 - whole domain */
-	u8	fc4_type;	/* FC_TYPE_FCP for SCSI devices */
-};				/* GID_FT Request */
-
-/**
- * GID_FT Response
- */
-struct fcgs_gidft_resp_s {
-	u8		last:1;	/* last port identifier flag */
-	u8		reserved:7;
-	u32	pid:24;	/* port identifier */
-};				/* GID_FT Response */
-
-/**
- * RSPN_ID
- */
-struct fcgs_rspnid_req_s{
-	u32	rsvd:8;
-	u32	dap:24;		/* port identifier */
-	u8		spn_len;	/* symbolic port name length */
-	u8		spn[256];	/* symbolic port name */
-};
-
-/**
- * RPN_ID
- */
-struct fcgs_rpnid_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-	wwn_t		port_name;
-};
-
-/**
- * RNN_ID
- */
-struct fcgs_rnnid_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-	wwn_t		node_name;
-};
-
-/**
- * RCS_ID
- */
-struct fcgs_rcsid_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-	u32	cos;
-};
-
-/**
- * RPT_ID
- */
-struct fcgs_rptid_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-	u32	port_type:8;
-	u32	rsvd1:24;
-};
-
-/**
- * GA_NXT Request
- */
-struct fcgs_ganxt_req_s{
-	u32	rsvd:8;
-	u32	port_id:24;
-};
-
-/**
- * GA_NXT Response
- */
-struct fcgs_ganxt_rsp_s{
-	u32	port_type:8;	/* Port Type */
-	u32	port_id:24;	/* Port Identifier */
-	wwn_t		port_name;	/* Port Name */
-	u8		spn_len;	/* Length of Symbolic Port Name */
-	char		spn[255];	/* Symbolic Port Name */
-	wwn_t		node_name;	/* Node Name */
-	u8		snn_len;	/* Length of Symbolic Node Name */
-	char		snn[255];	/* Symbolic Node Name */
-	u8		ipa[8];		/* Initial Process Associator */
-	u8		ip[16];		/* IP Address */
-	u32	cos;		/* Class of Service */
-	u32	fc4types[8];	/* FC-4 TYPEs */
-	wwn_t		fabric_port_name;
-					/* Fabric Port Name */
-	u32	rsvd:8;		/* Reserved */
-	u32	hard_addr:24;	/* Hard Address */
-};
-
-/*
- * Fabric Config Server
- */
-
-/*
- * Command codes for Fabric Configuration Server
- */
-enum {
-	GS_FC_GFN_CMD	= 0x0114,	/* GS FC Get Fabric Name  */
-	GS_FC_GMAL_CMD	= 0x0116,	/* GS FC GMAL  */
-	GS_FC_TRACE_CMD	= 0x0400,	/* GS FC Trace Route */
-	GS_FC_PING_CMD	= 0x0401,	/* GS FC Ping */
-};
-
-/*
- * Source or Destination Port Tags.
- */
-enum {
-	GS_FTRACE_TAG_NPORT_ID		= 1,
-	GS_FTRACE_TAG_NPORT_NAME	= 2,
-};
-
-/*
-* Port Value : Could be a Port id or wwn
- */
-union fcgs_port_val_u{
-	u32	nport_id;
-	wwn_t		nport_wwn;
-};
-
-#define GS_FTRACE_MAX_HOP_COUNT	20
-#define GS_FTRACE_REVISION	1
-
-/*
- * Ftrace Related Structures.
- */
-
-/*
- * STR (Switch Trace) Reject Reason Codes. From FC-SW.
- */
-enum {
-	GS_FTRACE_STR_CMD_COMPLETED_SUCC	= 0,
-	GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH,
-	GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH,
-	GS_FTRACE_STR_MAX_HOP_CNT_REACHED,
-	GS_FTRACE_STR_SRC_PORT_NOT_FOUND,
-	GS_FTRACE_STR_DST_PORT_NOT_FOUND,
-	GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE,
-	GS_FTRACE_STR_NO_ROUTE_BW_PORTS,
-	GS_FTRACE_STR_NO_ADDL_EXPLN,
-	GS_FTRACE_STR_FABRIC_BUSY,
-	GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS,
-	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0,
-	GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff,
-};
-
-/*
- * Ftrace Request
- */
-struct fcgs_ftrace_req_s{
-	u32	revision;
-	u16	src_port_tag;	/* Source Port tag */
-	u16	src_port_len;	/* Source Port len */
-	union fcgs_port_val_u src_port_val;	/* Source Port value */
-	u16	dst_port_tag;	/* Destination Port tag */
-	u16	dst_port_len;	/* Destination Port len */
-	union fcgs_port_val_u dst_port_val;	/* Destination Port value */
-	u32	token;
-	u8		vendor_id[8];	/* T10 Vendor Identifier */
-	u8		vendor_info[8];	/* Vendor specific Info */
-	u32	max_hop_cnt;	/* Max Hop Count */
-};
-
-/*
- * Path info structure
- */
-struct fcgs_ftrace_path_info_s{
-	wwn_t		switch_name;		/* Switch WWN */
-	u32	domain_id;
-	wwn_t		ingress_port_name;	/* Ingress ports wwn */
-	u32	ingress_phys_port_num;	/* Ingress ports physical port
-						 * number
-						 */
-	wwn_t		egress_port_name;	/* Ingress ports wwn */
-	u32	egress_phys_port_num;	/* Ingress ports physical port
-						 * number
-						 */
-};
-
-/*
- * Ftrace Acc Response
- */
-struct fcgs_ftrace_resp_s{
-	u32	revision;
-	u32	token;
-	u8		vendor_id[8];		/* T10 Vendor Identifier */
-	u8		vendor_info[8];		/* Vendor specific Info */
-	u32	str_rej_reason_code;	/* STR Reject Reason Code */
-	u32	num_path_info_entries;	/* No. of path info entries */
-	/*
-	 * path info entry/entries.
-	 */
-	struct fcgs_ftrace_path_info_s path_info[1];
-
-};
-
-/*
-* Fabric Config Server : FCPing
- */
-
-/*
- * FC Ping Request
- */
-struct fcgs_fcping_req_s{
-	u32	revision;
-	u16	port_tag;
-	u16	port_len;	/* Port len */
-	union fcgs_port_val_u port_val;	/* Port value */
-	u32	token;
-};
-
-/*
- * FC Ping Response
- */
-struct fcgs_fcping_resp_s{
-	u32	token;
-};
-
-/*
- * Command codes for zone server query.
- */
-enum {
-	ZS_GZME = 0x0124,	/* Get zone member extended */
-};
-
-/*
- * ZS GZME request
- */
-#define ZS_GZME_ZNAMELEN	32
-struct zs_gzme_req_s{
-	u8	znamelen;
-	u8	rsvd[3];
-	u8	zname[ZS_GZME_ZNAMELEN];
-};
-
-enum zs_mbr_type{
-	ZS_MBR_TYPE_PWWN	= 1,
-	ZS_MBR_TYPE_DOMPORT	= 2,
-	ZS_MBR_TYPE_PORTID	= 3,
-	ZS_MBR_TYPE_NWWN	= 4,
-};
-
-struct zs_mbr_wwn_s{
-	u8	mbr_type;
-	u8	rsvd[3];
-	wwn_t	wwn;
-};
-
-struct zs_query_resp_s{
-	u32	nmbrs;	/*  number of zone members */
-	struct zs_mbr_wwn_s	mbr[1];
-};
-
-/*
- * GMAL Command ( Get ( interconnect Element) Management Address List)
- * To retrieve the IP Address of a Switch.
- */
-
-#define CT_GMAL_RESP_PREFIX_TELNET	 "telnet://"
-#define CT_GMAL_RESP_PREFIX_HTTP	 "http://"
-
-/*  GMAL/GFN request */
-struct fcgs_req_s {
-	wwn_t    wwn; 	/* PWWN/NWWN */
-};
-
-#define fcgs_gmal_req_t struct fcgs_req_s
-#define fcgs_gfn_req_t struct fcgs_req_s
-
-/* Accept Response to GMAL */
-struct fcgs_gmal_resp_s {
-	u32 		ms_len;   /* Num of entries */
-	u8     	ms_ma[256];
-};
-
-struct fc_gmal_entry_s {
-	u8  len;
-	u8  prefix[7]; /* like "http://" */
-	u8  ip_addr[248];
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/fc.h b/drivers/scsi/bfa/include/protocol/fc.h
deleted file mode 100644
index 436dd7c..0000000
--- a/drivers/scsi/bfa/include/protocol/fc.h
+++ /dev/null
@@ -1,1111 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __FC_H__
-#define __FC_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-/*
- * Fibre Channel Header Structure (FCHS) definition
- */
-struct fchs_s {
-#ifdef __BIGENDIAN
-	u32        routing:4;	/* routing bits */
-	u32        cat_info:4;	/* category info */
-#else
-	u32        cat_info:4;	/* category info */
-	u32        routing:4;	/* routing bits */
-#endif
-	u32        d_id:24;	/* destination identifier */
-
-	u32        cs_ctl:8;	/* class specific control */
-	u32        s_id:24;	/* source identifier */
-
-	u32        type:8;		/* data structure type */
-	u32        f_ctl:24;	/* initial frame control */
-
-	u8         seq_id;		/* sequence identifier */
-	u8         df_ctl;		/* data field control */
-	u16        seq_cnt;	/* sequence count */
-
-	u16        ox_id;		/* originator exchange ID */
-	u16        rx_id;		/* responder exchange ID */
-
-	u32        ro;		/* relative offset */
-};
-
-#define FC_SOF_LEN      4
-#define FC_EOF_LEN      4
-#define FC_CRC_LEN      4
-
-/*
- * Fibre Channel BB_E Header Structure
- */
-struct fcbbehs_s {
-	u16	ver_rsvd;
-	u32	rsvd[2];
-	u32	rsvd__sof;
-};
-
-#define FC_SEQ_ID_MAX		256
-
-/*
- * routing bit definitions
- */
-enum {
-	FC_RTG_FC4_DEV_DATA	= 0x0,	/* FC-4 Device Data */
-	FC_RTG_EXT_LINK		= 0x2,	/* Extended Link Data */
-	FC_RTG_FC4_LINK_DATA	= 0x3,	/* FC-4 Link Data */
-	FC_RTG_VIDEO_DATA	= 0x4,	/* Video Data */
-	FC_RTG_EXT_HDR		= 0x5,	/* VFT, IFR or Encapsuled */
-	FC_RTG_BASIC_LINK	= 0x8,	/* Basic Link data */
-	FC_RTG_LINK_CTRL	= 0xC,	/* Link Control */
-};
-
-/*
- * information category for extended link data and FC-4 Link Data
- */
-enum {
-	FC_CAT_LD_REQUEST	= 0x2,	/* Request */
-	FC_CAT_LD_REPLY		= 0x3,	/* Reply */
-	FC_CAT_LD_DIAG		= 0xF,	/* for DIAG use only */
-};
-
-/*
- * information category for extended headers (VFT, IFR or encapsulation)
- */
-enum {
-	FC_CAT_VFT_HDR = 0x0,	/* Virtual fabric tagging header */
-	FC_CAT_IFR_HDR = 0x1,	/* Inter-Fabric routing header */
-	FC_CAT_ENC_HDR = 0x2,	/* Encapsulation header */
-};
-
-/*
- * information category for FC-4 device data
- */
-enum {
-	FC_CAT_UNCATEG_INFO	= 0x0,	/* Uncategorized information */
-	FC_CAT_SOLICIT_DATA	= 0x1,	/* Solicited Data */
-	FC_CAT_UNSOLICIT_CTRL	= 0x2,	/* Unsolicited Control */
-	FC_CAT_SOLICIT_CTRL	= 0x3,	/* Solicited Control */
-	FC_CAT_UNSOLICIT_DATA	= 0x4,	/* Unsolicited Data */
-	FC_CAT_DATA_DESC	= 0x5,	/* Data Descriptor */
-	FC_CAT_UNSOLICIT_CMD	= 0x6,	/* Unsolicited Command */
-	FC_CAT_CMD_STATUS	= 0x7,	/* Command Status */
-};
-
-/*
- * information category for Link Control
- */
-enum {
-	FC_CAT_ACK_1		= 0x00,
-	FC_CAT_ACK_0_N		= 0x01,
-	FC_CAT_P_RJT		= 0x02,
-	FC_CAT_F_RJT		= 0x03,
-	FC_CAT_P_BSY		= 0x04,
-	FC_CAT_F_BSY_DATA	= 0x05,
-	FC_CAT_F_BSY_LINK_CTL	= 0x06,
-	FC_CAT_F_LCR		= 0x07,
-	FC_CAT_NTY		= 0x08,
-	FC_CAT_END		= 0x09,
-};
-
-/*
- * Type Field Definitions. FC-PH Section 18.5 pg. 165
- */
-enum {
-	FC_TYPE_BLS		= 0x0,	/* Basic Link Service */
-	FC_TYPE_ELS		= 0x1,	/* Extended Link Service */
-	FC_TYPE_IP		= 0x5,	/* IP */
-	FC_TYPE_FCP		= 0x8,	/* SCSI-FCP */
-	FC_TYPE_GPP		= 0x9,	/* SCSI_GPP */
-	FC_TYPE_SERVICES	= 0x20,	/* Fibre Channel Services */
-	FC_TYPE_FC_FSS		= 0x22,	/* Fabric Switch Services */
-	FC_TYPE_FC_AL		= 0x23,	/* FC-AL */
-	FC_TYPE_FC_SNMP		= 0x24,	/* FC-SNMP */
-	FC_TYPE_MAX		= 256,	/* 256 FC-4 types */
-};
-
-struct fc_fc4types_s{
-	u8         bits[FC_TYPE_MAX / 8];
-};
-
-/*
- * Frame Control Definitions. FC-PH Table-45. pg. 168
- */
-enum {
-	FCTL_EC_ORIG = 0x000000,	/* exchange originator */
-	FCTL_EC_RESP = 0x800000,	/* exchange responder */
-	FCTL_SEQ_INI = 0x000000,	/* sequence initiator */
-	FCTL_SEQ_REC = 0x400000,	/* sequence recipient */
-	FCTL_FS_EXCH = 0x200000,	/* first sequence of xchg */
-	FCTL_LS_EXCH = 0x100000,	/* last sequence of xchg */
-	FCTL_END_SEQ = 0x080000,	/* last frame of sequence */
-	FCTL_SI_XFER = 0x010000,	/* seq initiative transfer */
-	FCTL_RO_PRESENT = 0x000008,	/* relative offset present */
-	FCTL_FILLBYTE_MASK = 0x000003	/* , fill byte mask */
-};
-
-/*
- * Fabric Well Known Addresses
- */
-enum {
-	FC_MIN_WELL_KNOWN_ADDR		= 0xFFFFF0,
-	FC_DOMAIN_CONTROLLER_MASK 	= 0xFFFC00,
-	FC_ALIAS_SERVER			= 0xFFFFF8,
-	FC_MGMT_SERVER			= 0xFFFFFA,
-	FC_TIME_SERVER			= 0xFFFFFB,
-	FC_NAME_SERVER			= 0xFFFFFC,
-	FC_FABRIC_CONTROLLER		= 0xFFFFFD,
-	FC_FABRIC_PORT			= 0xFFFFFE,
-	FC_BROADCAST_SERVER		= 0xFFFFFF
-};
-
-/*
- * domain/area/port defines
- */
-#define FC_DOMAIN_MASK  0xFF0000
-#define FC_DOMAIN_SHIFT 16
-#define FC_AREA_MASK    0x00FF00
-#define FC_AREA_SHIFT   8
-#define FC_PORT_MASK    0x0000FF
-#define FC_PORT_SHIFT   0
-
-#define FC_GET_DOMAIN(p)	(((p) & FC_DOMAIN_MASK) >> FC_DOMAIN_SHIFT)
-#define FC_GET_AREA(p)		(((p) & FC_AREA_MASK) >> FC_AREA_SHIFT)
-#define FC_GET_PORT(p)		(((p) & FC_PORT_MASK) >> FC_PORT_SHIFT)
-
-#define FC_DOMAIN_CTRLR(p)	(FC_DOMAIN_CONTROLLER_MASK | (FC_GET_DOMAIN(p)))
-
-enum {
-	FC_RXID_ANY = 0xFFFFU,
-};
-
-/*
- * generic ELS command
- */
-struct fc_els_cmd_s{
-	u32        els_code:8;	/* ELS Command Code */
-	u32        reserved:24;
-};
-
-/*
- * ELS Command Codes. FC-PH Table-75. pg. 223
- */
-enum {
-	FC_ELS_LS_RJT = 0x1,	/* Link Service Reject. */
-	FC_ELS_ACC = 0x02,	/* Accept */
-	FC_ELS_PLOGI = 0x03,	/* N_Port Login. */
-	FC_ELS_FLOGI = 0x04,	/* F_Port Login. */
-	FC_ELS_LOGO = 0x05,	/* Logout. */
-	FC_ELS_ABTX = 0x06,	/* Abort Exchange */
-	FC_ELS_RES = 0x08,	/* Read Exchange status */
-	FC_ELS_RSS = 0x09,	/* Read sequence status block */
-	FC_ELS_RSI = 0x0A,	/* Request Sequence Initiative */
-	FC_ELS_ESTC = 0x0C,	/* Estimate Credit. */
-	FC_ELS_RTV = 0x0E,	/* Read Timeout Value. */
-	FC_ELS_RLS = 0x0F,	/* Read Link Status. */
-	FC_ELS_ECHO = 0x10,	/* Echo */
-	FC_ELS_TEST = 0x11,	/* Test */
-	FC_ELS_RRQ = 0x12,	/* Reinstate Recovery Qualifier. */
-	FC_ELS_REC = 0x13,	/* Add this for TAPE support in FCR */
-	FC_ELS_PRLI = 0x20,	/* Process Login */
-	FC_ELS_PRLO = 0x21,	/* Process Logout. */
-	FC_ELS_SCN = 0x22,	/* State Change Notification. */
-	FC_ELS_TPRLO = 0x24,	/* Third Party Process Logout. */
-	FC_ELS_PDISC = 0x50,	/* Discover N_Port Parameters. */
-	FC_ELS_FDISC = 0x51,	/* Discover F_Port Parameters. */
-	FC_ELS_ADISC = 0x52,	/* Discover Address. */
-	FC_ELS_FAN = 0x60,	/* Fabric Address Notification */
-	FC_ELS_RSCN = 0x61,	/* Reg State Change Notification */
-	FC_ELS_SCR = 0x62,	/* State Change Registration. */
-	FC_ELS_RTIN = 0x77,	/* Mangement server request */
-	FC_ELS_RNID = 0x78,	/* Mangement server request */
-	FC_ELS_RLIR = 0x79,	/* Registered Link Incident Record */
-
-	FC_ELS_RPSC = 0x7D,	/* Report Port Speed Capabilities */
-	FC_ELS_QSA = 0x7E,	/* Query Security Attributes. Ref FC-SP */
-	FC_ELS_E2E_LBEACON = 0x81,
-				/* End-to-End Link Beacon */
-	FC_ELS_AUTH = 0x90,	/* Authentication. Ref FC-SP */
-	FC_ELS_RFCN = 0x97,	/* Request Fabric Change Notification. Ref
-				 *FC-SP */
-
-};
-
-/*
- *  Version numbers for FC-PH standards,
- *  used in login to indicate what port
- *  supports. See FC-PH-X table 158.
- */
-enum {
-	FC_PH_VER_4_3 = 0x09,
-	FC_PH_VER_PH_3 = 0x20,
-};
-
-/*
- * PDU size defines
- */
-enum {
-	FC_MIN_PDUSZ = 512,
-	FC_MAX_PDUSZ = 2112,
-};
-
-/*
- * N_Port PLOGI Common Service Parameters.
- * FC-PH-x. Figure-76. pg. 308.
- */
-struct fc_plogi_csp_s{
-	u8         verhi;	/* FC-PH high version */
-	u8         verlo;	/* FC-PH low version */
-	u16        bbcred;	/* BB_Credit */
-
-#ifdef __BIGENDIAN
-	u8         ciro:1,		/* continuously increasing RO */
-			rro:1,		/* random relative offset */
-			npiv_supp:1,	/* NPIV supported */
-			port_type:1,	/* N_Port/F_port */
-			altbbcred:1,	/* alternate BB_Credit */
-			resolution:1,	/* ms/ns ED_TOV resolution */
-			vvl_info:1,	/* VVL Info included */
-			reserved1:1;
-
-	u8         hg_supp:1,
-			query_dbc:1,
-			security:1,
-			sync_cap:1,
-			r_t_tov:1,
-			dh_dup_supp:1,
-			cisc:1,		/* continuously increasing seq count */
-			payload:1;
-#else
-	u8         reserved2:2,
-			resolution:1,	/* ms/ns ED_TOV resolution */
-			altbbcred:1,	/* alternate BB_Credit */
-			port_type:1,	/* N_Port/F_port */
-			npiv_supp:1,	/* NPIV supported */
-			rro:1,		/* random relative offset */
-			ciro:1;		/* continuously increasing RO */
-
-	u8         payload:1,
-			cisc:1,		/* continuously increasing seq count */
-			dh_dup_supp:1,
-			r_t_tov:1,
-			sync_cap:1,
-			security:1,
-			query_dbc:1,
-			hg_supp:1;
-#endif
-
-	u16        rxsz;		/* recieve data_field size */
-
-	u16        conseq;
-	u16        ro_bitmap;
-
-	u32        e_d_tov;
-};
-
-/*
- * N_Port PLOGI Class Specific Parameters.
- * FC-PH-x. Figure 78. pg. 318.
- */
-struct fc_plogi_clp_s{
-#ifdef __BIGENDIAN
-	u32        class_valid:1;
-	u32        intermix:1;	/* class intermix supported if set =1.
-					 * valid only for class1. Reserved for
-					 * class2 & class3
-					 */
-	u32        reserved1:2;
-	u32        sequential:1;
-	u32        reserved2:3;
-#else
-	u32        reserved2:3;
-	u32        sequential:1;
-	u32        reserved1:2;
-	u32        intermix:1;	/* class intermix supported if set =1.
-					 * valid only for class1. Reserved for
-					 * class2 & class3
-					 */
-	u32        class_valid:1;
-#endif
-
-	u32        reserved3:24;
-
-	u32        reserved4:16;
-	u32        rxsz:16;	/* Receive data_field size */
-
-	u32        reserved5:8;
-	u32        conseq:8;
-	u32        e2e_credit:16;	/* end to end credit */
-
-	u32        reserved7:8;
-	u32        ospx:8;
-	u32        reserved8:16;
-};
-
-#define FLOGI_VVL_BRCD    0x42524344 /* ASCII value for each character in
-				      * string "BRCD" */
-
-/*
- * PLOGI els command and reply payload
- */
-struct fc_logi_s{
-	struct fc_els_cmd_s els_cmd;	/* ELS command code */
-	struct fc_plogi_csp_s  csp;		/* common service params */
-	wwn_t           port_name;
-	wwn_t           node_name;
-	struct fc_plogi_clp_s  class1;		/* class 1 service parameters */
-	struct fc_plogi_clp_s  class2;		/* class 2 service parameters */
-	struct fc_plogi_clp_s  class3;		/* class 3 service parameters */
-	struct fc_plogi_clp_s  class4;		/* class 4 service parameters */
-	u8         vvl[16];	/* vendor version level */
-};
-
-/*
- * LOGO els command payload
- */
-struct fc_logo_s{
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        nport_id:24;	/* N_Port identifier of source */
-	wwn_t           orig_port_name;	/* Port name of the LOGO originator */
-};
-
-/*
- * ADISC els command payload
- */
-struct fc_adisc_s {
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        orig_HA:24;	/* originator hard address */
-	wwn_t           orig_port_name;	/* originator port name */
-	wwn_t           orig_node_name;	/* originator node name */
-	u32        res2:8;
-	u32        nport_id:24;	/* originator NPortID */
-};
-
-/*
- * Exchange status block
- */
-struct fc_exch_status_blk_s{
-	u32        oxid:16;
-	u32        rxid:16;
-	u32        res1:8;
-	u32        orig_np:24;	/* originator NPortID */
-	u32        res2:8;
-	u32        resp_np:24;	/* responder NPortID */
-	u32        es_bits;
-	u32        res3;
-	/*
-	 * un modified section of the fields
-	 */
-};
-
-/*
- * RES els command payload
- */
-struct fc_res_s {
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        nport_id:24;	/* N_Port identifier of source */
-	u32        oxid:16;
-	u32        rxid:16;
-	u8         assoc_hdr[32];
-};
-
-/*
- * RES els accept payload
- */
-struct fc_res_acc_s{
-	struct fc_els_cmd_s els_cmd;	/* ELS command code */
-	struct fc_exch_status_blk_s fc_exch_blk; /* Exchange status block */
-};
-
-/*
- * REC els command payload
- */
-struct fc_rec_s {
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        nport_id:24;	/* N_Port identifier of source */
-	u32        oxid:16;
-	u32        rxid:16;
-};
-
-#define FC_REC_ESB_OWN_RSP	0x80000000	/* responder owns */
-#define FC_REC_ESB_SI		0x40000000	/* SI is owned 	*/
-#define FC_REC_ESB_COMP		0x20000000	/* exchange is complete	*/
-#define FC_REC_ESB_ENDCOND_ABN	0x10000000	/* abnormal ending 	*/
-#define FC_REC_ESB_RQACT	0x04000000	/* recovery qual active	*/
-#define FC_REC_ESB_ERRP_MSK	0x03000000
-#define FC_REC_ESB_OXID_INV	0x00800000	/* invalid OXID		*/
-#define FC_REC_ESB_RXID_INV	0x00400000	/* invalid RXID		*/
-#define FC_REC_ESB_PRIO_INUSE	0x00200000
-
-/*
- * REC els accept payload
- */
-struct fc_rec_acc_s {
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        oxid:16;
-	u32        rxid:16;
-	u32        res1:8;
-	u32        orig_id:24;	/* N_Port id of exchange originator */
-	u32        res2:8;
-	u32        resp_id:24;	/* N_Port id of exchange responder */
-	u32        count;		/* data transfer count */
-	u32        e_stat;		/* exchange status */
-};
-
-/*
- * RSI els payload
- */
-struct fc_rsi_s {
-	struct fc_els_cmd_s    els_cmd;
-	u32        res1:8;
-	u32        orig_sid:24;
-	u32        oxid:16;
-	u32        rxid:16;
-};
-
-/*
- * structure for PRLI paramater pages, both request & response
- * see FC-PH-X table 113 & 115 for explanation also FCP table 8
- */
-struct fc_prli_params_s{
-	u32        reserved:16;
-#ifdef __BIGENDIAN
-	u32        reserved1:5;
-	u32        rec_support:1;
-	u32        task_retry_id:1;
-	u32        retry:1;
-
-	u32        confirm:1;
-	u32        doverlay:1;
-	u32        initiator:1;
-	u32        target:1;
-	u32        cdmix:1;
-	u32        drmix:1;
-	u32        rxrdisab:1;
-	u32        wxrdisab:1;
-#else
-	u32        retry:1;
-	u32        task_retry_id:1;
-	u32        rec_support:1;
-	u32        reserved1:5;
-
-	u32        wxrdisab:1;
-	u32        rxrdisab:1;
-	u32        drmix:1;
-	u32        cdmix:1;
-	u32        target:1;
-	u32        initiator:1;
-	u32        doverlay:1;
-	u32        confirm:1;
-#endif
-};
-
-/*
- * valid values for rspcode in PRLI ACC payload
- */
-enum {
-	FC_PRLI_ACC_XQTD = 0x1,		/* request executed */
-	FC_PRLI_ACC_PREDEF_IMG = 0x5,	/* predefined image - no prli needed */
-};
-
-struct fc_prli_params_page_s{
-	u32        type:8;
-	u32        codext:8;
-#ifdef __BIGENDIAN
-	u32        origprocasv:1;
-	u32        rsppav:1;
-	u32        imagepair:1;
-	u32        reserved1:1;
-	u32        rspcode:4;
-#else
-	u32        rspcode:4;
-	u32        reserved1:1;
-	u32        imagepair:1;
-	u32        rsppav:1;
-	u32        origprocasv:1;
-#endif
-	u32        reserved2:8;
-
-	u32        origprocas;
-	u32        rspprocas;
-	struct fc_prli_params_s  servparams;
-};
-
-/*
- * PRLI request and accept payload, FC-PH-X tables 112 & 114
- */
-struct fc_prli_s{
-	u32        command:8;
-	u32        pglen:8;
-	u32        pagebytes:16;
-	struct fc_prli_params_page_s parampage;
-};
-
-/*
- * PRLO logout params page
- */
-struct fc_prlo_params_page_s{
-	u32        type:8;
-	u32        type_ext:8;
-#ifdef __BIGENDIAN
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
-	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        res1:14;
-#else
-	u32        res1:14;
-	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
-#endif
-	u32        orig_process_assc;
-	u32        resp_process_assc;
-
-	u32        res2;
-};
-
-/*
- * PRLO els command payload
- */
-struct fc_prlo_s{
-	u32        	command:8;
-	u32        	page_len:8;
-	u32        	payload_len:16;
-	struct fc_prlo_params_page_s 	prlo_params[1];
-};
-
-/*
- * PRLO Logout response parameter page
- */
-struct fc_prlo_acc_params_page_s{
-	u32        type:8;
-	u32        type_ext:8;
-
-#ifdef __BIGENDIAN
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
-	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        res1:14;
-#else
-	u32        res1:14;
-	u32        rpa_valid:1;	/* responder process associator valid */
-	u32        opa_valid:1;	/* originator process associator
-					 * valid
-					 */
-#endif
-	u32        orig_process_assc;
-	u32        resp_process_assc;
-
-	u32        fc4type_csp;
-};
-
-/*
- * PRLO els command ACC payload
- */
-struct fc_prlo_acc_s{
-	u32        command:8;
-	u32        page_len:8;
-	u32        payload_len:16;
-	struct fc_prlo_acc_params_page_s prlo_acc_params[1];
-};
-
-/*
- * SCR els command payload
- */
-enum {
-	FC_SCR_REG_FUNC_FABRIC_DETECTED = 0x01,
-	FC_SCR_REG_FUNC_N_PORT_DETECTED = 0x02,
-	FC_SCR_REG_FUNC_FULL = 0x03,
-	FC_SCR_REG_FUNC_CLEAR_REG = 0xFF,
-};
-
-/* SCR VU registrations */
-enum {
-	FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE = 0x01
-};
-
-struct fc_scr_s{
-	u32 command:8;
-	u32 res:24;
-	u32 vu_reg_func:8; /* Vendor Unique Registrations */
-	u32 res1:16;
-	u32 reg_func:8;
-};
-
-/*
- * Information category for Basic link data
- */
-enum {
-	FC_CAT_NOP	= 0x0,
-	FC_CAT_ABTS	= 0x1,
-	FC_CAT_RMC	= 0x2,
-	FC_CAT_BA_ACC	= 0x4,
-	FC_CAT_BA_RJT	= 0x5,
-	FC_CAT_PRMT	= 0x6,
-};
-
-/*
- * LS_RJT els reply payload
- */
-struct fc_ls_rjt_s {
-	struct fc_els_cmd_s    els_cmd;		/* ELS command code */
-	u32        res1:8;
-	u32        reason_code:8;		/* Reason code for reject */
-	u32        reason_code_expl:8;	/* Reason code explanation */
-	u32        vendor_unique:8;	/* Vendor specific */
-};
-
-/*
- * LS_RJT reason codes
- */
-enum {
-	FC_LS_RJT_RSN_INV_CMD_CODE	= 0x01,
-	FC_LS_RJT_RSN_LOGICAL_ERROR	= 0x03,
-	FC_LS_RJT_RSN_LOGICAL_BUSY	= 0x05,
-	FC_LS_RJT_RSN_PROTOCOL_ERROR	= 0x07,
-	FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD = 0x09,
-	FC_LS_RJT_RSN_CMD_NOT_SUPP	= 0x0B,
-};
-
-/*
- * LS_RJT reason code explanation
- */
-enum {
-	FC_LS_RJT_EXP_NO_ADDL_INFO		= 0x00,
-	FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS	= 0x01,
-	FC_LS_RJT_EXP_SPARMS_ERR_INI_CTL	= 0x03,
-	FC_LS_RJT_EXP_SPARMS_ERR_REC_CTL	= 0x05,
-	FC_LS_RJT_EXP_SPARMS_ERR_RXSZ		= 0x07,
-	FC_LS_RJT_EXP_SPARMS_ERR_CONSEQ		= 0x09,
-	FC_LS_RJT_EXP_SPARMS_ERR_CREDIT		= 0x0B,
-	FC_LS_RJT_EXP_INV_PORT_NAME		= 0x0D,
-	FC_LS_RJT_EXP_INV_NODE_FABRIC_NAME	= 0x0E,
-	FC_LS_RJT_EXP_INV_CSP			= 0x0F,
-	FC_LS_RJT_EXP_INV_ASSOC_HDR		= 0x11,
-	FC_LS_RJT_EXP_ASSOC_HDR_REQD		= 0x13,
-	FC_LS_RJT_EXP_INV_ORIG_S_ID		= 0x15,
-	FC_LS_RJT_EXP_INV_OXID_RXID_COMB	= 0x17,
-	FC_LS_RJT_EXP_CMD_ALREADY_IN_PROG	= 0x19,
-	FC_LS_RJT_EXP_LOGIN_REQUIRED		= 0x1E,
-	FC_LS_RJT_EXP_INVALID_NPORT_ID		= 0x1F,
-	FC_LS_RJT_EXP_INSUFF_RES		= 0x29,
-	FC_LS_RJT_EXP_CMD_NOT_SUPP		= 0x2C,
-	FC_LS_RJT_EXP_INV_PAYLOAD_LEN		= 0x2D,
-};
-
-/*
- * RRQ els command payload
- */
-struct fc_rrq_s{
-	struct fc_els_cmd_s    els_cmd;	/* ELS command code */
-	u32        res1:8;
-	u32        s_id:24;	/* exchange originator S_ID */
-
-	u32        ox_id:16;	/* originator exchange ID */
-	u32        rx_id:16;	/* responder exchange ID */
-
-	u32        res2[8];	/* optional association header */
-};
-
-/*
- * ABTS BA_ACC reply payload
- */
-struct fc_ba_acc_s{
-	u32        seq_id_valid:8;	/* set to 0x00 for Abort Exchange */
-	u32        seq_id:8;	/* invalid for Abort Exchange */
-	u32        res2:16;
-	u32        ox_id:16;	/* OX_ID from ABTS frame */
-	u32        rx_id:16;	/* RX_ID from ABTS frame */
-	u32        low_seq_cnt:16;	/* set to 0x0000 for Abort Exchange */
-	u32        high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */
-};
-
-/*
- * ABTS BA_RJT reject payload
- */
-struct fc_ba_rjt_s{
-	u32        res1:8;		/* Reserved */
-	u32        reason_code:8;	/* reason code for reject */
-	u32        reason_expl:8;	/* reason code explanation */
-	u32        vendor_unique:8;/* vendor unique reason code,set to 0 */
-};
-
-/*
- * TPRLO logout parameter page
- */
-struct fc_tprlo_params_page_s{
-	u32        type:8;
-	u32        type_ext:8;
-
-#ifdef __BIGENDIAN
-	u32        opa_valid:1;
-	u32        rpa_valid:1;
-	u32        tpo_nport_valid:1;
-	u32        global_process_logout:1;
-	u32        res1:12;
-#else
-	u32        res1:12;
-	u32        global_process_logout:1;
-	u32        tpo_nport_valid:1;
-	u32        rpa_valid:1;
-	u32        opa_valid:1;
-#endif
-
-	u32        orig_process_assc;
-	u32        resp_process_assc;
-
-	u32        res2:8;
-	u32        tpo_nport_id;
-};
-
-/*
- * TPRLO ELS command payload
- */
-struct fc_tprlo_s{
-	u32        command:8;
-	u32        page_len:8;
-	u32        payload_len:16;
-
-	struct fc_tprlo_params_page_s tprlo_params[1];
-};
-
-enum fc_tprlo_type{
-	FC_GLOBAL_LOGO = 1,
-	FC_TPR_LOGO
-};
-
-/*
- * TPRLO els command ACC payload
- */
-struct fc_tprlo_acc_s{
-	u32	command:8;
-	u32	page_len:8;
-	u32	payload_len:16;
-	struct fc_prlo_acc_params_page_s tprlo_acc_params[1];
-};
-
-/*
- * RSCN els command req payload
- */
-#define FC_RSCN_PGLEN	0x4
-
-enum fc_rscn_format{
-	FC_RSCN_FORMAT_PORTID	= 0x0,
-	FC_RSCN_FORMAT_AREA	= 0x1,
-	FC_RSCN_FORMAT_DOMAIN	= 0x2,
-	FC_RSCN_FORMAT_FABRIC	= 0x3,
-};
-
-struct fc_rscn_event_s{
-	u32        format:2;
-	u32        qualifier:4;
-	u32        resvd:2;
-	u32        portid:24;
-};
-
-struct fc_rscn_pl_s{
-	u8         command;
-	u8         pagelen;
-	u16        payldlen;
-	struct fc_rscn_event_s event[1];
-};
-
-/*
- * ECHO els command req payload
- */
-struct fc_echo_s {
-	struct fc_els_cmd_s    els_cmd;
-};
-
-/*
- * RNID els command
- */
-
-#define RNID_NODEID_DATA_FORMAT_COMMON    		 0x00
-#define RNID_NODEID_DATA_FORMAT_FCP3        		 0x08
-#define RNID_NODEID_DATA_FORMAT_DISCOVERY     		0xDF
-
-#define RNID_ASSOCIATED_TYPE_UNKNOWN                    0x00000001
-#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
-#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
-#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
-#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
-#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
-#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
-#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
-#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
-#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
-#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
-#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
-#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
-
-/*
- * RNID els command payload
- */
-struct fc_rnid_cmd_s{
-	struct fc_els_cmd_s    els_cmd;
-	u32        node_id_data_format:8;
-	u32        reserved:24;
-};
-
-/*
- * RNID els response payload
- */
-
-struct fc_rnid_common_id_data_s{
-	wwn_t           port_name;
-	wwn_t           node_name;
-};
-
-struct fc_rnid_general_topology_data_s{
-	u32        vendor_unique[4];
-	u32        asso_type;
-	u32        phy_port_num;
-	u32        num_attached_nodes;
-	u32        node_mgmt:8;
-	u32        ip_version:8;
-	u32        udp_tcp_port_num:16;
-	u32        ip_address[4];
-	u32        reserved:16;
-	u32        vendor_specific:16;
-};
-
-struct fc_rnid_acc_s{
-	struct fc_els_cmd_s    els_cmd;
-	u32        node_id_data_format:8;
-	u32        common_id_data_length:8;
-	u32        reserved:8;
-	u32        specific_id_data_length:8;
-	struct fc_rnid_common_id_data_s common_id_data;
-	struct fc_rnid_general_topology_data_s gen_topology_data;
-};
-
-#define RNID_ASSOCIATED_TYPE_UNKNOWN                    0x00000001
-#define RNID_ASSOCIATED_TYPE_OTHER                      0x00000002
-#define RNID_ASSOCIATED_TYPE_HUB                        0x00000003
-#define RNID_ASSOCIATED_TYPE_SWITCH                     0x00000004
-#define RNID_ASSOCIATED_TYPE_GATEWAY                    0x00000005
-#define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE             0x00000009
-#define RNID_ASSOCIATED_TYPE_HOST                       0x0000000A
-#define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM          0x0000000B
-#define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE      0x0000000E
-#define RNID_ASSOCIATED_TYPE_NAS_SERVER                 0x00000011
-#define RNID_ASSOCIATED_TYPE_BRIDGE                     0x00000002
-#define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE      0x00000003
-#define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE      0x000000FF
-
-enum fc_rpsc_speed_cap{
-	RPSC_SPEED_CAP_1G = 0x8000,
-	RPSC_SPEED_CAP_2G = 0x4000,
-	RPSC_SPEED_CAP_4G = 0x2000,
-	RPSC_SPEED_CAP_10G = 0x1000,
-	RPSC_SPEED_CAP_8G = 0x0800,
-	RPSC_SPEED_CAP_16G = 0x0400,
-
-	RPSC_SPEED_CAP_UNKNOWN = 0x0001,
-};
-
-enum fc_rpsc_op_speed_s{
-	RPSC_OP_SPEED_1G = 0x8000,
-	RPSC_OP_SPEED_2G = 0x4000,
-	RPSC_OP_SPEED_4G = 0x2000,
-	RPSC_OP_SPEED_10G = 0x1000,
-	RPSC_OP_SPEED_8G = 0x0800,
-	RPSC_OP_SPEED_16G = 0x0400,
-
-	RPSC_OP_SPEED_NOT_EST = 0x0001,	/*! speed not established */
-};
-
-struct fc_rpsc_speed_info_s{
-	u16        port_speed_cap;	/*! see fc_rpsc_speed_cap_t */
-	u16        port_op_speed;	/*! see fc_rpsc_op_speed_t */
-};
-
-enum link_e2e_beacon_subcmd{
-	LINK_E2E_BEACON_ON = 1,
-	LINK_E2E_BEACON_OFF = 2
-};
-
-enum beacon_type{
-	BEACON_TYPE_NORMAL	= 1,	/*! Normal Beaconing. Green */
-	BEACON_TYPE_WARN	= 2,	/*! Warning Beaconing. Yellow/Amber */
-	BEACON_TYPE_CRITICAL	= 3	/*! Critical Beaconing. Red */
-};
-
-struct link_e2e_beacon_param_s {
-	u8         beacon_type;	/* Beacon Type. See beacon_type_t */
-	u8         beacon_frequency;
-					/* Beacon frequency. Number of blinks
-					 * per 10 seconds
-					 */
-	u16        beacon_duration;/* Beacon duration (in Seconds). The
-					 * command operation should be
-					 * terminated at the end of this
-					 * timeout value.
-					 *
-					 * Ignored if diag_sub_cmd is
-					 * LINK_E2E_BEACON_OFF.
-					 *
-					 * If 0, beaconing will continue till a
-					 * BEACON OFF request is received
-					 */
-};
-
-/*
- * Link E2E beacon request/good response format. For LS_RJTs use fc_ls_rjt_t
- */
-struct link_e2e_beacon_req_s{
-	u32        ls_code;	/*! FC_ELS_E2E_LBEACON in requests *
-					 *or FC_ELS_ACC in good replies */
-	u32        ls_sub_cmd;	/*! See link_e2e_beacon_subcmd_t */
-	struct link_e2e_beacon_param_s beacon_parm;
-};
-
-/**
- * If RPSC request is sent to the Domain Controller, the request is for
- * all the ports within that domain (TODO - I don't think FOS implements
- * this...).
- */
-struct fc_rpsc_cmd_s{
-	struct fc_els_cmd_s    els_cmd;
-};
-
-/*
- * RPSC Acc
- */
-struct fc_rpsc_acc_s{
-	u32        command:8;
-	u32        rsvd:8;
-	u32        num_entries:16;
-
-	struct fc_rpsc_speed_info_s speed_info[1];
-};
-
-/**
- * If RPSC2 request is sent to the Domain Controller,
- */
-#define FC_BRCD_TOKEN    0x42524344
-
-struct fc_rpsc2_cmd_s{
-	struct fc_els_cmd_s    els_cmd;
-	u32       	token;
-	u16     	resvd;
-	u16     	num_pids;       /* Number of pids in the request */
-	struct  {
-		u32	rsvd1:8;
-		u32	pid:24;	/* port identifier */
-	} pid_list[1];
-};
-
-enum fc_rpsc2_port_type{
-	RPSC2_PORT_TYPE_UNKNOWN = 0,
-	RPSC2_PORT_TYPE_NPORT   = 1,
-	RPSC2_PORT_TYPE_NLPORT  = 2,
-	RPSC2_PORT_TYPE_NPIV_PORT  = 0x5f,
-	RPSC2_PORT_TYPE_NPORT_TRUNK  = 0x6f,
-};
-
-/*
- * RPSC2 portInfo entry structure
- */
-struct fc_rpsc2_port_info_s{
-    u32    pid;        /* PID */
-    u16    resvd1;
-    u16    index;      /* port number / index */
-    u8     resvd2;
-    u8    	type;        /* port type N/NL/... */
-    u16    speed;      /* port Operating Speed */
-};
-
-/*
- * RPSC2 Accept payload
- */
-struct fc_rpsc2_acc_s{
-	u8        els_cmd;
-	u8        resvd;
-	u16       num_pids;  /* Number of pids in the request */
-	struct fc_rpsc2_port_info_s  port_info[1];    /* port information */
-};
-
-/**
- * bit fields so that multiple classes can be specified
- */
-enum fc_cos{
-	FC_CLASS_2	= 0x04,
-	FC_CLASS_3	= 0x08,
-	FC_CLASS_2_3	= 0x0C,
-};
-
-/*
- * symbolic name
- */
-struct fc_symname_s{
-	u8         symname[FC_SYMNAME_MAX];
-};
-
-struct fc_alpabm_s{
-	u8         alpa_bm[FC_ALPA_MAX / 8];
-};
-
-/*
- * protocol default timeout values
- */
-#define FC_ED_TOV		2
-#define FC_REC_TOV		(FC_ED_TOV + 1)
-#define FC_RA_TOV		10
-#define FC_ELS_TOV		(2 * FC_RA_TOV)
-#define FC_FCCT_TOV		(3 * FC_RA_TOV)
-
-/*
- * virtual fabric related defines
- */
-#define FC_VF_ID_NULL    0	/*  must not be used as VF_ID */
-#define FC_VF_ID_MIN     1
-#define FC_VF_ID_MAX     0xEFF
-#define FC_VF_ID_CTL     0xFEF	/*  control VF_ID */
-
-/**
- * Virtual Fabric Tagging header format
- * @caution This is defined only in BIG ENDIAN format.
- */
-struct fc_vft_s{
-	u32        r_ctl:8;
-	u32        ver:2;
-	u32        type:4;
-	u32        res_a:2;
-	u32        priority:3;
-	u32        vf_id:12;
-	u32        res_b:1;
-	u32        hopct:8;
-	u32        res_c:24;
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/fc_sp.h b/drivers/scsi/bfa/include/protocol/fc_sp.h
deleted file mode 100644
index 55bb0b3..0000000
--- a/drivers/scsi/bfa/include/protocol/fc_sp.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __FC_SP_H__
-#define __FC_SP_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-enum auth_els_flags{
-	FC_AUTH_ELS_MORE_FRAGS_FLAG 	= 0x80,	/*! bit-7. More Fragments
-						 * Follow
-						 */
-	FC_AUTH_ELS_CONCAT_FLAG 	= 0x40,	/*! bit-6. Concatenation Flag */
-	FC_AUTH_ELS_SEQ_NUM_FLAG 	= 0x01 	/*! bit-0. Sequence Number */
-};
-
-enum auth_msg_codes{
-	FC_AUTH_MC_AUTH_RJT		= 0x0A,	/*! Auth Reject */
-	FC_AUTH_MC_AUTH_NEG 		= 0x0B, /*! Auth Negotiate */
-	FC_AUTH_MC_AUTH_DONE 		= 0x0C, /*! Auth Done */
-
-	FC_AUTH_MC_DHCHAP_CHAL 		= 0x10, /*! DHCHAP Challenge */
-	FC_AUTH_MC_DHCHAP_REPLY 	= 0x11, /*! DHCHAP Reply */
-	FC_AUTH_MC_DHCHAP_SUCC 		= 0x12, /*! DHCHAP Success */
-
-	FC_AUTH_MC_FCAP_REQ 		= 0x13, /*! FCAP Request */
-	FC_AUTH_MC_FCAP_ACK 		= 0x14, /*! FCAP Acknowledge */
-	FC_AUTH_MC_FCAP_CONF 		= 0x15, /*! FCAP Confirm */
-
-	FC_AUTH_MC_FCPAP_INIT 		= 0x16, /*! FCPAP Init */
-	FC_AUTH_MC_FCPAP_ACC 		= 0x17, /*! FCPAP Accept */
-	FC_AUTH_MC_FCPAP_COMP 		= 0x18, /*! FCPAP Complete */
-
-	FC_AUTH_MC_IKE_SA_INIT 		= 0x22, /*! IKE SA INIT */
-	FC_AUTH_MC_IKE_SA_AUTH 		= 0x23, /*! IKE SA Auth */
-	FC_AUTH_MC_IKE_CREATE_CHILD_SA	= 0x24, /*! IKE Create Child SA */
-	FC_AUTH_MC_IKE_INFO 		= 0x25, /*! IKE informational */
-};
-
-enum auth_proto_version{
-	FC_AUTH_PROTO_VER_1 	= 1,	/*! Protocol Version 1 */
-};
-
-enum {
-	FC_AUTH_ELS_COMMAND_CODE = 0x90,/*! Authentication ELS Command code  */
-	FC_AUTH_PROTO_PARAM_LEN_SZ = 4,	/*! Size of Proto Parameter Len Field */
-	FC_AUTH_PROTO_PARAM_VAL_SZ = 4,	/*! Size of Proto Parameter Val Field */
-	FC_MAX_AUTH_SECRET_LEN     = 256,
-					/*! Maximum secret string length */
-	FC_AUTH_NUM_USABLE_PROTO_LEN_SZ = 4,
-					/*! Size of usable protocols field */
-	FC_AUTH_RESP_VALUE_LEN_SZ	= 4,
-					/*! Size of response value length */
-	FC_MAX_CHAP_KEY_LEN	= 256,	/*! Maximum md5 digest length */
-	FC_MAX_AUTH_RETRIES     = 3,	/*! Maximum number of retries */
-	FC_MD5_DIGEST_LEN       = 16,	/*! MD5 digest length */
-	FC_SHA1_DIGEST_LEN      = 20,	/*! SHA1 digest length */
-	FC_MAX_DHG_SUPPORTED    = 1,	/*! Maximum DH Groups supported */
-	FC_MAX_ALG_SUPPORTED    = 1,	/*! Maximum algorithms supported */
-	FC_MAX_PROTO_SUPPORTED  = 1,	/*! Maximum protocols supported */
-	FC_START_TXN_ID         = 2,	/*! Starting transaction ID */
-};
-
-enum auth_proto_id{
-	FC_AUTH_PROTO_DHCHAP		= 0x00000001,
-	FC_AUTH_PROTO_FCAP 		= 0x00000002,
-	FC_AUTH_PROTO_FCPAP 		= 0x00000003,
-	FC_AUTH_PROTO_IKEv2 		= 0x00000004,
-	FC_AUTH_PROTO_IKEv2_AUTH 	= 0x00000005,
-};
-
-struct auth_name_s{
-	u16	name_tag;	/*! Name Tag = 1 for Authentication */
-	u16	name_len;	/*! Name Length = 8 for Authentication
-					 */
-	wwn_t		name;  		/*! Name. TODO - is this PWWN */
-};
-
-
-enum auth_hash_func{
-	FC_AUTH_HASH_FUNC_MD5 		= 0x00000005,
-	FC_AUTH_HASH_FUNC_SHA_1 	= 0x00000006,
-};
-
-enum auth_dh_gid{
-	FC_AUTH_DH_GID_0_DHG_NULL	= 0x00000000,
-	FC_AUTH_DH_GID_1_DHG_1024	= 0x00000001,
-	FC_AUTH_DH_GID_2_DHG_1280	= 0x00000002,
-	FC_AUTH_DH_GID_3_DHG_1536	= 0x00000003,
-	FC_AUTH_DH_GID_4_DHG_2048	= 0x00000004,
-	FC_AUTH_DH_GID_6_DHG_3072	= 0x00000006,
-	FC_AUTH_DH_GID_7_DHG_4096	= 0x00000007,
-	FC_AUTH_DH_GID_8_DHG_6144	= 0x00000008,
-	FC_AUTH_DH_GID_9_DHG_8192	= 0x00000009,
-};
-
-struct auth_els_msg_s {
-	u8		auth_els_code;	/*  Authentication ELS Code (0x90) */
-	u8 	auth_els_flag; 	/*  Authentication ELS Flags */
-	u8 	auth_msg_code; 	/*  Authentication Message Code */
-	u8 	proto_version; 	/*  Protocol Version */
-	u32	msg_len; 	/*  Message Length */
-	u32	trans_id; 	/*  Transaction Identifier (T_ID) */
-
-	/* Msg payload follows... */
-};
-
-
-enum auth_neg_param_tags {
-	FC_AUTH_NEG_DHCHAP_HASHLIST 	= 0x0001,
-	FC_AUTH_NEG_DHCHAP_DHG_ID_LIST 	= 0x0002,
-};
-
-
-struct dhchap_param_format_s {
-	u16	tag;		/*! Parameter Tag. See
-					 * auth_neg_param_tags_t
-					 */
-	u16	word_cnt;
-
-	/* followed by variable length parameter value... */
-};
-
-struct auth_proto_params_s {
-	u32	proto_param_len;
-	u32	proto_id;
-
-	/*
-	 * Followed by variable length Protocol specific parameters. DH-CHAP
-	 * uses dhchap_param_format_t
-	 */
-};
-
-struct auth_neg_msg_s {
-	struct auth_name_s	auth_ini_name;
-	u32		usable_auth_protos;
-	struct auth_proto_params_s proto_params[1]; /*! (1..usable_auth_proto)
-						     * protocol params
-						     */
-};
-
-struct auth_dh_val_s {
-	u32 dh_val_len;
-	u32 dh_val[1];
-};
-
-struct auth_dhchap_chal_msg_s {
-	struct auth_els_msg_s	hdr;
-	struct auth_name_s auth_responder_name;	/* TODO VRK - is auth_name_t
-						 * type OK?
-						 */
-	u32 	hash_id;
-	u32 	dh_grp_id;
-	u32 	chal_val_len;
-	char		chal_val[1];
-
-	/* ...followed by variable Challenge length/value and DH length/value */
-};
-
-
-enum auth_rjt_codes {
-	FC_AUTH_RJT_CODE_AUTH_FAILURE 	= 0x01,
-	FC_AUTH_RJT_CODE_LOGICAL_ERR	= 0x02,
-};
-
-enum auth_rjt_code_exps {
-	FC_AUTH_CEXP_AUTH_MECH_NOT_USABLE	= 0x01,
-	FC_AUTH_CEXP_DH_GROUP_NOT_USABLE 	= 0x02,
-	FC_AUTH_CEXP_HASH_FUNC_NOT_USABLE 	= 0x03,
-	FC_AUTH_CEXP_AUTH_XACT_STARTED		= 0x04,
-	FC_AUTH_CEXP_AUTH_FAILED 		= 0x05,
-	FC_AUTH_CEXP_INCORRECT_PLD 		= 0x06,
-	FC_AUTH_CEXP_INCORRECT_PROTO_MSG 	= 0x07,
-	FC_AUTH_CEXP_RESTART_AUTH_PROTO 	= 0x08,
-	FC_AUTH_CEXP_AUTH_CONCAT_NOT_SUPP 	= 0x09,
-	FC_AUTH_CEXP_PROTO_VER_NOT_SUPP 	= 0x0A,
-};
-
-enum auth_status {
-	FC_AUTH_STATE_INPROGRESS = 0, 	/*! authentication in progress 	*/
-	FC_AUTH_STATE_FAILED	= 1, 	/*! authentication failed */
-	FC_AUTH_STATE_SUCCESS	= 2 	/*! authentication successful	*/
-};
-
-struct auth_rjt_msg_s {
-	struct auth_els_msg_s	hdr;
-	u8		reason_code;
-	u8		reason_code_exp;
-	u8		rsvd[2];
-};
-
-
-struct auth_dhchap_neg_msg_s {
-	struct auth_els_msg_s hdr;
-	struct auth_neg_msg_s nego;
-};
-
-struct auth_dhchap_reply_msg_s {
-	struct auth_els_msg_s	hdr;
-
-	/*
-	 * followed by response value length & Value + DH Value Length & Value
-	 */
-};
-
-#pragma pack()
-
-#endif /* __FC_SP_H__ */
diff --git a/drivers/scsi/bfa/include/protocol/fcp.h b/drivers/scsi/bfa/include/protocol/fcp.h
deleted file mode 100644
index 74ea63c..0000000
--- a/drivers/scsi/bfa/include/protocol/fcp.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __FCPPROTO_H__
-#define __FCPPROTO_H__
-
-#include <linux/bitops.h>
-#include <protocol/scsi.h>
-
-#pragma pack(1)
-
-enum {
-	FCP_RJT		= 0x01000000,	/* SRR reject */
-	FCP_SRR_ACCEPT	= 0x02000000,	/* SRR accept */
-	FCP_SRR		= 0x14000000,	/* Sequence Retransmission Request */
-};
-
-/*
- * SRR FC-4 LS payload
- */
-struct fc_srr_s{
-	u32	ls_cmd;
-	u32        ox_id:16;	/* ox-id */
-	u32        rx_id:16;	/* rx-id */
-	u32        ro;		/* relative offset */
-	u32        r_ctl:8;		/* R_CTL for I.U. */
-	u32        res:24;
-};
-
-
-/*
- * FCP_CMND definitions
- */
-#define FCP_CMND_CDB_LEN    16
-#define FCP_CMND_LUN_LEN    8
-
-struct fcp_cmnd_s{
-	lun_t           lun;		/* 64-bit LU number */
-	u8         crn;		/* command reference number */
-#ifdef __BIGENDIAN
-	u8         resvd:1,
-			priority:4,	/* FCP-3: SAM-3 priority */
-			taskattr:3;	/* scsi task attribute */
-#else
-	u8         taskattr:3,	/* scsi task attribute */
-			priority:4,	/* FCP-3: SAM-3 priority */
-			resvd:1;
-#endif
-	u8         tm_flags;	/* task management flags */
-#ifdef __BIGENDIAN
-	u8         addl_cdb_len:6,	/* additional CDB length words */
-			iodir:2;	/* read/write FCP_DATA IUs */
-#else
-	u8         iodir:2,	/* read/write FCP_DATA IUs */
-			addl_cdb_len:6;	/* additional CDB length */
-#endif
-	struct scsi_cdb_s      cdb;
-
-	/*
-	 * !!! additional cdb bytes follows here!!!
-	 */
-	u32        fcp_dl;	/* bytes to be transferred */
-};
-
-#define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN)
-#define fcp_cmnd_fcpdl(_cmnd)	((&(_cmnd)->fcp_dl)[(_cmnd)->addl_cdb_len])
-
-/*
- * fcp_cmnd_t.iodir field values
- */
-enum fcp_iodir{
-	FCP_IODIR_NONE	= 0,
-	FCP_IODIR_WRITE = 1,
-	FCP_IODIR_READ	= 2,
-	FCP_IODIR_RW	= 3,
-};
-
-/*
- * Task attribute field
- */
-enum {
-	FCP_TASK_ATTR_SIMPLE	= 0,
-	FCP_TASK_ATTR_HOQ	= 1,
-	FCP_TASK_ATTR_ORDERED	= 2,
-	FCP_TASK_ATTR_ACA	= 4,
-	FCP_TASK_ATTR_UNTAGGED	= 5,	/* obsolete in FCP-3 */
-};
-
-/*
- * Task management flags field - only one bit shall be set
- */
-enum fcp_tm_cmnd{
-	FCP_TM_ABORT_TASK_SET	= BIT(1),
-	FCP_TM_CLEAR_TASK_SET	= BIT(2),
-	FCP_TM_LUN_RESET	= BIT(4),
-	FCP_TM_TARGET_RESET	= BIT(5),	/* obsolete in FCP-3 */
-	FCP_TM_CLEAR_ACA	= BIT(6),
-};
-
-/*
- * FCP_XFER_RDY IU defines
- */
-struct fcp_xfer_rdy_s{
-	u32        data_ro;
-	u32        burst_len;
-	u32        reserved;
-};
-
-/*
- * FCP_RSP residue flags
- */
-enum fcp_residue{
-	FCP_NO_RESIDUE = 0,	/* no residue */
-	FCP_RESID_OVER = 1,	/* more data left that was not sent */
-	FCP_RESID_UNDER = 2,	/* less data than requested */
-};
-
-enum {
-	FCP_RSPINFO_GOOD = 0,
-	FCP_RSPINFO_DATALEN_MISMATCH = 1,
-	FCP_RSPINFO_CMND_INVALID = 2,
-	FCP_RSPINFO_ROLEN_MISMATCH = 3,
-	FCP_RSPINFO_TM_NOT_SUPP = 4,
-	FCP_RSPINFO_TM_FAILED = 5,
-};
-
-struct fcp_rspinfo_s{
-	u32        res0:24;
-	u32        rsp_code:8;	/* response code (as above) */
-	u32        res1;
-};
-
-struct fcp_resp_s{
-	u32        reserved[2];	/* 2 words reserved */
-	u16        reserved2;
-#ifdef __BIGENDIAN
-	u8         reserved3:3;
-	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
-	u8         resid_flags:2;	/* underflow/overflow */
-	u8         sns_len_valid:1;/* sense len is valid */
-	u8         rsp_len_valid:1;/* response len is valid */
-#else
-	u8         rsp_len_valid:1;/* response len is valid */
-	u8         sns_len_valid:1;/* sense len is valid */
-	u8         resid_flags:2;	/* underflow/overflow */
-	u8         fcp_conf_req:1;	/* FCP_CONF is requested */
-	u8         reserved3:3;
-#endif
-	u8         scsi_status;	/* one byte SCSI status */
-	u32        residue;	/* residual data bytes */
-	u32        sns_len;	/* length od sense info */
-	u32        rsp_len;	/* length of response info */
-};
-
-#define fcp_snslen(__fcprsp)	((__fcprsp)->sns_len_valid ? 		\
-					(__fcprsp)->sns_len : 0)
-#define fcp_rsplen(__fcprsp)	((__fcprsp)->rsp_len_valid ? 		\
-					(__fcprsp)->rsp_len : 0)
-#define fcp_rspinfo(__fcprsp)	((struct fcp_rspinfo_s *)((__fcprsp) + 1))
-#define fcp_snsinfo(__fcprsp)	(((u8 *)fcp_rspinfo(__fcprsp)) + 	\
-						fcp_rsplen(__fcprsp))
-
-struct fcp_cmnd_fr_s{
-	struct fchs_s          fchs;
-	struct fcp_cmnd_s      fcp;
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/fdmi.h b/drivers/scsi/bfa/include/protocol/fdmi.h
deleted file mode 100644
index 6c05c26..0000000
--- a/drivers/scsi/bfa/include/protocol/fdmi.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __FDMI_H__
-#define __FDMI_H__
-
-#include <protocol/types.h>
-#include <protocol/fc.h>
-#include <protocol/ct.h>
-
-#pragma pack(1)
-
-/*
- * FDMI Command Codes
- */
-#define	FDMI_GRHL		0x0100
-#define	FDMI_GHAT		0x0101
-#define	FDMI_GRPL		0x0102
-#define	FDMI_GPAT		0x0110
-#define	FDMI_RHBA		0x0200
-#define	FDMI_RHAT		0x0201
-#define	FDMI_RPRT		0x0210
-#define	FDMI_RPA		0x0211
-#define	FDMI_DHBA		0x0300
-#define	FDMI_DPRT		0x0310
-
-/*
- * FDMI reason codes
- */
-#define	FDMI_NO_ADDITIONAL_EXP		0x00
-#define	FDMI_HBA_ALREADY_REG		0x10
-#define	FDMI_HBA_ATTRIB_NOT_REG		0x11
-#define	FDMI_HBA_ATTRIB_MULTIPLE	0x12
-#define	FDMI_HBA_ATTRIB_LENGTH_INVALID	0x13
-#define	FDMI_HBA_ATTRIB_NOT_PRESENT	0x14
-#define	FDMI_PORT_ORIG_NOT_IN_LIST	0x15
-#define	FDMI_PORT_HBA_NOT_IN_LIST	0x16
-#define	FDMI_PORT_ATTRIB_NOT_REG	0x20
-#define	FDMI_PORT_NOT_REG		0x21
-#define	FDMI_PORT_ATTRIB_MULTIPLE	0x22
-#define	FDMI_PORT_ATTRIB_LENGTH_INVALID	0x23
-#define	FDMI_PORT_ALREADY_REGISTEREED	0x24
-
-/*
- * FDMI Transmission Speed Mask values
- */
-#define	FDMI_TRANS_SPEED_1G		0x00000001
-#define	FDMI_TRANS_SPEED_2G		0x00000002
-#define	FDMI_TRANS_SPEED_10G		0x00000004
-#define	FDMI_TRANS_SPEED_4G		0x00000008
-#define	FDMI_TRANS_SPEED_8G		0x00000010
-#define	FDMI_TRANS_SPEED_16G		0x00000020
-#define	FDMI_TRANS_SPEED_UNKNOWN	0x00008000
-
-/*
- * FDMI HBA attribute types
- */
-enum fdmi_hba_attribute_type {
-	FDMI_HBA_ATTRIB_NODENAME = 1,	/* 0x0001 */
-	FDMI_HBA_ATTRIB_MANUFACTURER,	/* 0x0002 */
-	FDMI_HBA_ATTRIB_SERIALNUM,	/* 0x0003 */
-	FDMI_HBA_ATTRIB_MODEL,		/* 0x0004 */
-	FDMI_HBA_ATTRIB_MODEL_DESC,	/* 0x0005 */
-	FDMI_HBA_ATTRIB_HW_VERSION,	/* 0x0006 */
-	FDMI_HBA_ATTRIB_DRIVER_VERSION,	/* 0x0007 */
-	FDMI_HBA_ATTRIB_ROM_VERSION,	/* 0x0008 */
-	FDMI_HBA_ATTRIB_FW_VERSION,	/* 0x0009 */
-	FDMI_HBA_ATTRIB_OS_NAME,	/* 0x000A */
-	FDMI_HBA_ATTRIB_MAX_CT,		/* 0x000B */
-
-	FDMI_HBA_ATTRIB_MAX_TYPE
-};
-
-/*
- * FDMI Port attribute types
- */
-enum fdmi_port_attribute_type {
-	FDMI_PORT_ATTRIB_FC4_TYPES = 1,	/* 0x0001 */
-	FDMI_PORT_ATTRIB_SUPP_SPEED,	/* 0x0002 */
-	FDMI_PORT_ATTRIB_PORT_SPEED,	/* 0x0003 */
-	FDMI_PORT_ATTRIB_FRAME_SIZE,	/* 0x0004 */
-	FDMI_PORT_ATTRIB_DEV_NAME,	/* 0x0005 */
-	FDMI_PORT_ATTRIB_HOST_NAME,	/* 0x0006 */
-
-	FDMI_PORT_ATTR_MAX_TYPE
-};
-
-/*
- * FDMI attribute
- */
-struct fdmi_attr_s {
-	u16        type;
-	u16        len;
-	u8         value[1];
-};
-
-/*
- * HBA Attribute Block
- */
-struct fdmi_hba_attr_s {
-	u32        attr_count;	/* # of attributes */
-	struct fdmi_attr_s     hba_attr;	/* n attributes */
-};
-
-/*
- * Registered Port List
- */
-struct fdmi_port_list_s {
-	u32        num_ports;	/* number Of Port Entries */
-	wwn_t           port_entry;	/* one or more */
-};
-
-/*
- * Port Attribute Block
- */
-struct fdmi_port_attr_s {
-	u32        attr_count;	/* # of attributes */
-	struct fdmi_attr_s     port_attr;	/* n attributes */
-};
-
-/*
- * FDMI Register HBA Attributes
- */
-struct fdmi_rhba_s {
-	wwn_t           hba_id;		/* HBA Identifier */
-	struct fdmi_port_list_s port_list;	/* Registered Port List */
-	struct fdmi_hba_attr_s hba_attr_blk;	/* HBA attribute block */
-};
-
-/*
- * FDMI Register Port
- */
-struct fdmi_rprt_s {
-	wwn_t           hba_id;		/* HBA Identifier */
-	wwn_t           port_name;	/* Port wwn */
-	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
-};
-
-/*
- * FDMI Register Port Attributes
- */
-struct fdmi_rpa_s {
-	wwn_t           port_name;	/* port wwn */
-	struct fdmi_port_attr_s port_attr_blk;	/* Port Attr Block */
-};
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/include/protocol/scsi.h b/drivers/scsi/bfa/include/protocol/scsi.h
deleted file mode 100644
index b220e6b..0000000
--- a/drivers/scsi/bfa/include/protocol/scsi.h
+++ /dev/null
@@ -1,1648 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __SCSI_H__
-#define __SCSI_H__
-
-#include <protocol/types.h>
-
-#pragma pack(1)
-
-/*
- * generic SCSI cdb definition
- */
-#define SCSI_MAX_CDBLEN     16
-struct scsi_cdb_s{
-	u8         scsi_cdb[SCSI_MAX_CDBLEN];
-};
-
-/*
- * scsi lun serial number definition
- */
-#define SCSI_LUN_SN_LEN     32
-struct scsi_lun_sn_s{
-	u8         lun_sn[SCSI_LUN_SN_LEN];
-};
-
-/*
- * SCSI Direct Access Commands
- */
-enum {
-	SCSI_OP_TEST_UNIT_READY		= 0x00,
-	SCSI_OP_REQUEST_SENSE		= 0x03,
-	SCSI_OP_FORMAT_UNIT		= 0x04,
-	SCSI_OP_READ6			= 0x08,
-	SCSI_OP_WRITE6			= 0x0A,
-	SCSI_OP_WRITE_FILEMARKS		= 0x10,
-	SCSI_OP_INQUIRY			= 0x12,
-	SCSI_OP_MODE_SELECT6		= 0x15,
-	SCSI_OP_RESERVE6		= 0x16,
-	SCSI_OP_RELEASE6		= 0x17,
-	SCSI_OP_MODE_SENSE6		= 0x1A,
-	SCSI_OP_START_STOP_UNIT		= 0x1B,
-	SCSI_OP_SEND_DIAGNOSTIC		= 0x1D,
-	SCSI_OP_READ_CAPACITY		= 0x25,
-	SCSI_OP_READ10			= 0x28,
-	SCSI_OP_WRITE10			= 0x2A,
-	SCSI_OP_VERIFY10		= 0x2F,
-	SCSI_OP_READ_DEFECT_DATA	= 0x37,
-	SCSI_OP_LOG_SELECT		= 0x4C,
-	SCSI_OP_LOG_SENSE		= 0x4D,
-	SCSI_OP_MODE_SELECT10		= 0x55,
-	SCSI_OP_RESERVE10		= 0x56,
-	SCSI_OP_RELEASE10		= 0x57,
-	SCSI_OP_MODE_SENSE10		= 0x5A,
-	SCSI_OP_PER_RESERVE_IN		= 0x5E,
-	SCSI_OP_PER_RESERVE_OUR		= 0x5E,
-	SCSI_OP_READ16			= 0x88,
-	SCSI_OP_WRITE16			= 0x8A,
-	SCSI_OP_VERIFY16		= 0x8F,
-	SCSI_OP_READ_CAPACITY16		= 0x9E,
-	SCSI_OP_REPORT_LUNS		= 0xA0,
-	SCSI_OP_READ12			= 0xA8,
-	SCSI_OP_WRITE12			= 0xAA,
-	SCSI_OP_UNDEF			= 0xFF,
-};
-
-/*
- * SCSI START_STOP_UNIT command
- */
-struct scsi_start_stop_unit_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         reserved1:4;
-	u8         immed:1;
-#else
-	u8         immed:1;
-	u8         reserved1:4;
-	u8         lun:3;
-#endif
-	u8         reserved2;
-	u8         reserved3;
-#ifdef __BIGENDIAN
-	u8         power_conditions:4;
-	u8         reserved4:2;
-	u8         loEj:1;
-	u8         start:1;
-#else
-	u8         start:1;
-	u8         loEj:1;
-	u8         reserved4:2;
-	u8         power_conditions:4;
-#endif
-	u8         control;
-};
-
-/*
- * SCSI SEND_DIAGNOSTIC command
- */
-struct scsi_send_diagnostic_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         self_test_code:3;
-	u8         pf:1;
-	u8         reserved1:1;
-	u8         self_test:1;
-	u8         dev_offl:1;
-	u8         unit_offl:1;
-#else
-	u8         unit_offl:1;
-	u8         dev_offl:1;
-	u8         self_test:1;
-	u8         reserved1:1;
-	u8         pf:1;
-	u8         self_test_code:3;
-#endif
-	u8         reserved2;
-
-	u8         param_list_length[2];	/* MSB first */
-	u8         control;
-
-};
-
-/*
- * SCSI READ10/WRITE10 commands
- */
-struct scsi_rw10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         dpo:1;	/* Disable Page Out */
-	u8         fua:1;	/* Force Unit Access */
-	u8         reserved1:2;
-	u8         rel_adr:1;	/* relative address */
-#else
-	u8         rel_adr:1;
-	u8         reserved1:2;
-	u8         fua:1;
-	u8         dpo:1;
-	u8         lun:3;
-#endif
-	u8         lba0;	/* logical block address - MSB */
-	u8         lba1;
-	u8         lba2;
-	u8         lba3;	/* LSB */
-	u8         reserved3;
-	u8         xfer_length0;	/* transfer length in blocks - MSB */
-	u8         xfer_length1;	/* LSB */
-	u8         control;
-};
-
-#define SCSI_CDB10_GET_LBA(cdb)                     \
-    (((cdb)->lba0 << 24) | ((cdb)->lba1 << 16) |    \
-     ((cdb)->lba2 << 8) | (cdb)->lba3)
-
-#define SCSI_CDB10_SET_LBA(cdb, lba) {      \
-    (cdb)->lba0 = lba >> 24;            \
-    (cdb)->lba1 = (lba >> 16) & 0xFF;   \
-    (cdb)->lba2 = (lba >> 8) & 0xFF;    \
-    (cdb)->lba3 = lba & 0xFF;           \
-}
-
-#define SCSI_CDB10_GET_TL(cdb)  \
-    ((cdb)->xfer_length0 << 8 | (cdb)->xfer_length1)
-#define SCSI_CDB10_SET_TL(cdb, tl) {      \
-    (cdb)->xfer_length0 = tl >> 8;       \
-    (cdb)->xfer_length1 = tl & 0xFF;     \
-}
-
-/*
- * SCSI READ6/WRITE6 commands
- */
-struct scsi_rw6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         lba0:5;		/* MSb */
-#else
-	u8         lba0:5;		/* MSb */
-	u8         lun:3;
-#endif
-	u8         lba1;
-	u8         lba2;		/* LSB */
-	u8         xfer_length;
-	u8         control;
-};
-
-#define SCSI_TAPE_CDB6_GET_TL(cdb)              \
-    (((cdb)->tl0 << 16) | ((cdb)->tl1 << 8) | (cdb)->tl2)
-
-#define SCSI_TAPE_CDB6_SET_TL(cdb, tl) {      \
-    (cdb)->tl0 = tl >> 16;            \
-    (cdb)->tl1 = (tl >> 8) & 0xFF;    \
-    (cdb)->tl2 = tl & 0xFF;           \
-}
-
-/*
- * SCSI sequential (TAPE) wrtie command
- */
-struct scsi_tape_wr_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         rsvd:7;
-	u8         fixed:1;	/* MSb */
-#else
-	u8         fixed:1;	/* MSb */
-	u8         rsvd:7;
-#endif
-	u8         tl0;		/* Msb */
-	u8         tl1;
-	u8         tl2;		/* Lsb */
-
-	u8         control;
-};
-
-#define SCSI_CDB6_GET_LBA(cdb)              \
-    (((cdb)->lba0 << 16) | ((cdb)->lba1 << 8) | (cdb)->lba2)
-
-#define SCSI_CDB6_SET_LBA(cdb, lba) {      \
-    (cdb)->lba0 = lba >> 16;            \
-    (cdb)->lba1 = (lba >> 8) & 0xFF;    \
-    (cdb)->lba2 = lba & 0xFF;           \
-}
-
-#define SCSI_CDB6_GET_TL(cdb) ((cdb)->xfer_length)
-#define SCSI_CDB6_SET_TL(cdb, tl) {      \
-    (cdb)->xfer_length = tl;         \
-}
-
-/*
- * SCSI sense data format
- */
-struct scsi_sense_s{
-#ifdef __BIGENDIAN
-	u8         valid:1;
-	u8         rsp_code:7;
-#else
-	u8         rsp_code:7;
-	u8         valid:1;
-#endif
-	u8         seg_num;
-#ifdef __BIGENDIAN
-	u8         file_mark:1;
-	u8         eom:1;		/* end of media */
-	u8         ili:1;		/* incorrect length indicator */
-	u8         reserved:1;
-	u8         sense_key:4;
-#else
-	u8         sense_key:4;
-	u8         reserved:1;
-	u8         ili:1;		/* incorrect length indicator */
-	u8         eom:1;		/* end of media */
-	u8         file_mark:1;
-#endif
-	u8         information[4];	/* device-type or command specific info
-					 */
-	u8         add_sense_length;
-					/* additional sense length */
-	u8         command_info[4];/* command specific information
-						 */
-	u8         asc;		/* additional sense code */
-	u8         ascq;		/* additional sense code qualifier */
-	u8         fru_code;	/* field replaceable unit code */
-#ifdef __BIGENDIAN
-	u8         sksv:1;		/* sense key specific valid */
-	u8         c_d:1;		/* command/data bit */
-	u8         res1:2;
-	u8         bpv:1;		/* bit pointer valid */
-	u8         bpointer:3;	/* bit pointer */
-#else
-	u8         bpointer:3;	/* bit pointer */
-	u8         bpv:1;		/* bit pointer valid */
-	u8         res1:2;
-	u8         c_d:1;		/* command/data bit */
-	u8         sksv:1;		/* sense key specific valid */
-#endif
-	u8         fpointer[2];	/* field pointer */
-};
-
-#define SCSI_SENSE_CUR_ERR          0x70
-#define SCSI_SENSE_DEF_ERR          0x71
-
-/*
- * SCSI sense key values
- */
-#define SCSI_SK_NO_SENSE        0x0
-#define SCSI_SK_REC_ERR         0x1	/* recovered error */
-#define SCSI_SK_NOT_READY       0x2
-#define SCSI_SK_MED_ERR         0x3	/* medium error */
-#define SCSI_SK_HW_ERR          0x4	/* hardware error */
-#define SCSI_SK_ILLEGAL_REQ     0x5
-#define SCSI_SK_UNIT_ATT        0x6	/* unit attention */
-#define SCSI_SK_DATA_PROTECT    0x7
-#define SCSI_SK_BLANK_CHECK     0x8
-#define SCSI_SK_VENDOR_SPEC     0x9
-#define SCSI_SK_COPY_ABORTED    0xA
-#define SCSI_SK_ABORTED_CMND    0xB
-#define SCSI_SK_VOL_OVERFLOW    0xD
-#define SCSI_SK_MISCOMPARE      0xE
-
-/*
- * SCSI additional sense codes
- */
-#define SCSI_ASC_NO_ADD_SENSE           0x00
-#define SCSI_ASC_LUN_NOT_READY          0x04
-#define SCSI_ASC_LUN_COMMUNICATION      0x08
-#define SCSI_ASC_WRITE_ERROR            0x0C
-#define SCSI_ASC_INVALID_CMND_CODE      0x20
-#define SCSI_ASC_BAD_LBA                0x21
-#define SCSI_ASC_INVALID_FIELD_IN_CDB   0x24
-#define SCSI_ASC_LUN_NOT_SUPPORTED      0x25
-#define SCSI_ASC_LUN_WRITE_PROTECT      0x27
-#define SCSI_ASC_POWERON_BDR            0x29	/* power on reset, bus reset,
-						 * bus device reset
-						 */
-#define SCSI_ASC_PARAMS_CHANGED         0x2A
-#define SCSI_ASC_CMND_CLEARED_BY_A_I    0x2F
-#define SCSI_ASC_SAVING_PARAM_NOTSUPP   0x39
-#define SCSI_ASC_TOCC                   0x3F	/* target operating condtions
-						 * changed
-						 */
-#define SCSI_ASC_PARITY_ERROR           0x47
-#define SCSI_ASC_CMND_PHASE_ERROR       0x4A
-#define SCSI_ASC_DATA_PHASE_ERROR       0x4B
-#define SCSI_ASC_VENDOR_SPEC            0x7F
-
-/*
- * SCSI additional sense code qualifiers
- */
-#define SCSI_ASCQ_CAUSE_NOT_REPORT      0x00
-#define SCSI_ASCQ_BECOMING_READY        0x01
-#define SCSI_ASCQ_INIT_CMD_REQ          0x02
-#define SCSI_ASCQ_FORMAT_IN_PROGRESS    0x04
-#define SCSI_ASCQ_OPERATION_IN_PROGRESS 0x07
-#define SCSI_ASCQ_SELF_TEST_IN_PROGRESS 0x09
-#define SCSI_ASCQ_WR_UNEXP_UNSOL_DATA   0x0C
-#define SCSI_ASCQ_WR_NOTENG_UNSOL_DATA  0x0D
-
-#define SCSI_ASCQ_LBA_OUT_OF_RANGE      0x00
-#define SCSI_ASCQ_INVALID_ELEMENT_ADDR  0x01
-
-#define SCSI_ASCQ_LUN_WRITE_PROTECTED       0x00
-#define SCSI_ASCQ_LUN_HW_WRITE_PROTECTED    0x01
-#define SCSI_ASCQ_LUN_SW_WRITE_PROTECTED    0x02
-
-#define SCSI_ASCQ_POR   0x01	/* power on reset */
-#define SCSI_ASCQ_SBR   0x02	/* scsi bus reset */
-#define SCSI_ASCQ_BDR   0x03	/* bus device reset */
-#define SCSI_ASCQ_DIR   0x04	/* device internal reset */
-
-#define SCSI_ASCQ_MODE_PARAMS_CHANGED       0x01
-#define SCSI_ASCQ_LOG_PARAMS_CHANGED        0x02
-#define SCSI_ASCQ_RESERVATIONS_PREEMPTED    0x03
-#define SCSI_ASCQ_RESERVATIONS_RELEASED     0x04
-#define SCSI_ASCQ_REGISTRATIONS_PREEMPTED   0x05
-
-#define SCSI_ASCQ_MICROCODE_CHANGED 0x01
-#define SCSI_ASCQ_CHANGED_OPER_COND 0x02
-#define SCSI_ASCQ_INQ_CHANGED       0x03	/* inquiry data changed */
-#define SCSI_ASCQ_DI_CHANGED        0x05	/* device id changed */
-#define SCSI_ASCQ_RL_DATA_CHANGED   0x0E	/* report luns data changed */
-
-#define SCSI_ASCQ_DP_CRC_ERR            0x01	/* data phase crc error */
-#define SCSI_ASCQ_DP_SCSI_PARITY_ERR    0x02	/* data phase scsi parity error
-						 */
-#define SCSI_ASCQ_IU_CRC_ERR            0x03	/* information unit crc error */
-#define SCSI_ASCQ_PROTO_SERV_CRC_ERR    0x05
-
-#define SCSI_ASCQ_LUN_TIME_OUT          0x01
-
-/* ------------------------------------------------------------
- * SCSI INQUIRY
- * ------------------------------------------------------------*/
-
-struct scsi_inquiry_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         reserved1:3;
-	u8         cmd_dt:1;
-	u8         evpd:1;
-#else
-	u8         evpd:1;
-	u8         cmd_dt:1;
-	u8         reserved1:3;
-	u8         lun:3;
-#endif
-	u8         page_code;
-	u8         reserved2;
-	u8         alloc_length;
-	u8         control;
-};
-
-struct scsi_inquiry_vendor_s{
-	u8         vendor_id[8];
-};
-
-struct scsi_inquiry_prodid_s{
-	u8         product_id[16];
-};
-
-struct scsi_inquiry_prodrev_s{
-	u8         product_rev[4];
-};
-
-struct scsi_inquiry_data_s{
-#ifdef __BIGENDIAN
-	u8         peripheral_qual:3;	/* peripheral qualifier */
-	u8         device_type:5;		/* peripheral device type */
-
-	u8         rmb:1;			/* removable medium bit */
-	u8         device_type_mod:7;	/* device type modifier */
-
-	u8         version;
-
-	u8         aenc:1;		/* async event notification capability
-					 */
-	u8         trm_iop:1;	/* terminate I/O process */
-	u8         norm_aca:1;	/* normal ACA supported */
-	u8         hi_support:1;	/* SCSI-3: supports REPORT LUNS */
-	u8         rsp_data_format:4;
-
-	u8         additional_len;
-	u8         sccs:1;
-	u8         reserved1:7;
-
-	u8         reserved2:1;
-	u8         enc_serv:1;	/* enclosure service component */
-	u8         reserved3:1;
-	u8         multi_port:1;	/* multi-port device */
-	u8         m_chngr:1;	/* device in medium transport element */
-	u8         ack_req_q:1;	/* SIP specific bit */
-	u8         addr32:1;	/* SIP specific bit */
-	u8         addr16:1;	/* SIP specific bit */
-
-	u8         rel_adr:1;	/* relative address */
-	u8         w_bus32:1;
-	u8         w_bus16:1;
-	u8         synchronous:1;
-	u8         linked_commands:1;
-	u8         trans_dis:1;
-	u8         cmd_queue:1;	/* command queueing supported */
-	u8         soft_reset:1;	/* soft reset alternative (VS) */
-#else
-	u8         device_type:5;	/* peripheral device type */
-	u8         peripheral_qual:3;
-					/* peripheral qualifier */
-
-	u8         device_type_mod:7;
-					/* device type modifier */
-	u8         rmb:1;		/* removable medium bit */
-
-	u8         version;
-
-	u8         rsp_data_format:4;
-	u8         hi_support:1;	/* SCSI-3: supports REPORT LUNS */
-	u8         norm_aca:1;	/* normal ACA supported */
-	u8         terminate_iop:1;/* terminate I/O process */
-	u8         aenc:1;		/* async event notification capability
-					 */
-
-	u8         additional_len;
-	u8         reserved1:7;
-	u8         sccs:1;
-
-	u8         addr16:1;	/* SIP specific bit */
-	u8         addr32:1;	/* SIP specific bit */
-	u8         ack_req_q:1;	/* SIP specific bit */
-	u8         m_chngr:1;	/* device in medium transport element */
-	u8         multi_port:1;	/* multi-port device */
-	u8         reserved3:1;	/* TBD - Vendor Specific */
-	u8         enc_serv:1;	/* enclosure service component */
-	u8         reserved2:1;
-
-	u8         soft_seset:1;	/* soft reset alternative (VS) */
-	u8         cmd_queue:1;	/* command queueing supported */
-	u8         trans_dis:1;
-	u8         linked_commands:1;
-	u8         synchronous:1;
-	u8         w_bus16:1;
-	u8         w_bus32:1;
-	u8         rel_adr:1;	/* relative address */
-#endif
-	struct scsi_inquiry_vendor_s vendor_id;
-	struct scsi_inquiry_prodid_s product_id;
-	struct scsi_inquiry_prodrev_s product_rev;
-	u8         vendor_specific[20];
-	u8         reserved4[40];
-};
-
-/*
- * inquiry.peripheral_qual field values
- */
-#define SCSI_DEVQUAL_DEFAULT        0
-#define SCSI_DEVQUAL_NOT_CONNECTED  1
-#define SCSI_DEVQUAL_NOT_SUPPORTED  3
-
-/*
- * inquiry.device_type field values
- */
-#define SCSI_DEVICE_DIRECT_ACCESS       0x00
-#define SCSI_DEVICE_SEQ_ACCESS          0x01
-#define SCSI_DEVICE_ARRAY_CONTROLLER    0x0C
-#define SCSI_DEVICE_UNKNOWN             0x1F
-
-/*
- * inquiry.version
- */
-#define SCSI_VERSION_ANSI_X3131     2	/* ANSI X3.131 SCSI-2 */
-#define SCSI_VERSION_SPC            3	/* SPC (SCSI-3), ANSI X3.301:1997 */
-#define SCSI_VERSION_SPC_2          4	/* SPC-2 */
-
-/*
- * response data format
- */
-#define SCSI_RSP_DATA_FORMAT        2	/* SCSI-2 & SPC */
-
-/*
- * SCSI inquiry page codes
- */
-#define SCSI_INQ_PAGE_VPD_PAGES     0x00	/* supported vpd pages */
-#define SCSI_INQ_PAGE_USN_PAGE      0x80	/* unit serial number page */
-#define SCSI_INQ_PAGE_DEV_IDENT     0x83	/* device indentification page
-						 */
-#define SCSI_INQ_PAGES_MAX          3
-
-/*
- * supported vital product data pages
- */
-struct scsi_inq_page_vpd_pages_s{
-#ifdef __BIGENDIAN
-	u8         peripheral_qual:3;
-	u8         device_type:5;
-#else
-	u8         device_type:5;
-	u8         peripheral_qual:3;
-#endif
-	u8         page_code;
-	u8         reserved;
-	u8         page_length;
-	u8         pages[SCSI_INQ_PAGES_MAX];
-};
-
-/*
- * Unit serial number page
- */
-#define SCSI_INQ_USN_LEN 32
-
-struct scsi_inq_usn_s{
-	char            usn[SCSI_INQ_USN_LEN];
-};
-
-struct scsi_inq_page_usn_s{
-#ifdef __BIGENDIAN
-	u8         peripheral_qual:3;
-	u8         device_type:5;
-#else
-	u8         device_type:5;
-	u8         peripheral_qual:3;
-#endif
-	u8         page_code;
-	u8         reserved1;
-	u8         page_length;
-	struct scsi_inq_usn_s  usn;
-};
-
-enum {
-	SCSI_INQ_DIP_CODE_BINARY = 1,	/* identifier has binary value */
-	SCSI_INQ_DIP_CODE_ASCII = 2,	/* identifier has ascii value */
-};
-
-enum {
-	SCSI_INQ_DIP_ASSOC_LUN = 0,	/* id is associated with device */
-	SCSI_INQ_DIP_ASSOC_PORT = 1,	/* id is associated with port that
-					 * received the request
-					 */
-};
-
-enum {
-	SCSI_INQ_ID_TYPE_VENDOR = 1,
-	SCSI_INQ_ID_TYPE_IEEE = 2,
-	SCSI_INQ_ID_TYPE_FC_FS = 3,
-	SCSI_INQ_ID_TYPE_OTHER = 4,
-};
-
-struct scsi_inq_dip_desc_s{
-#ifdef __BIGENDIAN
-	u8         res0:4;
-	u8         code_set:4;
-	u8         res1:2;
-	u8         association:2;
-	u8         id_type:4;
-#else
-	u8         code_set:4;
-	u8         res0:4;
-	u8         id_type:4;
-	u8         association:2;
-	u8         res1:2;
-#endif
-	u8         res2;
-	u8         id_len;
-	struct scsi_lun_sn_s   id;
-};
-
-/*
- * Device indentification page
- */
-struct scsi_inq_page_dev_ident_s{
-#ifdef __BIGENDIAN
-	u8         peripheral_qual:3;
-	u8         device_type:5;
-#else
-	u8         device_type:5;
-	u8         peripheral_qual:3;
-#endif
-	u8         page_code;
-	u8         reserved1;
-	u8         page_length;
-	struct scsi_inq_dip_desc_s desc;
-};
-
-/* ------------------------------------------------------------
- * READ CAPACITY
- * ------------------------------------------------------------
- */
-
-struct scsi_read_capacity_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         reserved1:4;
-	u8         rel_adr:1;
-#else
-	u8         rel_adr:1;
-	u8         reserved1:4;
-	u8         lun:3;
-#endif
-	u8         lba0;	/* MSB */
-	u8         lba1;
-	u8         lba2;
-	u8         lba3;	/* LSB */
-	u8         reserved2;
-	u8         reserved3;
-#ifdef __BIGENDIAN
-	u8         reserved4:7;
-	u8         pmi:1;	/* partial medium indicator */
-#else
-	u8         pmi:1;	/* partial medium indicator */
-	u8         reserved4:7;
-#endif
-	u8         control;
-};
-
-struct scsi_read_capacity_data_s{
-	u32        max_lba;	/* maximum LBA available */
-	u32        block_length;	/* in bytes */
-};
-
-struct scsi_read_capacity16_data_s{
-	u64        lba;	/* maximum LBA available */
-	u32        block_length;	/* in bytes */
-#ifdef __BIGENDIAN
-	u8         reserved1:4,
-			p_type:3,
-			prot_en:1;
-	u8		reserved2:4,
-			lb_pbe:4;	/* logical blocks per physical block
-					 * exponent */
-	u16	reserved3:2,
-			lba_align:14;	/* lowest aligned logical block
-					 * address */
-#else
-	u16	lba_align:14,	/* lowest aligned logical block
-					 * address */
-			reserved3:2;
-	u8		lb_pbe:4,	/* logical blocks per physical block
-					 * exponent */
-			reserved2:4;
-	u8		prot_en:1,
-			p_type:3,
-			reserved1:4;
-#endif
-	u64	reserved4;
-	u64	reserved5;
-};
-
-/* ------------------------------------------------------------
- * REPORT LUNS command
- * ------------------------------------------------------------
- */
-
-struct scsi_report_luns_s{
-	u8         opcode;		/* A0h - REPORT LUNS opCode */
-	u8         reserved1[5];
-	u8         alloc_length[4];/* allocation length MSB first */
-	u8         reserved2;
-	u8         control;
-};
-
-#define SCSI_REPORT_LUN_ALLOC_LENGTH(rl)                		\
-    ((rl->alloc_length[0] << 24) | (rl->alloc_length[1] << 16) | 	\
-     (rl->alloc_length[2] << 8) | (rl->alloc_length[3]))
-
-#define SCSI_REPORT_LUNS_SET_ALLOCLEN(rl, alloc_len) {      \
-    (rl)->alloc_length[0] = (alloc_len) >> 24;      			\
-    (rl)->alloc_length[1] = ((alloc_len) >> 16) & 0xFF; 		\
-    (rl)->alloc_length[2] = ((alloc_len) >> 8) & 0xFF;  		\
-    (rl)->alloc_length[3] = (alloc_len) & 0xFF;     			\
-}
-
-struct scsi_report_luns_data_s{
-	u32        lun_list_length;	/* length of LUN list length */
-	u32        reserved;
-	lun_t           lun[1];			/* first LUN in lun list */
-};
-
-/* -------------------------------------------------------------
- * SCSI mode  parameters
- * -----------------------------------------------------------
- */
-enum {
-	SCSI_DA_MEDIUM_DEF = 0,	/* direct access default medium type */
-	SCSI_DA_MEDIUM_SS = 1,	/* direct access single sided */
-	SCSI_DA_MEDIUM_DS = 2,	/* direct access double sided */
-};
-
-/*
- * SCSI Mode Select(6) cdb
- */
-struct scsi_mode_select6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         pf:1;		/* page format */
-	u8         reserved2:3;
-	u8         sp:1;		/* save pages if set to 1 */
-#else
-	u8         sp:1;	/* save pages if set to 1 */
-	u8         reserved2:3;
-	u8         pf:1;	/* page format */
-	u8         reserved1:3;
-#endif
-	u8         reserved3[2];
-	u8         alloc_len;
-	u8         control;
-};
-
-/*
- * SCSI Mode Select(10) cdb
- */
-struct scsi_mode_select10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         pf:1;	/* page format */
-	u8         reserved2:3;
-	u8         sp:1;	/* save pages if set to 1 */
-#else
-	u8         sp:1;	/* save pages if set to 1 */
-	u8         reserved2:3;
-	u8         pf:1;	/* page format */
-	u8         reserved1:3;
-#endif
-	u8         reserved3[5];
-	u8         alloc_len_msb;
-	u8         alloc_len_lsb;
-	u8         control;
-};
-
-/*
- * SCSI Mode Sense(6) cdb
- */
-struct scsi_mode_sense6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:4;
-	u8         dbd:1;	/* disable block discriptors if set to 1 */
-	u8         reserved2:3;
-
-	u8         pc:2;	/* page control */
-	u8         page_code:6;
-#else
-	u8         reserved2:3;
-	u8         dbd:1;	/* disable block descriptors if set to 1 */
-	u8         reserved1:4;
-
-	u8         page_code:6;
-	u8         pc:2;	/* page control */
-#endif
-	u8         reserved3;
-	u8         alloc_len;
-	u8         control;
-};
-
-/*
- * SCSI Mode Sense(10) cdb
- */
-struct scsi_mode_sense10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         LLBAA:1;	/* long LBA accepted if set to 1 */
-	u8         dbd:1;		/* disable block descriptors if set
-					 * to 1
-					 */
-	u8         reserved2:3;
-
-	u8         pc:2;		/* page control */
-	u8         page_code:6;
-#else
-	u8         reserved2:3;
-	u8         dbd:1;		/* disable block descriptors if set to
-					 * 1
-					 */
-	u8         LLBAA:1;	/* long LBA accepted if set to 1 */
-	u8         reserved1:3;
-
-	u8         page_code:6;
-	u8         pc:2;		/* page control */
-#endif
-	u8         reserved3[4];
-	u8         alloc_len_msb;
-	u8         alloc_len_lsb;
-	u8         control;
-};
-
-#define SCSI_CDB10_GET_AL(cdb)  					\
-    ((cdb)->alloc_len_msb << 8 | (cdb)->alloc_len_lsb)
-
-#define SCSI_CDB10_SET_AL(cdb, al) {      \
-    (cdb)->alloc_len_msb = al >> 8;       				\
-    (cdb)->alloc_len_lsb = al & 0xFF;     				\
-}
-
-#define SCSI_CDB6_GET_AL(cdb) ((cdb)->alloc_len)
-
-#define SCSI_CDB6_SET_AL(cdb, al) {      \
-    (cdb)->alloc_len = al;         					\
-}
-
-/*
- * page control field values
- */
-#define SCSI_PC_CURRENT_VALUES       0x0
-#define SCSI_PC_CHANGEABLE_VALUES    0x1
-#define SCSI_PC_DEFAULT_VALUES       0x2
-#define SCSI_PC_SAVED_VALUES         0x3
-
-/*
- * SCSI mode page codes
- */
-#define SCSI_MP_VENDOR_SPEC     0x00
-#define SCSI_MP_DISC_RECN       0x02	/* disconnect-reconnect page */
-#define SCSI_MP_FORMAT_DEVICE   0x03
-#define SCSI_MP_RDG             0x04	/* rigid disk geometry page */
-#define SCSI_MP_FDP             0x05	/* flexible disk page */
-#define SCSI_MP_CACHING         0x08	/* caching page */
-#define SCSI_MP_CONTROL         0x0A	/* control mode page */
-#define SCSI_MP_MED_TYPES_SUP   0x0B	/* medium types supported page */
-#define SCSI_MP_INFO_EXCP_CNTL  0x1C	/* informational exception control */
-#define SCSI_MP_ALL             0x3F	/* return all pages - mode sense only */
-
-/*
- * mode parameter header
- */
-struct scsi_mode_param_header6_s{
-	u8         mode_datalen;
-	u8         medium_type;
-
-	/*
-	 * device specific parameters expanded for direct access devices
-	 */
-#ifdef __BIGENDIAN
-	u32        wp:1;		/* write protected */
-	u32        reserved1:2;
-	u32        dpofua:1;	/* disable page out + force unit access
-					 */
-	u32        reserved2:4;
-#else
-	u32        reserved2:4;
-	u32        dpofua:1;	/* disable page out + force unit access
-					 */
-	u32        reserved1:2;
-	u32        wp:1;		/* write protected */
-#endif
-
-	u8         block_desclen;
-};
-
-struct scsi_mode_param_header10_s{
-	u32        mode_datalen:16;
-	u32        medium_type:8;
-
-	/*
-	 * device specific parameters expanded for direct access devices
-	 */
-#ifdef __BIGENDIAN
-	u32        wp:1;		/* write protected */
-	u32        reserved1:2;
-	u32        dpofua:1;	/* disable page out + force unit access
-					 */
-	u32        reserved2:4;
-#else
-	u32        reserved2:4;
-	u32        dpofua:1;	/* disable page out + force unit access
-					 */
-	u32        reserved1:2;
-	u32        wp:1;		/* write protected */
-#endif
-
-#ifdef __BIGENDIAN
-	u32        reserved3:7;
-	u32        longlba:1;
-#else
-	u32        longlba:1;
-	u32        reserved3:7;
-#endif
-	u32        reserved4:8;
-	u32        block_desclen:16;
-};
-
-/*
- * mode parameter block descriptor
- */
-struct scsi_mode_param_desc_s{
-	u32        nblks;
-	u32        density_code:8;
-	u32        block_length:24;
-};
-
-/*
- * Disconnect-reconnect mode page format
- */
-struct scsi_mp_disc_recn_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         reserved1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         reserved1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-	u8         buf_full_ratio;
-	u8         buf_empty_ratio;
-
-	u8         bil_msb;	/* bus inactivity limit -MSB */
-	u8         bil_lsb;	/* bus inactivity limit -LSB */
-
-	u8         dtl_msb;	/* disconnect time limit - MSB */
-	u8         dtl_lsb;	/* disconnect time limit - LSB */
-
-	u8         ctl_msb;	/* connect time limit - MSB */
-	u8         ctl_lsb;	/* connect time limit - LSB */
-
-	u8         max_burst_len_msb;
-	u8         max_burst_len_lsb;
-#ifdef __BIGENDIAN
-	u8         emdp:1;	/* enable modify data pointers */
-	u8         fa:3;	/* fair arbitration */
-	u8         dimm:1;	/* disconnect immediate */
-	u8         dtdc:3;	/* data transfer disconnect control */
-#else
-	u8         dtdc:3;	/* data transfer disconnect control */
-	u8         dimm:1;	/* disconnect immediate */
-	u8         fa:3;	/* fair arbitration */
-	u8         emdp:1;	/* enable modify data pointers */
-#endif
-
-	u8         reserved3;
-
-	u8         first_burst_len_msb;
-	u8         first_burst_len_lsb;
-};
-
-/*
- * SCSI format device mode page
- */
-struct scsi_mp_format_device_s{
-#ifdef __BIGENDIAN
-	u32        ps:1;
-	u32        reserved1:1;
-	u32        page_code:6;
-#else
-	u32        page_code:6;
-	u32        reserved1:1;
-	u32        ps:1;
-#endif
-	u32        page_len:8;
-	u32        tracks_per_zone:16;
-
-	u32        a_sec_per_zone:16;
-	u32        a_tracks_per_zone:16;
-
-	u32        a_tracks_per_lun:16;	/* alternate tracks/lun-MSB */
-	u32        sec_per_track:16;	/* sectors/track-MSB */
-
-	u32        bytes_per_sector:16;
-	u32        interleave:16;
-
-	u32        tsf:16;			/* track skew factor-MSB */
-	u32        csf:16;			/* cylinder skew factor-MSB */
-
-#ifdef __BIGENDIAN
-	u32        ssec:1;	/* soft sector formatting */
-	u32        hsec:1;	/* hard sector formatting */
-	u32        rmb:1;	/* removable media */
-	u32        surf:1;	/* surface */
-	u32        reserved2:4;
-#else
-	u32        reserved2:4;
-	u32        surf:1;	/* surface */
-	u32        rmb:1;	/* removable media */
-	u32        hsec:1;	/* hard sector formatting */
-	u32        ssec:1;	/* soft sector formatting */
-#endif
-	u32        reserved3:24;
-};
-
-/*
- * SCSI rigid disk device geometry page
- */
-struct scsi_mp_rigid_device_geometry_s{
-#ifdef __BIGENDIAN
-	u32        ps:1;
-	u32        reserved1:1;
-	u32        page_code:6;
-#else
-	u32        page_code:6;
-	u32        reserved1:1;
-	u32        ps:1;
-#endif
-	u32        page_len:8;
-	u32        num_cylinders0:8;
-	u32        num_cylinders1:8;
-
-	u32        num_cylinders2:8;
-	u32        num_heads:8;
-	u32        scwp0:8;
-	u32        scwp1:8;
-
-	u32        scwp2:8;
-	u32        scrwc0:8;
-	u32        scrwc1:8;
-	u32        scrwc2:8;
-
-	u32        dsr:16;
-	u32        lscyl0:8;
-	u32        lscyl1:8;
-
-	u32        lscyl2:8;
-#ifdef __BIGENDIAN
-	u32        reserved2:6;
-	u32        rpl:2;	/* rotational position locking */
-#else
-	u32        rpl:2;	/* rotational position locking */
-	u32        reserved2:6;
-#endif
-	u32        rot_off:8;
-	u32        reserved3:8;
-
-	u32        med_rot_rate:16;
-	u32        reserved4:16;
-};
-
-/*
- * SCSI caching mode page
- */
-struct scsi_mp_caching_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         res1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         res1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-#ifdef __BIGENDIAN
-	u8         ic:1;	/* initiator control */
-	u8         abpf:1;	/* abort pre-fetch */
-	u8         cap:1;	/* caching analysis permitted */
-	u8         disc:1;	/* discontinuity */
-	u8         size:1;	/* size enable */
-	u8         wce:1;	/* write cache enable */
-	u8         mf:1;	/* multiplication factor */
-	u8         rcd:1;	/* read cache disable */
-
-	u8         drrp:4;	/* demand read retention priority */
-	u8         wrp:4;	/* write retention priority */
-#else
-	u8         rcd:1;	/* read cache disable */
-	u8         mf:1;	/* multiplication factor */
-	u8         wce:1;	/* write cache enable */
-	u8         size:1;	/* size enable */
-	u8         disc:1;	/* discontinuity */
-	u8         cap:1;	/* caching analysis permitted */
-	u8         abpf:1;	/* abort pre-fetch */
-	u8         ic:1;	/* initiator control */
-
-	u8         wrp:4;	/* write retention priority */
-	u8         drrp:4;	/* demand read retention priority */
-#endif
-	u8         dptl[2];/* disable pre-fetch transfer length */
-	u8         min_prefetch[2];
-	u8         max_prefetch[2];
-	u8         max_prefetch_limit[2];
-#ifdef __BIGENDIAN
-	u8         fsw:1;	/* force sequential write */
-	u8         lbcss:1;/* logical block cache segment size */
-	u8         dra:1;	/* disable read ahead */
-	u8         vs:2;	/* vendor specific */
-	u8         res2:3;
-#else
-	u8         res2:3;
-	u8         vs:2;	/* vendor specific */
-	u8         dra:1;	/* disable read ahead */
-	u8         lbcss:1;/* logical block cache segment size */
-	u8         fsw:1;	/* force sequential write */
-#endif
-	u8         num_cache_segs;
-
-	u8         cache_seg_size[2];
-	u8         res3;
-	u8         non_cache_seg_size[3];
-};
-
-/*
- * SCSI control mode page
- */
-struct scsi_mp_control_page_s{
-#ifdef __BIGENDIAN
-u8         ps:1;
-u8         reserved1:1;
-u8         page_code:6;
-#else
-u8         page_code:6;
-u8         reserved1:1;
-u8         ps:1;
-#endif
-	u8         page_len;
-#ifdef __BIGENDIAN
-	u8         tst:3;		/* task set type */
-	u8         reserved3:3;
-	u8         gltsd:1;	/* global logging target save disable */
-	u8         rlec:1;		/* report log exception condition */
-
-	u8         qalgo_mod:4;	/* queue alogorithm modifier */
-	u8         reserved4:1;
-	u8         qerr:2;		/* queue error management */
-	u8         dque:1;		/* disable queuing */
-
-	u8         reserved5:1;
-	u8         rac:1;		/* report a check */
-	u8         reserved6:2;
-	u8         swp:1;		/* software write protect */
-	u8         raerp:1;	/* ready AER permission */
-	u8         uaaerp:1;	/* unit attenstion AER permission */
-	u8         eaerp:1;	/* error AER permission */
-
-	u8         reserved7:5;
-	u8         autoload_mod:3;
-#else
-	u8         rlec:1;		/* report log exception condition */
-	u8         gltsd:1;	/* global logging target save disable */
-	u8         reserved3:3;
-	u8         tst:3;		/* task set type */
-
-	u8         dque:1;		/* disable queuing */
-	u8         qerr:2;		/* queue error management */
-	u8         reserved4:1;
-	u8         qalgo_mod:4;	/* queue alogorithm modifier */
-
-	u8         eaerp:1;	/* error AER permission */
-	u8         uaaerp:1;	/* unit attenstion AER permission */
-	u8         raerp:1;	/* ready AER permission */
-	u8         swp:1;		/* software write protect */
-	u8         reserved6:2;
-	u8         rac:1;		/* report a check */
-	u8         reserved5:1;
-
-	u8         autoload_mod:3;
-	u8         reserved7:5;
-#endif
-	u8         rahp_msb;	/* ready AER holdoff period - MSB */
-	u8         rahp_lsb;	/* ready AER holdoff period - LSB */
-
-	u8         busy_timeout_period_msb;
-	u8         busy_timeout_period_lsb;
-
-	u8         ext_selftest_compl_time_msb;
-	u8         ext_selftest_compl_time_lsb;
-};
-
-/*
- * SCSI medium types supported mode page
- */
-struct scsi_mp_medium_types_sup_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         reserved1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         reserved1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-
-	u8         reserved3[2];
-	u8         med_type1_sup;	/* medium type one supported */
-	u8         med_type2_sup;	/* medium type two supported */
-	u8         med_type3_sup;	/* medium type three supported */
-	u8         med_type4_sup;	/* medium type four supported */
-};
-
-/*
- * SCSI informational exception control mode page
- */
-struct scsi_mp_info_excpt_cntl_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         reserved1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         reserved1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-#ifdef __BIGENDIAN
-	u8         perf:1;		/* performance */
-	u8         reserved3:1;
-	u8         ebf:1;		/* enable background fucntion */
-	u8         ewasc:1;	/* enable warning */
-	u8         dexcpt:1;	/* disable exception control */
-	u8         test:1;		/* enable test device failure
-					 * notification
-					 */
-	u8         reserved4:1;
-	u8         log_error:1;
-
-	u8         reserved5:4;
-	u8         mrie:4;		/* method of reporting info
-					 * exceptions
-					 */
-#else
-	u8         log_error:1;
-	u8         reserved4:1;
-	u8         test:1;		/* enable test device failure
-					 * notification
-					 */
-	u8         dexcpt:1;	/* disable exception control */
-	u8         ewasc:1;	/* enable warning */
-	u8         ebf:1;		/* enable background fucntion */
-	u8         reserved3:1;
-	u8         perf:1;		/* performance */
-
-	u8         mrie:4;		/* method of reporting info
-					 * exceptions
-					 */
-	u8         reserved5:4;
-#endif
-	u8         interval_timer_msb;
-	u8         interval_timer_lsb;
-
-	u8         report_count_msb;
-	u8         report_count_lsb;
-};
-
-/*
- * Methods of reporting informational exceptions
- */
-#define SCSI_MP_IEC_NO_REPORT       0x0	/* no reporting of exceptions */
-#define SCSI_MP_IEC_AER             0x1	/* async event reporting */
-#define SCSI_MP_IEC_UNIT_ATTN       0x2	/* generate unit attenstion */
-#define SCSI_MO_IEC_COND_REC_ERR    0x3	/* conditionally generate recovered
-					 * error
-					 */
-#define SCSI_MP_IEC_UNCOND_REC_ERR  0x4	/* unconditionally generate recovered
-					 * error
-					 */
-#define SCSI_MP_IEC_NO_SENSE        0x5	/* generate no sense */
-#define SCSI_MP_IEC_ON_REQUEST      0x6	/* only report exceptions on request */
-
-/*
- * SCSI flexible disk page
- */
-struct scsi_mp_flexible_disk_s{
-#ifdef __BIGENDIAN
-	u8         ps:1;
-	u8         reserved1:1;
-	u8         page_code:6;
-#else
-	u8         page_code:6;
-	u8         reserved1:1;
-	u8         ps:1;
-#endif
-	u8         page_len;
-
-	u8         transfer_rate_msb;
-	u8         transfer_rate_lsb;
-
-	u8         num_heads;
-	u8         num_sectors;
-
-	u8         bytes_per_sector_msb;
-	u8         bytes_per_sector_lsb;
-
-	u8         num_cylinders_msb;
-	u8         num_cylinders_lsb;
-
-	u8         sc_wpc_msb;	/* starting cylinder-write
-					 * precompensation msb
-					 */
-	u8         sc_wpc_lsb;	/* starting cylinder-write
-					 * precompensation lsb
-					 */
-	u8         sc_rwc_msb;	/* starting cylinder-reduced write
-					 * current msb
-					 */
-	u8         sc_rwc_lsb;	/* starting cylinder-reduced write
-					 * current lsb
-					 */
-
-	u8         dev_step_rate_msb;
-	u8         dev_step_rate_lsb;
-
-	u8         dev_step_pulse_width;
-
-	u8         head_sd_msb;	/* head settle delay msb */
-	u8         head_sd_lsb;	/* head settle delay lsb */
-
-	u8         motor_on_delay;
-	u8         motor_off_delay;
-#ifdef __BIGENDIAN
-	u8         trdy:1;		/* true ready bit */
-	u8         ssn:1;		/* start sector number bit */
-	u8         mo:1;		/* motor on bit */
-	u8         reserved3:5;
-
-	u8         reserved4:4;
-	u8         spc:4;		/* step pulse per cylinder */
-#else
-	u8         reserved3:5;
-	u8         mo:1;		/* motor on bit */
-	u8         ssn:1;		/* start sector number bit */
-	u8         trdy:1;		/* true ready bit */
-
-	u8         spc:4;		/* step pulse per cylinder */
-	u8         reserved4:4;
-#endif
-	u8         write_comp;
-	u8         head_load_delay;
-	u8         head_unload_delay;
-#ifdef __BIGENDIAN
-	u8         pin34:4;	/* pin34 usage */
-	u8         pin2:4;		/* pin2 usage */
-
-	u8         pin4:4;		/* pin4 usage */
-	u8         pin1:4;		/* pin1 usage */
-#else
-	u8         pin2:4;		/* pin2 usage */
-	u8         pin34:4;	/* pin34 usage */
-
-	u8         pin1:4;		/* pin1 usage */
-	u8         pin4:4;		/* pin4 usage */
-#endif
-	u8         med_rot_rate_msb;
-	u8         med_rot_rate_lsb;
-
-	u8         reserved5[2];
-};
-
-struct scsi_mode_page_format_data6_s{
-	struct scsi_mode_param_header6_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_format_device_s format;	/* format device data */
-};
-
-struct scsi_mode_page_format_data10_s{
-	struct scsi_mode_param_header10_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_format_device_s format;	/* format device data */
-};
-
-struct scsi_mode_page_rdg_data6_s{
-	struct scsi_mode_param_header6_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_rigid_device_geometry_s rdg;
-					/* rigid geometry data */
-};
-
-struct scsi_mode_page_rdg_data10_s{
-	struct scsi_mode_param_header10_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_rigid_device_geometry_s rdg;
-					/* rigid geometry data */
-};
-
-struct scsi_mode_page_cache6_s{
-	struct scsi_mode_param_header6_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_caching_s cache;	/* cache page data */
-};
-
-struct scsi_mode_page_cache10_s{
-	struct scsi_mode_param_header10_s mph;	/* mode page header */
-	struct scsi_mode_param_desc_s desc;	/* block descriptor */
-	struct scsi_mp_caching_s cache;	/* cache page data */
-};
-
-/* --------------------------------------------------------------
- * Format Unit command
- * ------------------------------------------------------------
- */
-
-/*
- * Format Unit CDB
- */
-struct scsi_format_unit_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         res1:3;
-	u8         fmtdata:1;	/* if set, data out phase has format
-					 * data
-					 */
-	u8         cmplst:1;	/* if set, defect list is complete */
-	u8         def_list:3;	/* format of defect descriptor is
-					 * fmtdata =1
-					 */
-#else
-	u8         def_list:3;	/* format of defect descriptor is
-					 * fmtdata = 1
-					 */
-	u8         cmplst:1;	/* if set, defect list is complete */
-	u8         fmtdata:1;	/* if set, data out phase has format
-					 * data
-					 */
-	u8         res1:3;
-#endif
-	u8         interleave_msb;
-	u8         interleave_lsb;
-	u8         vendor_spec;
-	u8         control;
-};
-
-/*
- * h
- */
-struct scsi_reserve6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved:3;
-	u8         obsolete:4;
-	u8         extent:1;
-#else
-	u8         extent:1;
-	u8         obsolete:4;
-	u8         reserved:3;
-#endif
-	u8         reservation_id;
-	u16        param_list_len;
-	u8         control;
-};
-
-/*
- * h
- */
-struct scsi_release6_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         obsolete:4;
-	u8         extent:1;
-#else
-	u8         extent:1;
-	u8         obsolete:4;
-	u8         reserved1:3;
-#endif
-	u8         reservation_id;
-	u16        reserved2;
-	u8         control;
-};
-
-/*
- * h
- */
-struct scsi_reserve10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         third_party:1;
-	u8         reserved2:2;
-	u8         long_id:1;
-	u8         extent:1;
-#else
-	u8         extent:1;
-	u8         long_id:1;
-	u8         reserved2:2;
-	u8         third_party:1;
-	u8         reserved1:3;
-#endif
-	u8         reservation_id;
-	u8         third_pty_dev_id;
-	u8         reserved3;
-	u8         reserved4;
-	u8         reserved5;
-	u16        param_list_len;
-	u8         control;
-};
-
-struct scsi_release10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         third_party:1;
-	u8         reserved2:2;
-	u8         long_id:1;
-	u8         extent:1;
-#else
-	u8         extent:1;
-	u8         long_id:1;
-	u8         reserved2:2;
-	u8         third_party:1;
-	u8         reserved1:3;
-#endif
-	u8         reservation_id;
-	u8         third_pty_dev_id;
-	u8         reserved3;
-	u8         reserved4;
-	u8         reserved5;
-	u16        param_list_len;
-	u8         control;
-};
-
-struct scsi_verify10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         dpo:1;
-	u8         reserved:2;
-	u8         bytchk:1;
-	u8         reladdr:1;
-#else
-	u8         reladdr:1;
-	u8         bytchk:1;
-	u8         reserved:2;
-	u8         dpo:1;
-	u8         lun:3;
-#endif
-	u8         lba0;
-	u8         lba1;
-	u8         lba2;
-	u8         lba3;
-	u8         reserved1;
-	u8         verification_len0;
-	u8         verification_len1;
-	u8         control_byte;
-};
-
-struct scsi_request_sense_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         lun:3;
-	u8         reserved:5;
-#else
-	u8         reserved:5;
-	u8         lun:3;
-#endif
-	u8         reserved0;
-	u8         reserved1;
-	u8         alloc_len;
-	u8         control_byte;
-};
-
-/* ------------------------------------------------------------
- * SCSI status byte values
- * ------------------------------------------------------------
- */
-#define SCSI_STATUS_GOOD                   0x00
-#define SCSI_STATUS_CHECK_CONDITION        0x02
-#define SCSI_STATUS_CONDITION_MET          0x04
-#define SCSI_STATUS_BUSY                   0x08
-#define SCSI_STATUS_INTERMEDIATE           0x10
-#define SCSI_STATUS_ICM                    0x14	/* intermediate condition met */
-#define SCSI_STATUS_RESERVATION_CONFLICT   0x18
-#define SCSI_STATUS_COMMAND_TERMINATED     0x22
-#define SCSI_STATUS_QUEUE_FULL             0x28
-#define SCSI_STATUS_ACA_ACTIVE             0x30
-
-#define SCSI_MAX_ALLOC_LEN		0xFF	/* maximum allocarion length
-						 * in CDBs
-						 */
-
-#define SCSI_OP_WRITE_VERIFY10      0x2E
-#define SCSI_OP_WRITE_VERIFY12      0xAE
-#define SCSI_OP_UNDEF               0xFF
-
-/*
- * SCSI WRITE-VERIFY(10) command
- */
-struct scsi_write_verify10_s{
-	u8         opcode;
-#ifdef __BIGENDIAN
-	u8         reserved1:3;
-	u8         dpo:1;		/* Disable Page Out */
-	u8         reserved2:1;
-	u8         ebp:1;		/* erse by-pass */
-	u8         bytchk:1;	/* byte check */
-	u8         rel_adr:1;	/* relative address */
-#else
-	u8         rel_adr:1;	/* relative address */
-	u8         bytchk:1;	/* byte check */
-	u8         ebp:1;		/* erse by-pass */
-	u8         reserved2:1;
-	u8         dpo:1;		/* Disable Page Out */
-	u8         reserved1:3;
-#endif
-	u8         lba0;		/* logical block address - MSB */
-	u8         lba1;
-	u8         lba2;
-	u8         lba3;		/* LSB */
-	u8         reserved3;
-	u8         xfer_length0;	/* transfer length in blocks - MSB */
-	u8         xfer_length1;	/* LSB */
-	u8         control;
-};
-
-#pragma pack()
-
-#endif /* __SCSI_H__ */
diff --git a/drivers/scsi/bfa/include/protocol/types.h b/drivers/scsi/bfa/include/protocol/types.h
deleted file mode 100644
index 2875a6c..0000000
--- a/drivers/scsi/bfa/include/protocol/types.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  types.h Protocol defined base types
- */
-
-#ifndef __TYPES_H__
-#define __TYPES_H__
-
-#include <bfa_os_inc.h>
-
-#define wwn_t u64
-#define lun_t u64
-
-#define WWN_NULL	(0)
-#define FC_SYMNAME_MAX	256	/*  max name server symbolic name size */
-#define FC_ALPA_MAX	128
-
-#pragma pack(1)
-
-#define MAC_ADDRLEN	(6)
-struct mac_s { u8 mac[MAC_ADDRLEN]; };
-#define mac_t struct mac_s
-
-#pragma pack()
-
-#endif
diff --git a/drivers/scsi/bfa/loop.c b/drivers/scsi/bfa/loop.c
deleted file mode 100644
index f6342ef..0000000
--- a/drivers/scsi/bfa/loop.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  port_loop.c vport private loop implementation.
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, LOOP);
-
-/**
- *   ALPA to LIXA bitmap mapping
- *
- *   ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31
- * is for L_bit (login required) and is filled as ALPA 0x00 here.
- */
-static const u8   port_loop_alpa_map[] = {
-	0xEF, 0xE8, 0xE4, 0xE2, 0xE1, 0xE0, 0xDC, 0xDA,	/* Word 3 Bits 0..7 */
-	0xD9, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xCE,	/* Word 3 Bits 8..15 */
-	0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7, 0xC6, 0xC5,	/* Word 3 Bits 16..23 */
-	0xC3, 0xBC, 0xBA, 0xB9, 0xB6, 0xB5, 0xB4, 0xB3,	/* Word 3 Bits 24..31 */
-
-	0xB2, 0xB1, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9,	/* Word 2 Bits 0..7 */
-	0xA7, 0xA6, 0xA5, 0xA3, 0x9F, 0x9E, 0x9D, 0x9B,	/* Word 2 Bits 8..15 */
-	0x98, 0x97, 0x90, 0x8F, 0x88, 0x84, 0x82, 0x81,	/* Word 2 Bits 16..23 */
-	0x80, 0x7C, 0x7A, 0x79, 0x76, 0x75, 0x74, 0x73,	/* Word 2 Bits 24..31 */
-
-	0x72, 0x71, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69,	/* Word 1 Bits 0..7 */
-	0x67, 0x66, 0x65, 0x63, 0x5C, 0x5A, 0x59, 0x56,	/* Word 1 Bits 8..15 */
-	0x55, 0x54, 0x53, 0x52, 0x51, 0x4E, 0x4D, 0x4C,	/* Word 1 Bits 16..23 */
-	0x4B, 0x4A, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3C,	/* Word 1 Bits 24..31 */
-
-	0x3A, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,	/* Word 0 Bits 0..7 */
-	0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x27, 0x26,	/* Word 0 Bits 8..15 */
-	0x25, 0x23, 0x1F, 0x1E, 0x1D, 0x1B, 0x18, 0x17,	/* Word 0 Bits 16..23 */
-	0x10, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00,	/* Word 0 Bits 24..31 */
-};
-
-/*
- * Local Functions
- */
-static bfa_status_t bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port,
-					u8 alpa);
-
-static void bfa_fcs_port_loop_plogi_response(void *fcsarg,
-					struct bfa_fcxp_s *fcxp,
-					void *cbarg,
-					bfa_status_t req_status,
-					u32 rsp_len,
-					u32 resid_len,
-					struct fchs_s *rsp_fchs);
-/**
- *   Called by port to initializar in provate LOOP topology.
- */
-void
-bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
- *   Called by port to notify transition to online state.
- */
-void
-bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port)
-{
-
-	u8         num_alpa = port->port_topo.ploop.num_alpa;
-	u8        *alpa_pos_map = port->port_topo.ploop.alpa_pos_map;
-	struct bfa_fcs_rport_s *r_port;
-	int             ii = 0;
-
-	/*
-	 * If the port role is Initiator Mode, create Rports.
-	 */
-	if (port->port_cfg.roles == BFA_PORT_ROLE_FCP_IM) {
-		/*
-		 * Check if the ALPA positional bitmap is available.
-		 * if not, we send PLOGI to all possible ALPAs.
-		 */
-		if (num_alpa > 0) {
-			for (ii = 0; ii < num_alpa; ii++) {
-				/*
-				 * ignore ALPA of bfa port
-				 */
-				if (alpa_pos_map[ii] != port->pid) {
-					r_port = bfa_fcs_rport_create(port,
-						alpa_pos_map[ii]);
-				}
-			}
-		} else {
-			for (ii = 0; ii < MAX_ALPA_COUNT; ii++) {
-				/*
-				 * ignore ALPA of bfa port
-				 */
-				if ((port_loop_alpa_map[ii] > 0)
-				    && (port_loop_alpa_map[ii] != port->pid))
-					bfa_fcs_port_loop_send_plogi(port,
-						port_loop_alpa_map[ii]);
-				/**TBD */
-			}
-		}
-	} else {
-		/*
-		 * TBD Target Mode ??
-		 */
-	}
-
-}
-
-/**
- *   Called by port to notify transition to offline state.
- */
-void
-bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port)
-{
-
-}
-
-/**
- *   Called by port to notify a LIP on the loop.
- */
-void
-bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
- * Local Functions.
- */
-static bfa_status_t
-bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port, u8 alpa)
-{
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp = NULL;
-	int             len;
-
-	bfa_trc(port->fcs, alpa);
-
-	fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL,
-				  NULL);
-	bfa_assert(fcxp);
-
-	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa,
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-			  FC_CLASS_3, len, &fchs,
-			  bfa_fcs_port_loop_plogi_response, (void *)port,
-			  FC_MAX_PDUSZ, FC_RA_TOV);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *   Called by fcxp to notify the Plogi response
- */
-static void
-bfa_fcs_port_loop_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				 void *cbarg, bfa_status_t req_status,
-				 u32 rsp_len, u32 resid_len,
-				 struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg;
-	struct fc_logi_s     *plogi_resp;
-	struct fc_els_cmd_s   *els_cmd;
-
-	bfa_trc(port->fcs, req_status);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		/*
-		 * @todo
-		 * This could mean that the device with this APLA does not
-		 * exist on the loop.
-		 */
-
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-	plogi_resp = (struct fc_logi_s *) els_cmd;
-
-	if (els_cmd->els_code == FC_ELS_ACC) {
-		bfa_fcs_rport_start(port, rsp_fchs, plogi_resp);
-	} else {
-		bfa_trc(port->fcs, plogi_resp->els_cmd.els_code);
-		bfa_assert(0);
-	}
-}
diff --git a/drivers/scsi/bfa/lport_api.c b/drivers/scsi/bfa/lport_api.c
deleted file mode 100644
index 72b3f50..0000000
--- a/drivers/scsi/bfa/lport_api.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  port_api.c BFA FCS port
- */
-
-#include <fcs/bfa_fcs.h>
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_rport.h>
-#include "fcs_rport.h"
-#include "fcs_fabric.h"
-#include "fcs_trcmod.h"
-#include "fcs_vport.h"
-
-BFA_TRC_FILE(FCS, PORT_API);
-
-
-
-/**
- *  fcs_port_api BFA FCS port API
- */
-
-void
-bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg)
-{
-}
-
-struct bfa_fcs_port_s *
-bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
-{
-	return &fcs->fabric.bport;
-}
-
-wwn_t
-bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn, int index,
-		       int nrports, bfa_boolean_t bwwn)
-{
-	struct list_head *qh, *qe;
-	struct bfa_fcs_rport_s *rport = NULL;
-	int             i;
-	struct bfa_fcs_s *fcs;
-
-	if (port == NULL || nrports == 0)
-		return (wwn_t) 0;
-
-	fcs = port->fcs;
-	bfa_trc(fcs, (u32) nrports);
-
-	i = 0;
-	qh = &port->rport_q;
-	qe = bfa_q_first(qh);
-
-	while ((qe != qh) && (i < nrports)) {
-		rport = (struct bfa_fcs_rport_s *)qe;
-		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
-			qe = bfa_q_next(qe);
-			bfa_trc(fcs, (u32) rport->pwwn);
-			bfa_trc(fcs, rport->pid);
-			bfa_trc(fcs, i);
-			continue;
-		}
-
-		if (bwwn) {
-			if (!memcmp(&wwn, &rport->pwwn, 8))
-				break;
-		} else {
-			if (i == index)
-				break;
-		}
-
-		i++;
-		qe = bfa_q_next(qe);
-	}
-
-	bfa_trc(fcs, i);
-	if (rport)
-		return rport->pwwn;
-	else
-		return (wwn_t) 0;
-}
-
-void
-bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port, wwn_t rport_wwns[],
-			int *nrports)
-{
-	struct list_head *qh, *qe;
-	struct bfa_fcs_rport_s *rport = NULL;
-	int             i;
-	struct bfa_fcs_s *fcs;
-
-	if (port == NULL || rport_wwns == NULL || *nrports == 0)
-		return;
-
-	fcs = port->fcs;
-	bfa_trc(fcs, (u32) *nrports);
-
-	i = 0;
-	qh = &port->rport_q;
-	qe = bfa_q_first(qh);
-
-	while ((qe != qh) && (i < *nrports)) {
-		rport = (struct bfa_fcs_rport_s *)qe;
-		if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) {
-			qe = bfa_q_next(qe);
-			bfa_trc(fcs, (u32) rport->pwwn);
-			bfa_trc(fcs, rport->pid);
-			bfa_trc(fcs, i);
-			continue;
-		}
-
-		rport_wwns[i] = rport->pwwn;
-
-		i++;
-		qe = bfa_q_next(qe);
-	}
-
-	bfa_trc(fcs, i);
-	*nrports = i;
-	return;
-}
-
-/*
- * Iterate's through all the rport's in the given port to
- * determine the maximum operating speed.
- *
- * To be used in TRL Functionality only
- */
-enum bfa_pport_speed
-bfa_fcs_port_get_rport_max_speed(struct bfa_fcs_port_s *port)
-{
-	struct list_head *qh, *qe;
-	struct bfa_fcs_rport_s *rport = NULL;
-	struct bfa_fcs_s *fcs;
-	enum bfa_pport_speed max_speed = 0;
-	struct bfa_pport_attr_s pport_attr;
-	enum bfa_pport_speed pport_speed, rport_speed;
-	bfa_boolean_t     trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
-
-	if (port == NULL)
-		return 0;
-
-	fcs = port->fcs;
-
-	/*
-	 * Get Physical port's current speed
-	 */
-	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
-	pport_speed = pport_attr.speed;
-	bfa_trc(fcs, pport_speed);
-
-	qh = &port->rport_q;
-	qe = bfa_q_first(qh);
-
-	while (qe != qh) {
-		rport = (struct bfa_fcs_rport_s *) qe;
-		if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) ||
-			(bfa_fcs_rport_get_state(rport) ==
-						BFA_RPORT_OFFLINE)) {
-			qe = bfa_q_next(qe);
-			continue;
-		}
-
-		rport_speed = rport->rpf.rpsc_speed;
-		if ((trl_enabled) &&  (rport_speed ==
-						BFA_PPORT_SPEED_UNKNOWN)) {
-			/* Use default ratelim speed setting */
-			rport_speed =
-				bfa_fcport_get_ratelim_speed(port->fcs->bfa);
-		}
-
-		if ((rport_speed  == BFA_PPORT_SPEED_8GBPS) ||
-			(rport_speed > pport_speed)) {
-			max_speed = rport_speed;
-			break;
-		} else if (rport_speed > max_speed) {
-			max_speed = rport_speed;
-		}
-
-		qe = bfa_q_next(qe);
-	}
-
-	bfa_trc(fcs, max_speed);
-	return max_speed;
-}
-
-struct bfa_fcs_port_s *
-bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
-{
-	struct bfa_fcs_vport_s *vport;
-	bfa_fcs_vf_t   *vf;
-
-	bfa_assert(fcs != NULL);
-
-	vf = bfa_fcs_vf_lookup(fcs, vf_id);
-	if (vf == NULL) {
-		bfa_trc(fcs, vf_id);
-		return NULL;
-	}
-
-	if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
-		return &vf->bport;
-
-	vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
-	if (vport)
-		return &vport->lport;
-
-	return NULL;
-}
-
-/*
- *  API corresponding to VmWare's NPIV_VPORT_GETINFO.
- */
-void
-bfa_fcs_port_get_info(struct bfa_fcs_port_s *port,
-		      struct bfa_port_info_s *port_info)
-{
-
-	bfa_trc(port->fcs, port->fabric->fabric_name);
-
-	if (port->vport == NULL) {
-		/*
-		 * This is a Physical port
-		 */
-		port_info->port_type = BFA_PORT_TYPE_PHYSICAL;
-
-		/*
-		 * @todo : need to fix the state & reason
-		 */
-		port_info->port_state = 0;
-		port_info->offline_reason = 0;
-
-		port_info->port_wwn = bfa_fcs_port_get_pwwn(port);
-		port_info->node_wwn = bfa_fcs_port_get_nwwn(port);
-
-		port_info->max_vports_supp =
-			bfa_lps_get_max_vport(port->fcs->bfa);
-		port_info->num_vports_inuse =
-			bfa_fcs_fabric_vport_count(port->fabric);
-		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
-		port_info->num_rports_inuse = port->num_rports;
-	} else {
-		/*
-		 * This is a virtual port
-		 */
-		port_info->port_type = BFA_PORT_TYPE_VIRTUAL;
-
-		/*
-		 * @todo : need to fix the state & reason
-		 */
-		port_info->port_state = 0;
-		port_info->offline_reason = 0;
-
-		port_info->port_wwn = bfa_fcs_port_get_pwwn(port);
-		port_info->node_wwn = bfa_fcs_port_get_nwwn(port);
-	}
-}
-
-void
-bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port,
-		       struct bfa_port_stats_s *port_stats)
-{
-	bfa_os_memcpy(port_stats, &fcs_port->stats,
-		      sizeof(struct bfa_port_stats_s));
-	return;
-}
-
-void
-bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port)
-{
-	bfa_os_memset(&fcs_port->stats, 0, sizeof(struct bfa_port_stats_s));
-	return;
-}
-
-void
-bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port)
-{
-	fcs_port->port_cfg.roles |= BFA_PORT_ROLE_FCP_IPFC;
-	return;
-}
-
-void
-bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port)
-{
-	fcs_port->port_cfg.roles &= ~BFA_PORT_ROLE_FCP_IPFC;
-	return;
-}
-
-
diff --git a/drivers/scsi/bfa/lport_priv.h b/drivers/scsi/bfa/lport_priv.h
deleted file mode 100644
index dbae370..0000000
--- a/drivers/scsi/bfa/lport_priv.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#ifndef __VP_PRIV_H__
-#define __VP_PRIV_H__
-
-#include <fcs/bfa_fcs_lport.h>
-#include <fcs/bfa_fcs_vport.h>
-
-/*
- * Functions exported by vps
- */
-void            bfa_fcs_vport_init(struct bfa_fcs_vport_s *vport);
-
-/*
- * Functions exported by vps
- */
-void            bfa_fcs_vps_online(struct bfa_fcs_port_s *port);
-void            bfa_fcs_vps_offline(struct bfa_fcs_port_s *port);
-void            bfa_fcs_vps_lip(struct bfa_fcs_port_s *port);
-
-/*
- * Functions exported by port_fab
- */
-void            bfa_fcs_port_fab_init(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_fab_online(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_fab_rx_frame(struct bfa_fcs_port_s *port,
-					  u8 *rx_frame, u32 len);
-
-/*
- * Functions exported by VP-NS.
- */
-void            bfa_fcs_port_ns_init(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_ns_online(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port);
-
-/*
- * Functions exported by VP-SCN
- */
-void            bfa_fcs_port_scn_init(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_scn_online(struct bfa_fcs_port_s *vport);
-void            bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port,
-					      struct fchs_s *rx_frame, u32 len);
-
-/*
- * Functions exported by VP-N2N
- */
-
-void            bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_n2n_rx_frame(struct bfa_fcs_port_s *port,
-					  u8 *rx_frame, u32 len);
-
-/*
- * Functions exported by VP-LOOP
- */
-void            bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port);
-void            bfa_fcs_port_loop_rx_frame(struct bfa_fcs_port_s *port,
-					   u8 *rx_frame, u32 len);
-
-#endif /* __VP_PRIV_H__ */
diff --git a/drivers/scsi/bfa/ms.c b/drivers/scsi/bfa/ms.c
deleted file mode 100644
index 1d579ef..0000000
--- a/drivers/scsi/bfa/ms.c
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, MS);
-
-#define BFA_FCS_MS_CMD_MAX_RETRIES  2
-/*
- * forward declarations
- */
-static void     bfa_fcs_port_ms_send_plogi(void *ms_cbarg,
-					   struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ms_timeout(void *arg);
-static void     bfa_fcs_port_ms_plogi_response(void *fcsarg,
-					       struct bfa_fcxp_s *fcxp,
-					       void *cbarg,
-					       bfa_status_t req_status,
-					       u32 rsp_len,
-					       u32 resid_len,
-					       struct fchs_s *rsp_fchs);
-
-static void     bfa_fcs_port_ms_send_gmal(void *ms_cbarg,
-					  struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ms_gmal_response(void *fcsarg,
-					      struct bfa_fcxp_s *fcxp,
-					      void *cbarg,
-					      bfa_status_t req_status,
-					      u32 rsp_len,
-					      u32 resid_len,
-					      struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ms_send_gfn(void *ms_cbarg,
-					 struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ms_gfn_response(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg,
-					     bfa_status_t req_status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rsp_fchs);
-/**
- *  fcs_ms_sm FCS MS state machine
- */
-
-/**
- *  MS State Machine events
- */
-enum port_ms_event {
-	MSSM_EVENT_PORT_ONLINE = 1,
-	MSSM_EVENT_PORT_OFFLINE = 2,
-	MSSM_EVENT_RSP_OK = 3,
-	MSSM_EVENT_RSP_ERROR = 4,
-	MSSM_EVENT_TIMEOUT = 5,
-	MSSM_EVENT_FCXP_SENT = 6,
-	MSSM_EVENT_PORT_FABRIC_RSCN = 7
-};
-
-static void     bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
-					   enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
-						 enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms,
-					 enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
-					       enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
-						enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms,
-					enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
-					      enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
-					       enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms,
-				       enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
-					     enum port_ms_event event);
-static void     bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
-					  enum port_ms_event event);
-/**
- * 		Start in offline state - awaiting NS to send start.
- */
-static void
-bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
-			   enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_PORT_ONLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
-		bfa_fcs_port_ms_send_plogi(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
-				 enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-				       &ms->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_retry);
-		ms->port->stats.ms_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer,
-				bfa_fcs_port_ms_timeout, ms,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case MSSM_EVENT_RSP_OK:
-		/*
-		 * since plogi is done, now invoke MS related sub-modules
-		 */
-		bfa_fcs_port_fdmi_online(ms);
-
-		/**
-		 * if this is a Vport, go to online state.
-		 */
-		if (ms->port->vport) {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
-			break;
-		}
-
-		/*
-		 * For a base port we need to get the
-		 * switch's IP address.
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
-		bfa_fcs_port_ms_send_gmal(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_discard(ms->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
-			       enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
-		bfa_fcs_port_ms_send_plogi(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_timer_stop(&ms->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
-			  enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		break;
-
-	case MSSM_EVENT_PORT_FABRIC_RSCN:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
-		ms->retry_cnt = 0;
-		bfa_fcs_port_ms_send_gfn(ms, NULL);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
-				enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-				       &ms->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry);
-			ms->port->stats.ms_retries++;
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-					&ms->timer, bfa_fcs_port_ms_timeout, ms,
-					BFA_FCS_RETRY_TIMEOUT);
-		} else {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
-			bfa_fcs_port_ms_send_gfn(ms, NULL);
-			ms->retry_cnt = 0;
-		}
-		break;
-
-	case MSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
-		bfa_fcs_port_ms_send_gfn(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_discard(ms->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
-			      enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
-		bfa_fcs_port_ms_send_gmal(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_timer_stop(&ms->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-/**
- *  ms_pvt MS local functions
- */
-
-static void
-bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ms_s *ms = ms_cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-				    bfa_fcs_port_ms_send_gmal, ms);
-		return;
-	}
-	ms->fcxp = fcxp;
-
-	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-				bfa_fcs_port_get_fcid(port),
-				bfa_lps_get_peer_nwwn(port->fabric->lps));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response,
-		      (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_port_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			      void *cbarg, bfa_status_t req_status,
-			      u32 rsp_len, u32 resid_len,
-			      struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-	struct fcgs_gmal_resp_s *gmal_resp;
-	struct fc_gmal_entry_s *gmal_entry;
-	u32        num_entries;
-	u8        *rsp_str;
-
-	bfa_trc(port->fcs, req_status);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
-		num_entries = bfa_os_ntohl(gmal_resp->ms_len);
-		if (num_entries == 0) {
-			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-			return;
-		}
-		/*
-		 * The response could contain multiple Entries.
-		 * Entries for SNMP interface, etc.
-		 * We look for the entry with a telnet prefix.
-		 * First "http://" entry refers to IP addr
-		 */
-
-		gmal_entry = (struct fc_gmal_entry_s *)gmal_resp->ms_ma;
-		while (num_entries > 0) {
-			if (strncmp
-			    (gmal_entry->prefix, CT_GMAL_RESP_PREFIX_HTTP,
-			     sizeof(gmal_entry->prefix)) == 0) {
-
-				/*
-				 * if the IP address is terminating with a '/',
-				 * remove it. *Byte 0 consists of the length
-				 * of the string.
-				 */
-				rsp_str = &(gmal_entry->prefix[0]);
-				if (rsp_str[gmal_entry->len - 1] == '/')
-					rsp_str[gmal_entry->len - 1] = 0;
-				/*
-				 * copy IP Address to fabric
-				 */
-				strncpy(bfa_fcs_port_get_fabric_ipaddr(port),
-					gmal_entry->ip_addr,
-					BFA_FCS_FABRIC_IPADDR_SZ);
-				break;
-			} else {
-				--num_entries;
-				++gmal_entry;
-			}
-		}
-
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-}
-
-static void
-bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
-			       enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-				       &ms->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry);
-			ms->port->stats.ms_retries++;
-			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
-					&ms->timer, bfa_fcs_port_ms_timeout, ms,
-					BFA_FCS_RETRY_TIMEOUT);
-		} else {
-			bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
-			ms->retry_cnt = 0;
-		}
-		break;
-
-	case MSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_fcxp_discard(ms->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
-			     enum port_ms_event event)
-{
-	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
-	bfa_trc(ms->port->fcs, event);
-
-	switch (event) {
-	case MSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
-		bfa_fcs_port_ms_send_gfn(ms, NULL);
-		break;
-
-	case MSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-		bfa_timer_stop(&ms->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ms->port->fcs, event);
-	}
-}
-
-/**
- *  ms_pvt MS local functions
- */
-
-static void
-bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ms_s *ms = ms_cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-				    bfa_fcs_port_ms_send_gfn, ms);
-		return;
-	}
-	ms->fcxp = fcxp;
-
-	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			       bfa_fcs_port_get_fcid(port),
-			       bfa_lps_get_peer_nwwn(port->fabric->lps));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response,
-		      (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_port_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t req_status, u32 rsp_len,
-			       u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct ct_hdr_s       *cthdr = NULL;
-	wwn_t          *gfn_resp;
-
-	bfa_trc(port->fcs, req_status);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		gfn_resp = (wwn_t *) (cthdr + 1);
-		/*
-		 * check if it has actually changed
-		 */
-		if ((memcmp
-		     ((void *)&bfa_fcs_port_get_fabric_name(port), gfn_resp,
-		      sizeof(wwn_t)) != 0))
-			bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-}
-
-/**
- *  ms_pvt MS local functions
- */
-
-static void
-bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ms_s *ms = ms_cbarg;
-	struct bfa_fcs_port_s *port = ms->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ms_plogi_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
-				    bfa_fcs_port_ms_send_plogi, ms);
-		return;
-	}
-	ms->fcxp = fcxp;
-
-	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_os_hton3b(FC_MGMT_SERVER),
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-			     bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response,
-		      (void *)ms, FC_MAX_PDUSZ, FC_ELS_TOV);
-
-	port->stats.ms_plogi_sent++;
-	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_port_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			       void *cbarg, bfa_status_t req_status,
-			       u32 rsp_len, u32 resid_len,
-			       struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
-
-	struct bfa_fcs_port_s *port = ms->port;
-	struct fc_els_cmd_s   *els_cmd;
-	struct fc_ls_rjt_s    *ls_rjt;
-
-	bfa_trc(port->fcs, req_status);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		port->stats.ms_plogi_rsp_err++;
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-	switch (els_cmd->els_code) {
-
-	case FC_ELS_ACC:
-		if (rsp_len < sizeof(struct fc_logi_s)) {
-			bfa_trc(port->fcs, rsp_len);
-			port->stats.ms_plogi_acc_err++;
-			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-			break;
-		}
-		port->stats.ms_plogi_accepts++;
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
-		break;
-
-	case FC_ELS_LS_RJT:
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-		bfa_trc(port->fcs, ls_rjt->reason_code);
-		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
-
-		port->stats.ms_rejects++;
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-		break;
-
-	default:
-		port->stats.ms_plogi_unknown_rsp++;
-		bfa_trc(port->fcs, els_cmd->els_code);
-		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
-	}
-}
-
-static void
-bfa_fcs_port_ms_timeout(void *arg)
-{
-	struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)arg;
-
-	ms->port->stats.ms_timeouts++;
-	bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
-}
-
-
-void
-bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
-	ms->port = port;
-	bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
-
-	/*
-	 * Invoke init routines of sub modules.
-	 */
-	bfa_fcs_port_fdmi_init(ms);
-}
-
-void
-bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
-	ms->port = port;
-	bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
-	bfa_fcs_port_fdmi_offline(ms);
-}
-
-void
-bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
-	ms->port = port;
-	bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
-}
-
-void
-bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
-
-	/*
-	 * @todo.  Handle this only when in Online state
-	 */
-	if (bfa_sm_cmp_state(ms, bfa_fcs_port_ms_sm_online))
-		bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
-}
diff --git a/drivers/scsi/bfa/n2n.c b/drivers/scsi/bfa/n2n.c
deleted file mode 100644
index 7354568..0000000
--- a/drivers/scsi/bfa/n2n.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  n2n.c n2n implementation.
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, N2N);
-
-/**
- *   Called by fcs/port to initialize N2N topology.
- */
-void
-bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port)
-{
-}
-
-/**
- *   Called by fcs/port to notify transition to online state.
- */
-void
-bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n;
-	struct bfa_port_cfg_s *pcfg = &port->port_cfg;
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(port->fcs, pcfg->pwwn);
-
-	/*
-	 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
-	 * and assign an Address. if not, we need to wait for its PLOGI.
-	 *
-	 * If our PWWN is < than that of the remote port, it will send a PLOGI
-	 * with the PIDs assigned. The rport state machine take care of this
-	 * incoming PLOGI.
-	 */
-	if (memcmp
-	    ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
-	     sizeof(wwn_t)) > 0) {
-		port->pid = N2N_LOCAL_PID;
-		/**
-		 * First, check if we know the device by pwwn.
-		 */
-		rport = bfa_fcs_port_get_rport_by_pwwn(port,
-						       n2n_port->rem_port_wwn);
-		if (rport) {
-			bfa_trc(port->fcs, rport->pid);
-			bfa_trc(port->fcs, rport->pwwn);
-			rport->pid = N2N_REMOTE_PID;
-			bfa_fcs_rport_online(rport);
-			return;
-		}
-
-		/*
-		 * In n2n there can be only one rport. Delete the old one whose
-		 * pid should be zero, because it is offline.
-		 */
-		if (port->num_rports > 0) {
-			rport = bfa_fcs_port_get_rport_by_pid(port, 0);
-			bfa_assert(rport != NULL);
-			if (rport) {
-				bfa_trc(port->fcs, rport->pwwn);
-				bfa_fcs_rport_delete(rport);
-			}
-		}
-		bfa_fcs_rport_create(port, N2N_REMOTE_PID);
-	}
-}
-
-/**
- *   Called by fcs/port to notify transition to offline state.
- */
-void
-bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n;
-
-	bfa_trc(port->fcs, port->pid);
-	port->pid = 0;
-	n2n_port->rem_port_wwn = 0;
-	n2n_port->reply_oxid = 0;
-}
-
-
diff --git a/drivers/scsi/bfa/ns.c b/drivers/scsi/bfa/ns.c
deleted file mode 100644
index ae0edcc..0000000
--- a/drivers/scsi/bfa/ns.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- * @page ns_sm_info VPORT NS State Machine
- *
- * @section ns_sm_interactions VPORT NS State Machine Interactions
- *
- * @section ns_sm VPORT NS State Machine
- * 	img ns_sm.jpg
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <bfa_iocfc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, NS);
-
-/*
- * forward declarations
- */
-static void     bfa_fcs_port_ns_send_plogi(void *ns_cbarg,
-					   struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg,
-					     struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_send_rft_id(void *ns_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_send_rff_id(void *ns_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_ns_timeout(void *arg);
-static void     bfa_fcs_port_ns_plogi_response(void *fcsarg,
-					       struct bfa_fcxp_s *fcxp,
-					       void *cbarg,
-					       bfa_status_t req_status,
-					       u32 rsp_len,
-					       u32 resid_len,
-					       struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_rspn_id_response(void *fcsarg,
-						 struct bfa_fcxp_s *fcxp,
-						 void *cbarg,
-						 bfa_status_t req_status,
-						 u32 rsp_len,
-						 u32 resid_len,
-						 struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_rft_id_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_rff_id_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_gid_ft_response(void *fcsarg,
-						struct bfa_fcxp_s *fcxp,
-						void *cbarg,
-						bfa_status_t req_status,
-						u32 rsp_len,
-						u32 resid_len,
-						struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port,
-						   u32 *pid_buf,
-						   u32 n_pids);
-
-static void     bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port);
-/**
- *  fcs_ns_sm FCS nameserver interface state machine
- */
-
-/**
- * VPort NS State Machine events
- */
-enum vport_ns_event {
-	NSSM_EVENT_PORT_ONLINE = 1,
-	NSSM_EVENT_PORT_OFFLINE = 2,
-	NSSM_EVENT_PLOGI_SENT = 3,
-	NSSM_EVENT_RSP_OK = 4,
-	NSSM_EVENT_RSP_ERROR = 5,
-	NSSM_EVENT_TIMEOUT = 6,
-	NSSM_EVENT_NS_QUERY = 7,
-	NSSM_EVENT_RSPNID_SENT = 8,
-	NSSM_EVENT_RFTID_SENT = 9,
-	NSSM_EVENT_RFFID_SENT = 10,
-	NSSM_EVENT_GIDFT_SENT = 11,
-};
-
-static void     bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns,
-					   enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns,
-						 enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns,
-					 enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns,
-					       enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns,
-						   enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns,
-					   enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns,
-						 enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns,
-						  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns,
-						enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns,
-					  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns,
-						  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns,
-						enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns,
-					  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns,
-						  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns,
-					  enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns,
-						enum vport_ns_event event);
-static void     bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns,
-					  enum vport_ns_event event);
-/**
- * 		Start in offline state - awaiting linkup
- */
-static void
-bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns,
-			   enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_PORT_ONLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending);
-		bfa_fcs_port_ns_send_plogi(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns,
-				 enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_PLOGI_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns,
-			 enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id);
-		bfa_fcs_port_ns_send_rspn_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_discard(ns->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns,
-			       enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending);
-		bfa_fcs_port_ns_send_plogi(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns,
-				   enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSPNID_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns,
-			   enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id);
-		bfa_fcs_port_ns_send_rft_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_fcxp_discard(ns->fcxp);
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns,
-				 enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		/*
-		 * Retry Timer Expired. Re-send
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id);
-		bfa_fcs_port_ns_send_rspn_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns,
-				  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RFTID_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns,
-			  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_OK:
-		/*
-		 * Now move to register FC4 Features
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id);
-		bfa_fcs_port_ns_send_rff_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_discard(ns->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns,
-				enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id);
-		bfa_fcs_port_ns_send_rft_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns,
-				  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RFFID_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns,
-			  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_OK:
-
-		/*
-		 * If min cfg mode is enabled, we donot initiate rport
-		 * discovery with the fabric. Instead, we will retrieve the
-		 * boot targets from HAL/FW.
-		 */
-		if (__fcs_min_cfg(ns->port->fcs)) {
-			bfa_fcs_port_ns_boot_target_disc(ns->port);
-			bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
-			return;
-		}
-
-		/*
-		 * If the port role is Initiator Mode issue NS query.
-		 * If it is Target Mode, skip this and go to online.
-		 */
-		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
-			bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
-			bfa_fcs_port_ns_send_gid_ft(ns, NULL);
-		} else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port)) {
-			bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
-		}
-		/*
-		 * kick off mgmt srvr state machine
-		 */
-		bfa_fcs_port_ms_online(ns->port);
-		break;
-
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_discard(ns->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns,
-				enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id);
-		bfa_fcs_port_ns_send_rff_id(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-static void
-bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns,
-				  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_GIDFT_SENT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
-				       &ns->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns,
-			  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_RSP_OK:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online);
-		break;
-
-	case NSSM_EVENT_RSP_ERROR:
-		/*
-		 * TBD: for certain reject codes, we don't need to retry
-		 */
-		/*
-		 * Start timer for a delayed retry
-		 */
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft_retry);
-		ns->port->stats.ns_retries++;
-		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer,
-				bfa_fcs_port_ns_timeout, ns,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_fcxp_discard(ns->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns,
-				enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
-		bfa_fcs_port_ns_send_gid_ft(ns, NULL);
-		break;
-
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		bfa_timer_stop(&ns->timer);
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns,
-			  enum vport_ns_event event)
-{
-	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
-	bfa_trc(ns->port->fcs, event);
-
-	switch (event) {
-	case NSSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-		break;
-
-	case NSSM_EVENT_NS_QUERY:
-		/*
-		 * If the port role is Initiator Mode issue NS query.
-		 * If it is Target Mode, skip this and go to online.
-		 */
-		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
-			bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft);
-			bfa_fcs_port_ns_send_gid_ft(ns, NULL);
-		};
-		break;
-
-	default:
-		bfa_sm_fault(ns->port->fcs, event);
-	}
-}
-
-
-
-/**
- *  ns_pvt Nameserver local functions
- */
-
-static void
-bfa_fcs_port_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_plogi_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_plogi, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_os_hton3b(FC_NAME_SERVER),
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-			     bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_plogi_response,
-		      (void *)ns, FC_MAX_PDUSZ, FC_ELS_TOV);
-	port->stats.ns_plogi_sent++;
-
-	bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
-}
-
-static void
-bfa_fcs_port_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			       void *cbarg, bfa_status_t req_status,
-			       u32 rsp_len, u32 resid_len,
-			       struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	/* struct fc_logi_s *plogi_resp; */
-	struct fc_els_cmd_s   *els_cmd;
-	struct fc_ls_rjt_s    *ls_rjt;
-
-	bfa_trc(port->fcs, req_status);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_plogi_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-	switch (els_cmd->els_code) {
-
-	case FC_ELS_ACC:
-		if (rsp_len < sizeof(struct fc_logi_s)) {
-			bfa_trc(port->fcs, rsp_len);
-			port->stats.ns_plogi_acc_err++;
-			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-			break;
-		}
-		port->stats.ns_plogi_accepts++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		break;
-
-	case FC_ELS_LS_RJT:
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-		bfa_trc(port->fcs, ls_rjt->reason_code);
-		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
-
-		port->stats.ns_rejects++;
-
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		break;
-
-	default:
-		port->stats.ns_plogi_unknown_rsp++;
-		bfa_trc(port->fcs, els_cmd->els_code);
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-	}
-}
-
-/**
- * Register the symbolic port name.
- */
-static void
-bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-	u8         symbl[256];
-	u8        *psymbl = &symbl[0];
-
-	bfa_os_memset(symbl, 0, sizeof(symbl));
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_rspnid_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_rspn_id, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	/*
-	 * for V-Port, form a Port Symbolic Name
-	 */
-	if (port->vport) {
-		/**For Vports,
-		 *  we append the vport's port symbolic name to that of the base port.
-		 */
-
-		strncpy((char *)psymbl,
-			(char *)
-			&(bfa_fcs_port_get_psym_name
-			  (bfa_fcs_get_base_port(port->fcs))),
-			strlen((char *)
-			       &bfa_fcs_port_get_psym_name(bfa_fcs_get_base_port
-							   (port->fcs))));
-
-		/*
-		 * Ensure we have a null terminating string.
-		 */
-		((char *)
-		 psymbl)[strlen((char *)
-				&bfa_fcs_port_get_psym_name
-				(bfa_fcs_get_base_port(port->fcs)))] = 0;
-
-		strncat((char *)psymbl,
-			(char *)&(bfa_fcs_port_get_psym_name(port)),
-			strlen((char *)&bfa_fcs_port_get_psym_name(port)));
-	} else {
-		psymbl = (u8 *) &(bfa_fcs_port_get_psym_name(port));
-	}
-
-	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			      bfa_fcs_port_get_fcid(port), 0, psymbl);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rspn_id_response,
-		      (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	port->stats.ns_rspnid_sent++;
-
-	bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
-}
-
-static void
-bfa_fcs_port_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				 void *cbarg, bfa_status_t req_status,
-				 u32 rsp_len, u32 resid_len,
-				 struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_rspnid_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		port->stats.ns_rspnid_accepts++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	port->stats.ns_rspnid_rejects++;
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-}
-
-/**
- * Register FC4-Types
- * TBD, Need to retrieve this from the OS driver, in case IPFC is enabled ?
- */
-static void
-bfa_fcs_port_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_rftid_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_rft_id, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.roles);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rft_id_response,
-		      (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	port->stats.ns_rftid_sent++;
-	bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
-}
-
-static void
-bfa_fcs_port_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_rftid_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		port->stats.ns_rftid_accepts++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	port->stats.ns_rftid_rejects++;
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-}
-
-/**
-* Register FC4-Features : Should be done after RFT_ID
- */
-static void
-bfa_fcs_port_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-	u8         fc4_ftrs = 0;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_rffid_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_rff_id, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
-		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
-	else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port))
-		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_TARGET;
-
-	len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_fcs_port_get_fcid(port), 0, FC_TYPE_FCP,
-			     fc4_ftrs);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rff_id_response,
-		      (void *)ns, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	port->stats.ns_rffid_sent++;
-	bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
-}
-
-static void
-bfa_fcs_port_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct ct_hdr_s       *cthdr = NULL;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_rffid_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		port->stats.ns_rffid_accepts++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		return;
-	}
-
-	port->stats.ns_rffid_rejects++;
-	bfa_trc(port->fcs, cthdr->reason_code);
-	bfa_trc(port->fcs, cthdr->exp_code);
-
-	if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
-		/*
-		 * if this command is not supported, we don't retry
-		 */
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-	} else {
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-	}
-}
-
-/**
- * Query Fabric for FC4-Types Devices.
- *
-*  TBD : Need to use a local (FCS private) response buffer, since the response
- * can be larger than 2K.
- */
-static void
-bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_ns_s *ns = ns_cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		port->stats.ns_gidft_alloc_wait++;
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
-				    bfa_fcs_port_ns_send_gid_ft, ns);
-		return;
-	}
-	ns->fcxp = fcxp;
-
-	/*
-	 * This query is only initiated for FCP initiator mode.
-	 */
-	len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), ns->port->pid,
-			      FC_TYPE_FCP);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_gid_ft_response,
-		      (void *)ns, bfa_fcxp_get_maxrsp(port->fcs->bfa),
-		      FC_FCCT_TOV);
-
-	port->stats.ns_gidft_sent++;
-
-	bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
-}
-
-static void
-bfa_fcs_port_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-				void *cbarg, bfa_status_t req_status,
-				u32 rsp_len, u32 resid_len,
-				struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg;
-	struct bfa_fcs_port_s *port = ns->port;
-	struct ct_hdr_s       *cthdr = NULL;
-	u32        n_pids;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		port->stats.ns_gidft_rsp_err++;
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	if (resid_len != 0) {
-		/*
-		 * TBD : we will need to allocate a larger buffer & retry the
-		 * command
-		 */
-		bfa_trc(port->fcs, rsp_len);
-		bfa_trc(port->fcs, resid_len);
-		return;
-	}
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	switch (cthdr->cmd_rsp_code) {
-
-	case CT_RSP_ACCEPT:
-
-		port->stats.ns_gidft_accepts++;
-		n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
-		bfa_trc(port->fcs, n_pids);
-		bfa_fcs_port_ns_process_gidft_pids(port,
-						   (u32 *) (cthdr + 1),
-						   n_pids);
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		break;
-
-	case CT_RSP_REJECT:
-
-		/*
-		 * Check the reason code  & explanation.
-		 * There may not have been any FC4 devices in the fabric
-		 */
-		port->stats.ns_gidft_rejects++;
-		bfa_trc(port->fcs, cthdr->reason_code);
-		bfa_trc(port->fcs, cthdr->exp_code);
-
-		if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
-		    && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
-
-			bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
-		} else {
-			/*
-			 * for all other errors, retry
-			 */
-			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-		}
-		break;
-
-	default:
-		port->stats.ns_gidft_unknown_rsp++;
-		bfa_trc(port->fcs, cthdr->cmd_rsp_code);
-		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
-	}
-}
-
-/**
- *     This routine will be called by bfa_timer on timer timeouts.
- *
- * 	param[in] 	port 	- pointer to bfa_fcs_port_t.
- *
- * 	return
- * 		void
- *
-* 	Special Considerations:
- *
- * 	note
- */
-static void
-bfa_fcs_port_ns_timeout(void *arg)
-{
-	struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)arg;
-
-	ns->port->stats.ns_timeouts++;
-	bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
-}
-
-/*
- * Process the PID list in GID_FT response
- */
-static void
-bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port,
-				   u32 *pid_buf, u32 n_pids)
-{
-	struct fcgs_gidft_resp_s *gidft_entry;
-	struct bfa_fcs_rport_s *rport;
-	u32        ii;
-
-	for (ii = 0; ii < n_pids; ii++) {
-		gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
-
-		if (gidft_entry->pid == port->pid)
-			continue;
-
-		/*
-		 * Check if this rport already exists
-		 */
-		rport = bfa_fcs_port_get_rport_by_pid(port, gidft_entry->pid);
-		if (rport == NULL) {
-			/*
-			 * this is a new device. create rport
-			 */
-			rport = bfa_fcs_rport_create(port, gidft_entry->pid);
-		} else {
-			/*
-			 * this rport already exists
-			 */
-			bfa_fcs_rport_scn(rport);
-		}
-
-		bfa_trc(port->fcs, gidft_entry->pid);
-
-		/*
-		 * if the last entry bit is set, bail out.
-		 */
-		if (gidft_entry->last)
-			return;
-	}
-}
-
-/**
- *  fcs_ns_public FCS nameserver public interfaces
- */
-
-/*
- * Functions called by port/fab.
- * These will send relevant Events to the ns state machine.
- */
-void
-bfa_fcs_port_ns_init(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
-	ns->port = port;
-	bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline);
-}
-
-void
-bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
-	ns->port = port;
-	bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
-}
-
-void
-bfa_fcs_port_ns_online(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
-	ns->port = port;
-	bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
-}
-
-void
-bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
-
-	bfa_trc(port->fcs, port->pid);
-	bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
-}
-
-static void
-bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port)
-{
-
-	struct bfa_fcs_rport_s *rport;
-	u8         nwwns;
-	wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
-	int             ii;
-
-	bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
-
-	for (ii = 0; ii < nwwns; ++ii) {
-		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
-		bfa_assert(rport);
-	}
-}
-
-
diff --git a/drivers/scsi/bfa/plog.c b/drivers/scsi/bfa/plog.c
deleted file mode 100644
index fcb8864..0000000
--- a/drivers/scsi/bfa/plog.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa_os_inc.h>
-#include <cs/bfa_plog.h>
-#include <cs/bfa_debug.h>
-
-static int
-plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
-{
-	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT)
-	    && (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
-		return 1;
-
-	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT)
-	    && (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
-		return 1;
-
-	return 0;
-}
-
-static void
-bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
-{
-	u16        tail;
-	struct bfa_plog_rec_s *pl_recp;
-
-	if (plog->plog_enabled == 0)
-		return;
-
-	if (plkd_validate_logrec(pl_rec)) {
-		bfa_assert(0);
-		return;
-	}
-
-	tail = plog->tail;
-
-	pl_recp = &(plog->plog_recs[tail]);
-
-	bfa_os_memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
-
-	pl_recp->tv = BFA_TRC_TS(plog);
-	BFA_PL_LOG_REC_INCR(plog->tail);
-
-	if (plog->head == plog->tail)
-		BFA_PL_LOG_REC_INCR(plog->head);
-}
-
-void
-bfa_plog_init(struct bfa_plog_s *plog)
-{
-	bfa_os_memset((char *)plog, 0, sizeof(struct bfa_plog_s));
-
-	bfa_os_memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
-	plog->head = plog->tail = 0;
-	plog->plog_enabled = 1;
-}
-
-void
-bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-		enum bfa_plog_eid event,
-		u16 misc, char *log_str)
-{
-	struct bfa_plog_rec_s  lp;
-
-	if (plog->plog_enabled) {
-		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-		lp.mid = mid;
-		lp.eid = event;
-		lp.log_type = BFA_PL_LOG_TYPE_STRING;
-		lp.misc = misc;
-		strncpy(lp.log_entry.string_log, log_str,
-			BFA_PL_STRING_LOG_SZ - 1);
-		lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
-		bfa_plog_add(plog, &lp);
-	}
-}
-
-void
-bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-		enum bfa_plog_eid event,
-		u16 misc, u32 *intarr, u32 num_ints)
-{
-	struct bfa_plog_rec_s  lp;
-	u32        i;
-
-	if (num_ints > BFA_PL_INT_LOG_SZ)
-		num_ints = BFA_PL_INT_LOG_SZ;
-
-	if (plog->plog_enabled) {
-		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-		lp.mid = mid;
-		lp.eid = event;
-		lp.log_type = BFA_PL_LOG_TYPE_INT;
-		lp.misc = misc;
-
-		for (i = 0; i < num_ints; i++)
-			bfa_os_assign(lp.log_entry.int_log[i],
-					intarr[i]);
-
-		lp.log_num_ints = (u8) num_ints;
-
-		bfa_plog_add(plog, &lp);
-	}
-}
-
-void
-bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-			enum bfa_plog_eid event,
-			u16 misc, struct fchs_s *fchdr)
-{
-	struct bfa_plog_rec_s  lp;
-	u32       *tmp_int = (u32 *) fchdr;
-	u32        ints[BFA_PL_INT_LOG_SZ];
-
-	if (plog->plog_enabled) {
-		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-
-		ints[0] = tmp_int[0];
-		ints[1] = tmp_int[1];
-		ints[2] = tmp_int[4];
-
-		bfa_plog_intarr(plog, mid, event, misc, ints, 3);
-	}
-}
-
-void
-bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
-		      enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
-		      u32 pld_w0)
-{
-	struct bfa_plog_rec_s  lp;
-	u32       *tmp_int = (u32 *) fchdr;
-	u32        ints[BFA_PL_INT_LOG_SZ];
-
-	if (plog->plog_enabled) {
-		bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
-
-		ints[0] = tmp_int[0];
-		ints[1] = tmp_int[1];
-		ints[2] = tmp_int[4];
-		ints[3] = pld_w0;
-
-		bfa_plog_intarr(plog, mid, event, misc, ints, 4);
-	}
-}
-
-void
-bfa_plog_clear(struct bfa_plog_s *plog)
-{
-	plog->head = plog->tail = 0;
-}
-
-void
-bfa_plog_enable(struct bfa_plog_s *plog)
-{
-	plog->plog_enabled = 1;
-}
-
-void
-bfa_plog_disable(struct bfa_plog_s *plog)
-{
-	plog->plog_enabled = 0;
-}
-
-bfa_boolean_t
-bfa_plog_get_setting(struct bfa_plog_s *plog)
-{
-	return (bfa_boolean_t)plog->plog_enabled;
-}
diff --git a/drivers/scsi/bfa/rport.c b/drivers/scsi/bfa/rport.c
deleted file mode 100644
index 9b4c2c9..0000000
--- a/drivers/scsi/bfa/rport.c
+++ /dev/null
@@ -1,2676 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  rport.c Remote port implementation.
- */
-
-#include <linux/slab.h>
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcbuild.h"
-#include "fcs_vport.h"
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_fcpim.h"
-#include "fcs_fcptm.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include <fcb/bfa_fcb_rport.h>
-#include <aen/bfa_aen_rport.h>
-
-BFA_TRC_FILE(FCS, RPORT);
-
-/* In millisecs */
-static u32 bfa_fcs_rport_del_timeout =
-			BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
-
-/*
- * forward declarations
- */
-static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port,
-						   wwn_t pwwn, u32 rpid);
-static void     bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
-				     struct fc_logi_s *plogi);
-static void     bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport);
-static void     bfa_fcs_rport_timeout(void *arg);
-static void     bfa_fcs_rport_send_plogi(void *rport_cbarg,
-					 struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
-					    struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_plogi_response(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg,
-					     bfa_status_t req_status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rsp_fchs);
-static void     bfa_fcs_rport_send_adisc(void *rport_cbarg,
-					 struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_adisc_response(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg,
-					     bfa_status_t req_status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rsp_fchs);
-static void     bfa_fcs_rport_send_gidpn(void *rport_cbarg,
-					 struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_gidpn_response(void *fcsarg,
-					     struct bfa_fcxp_s *fcxp,
-					     void *cbarg,
-					     bfa_status_t req_status,
-					     u32 rsp_len,
-					     u32 resid_len,
-					     struct fchs_s *rsp_fchs);
-static void     bfa_fcs_rport_send_logo(void *rport_cbarg,
-					struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
-static void     bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len);
-static void     bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u8 reason_code,
-			u8 reason_code_expl);
-static void     bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len);
-static void	bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
-/**
- *  fcs_rport_sm FCS rport state machine events
- */
-
-enum rport_event {
-	RPSM_EVENT_PLOGI_SEND = 1,	/*  new rport; start with PLOGI */
-	RPSM_EVENT_PLOGI_RCVD = 2,	/*  Inbound PLOGI from remote port */
-	RPSM_EVENT_PLOGI_COMP = 3,	/*  PLOGI completed to rport */
-	RPSM_EVENT_LOGO_RCVD = 4,	/*  LOGO from remote device */
-	RPSM_EVENT_LOGO_IMP = 5,	/*  implicit logo for SLER */
-	RPSM_EVENT_FCXP_SENT = 6,	/*  Frame from has been sent */
-	RPSM_EVENT_DELETE = 7,	/*  RPORT delete request */
-	RPSM_EVENT_SCN = 8,	/*  state change notification */
-	RPSM_EVENT_ACCEPTED = 9,/*  Good response from remote device */
-	RPSM_EVENT_FAILED = 10,	/*  Request to rport failed.  */
-	RPSM_EVENT_TIMEOUT = 11,	/*  Rport SM timeout event */
-	RPSM_EVENT_HCB_ONLINE = 12,	/*  BFA rport online callback */
-	RPSM_EVENT_HCB_OFFLINE = 13,	/*  BFA rport offline callback */
-	RPSM_EVENT_FC4_OFFLINE = 14,	/*  FC-4 offline complete */
-	RPSM_EVENT_ADDRESS_CHANGE = 15,	/*  Rport's PID has changed */
-	RPSM_EVENT_ADDRESS_DISC = 16,	/*  Need to Discover rport's PID */
-	RPSM_EVENT_PRLO_RCVD = 17,      /*  PRLO from remote device      */
-};
-
-static void     bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
-					enum rport_event event);
-static void     bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
-					       enum rport_event event);
-static void     bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
-						  enum rport_event event);
-static void     bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
-				       enum rport_event event);
-static void     bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
-					    enum rport_event event);
-static void     bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
-					enum rport_event event);
-static void     bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
-						 enum rport_event event);
-static void     bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
-					 enum rport_event event);
-static void     bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
-					       enum rport_event event);
-static void     bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
-				       enum rport_event event);
-static void     bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
-					      enum rport_event event);
-static void     bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
-					      enum rport_event event);
-static void     bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
-					      enum rport_event event);
-static void     bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
-					 enum rport_event event);
-static void     bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
-						enum rport_event event);
-static void     bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
-					      enum rport_event event);
-static void     bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-static void     bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
-					     enum rport_event event);
-
-static struct bfa_sm_table_s rport_sm_table[] = {
-	{BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
-	{BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
-	{BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
-	{BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
-	{BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
-	{BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
-	{BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
-	{BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
-	{BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
-	{BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
-	{BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
-	{BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
-	{BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
-	{BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
-	{BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
-	{BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
-	{BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
-	{BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
-	{BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
-	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
-	{BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
-	{BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
-};
-
-/**
- * 		Beginning state.
- */
-static void
-bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_PLOGI_SEND:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
-		rport->plogi_retries = 0;
-		bfa_fcs_rport_send_plogi(rport, NULL);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-	case RPSM_EVENT_ADDRESS_DISC:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is being sent.
- */
-static void
-bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
-			       enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_SCN:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is being sent.
- */
-static void
-bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
-				  enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * Ignore, SCN is possibly online notification.
-		 */
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_HCB_OFFLINE:
-		/**
-		 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is sent.
- */
-static void
-bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_SCN:
-		bfa_timer_stop(&rport->timer);
-		/*
-		 * !! fall through !!
-		 */
-
-	case RPSM_EVENT_TIMEOUT:
-		if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
-			rport->plogi_retries++;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
-			bfa_fcs_rport_send_plogi(rport, NULL);
-		} else {
-			rport->pid = 0;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-			bfa_timer_start(rport->fcs->bfa, &rport->timer,
-					bfa_fcs_rport_timeout, rport,
-					bfa_fcs_rport_del_timeout);
-		}
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_LOGO_RCVD:
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_timer_stop(&rport->timer);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_timer_stop(&rport->timer);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is sent.
- */
-static void
-bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_ACCEPTED:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		rport->plogi_retries = 0;
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-		bfa_fcs_rport_send_logo_acc(rport);
-		/*
-		 * !! fall through !!
-		 */
-	case RPSM_EVENT_PRLO_RCVD:
-		if (rport->prlo == BFA_TRUE)
-			bfa_fcs_rport_send_prlo_acc(rport);
-
-		bfa_fcxp_discard(rport->fcxp);
-		/*
-		 * !! fall through !!
-		 */
-	case RPSM_EVENT_FAILED:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * Ignore SCN - wait for PLOGI response.
-		 */
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		PLOGI is complete. Awaiting BFA rport online callback. FC-4s
- * 		are offline.
- */
-static void
-bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_HCB_ONLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
-		bfa_fcs_rport_online_action(rport);
-		break;
-
-	case RPSM_EVENT_PRLO_RCVD:
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_rport_offline(rport->bfa_rport);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * @todo
-		 * Ignore SCN - PLOGI just completed, FC-4 login should detect
-		 * device failures.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is ONLINE. FC-4s active.
- */
-static void
-bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_SCN:
-		/**
-		 * Pause FC-4 activity till rport is authenticated.
-		 * In switched fabrics, check presence of device in nameserver
-		 * first.
-		 */
-		bfa_fcs_rport_fc4_pause(rport);
-
-		if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsquery_sending);
-			rport->ns_retries = 0;
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		} else {
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
-			bfa_fcs_rport_send_adisc(rport, NULL);
-		}
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-	case RPSM_EVENT_LOGO_IMP:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		An SCN event is received in ONLINE state. NS query is being sent
- * 		prior to ADISC authentication with rport. FC-4s are paused.
- */
-static void
-bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
-				 enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * ignore SCN, wait for response to query itself
-		 */
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 	An SCN event is received in ONLINE state. NS query is sent to rport.
- * 	FC-4s are paused.
- */
-static void
-bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_ACCEPTED:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
-		bfa_fcs_rport_send_adisc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_FAILED:
-		rport->ns_retries++;
-		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsquery_sending);
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		} else {
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-			bfa_fcs_rport_offline_action(rport);
-		}
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-	case RPSM_EVENT_PLOGI_RCVD:
-	case RPSM_EVENT_LOGO_IMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 	An SCN event is received in ONLINE state. ADISC is being sent for
- * 	authenticating with rport. FC-4s are paused.
- */
-static void
-bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
-			       enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		An SCN event is received in ONLINE state. ADISC is to rport.
- * 		FC-4s are paused.
- */
-static void
-bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_ACCEPTED:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
-		bfa_fcs_rport_fc4_resume(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		/**
-		 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
-		 * At least go offline when a PLOGI is received.
-		 */
-		bfa_fcxp_discard(rport->fcxp);
-		/*
-		 * !!! fall through !!!
-		 */
-
-	case RPSM_EVENT_FAILED:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * already processing RSCN
-		 */
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_offline_action(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport has sent LOGO. Awaiting FC-4 offline completion callback.
- */
-static void
-bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FC4_OFFLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		LOGO needs to be sent to rport. Awaiting FC-4 offline completion
- * 		callback.
- */
-static void
-bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
-			      enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FC4_OFFLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 	Rport is going offline. Awaiting FC-4 offline completion callback.
- */
-static void
-bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FC4_OFFLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-		bfa_rport_offline(rport->bfa_rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_LOGO_IMP:
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		/**
-		 * rport is already going offline.
-		 * SCN - ignore and wait till transitioning to offline state
-		 */
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
- * 		callback.
- */
-static void
-bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_HCB_OFFLINE:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		if (bfa_fcs_port_is_online(rport->port)) {
-			if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
-				bfa_sm_set_state(rport,
-					bfa_fcs_rport_sm_nsdisc_sending);
-				rport->ns_retries = 0;
-				bfa_fcs_rport_send_gidpn(rport, NULL);
-			} else {
-				bfa_sm_set_state(rport,
-					bfa_fcs_rport_sm_plogi_sending);
-				rport->plogi_retries = 0;
-				bfa_fcs_rport_send_plogi(rport, NULL);
-			}
-		} else {
-			rport->pid = 0;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-			bfa_timer_start(rport->fcs->bfa, &rport->timer,
-					bfa_fcs_rport_timeout, rport,
-					bfa_fcs_rport_del_timeout);
-		}
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		/**
-		 * Ignore, already offline.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is offline. FC-4s are offline. Awaiting BFA rport offline
- * 		callback to send LOGO accept.
- */
-static void
-bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_HCB_OFFLINE:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		if (rport->pid && (rport->prlo == BFA_TRUE))
-			bfa_fcs_rport_send_prlo_acc(rport);
-		if (rport->pid && (rport->prlo == BFA_FALSE))
-			bfa_fcs_rport_send_logo_acc(rport);
-
-		/*
-		 * If the lport is online and if the rport is not a well known
-		 * address port, we try to re-discover the r-port.
-		 */
-		if (bfa_fcs_port_is_online(rport->port)
-		    && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsdisc_sending);
-			rport->ns_retries = 0;
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		} else {
-			/*
-			 * if it is not a well known address, reset the pid to
-			 *
-			 */
-			if (!BFA_FCS_PID_IS_WKA(rport->pid))
-				rport->pid = 0;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-			bfa_timer_start(rport->fcs->bfa, &rport->timer,
-					bfa_fcs_rport_timeout, rport,
-					bfa_fcs_rport_del_timeout);
-		}
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		/**
-		 * Ignore - already processing a LOGO.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline
- * callback to send LOGO.
- */
-static void
-bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
-			      enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_HCB_OFFLINE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
-		bfa_fcs_rport_send_logo(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is being deleted. FC-4s are offline. LOGO is being sent.
- */
-static void
-bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
-			      enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		/*
-		 * Once LOGO is sent, we donot wait for the response
-		 */
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Rport is offline. FC-4s are offline. BFA rport is offline.
- * 		Timer active to delete stale rport.
- */
-static void
-bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		bfa_timer_stop(&rport->timer);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_LOGO_IMP:
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_SEND:
-		bfa_timer_stop(&rport->timer);
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
-		rport->plogi_retries = 0;
-		bfa_fcs_rport_send_plogi(rport, NULL);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 	Rport address has changed. Nameserver discovery request is being sent.
- */
-static void
-bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
-				enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_LOGO_RCVD:
-	case RPSM_EVENT_PRLO_RCVD:
-	case RPSM_EVENT_PLOGI_SEND:
-		break;
-
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		rport->ns_retries = 0;	/* reset the retry count */
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * 		Nameserver discovery failed. Waiting for timeout to retry.
- */
-static void
-bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
-			      enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_SCN:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
-		bfa_timer_stop(&rport->timer);
-		rport->ns_retries = 0;
-		bfa_fcs_rport_send_gidpn(rport, NULL);
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_timer_stop(&rport->timer);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-		bfa_fcs_rport_send_logo_acc(rport);
-		break;
-
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_fcs_rport_send_prlo_acc(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_timer_stop(&rport->timer);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-/**
- * Rport address has changed. Nameserver discovery request is sent.
- */
-static void
-bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
-			enum rport_event event)
-{
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPSM_EVENT_ACCEPTED:
-	case RPSM_EVENT_ADDRESS_CHANGE:
-		if (rport->pid) {
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
-			bfa_fcs_rport_send_plogi(rport, NULL);
-		} else {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsdisc_sending);
-			rport->ns_retries = 0;
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		}
-		break;
-
-	case RPSM_EVENT_FAILED:
-		rport->ns_retries++;
-		if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
-			bfa_sm_set_state(rport,
-					 bfa_fcs_rport_sm_nsdisc_sending);
-			bfa_fcs_rport_send_gidpn(rport, NULL);
-		} else {
-			rport->pid = 0;
-			bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-			bfa_timer_start(rport->fcs->bfa, &rport->timer,
-					bfa_fcs_rport_timeout, rport,
-					bfa_fcs_rport_del_timeout);
-		};
-		break;
-
-	case RPSM_EVENT_DELETE:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_free(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_RCVD:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_send_plogiacc(rport, NULL);
-		break;
-
-	case RPSM_EVENT_LOGO_IMP:
-		rport->pid = 0;
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_timer_start(rport->fcs->bfa, &rport->timer,
-				bfa_fcs_rport_timeout, rport,
-				bfa_fcs_rport_del_timeout);
-		break;
-
-	case RPSM_EVENT_PRLO_RCVD:
-		bfa_fcs_rport_send_prlo_acc(rport);
-		break;
-
-	case RPSM_EVENT_SCN:
-		/**
-		 * ignore, wait for NS query response
-		 */
-		break;
-
-	case RPSM_EVENT_LOGO_RCVD:
-		/**
-		 * Not logged-in yet. Accept LOGO.
-		 */
-		bfa_fcs_rport_send_logo_acc(rport);
-		break;
-
-	case RPSM_EVENT_PLOGI_COMP:
-		bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
-		bfa_fcxp_discard(rport->fcxp);
-		bfa_fcs_rport_hal_online(rport);
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-
-
-/**
- *  fcs_rport_private FCS RPORT provate functions
- */
-
-static void
-bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_plogi, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn,
-			     bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
-		      (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
-
-	rport->stats.plogis++;
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t req_status, u32 rsp_len,
-			     u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	struct fc_logi_s	*plogi_rsp;
-	struct fc_ls_rjt_s	*ls_rjt;
-	struct bfa_fcs_rport_s *twin;
-	struct list_head *qe;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(rport->fcs, req_status);
-		rport->stats.plogi_failed++;
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		return;
-	}
-
-	plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-	/**
-	 * Check for failure first.
-	 */
-	if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-		bfa_trc(rport->fcs, ls_rjt->reason_code);
-		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
-
-		rport->stats.plogi_rejects++;
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		return;
-	}
-
-	/**
-	 * PLOGI is complete. Make sure this device is not one of the known
-	 * device with a new FC port address.
-	 */
-	list_for_each(qe, &rport->port->rport_q) {
-		twin = (struct bfa_fcs_rport_s *)qe;
-		if (twin == rport)
-			continue;
-		if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
-			bfa_trc(rport->fcs, twin->pid);
-			bfa_trc(rport->fcs, rport->pid);
-
-			/*
-			 * Update plogi stats in twin
-			 */
-			twin->stats.plogis += rport->stats.plogis;
-			twin->stats.plogi_rejects += rport->stats.plogi_rejects;
-			twin->stats.plogi_timeouts +=
-				rport->stats.plogi_timeouts;
-			twin->stats.plogi_failed += rport->stats.plogi_failed;
-			twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
-			twin->stats.plogi_accs++;
-
-			bfa_fcs_rport_delete(rport);
-
-			bfa_fcs_rport_update(twin, plogi_rsp);
-			twin->pid = rsp_fchs->s_id;
-			bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
-			return;
-		}
-	}
-
-	/**
-	 * Normal login path -- no evil twins.
-	 */
-	rport->stats.plogi_accs++;
-	bfa_fcs_rport_update(rport, plogi_rsp);
-	bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
-}
-
-static void
-bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->reply_oxid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_plogiacc, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-				 bfa_fcs_port_get_fcid(port), rport->reply_oxid,
-				 port->port_cfg.pwwn, port->port_cfg.nwwn,
-				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_adisc, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-			     bfa_fcs_port_get_fcid(port), 0,
-			     port->port_cfg.pwwn, port->port_cfg.nwwn);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
-		      rport, FC_MAX_PDUSZ, FC_ELS_TOV);
-
-	rport->stats.adisc_sent++;
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t req_status, u32 rsp_len,
-			     u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	void           *pld = bfa_fcxp_get_rspbuf(fcxp);
-	struct fc_ls_rjt_s    *ls_rjt;
-
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(rport->fcs, req_status);
-		rport->stats.adisc_failed++;
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		return;
-	}
-
-	if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
-		rport->nwwn)  == FC_PARSE_OK) {
-		rport->stats.adisc_accs++;
-		bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
-		return;
-	}
-
-	rport->stats.adisc_rejects++;
-	ls_rjt = pld;
-	bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
-	bfa_trc(rport->fcs, ls_rjt->reason_code);
-	bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
-	bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-}
-
-static void
-bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	int             len;
-
-	bfa_trc(rport->fcs, rport->pid);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_gidpn, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			     bfa_fcs_port_get_fcid(port), 0, rport->pwwn);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response,
-		      (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
-
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-static void
-bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			     bfa_status_t req_status, u32 rsp_len,
-			     u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	struct bfa_fcs_rport_s *twin;
-	struct list_head *qe;
-	struct ct_hdr_s       	*cthdr;
-	struct fcgs_gidpn_resp_s	*gidpn_rsp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
-	cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
-
-	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
-		/*
-		 * Check if the pid is the same as before.
-		 */
-		gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
-
-		if (gidpn_rsp->dap == rport->pid) {
-			/*
-			 * Device is online
-			 */
-			bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
-		} else {
-			/*
-			 * Device's PID has changed. We need to cleanup and
-			 * re-login. If there is another device with the the
-			 * newly discovered pid, send an scn notice so that its
-			 * new pid can be discovered.
-			 */
-			list_for_each(qe, &rport->port->rport_q) {
-				twin = (struct bfa_fcs_rport_s *)qe;
-				if (twin == rport)
-					continue;
-				if (gidpn_rsp->dap == twin->pid) {
-					bfa_trc(rport->fcs, twin->pid);
-					bfa_trc(rport->fcs, rport->pid);
-
-					twin->pid = 0;
-					bfa_sm_send_event(twin,
-						RPSM_EVENT_ADDRESS_CHANGE);
-				}
-			}
-			rport->pid = gidpn_rsp->dap;
-			bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
-		}
-		return;
-	}
-
-	/*
-	 * Reject Response
-	 */
-	switch (cthdr->reason_code) {
-	case CT_RSN_LOGICAL_BUSY:
-		/*
-		 * Need to retry
-		 */
-		bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
-		break;
-
-	case CT_RSN_UNABLE_TO_PERF:
-		/*
-		 * device doesn't exist : Start timer to cleanup this later.
-		 */
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		break;
-
-	default:
-		bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
-		break;
-	}
-}
-
-/**
- *    Called to send a logout to the rport.
- */
-static void
-bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port;
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	u16        len;
-
-	bfa_trc(rport->fcs, rport->pid);
-
-	port = rport->port;
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
-				    bfa_fcs_rport_send_logo, rport);
-		return;
-	}
-	rport->fcxp = fcxp;
-
-	len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-			    bfa_fcs_port_get_fcid(port), 0,
-			    bfa_fcs_port_get_pwwn(port));
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ,
-		      FC_ELS_TOV);
-
-	rport->stats.logos++;
-	bfa_fcxp_discard(rport->fcxp);
-	bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
-}
-
-/**
- *    Send ACC for a LOGO received.
- */
-static void
-bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
-{
-	struct bfa_fcs_rport_s *rport = rport_cbarg;
-	struct bfa_fcs_port_s *port;
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	u16        len;
-
-	bfa_trc(rport->fcs, rport->pid);
-
-	port = rport->port;
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	rport->stats.logo_rcvd++;
-	len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-				bfa_fcs_port_get_fcid(port), rport->reply_oxid);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-/**
- *     This routine will be called by bfa_timer on timer timeouts.
- *
- * 	param[in] 	rport 			- pointer to bfa_fcs_port_ns_t.
- * 	param[out]	rport_status 	- pointer to return vport status in
- *
- * 	return
- * 		void
- *
-*  	Special Considerations:
- *
- * 	note
- */
-static void
-bfa_fcs_rport_timeout(void *arg)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg;
-
-	rport->stats.plogi_timeouts++;
-	bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
-}
-
-static void
-bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len)
-{
-	struct bfa_fcxp_s *fcxp;
-	struct fchs_s          fchs;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fc_prli_s      *prli;
-
-	bfa_trc(port->fcs, rx_fchs->s_id);
-	bfa_trc(port->fcs, rx_fchs->d_id);
-
-	rport->stats.prli_rcvd++;
-
-	if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
-		/*
-		 * Target Mode : Let the fcptm handle it
-		 */
-		bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len);
-		return;
-	}
-
-	/*
-	 * We are either in Initiator or ipfc Mode
-	 */
-	prli = (struct fc_prli_s *) (rx_fchs + 1);
-
-	if (prli->parampage.servparams.initiator) {
-		bfa_trc(rport->fcs, prli->parampage.type);
-		rport->scsi_function = BFA_RPORT_INITIATOR;
-		bfa_fcs_itnim_is_initiator(rport->itnim);
-	} else {
-		/*
-		 * @todo: PRLI from a target ?
-		 */
-		bfa_trc(port->fcs, rx_fchs->s_id);
-		rport->scsi_function = BFA_RPORT_TARGET;
-	}
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-				bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-				port->port_cfg.roles);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-static void
-bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len)
-{
-	struct bfa_fcxp_s *fcxp;
-	struct fchs_s          fchs;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fc_rpsc_speed_info_s speeds;
-	struct bfa_pport_attr_s pport_attr;
-
-	bfa_trc(port->fcs, rx_fchs->s_id);
-	bfa_trc(port->fcs, rx_fchs->d_id);
-
-	rport->stats.rpsc_rcvd++;
-	speeds.port_speed_cap =
-		RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
-		RPSC_SPEED_CAP_8G;
-
-	/*
-	 * get curent speed from pport attributes from BFA
-	 */
-	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
-
-	speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-				bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-				&speeds);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-static void
-bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
-			struct fchs_s *rx_fchs, u16 len)
-{
-	struct bfa_fcxp_s *fcxp;
-	struct fchs_s          fchs;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fc_adisc_s      *adisc;
-
-	bfa_trc(port->fcs, rx_fchs->s_id);
-	bfa_trc(port->fcs, rx_fchs->d_id);
-
-	rport->stats.adisc_rcvd++;
-
-	if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
-		/*
-		 * @todo : Target Mode handling
-		 */
-		bfa_trc(port->fcs, rx_fchs->d_id);
-		bfa_assert(0);
-		return;
-	}
-
-	adisc = (struct fc_adisc_s *) (rx_fchs + 1);
-
-	/*
-	 * Accept if the itnim for this rport is online. Else reject the ADISC
-	 */
-	if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
-
-		fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-		if (!fcxp)
-			return;
-
-		len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-					 rx_fchs->s_id,
-					 bfa_fcs_port_get_fcid(port),
-					 rx_fchs->ox_id, port->port_cfg.pwwn,
-					 port->port_cfg.nwwn);
-
-		bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
-			      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
-			      FC_MAX_PDUSZ, 0);
-	} else {
-		rport->stats.adisc_rejected++;
-		bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
-					  FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
-					  FC_LS_RJT_EXP_LOGIN_REQUIRED);
-	}
-
-}
-
-static void
-bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-	struct bfa_rport_info_s rport_info;
-
-	rport_info.pid = rport->pid;
-	rport_info.local_pid = port->pid;
-	rport_info.lp_tag = port->lp_tag;
-	rport_info.vf_id = port->fabric->vf_id;
-	rport_info.vf_en = port->fabric->is_vf;
-	rport_info.fc_class = rport->fc_cos;
-	rport_info.cisc = rport->cisc;
-	rport_info.max_frmsz = rport->maxfrsize;
-	bfa_rport_online(rport->bfa_rport, &rport_info);
-}
-
-static void
-bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport)
-{
-	if (bfa_fcs_port_is_initiator(rport->port))
-		bfa_fcs_itnim_pause(rport->itnim);
-
-	if (bfa_fcs_port_is_target(rport->port))
-		bfa_fcs_tin_pause(rport->tin);
-}
-
-static void
-bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport)
-{
-	if (bfa_fcs_port_is_initiator(rport->port))
-		bfa_fcs_itnim_resume(rport->itnim);
-
-	if (bfa_fcs_port_is_target(rport->port))
-		bfa_fcs_tin_resume(rport->tin);
-}
-
-static struct bfa_fcs_rport_s *
-bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
-{
-	struct bfa_fcs_s *fcs = port->fcs;
-	struct bfa_fcs_rport_s *rport;
-	struct bfad_rport_s *rport_drv;
-
-	/**
-	 * allocate rport
-	 */
-	if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
-	    != BFA_STATUS_OK) {
-		bfa_trc(fcs, rpid);
-		return NULL;
-	}
-
-	/*
-	 * Initialize r-port
-	 */
-	rport->port = port;
-	rport->fcs = fcs;
-	rport->rp_drv = rport_drv;
-	rport->pid = rpid;
-	rport->pwwn = pwwn;
-
-	/**
-	 * allocate BFA rport
-	 */
-	rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
-	if (!rport->bfa_rport) {
-		bfa_trc(fcs, rpid);
-		kfree(rport_drv);
-		return NULL;
-	}
-
-	/**
-	 * allocate FC-4s
-	 */
-	bfa_assert(bfa_fcs_port_is_initiator(port) ^
-		   bfa_fcs_port_is_target(port));
-
-	if (bfa_fcs_port_is_initiator(port)) {
-		rport->itnim = bfa_fcs_itnim_create(rport);
-		if (!rport->itnim) {
-			bfa_trc(fcs, rpid);
-			bfa_rport_delete(rport->bfa_rport);
-			kfree(rport_drv);
-			return NULL;
-		}
-	}
-
-	if (bfa_fcs_port_is_target(port)) {
-		rport->tin = bfa_fcs_tin_create(rport);
-		if (!rport->tin) {
-			bfa_trc(fcs, rpid);
-			bfa_rport_delete(rport->bfa_rport);
-			kfree(rport_drv);
-			return NULL;
-		}
-	}
-
-	bfa_fcs_port_add_rport(port, rport);
-
-	bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
-
-	/*
-	 * Initialize the Rport Features(RPF) Sub Module
-	 */
-	if (!BFA_FCS_PID_IS_WKA(rport->pid))
-		bfa_fcs_rpf_init(rport);
-
-	return rport;
-}
-
-
-static void
-bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-
-	/**
-	 * - delete FC-4s
-	 * - delete BFA rport
-	 * - remove from queue of rports
-	 */
-	if (bfa_fcs_port_is_initiator(port))
-		bfa_fcs_itnim_delete(rport->itnim);
-
-	if (bfa_fcs_port_is_target(port))
-		bfa_fcs_tin_delete(rport->tin);
-
-	bfa_rport_delete(rport->bfa_rport);
-	bfa_fcs_port_del_rport(port, rport);
-	kfree(rport->rp_drv);
-}
-
-static void
-bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
-		       enum bfa_rport_aen_event event,
-		       struct bfa_rport_aen_data_s *data)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = rport->fcs->logm;
-	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(rport->port);
-	wwn_t           rpwwn = rport->pwwn;
-	char            lpwwn_ptr[BFA_STRING_32];
-	char            rpwwn_ptr[BFA_STRING_32];
-	char           *prio_str[] = { "unknown", "high", "medium", "low" };
-
-	wwn2str(lpwwn_ptr, lpwwn);
-	wwn2str(rpwwn_ptr, rpwwn);
-
-	switch (event) {
-	case BFA_RPORT_AEN_ONLINE:
-	case BFA_RPORT_AEN_OFFLINE:
-	case BFA_RPORT_AEN_DISCONNECT:
-		bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, event),
-			rpwwn_ptr, lpwwn_ptr);
-		break;
-	case BFA_RPORT_AEN_QOS_PRIO:
-		aen_data.rport.priv.qos = data->priv.qos;
-		bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO,
-			prio_str[aen_data.rport.priv.qos.qos_priority],
-			rpwwn_ptr, lpwwn_ptr);
-		break;
-	case BFA_RPORT_AEN_QOS_FLOWID:
-		aen_data.rport.priv.qos = data->priv.qos;
-		bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID,
-			aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr,
-			lpwwn_ptr);
-		break;
-	default:
-		break;
-	}
-
-	aen_data.rport.vf_id = rport->port->fabric->vf_id;
-	aen_data.rport.ppwwn =
-		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs));
-	aen_data.rport.lpwwn = lpwwn;
-	aen_data.rport.rpwwn = rpwwn;
-}
-
-static void
-bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-
-	rport->stats.onlines++;
-
-	if (bfa_fcs_port_is_initiator(port)) {
-		bfa_fcs_itnim_rport_online(rport->itnim);
-		if (!BFA_FCS_PID_IS_WKA(rport->pid))
-			bfa_fcs_rpf_rport_online(rport);
-	};
-
-	if (bfa_fcs_port_is_target(port))
-		bfa_fcs_tin_rport_online(rport->tin);
-
-	/*
-	 * Don't post events for well known addresses
-	 */
-	if (!BFA_FCS_PID_IS_WKA(rport->pid))
-		bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
-}
-
-static void
-bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-
-	rport->stats.offlines++;
-
-	/*
-	 * Don't post events for well known addresses
-	 */
-	if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
-		if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) {
-			bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT,
-					       NULL);
-		} else {
-			bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE,
-					       NULL);
-		}
-	}
-
-	if (bfa_fcs_port_is_initiator(port)) {
-		bfa_fcs_itnim_rport_offline(rport->itnim);
-		if (!BFA_FCS_PID_IS_WKA(rport->pid))
-			bfa_fcs_rpf_rport_offline(rport);
-	}
-
-	if (bfa_fcs_port_is_target(port))
-		bfa_fcs_tin_rport_offline(rport->tin);
-}
-
-/**
- * Update rport parameters from PLOGI or PLOGI accept.
- */
-static void
-bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-
-	/**
-	 * - port name
-	 * - node name
-	 */
-	rport->pwwn = plogi->port_name;
-	rport->nwwn = plogi->node_name;
-
-	/**
-	 * - class of service
-	 */
-	rport->fc_cos = 0;
-	if (plogi->class3.class_valid)
-		rport->fc_cos = FC_CLASS_3;
-
-	if (plogi->class2.class_valid)
-		rport->fc_cos |= FC_CLASS_2;
-
-	/**
-	 * - CISC
-	 * - MAX receive frame size
-	 */
-	rport->cisc = plogi->csp.cisc;
-	rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
-
-	bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
-	bfa_trc(port->fcs, port->fabric->bb_credit);
-	/**
-	 * Direct Attach P2P mode :
-	 * This is to handle a bug (233476) in IBM targets in Direct Attach
-	 * Mode. Basically, in FLOGI Accept the target would have erroneously
-	 * set the BB Credit to the value used in the FLOGI sent by the HBA.
-	 * It uses the correct value (its own BB credit) in PLOGI.
-	 */
-	if ((!bfa_fcs_fabric_is_switched(port->fabric))
-	    && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
-
-		bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
-		bfa_trc(port->fcs, port->fabric->bb_credit);
-
-		port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
-		bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
-					  port->fabric->bb_credit);
-	}
-
-}
-
-/**
- *   Called to handle LOGO received from an existing remote port.
- */
-static void
-bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
-{
-	rport->reply_oxid = fchs->ox_id;
-	bfa_trc(rport->fcs, rport->reply_oxid);
-
-	rport->prlo = BFA_FALSE;
-	rport->stats.logo_rcvd++;
-	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
-}
-
-
-
-/**
- *  fcs_rport_public FCS rport public interfaces
- */
-
-/**
- * 	Called by bport/vport to create a remote port instance for a discovered
- * 	remote device.
- *
- * @param[in] port	- base port or vport
- * @param[in] rpid	- remote port ID
- *
- * @return None
- */
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(port->fcs, rpid);
-	rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
-	if (!rport)
-		return NULL;
-
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
-	return rport;
-}
-
-/**
- * Called to create a rport for which only the wwn is known.
- *
- * @param[in] port	- base port
- * @param[in] rpwwn	- remote port wwn
- *
- * @return None
- */
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(port->fcs, rpwwn);
-	rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
-	if (!rport)
-		return NULL;
-
-	bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
-	return rport;
-}
-
-/**
- * Called by bport in private loop topology to indicate that a
- * rport has been discovered and plogi has been completed.
- *
- * @param[in] port	- base port or vport
- * @param[in] rpid	- remote port ID
- */
-void
-bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
-			struct fc_logi_s *plogi)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
-	if (!rport)
-		return;
-
-	bfa_fcs_rport_update(rport, plogi);
-
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
-}
-
-/**
- *   Called by bport/vport to handle PLOGI received from a new remote port.
- *   If an existing rport does a plogi, it will be handled separately.
- */
-void
-bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
-			   struct fc_logi_s *plogi)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
-	if (!rport)
-		return;
-
-	bfa_fcs_rport_update(rport, plogi);
-
-	rport->reply_oxid = fchs->ox_id;
-	bfa_trc(rport->fcs, rport->reply_oxid);
-
-	rport->stats.plogi_rcvd++;
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
-}
-
-static int
-wwn_compare(wwn_t wwn1, wwn_t wwn2)
-{
-	u8        *b1 = (u8 *) &wwn1;
-	u8        *b2 = (u8 *) &wwn2;
-	int             i;
-
-	for (i = 0; i < sizeof(wwn_t); i++) {
-		if (b1[i] < b2[i])
-			return -1;
-		if (b1[i] > b2[i])
-			return 1;
-	}
-	return 0;
-}
-
-/**
- *   Called by bport/vport to handle PLOGI received from an existing
- * 	 remote port.
- */
-void
-bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
-		    struct fc_logi_s *plogi)
-{
-	/**
-	 * @todo Handle P2P and initiator-initiator.
-	 */
-
-	bfa_fcs_rport_update(rport, plogi);
-
-	rport->reply_oxid = rx_fchs->ox_id;
-	bfa_trc(rport->fcs, rport->reply_oxid);
-
-	/**
-	 * In Switched fabric topology,
-	 * PLOGI to each other. If our pwwn is smaller, ignore it,
-	 * if it is not a well known address.
-	 * If the link topology is N2N,
-	 * this Plogi should be accepted.
-	 */
-	if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1)
-	    && (bfa_fcs_fabric_is_switched(rport->port->fabric))
-	    && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
-		bfa_trc(rport->fcs, rport->pid);
-		return;
-	}
-
-	rport->stats.plogi_rcvd++;
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
-}
-
-/**
- * Called by bport/vport to delete a remote port instance.
- *
-* Rport delete is called under the following conditions:
- * 		- vport is deleted
- * 		- vf is deleted
- * 		- explicit request from OS to delete rport (vmware)
- */
-void
-bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
-}
-
-/**
- * Called by bport/vport to  when a target goes offline.
- *
- */
-void
-bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
-}
-
-/**
- * Called by bport in n2n when a target (attached port) becomes online.
- *
- */
-void
-bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
-}
-
-/**
- *   Called by bport/vport to notify SCN for the remote port
- */
-void
-bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
-{
-
-	rport->stats.rscns++;
-	bfa_sm_send_event(rport, RPSM_EVENT_SCN);
-}
-
-/**
- *   Called by  fcpim to notify that the ITN cleanup is done.
- */
-void
-bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
-}
-
-/**
- *   Called by fcptm to notify that the ITN cleanup is done.
- */
-void
-bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
-}
-
-/**
- *     This routine BFA callback for bfa_rport_online() call.
- *
- * 	param[in] 	cb_arg	-  rport struct.
- *
- * 	return
- * 		void
- *
-* 	Special Considerations:
- *
- * 	note
- */
-void
-bfa_cb_rport_online(void *cbarg)
-{
-
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
-}
-
-/**
- *     This routine BFA callback for bfa_rport_offline() call.
- *
- * 	param[in] 	rport 	-
- *
- * 	return
- * 		void
- *
- * 	Special Considerations:
- *
- * 	note
- */
-void
-bfa_cb_rport_offline(void *cbarg)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
-}
-
-/**
- * This routine is a static BFA callback when there is a QoS flow_id
- * change notification
- *
- * @param[in] 	rport 	-
- *
- * @return  	void
- *
- * Special Considerations:
- *
- * @note
- */
-void
-bfa_cb_rport_qos_scn_flowid(void *cbarg,
-			    struct bfa_rport_qos_attr_s old_qos_attr,
-			    struct bfa_rport_qos_attr_s new_qos_attr)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	struct bfa_rport_aen_data_s aen_data;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	aen_data.priv.qos = new_qos_attr;
-	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
-}
-
-/**
- * This routine is a static BFA callback when there is a QoS priority
- * change notification
- *
- * @param[in] 	rport 	-
- *
- * @return 	void
- *
- * Special Considerations:
- *
- * @note
- */
-void
-bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr,
-			  struct bfa_rport_qos_attr_s new_qos_attr)
-{
-	struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
-	struct bfa_rport_aen_data_s aen_data;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	aen_data.priv.qos = new_qos_attr;
-	bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
-}
-
-/**
- * 		Called to process any unsolicted frames from this remote port
- */
-void
-bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
-{
-	bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
-}
-
-/**
- * 		Called to process any unsolicted frames from this remote port
- */
-void
-bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
-			u16 len)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fc_els_cmd_s   *els_cmd;
-
-	bfa_trc(rport->fcs, fchs->s_id);
-	bfa_trc(rport->fcs, fchs->d_id);
-	bfa_trc(rport->fcs, fchs->type);
-
-	if (fchs->type != FC_TYPE_ELS)
-		return;
-
-	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
-
-	bfa_trc(rport->fcs, els_cmd->els_code);
-
-	switch (els_cmd->els_code) {
-	case FC_ELS_LOGO:
-		bfa_fcs_rport_process_logo(rport, fchs);
-		break;
-
-	case FC_ELS_ADISC:
-		bfa_fcs_rport_process_adisc(rport, fchs, len);
-		break;
-
-	case FC_ELS_PRLO:
-		if (bfa_fcs_port_is_initiator(port))
-			bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
-
-		if (bfa_fcs_port_is_target(port))
-			bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len);
-		break;
-
-	case FC_ELS_PRLI:
-		bfa_fcs_rport_process_prli(rport, fchs, len);
-		break;
-
-	case FC_ELS_RPSC:
-		bfa_fcs_rport_process_rpsc(rport, fchs, len);
-		break;
-
-	default:
-		bfa_fcs_rport_send_ls_rjt(rport, fchs,
-					  FC_LS_RJT_RSN_CMD_NOT_SUPP,
-					  FC_LS_RJT_EXP_NO_ADDL_INFO);
-		break;
-	}
-}
-
-/* Send best case acc to prlo */
-static void
-bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s fchs;
-	struct bfa_fcxp_s *fcxp;
-	int len;
-
-	bfa_trc(rport->fcs, rport->pid);
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-			rport->pid, bfa_fcs_port_get_fcid(port),
-			rport->reply_oxid, 0);
-
-	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
-			port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
-			NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-/*
- * Send a LS reject
- */
-static void
-bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
-			  u8 reason_code, u8 reason_code_expl)
-{
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	int             len;
-
-	bfa_trc(rport->fcs, rx_fchs->s_id);
-
-	fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
-			      reason_code, reason_code_expl);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
-}
-
-/**
- * Return state of rport.
- */
-int
-bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
-{
-	return bfa_sm_to_state(rport_sm_table, rport->sm);
-}
-
-/**
- * 		 Called by the Driver to set rport delete/ageout timeout
- *
- * 	param[in]		rport timeout value in seconds.
- *
- * 	return None
- */
-void
-bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
-{
-	/*
-	 * convert to Millisecs
-	 */
-	if (rport_tmo > 0)
-		bfa_fcs_rport_del_timeout = rport_tmo * 1000;
-}
-
-void
-bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id)
-{
-	bfa_trc(rport->fcs, rport->pid);
-
-	rport->prlo = BFA_TRUE;
-	rport->reply_oxid = ox_id;
-	bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
-}
diff --git a/drivers/scsi/bfa/rport_api.c b/drivers/scsi/bfa/rport_api.c
deleted file mode 100644
index 15e0c47..0000000
--- a/drivers/scsi/bfa/rport_api.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_vport.h"
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_trcmod.h"
-
-BFA_TRC_FILE(FCS, RPORT_API);
-
-/**
- *  rport_api.c Remote port implementation.
- */
-
-/**
- *  fcs_rport_api FCS rport API.
- */
-
-/**
- * 	Direct API to add a target by port wwn. This interface is used, for
- *	example, by bios when target pwwn is known from boot lun configuration.
- */
-bfa_status_t
-bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn,
-			struct bfa_fcs_rport_s *rport,
-			struct bfad_rport_s *rport_drv)
-{
-	bfa_trc(port->fcs, *pwwn);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *	Direct API to remove a target and its associated resources. This
- *	interface is used, for example, by vmware driver to remove target
- *	ports from the target list for a VM.
- */
-bfa_status_t
-bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
-{
-
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(rport_in->fcs, rport_in->pwwn);
-
-	rport = bfa_fcs_port_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
-	if (rport == NULL) {
-		/*
-		 * TBD Error handling
-		 */
-		bfa_trc(rport_in->fcs, rport_in->pid);
-		return BFA_STATUS_UNKNOWN_RWWN;
-	}
-
-	/*
-	 * TBD if this remote port is online, send a logo
-	 */
-	return BFA_STATUS_OK;
-
-}
-
-/**
- *	Remote device status for display/debug.
- */
-void
-bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_attr_s *rport_attr)
-{
-	struct bfa_rport_qos_attr_s qos_attr;
-	struct bfa_fcs_port_s *port = rport->port;
-	enum bfa_pport_speed rport_speed = rport->rpf.rpsc_speed;
-
-	bfa_os_memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
-
-	rport_attr->pid = rport->pid;
-	rport_attr->pwwn = rport->pwwn;
-	rport_attr->nwwn = rport->nwwn;
-	rport_attr->cos_supported = rport->fc_cos;
-	rport_attr->df_sz = rport->maxfrsize;
-	rport_attr->state = bfa_fcs_rport_get_state(rport);
-	rport_attr->fc_cos = rport->fc_cos;
-	rport_attr->cisc = rport->cisc;
-	rport_attr->scsi_function = rport->scsi_function;
-	rport_attr->curr_speed  = rport->rpf.rpsc_speed;
-	rport_attr->assigned_speed  = rport->rpf.assigned_speed;
-
-	bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
-	rport_attr->qos_attr = qos_attr;
-
-	rport_attr->trl_enforced = BFA_FALSE;
-
-	if (bfa_fcport_is_ratelim(port->fcs->bfa)) {
-		if (rport_speed == BFA_PPORT_SPEED_UNKNOWN) {
-			/* Use default ratelim speed setting */
-			rport_speed =
-				bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
-		}
-		if (rport_speed < bfa_fcs_port_get_rport_max_speed(port))
-			rport_attr->trl_enforced = BFA_TRUE;
-	}
-
-	/*
-	 * TODO
-	 * rport->symname
-	 */
-}
-
-/**
- * 	Per remote device statistics.
- */
-void
-bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
-			struct bfa_rport_stats_s *stats)
-{
-	*stats = rport->stats;
-}
-
-void
-bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
-{
-	bfa_os_memset((char *)&rport->stats, 0,
-			sizeof(struct bfa_rport_stats_s));
-}
-
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	rport = bfa_fcs_port_get_rport_by_pwwn(port, rpwwn);
-	if (rport == NULL) {
-		/*
-		 * TBD Error handling
-		 */
-	}
-
-	return rport;
-}
-
-struct bfa_fcs_rport_s *
-bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_port_s *port, wwn_t rnwwn)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	rport = bfa_fcs_port_get_rport_by_nwwn(port, rnwwn);
-	if (rport == NULL) {
-		/*
-		 * TBD Error handling
-		 */
-	}
-
-	return rport;
-}
-
-/*
- * This API is to set the Rport's speed. Should be used when RPSC is not
- * supported by the rport.
- */
-void
-bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport,
-			enum bfa_pport_speed speed)
-{
-	rport->rpf.assigned_speed  = speed;
-
-	/* Set this speed in f/w only if the RPSC speed is not available */
-	if (rport->rpf.rpsc_speed == BFA_PPORT_SPEED_UNKNOWN)
-		bfa_rport_speed(rport->bfa_rport, speed);
-}
-
-
diff --git a/drivers/scsi/bfa/rport_ftrs.c b/drivers/scsi/bfa/rport_ftrs.c
deleted file mode 100644
index f2a9361..0000000
--- a/drivers/scsi/bfa/rport_ftrs.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  rport_ftrs.c Remote port features (RPF) implementation.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcbuild.h"
-#include "fcs_rport.h"
-#include "fcs_lport.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-
-BFA_TRC_FILE(FCS, RPORT_FTRS);
-
-#define BFA_FCS_RPF_RETRIES	(3)
-#define BFA_FCS_RPF_RETRY_TIMEOUT  (1000) /* 1 sec (In millisecs) */
-
-static void     bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
-			struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_rpf_rpsc2_response(void *fcsarg,
-			struct bfa_fcxp_s *fcxp, void *cbarg,
-			bfa_status_t req_status, u32 rsp_len,
-			u32 resid_len,
-			struct fchs_s *rsp_fchs);
-static void     bfa_fcs_rpf_timeout(void *arg);
-
-/**
- *  fcs_rport_ftrs_sm FCS rport state machine events
- */
-
-enum rpf_event {
-	RPFSM_EVENT_RPORT_OFFLINE  = 1,     /*  Rport offline            */
-	RPFSM_EVENT_RPORT_ONLINE   = 2,     /*  Rport online            */
-	RPFSM_EVENT_FCXP_SENT      = 3,    /*  Frame from has been sent */
-	RPFSM_EVENT_TIMEOUT  	   = 4,    /*  Rport SM timeout event   */
-	RPFSM_EVENT_RPSC_COMP      = 5,
-	RPFSM_EVENT_RPSC_FAIL      = 6,
-	RPFSM_EVENT_RPSC_ERROR     = 7,
-};
-
-static void	bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
-					enum rpf_event event);
-static void     bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
-					       enum rpf_event event);
-static void     bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
-					       enum rpf_event event);
-static void 	bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
-							enum rpf_event event);
-static void     bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
-							enum rpf_event event);
-static void     bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
-							enum rpf_event event);
-
-static void
-bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-	struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_RPORT_ONLINE:
-		/* Send RPSC2 to a Brocade fabric only. */
-		if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
-			((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) ||
-			(bfa_fcs_fabric_get_switch_oui(fabric) ==
-						BFA_FCS_BRCD_SWITCH_OUI))) {
-			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
-			rpf->rpsc_retries = 0;
-			bfa_fcs_rpf_send_rpsc2(rpf, NULL);
-		}
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_FCXP_SENT:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
-		bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
-		rpf->rpsc_retries = 0;
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_RPSC_COMP:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
-		/* Update speed info in f/w via BFA */
-		if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN)
-			bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
-		else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN)
-			bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
-		break;
-
-	case RPFSM_EVENT_RPSC_FAIL:
-		/* RPSC not supported by rport */
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
-		break;
-
-	case RPFSM_EVENT_RPSC_ERROR:
-		/* need to retry...delayed a bit. */
-		if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
-			bfa_timer_start(rport->fcs->bfa, &rpf->timer,
-				    bfa_fcs_rpf_timeout, rpf,
-				    BFA_FCS_RPF_RETRY_TIMEOUT);
-			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
-		} else {
-			bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
-		}
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
-		bfa_fcxp_discard(rpf->fcxp);
-		rpf->rpsc_retries = 0;
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_TIMEOUT:
-		/* re-send the RPSC */
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
-		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		bfa_timer_stop(&rpf->timer);
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
-		rpf->rpsc_retries = 0;
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
-		rpf->rpsc_retries = 0;
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
-{
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_trc(rport->fcs, event);
-
-	switch (event) {
-	case RPFSM_EVENT_RPORT_ONLINE:
-		bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
-		bfa_fcs_rpf_send_rpsc2(rpf, NULL);
-		break;
-
-	case RPFSM_EVENT_RPORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(rport->fcs, event);
-	}
-}
-/**
- * Called when Rport is created.
- */
-void  bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
-{
-	struct bfa_fcs_rpf_s *rpf = &rport->rpf;
-
-	bfa_trc(rport->fcs, rport->pid);
-	rpf->rport = rport;
-
-	bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
-}
-
-/**
- * Called when Rport becomes online
- */
-void  bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
-{
-	bfa_trc(rport->fcs, rport->pid);
-
-	if (__fcs_min_cfg(rport->port->fcs))
-		return;
-
-	if (bfa_fcs_fabric_is_switched(rport->port->fabric))
-		bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
-}
-
-/**
- * Called when Rport becomes offline
- */
-void  bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
-{
-	bfa_trc(rport->fcs, rport->pid);
-
-	if (__fcs_min_cfg(rport->port->fcs))
-		return;
-
-	rport->rpf.rpsc_speed = 0;
-	bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
-}
-
-static void
-bfa_fcs_rpf_timeout(void *arg)
-{
-	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-
-	bfa_trc(rport->fcs, rport->pid);
-	bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
-}
-
-static void
-bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_rpf_s *rpf 	= (struct bfa_fcs_rpf_s *)rpf_cbarg;
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-	struct bfa_fcs_port_s *port = rport->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(rport->fcs, rport->pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
-					bfa_fcs_rpf_send_rpsc2, rpf);
-		return;
-	}
-	rpf->fcxp = fcxp;
-
-	len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
-			    bfa_fcs_port_get_fcid(port), &rport->pid, 1);
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-			  FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
-			  rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
-	rport->stats.rpsc_sent++;
-	bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
-
-}
-
-static void
-bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
-			    bfa_status_t req_status, u32 rsp_len,
-			    u32 resid_len, struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
-	struct bfa_fcs_rport_s *rport = rpf->rport;
-	struct fc_ls_rjt_s    *ls_rjt;
-	struct fc_rpsc2_acc_s  *rpsc2_acc;
-	u16        num_ents;
-
-	bfa_trc(rport->fcs, req_status);
-
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(rport->fcs, req_status);
-		if (req_status == BFA_STATUS_ETIMER)
-			rport->stats.rpsc_failed++;
-		bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
-		return;
-	}
-
-	rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
-	if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
-		rport->stats.rpsc_accs++;
-		num_ents = bfa_os_ntohs(rpsc2_acc->num_pids);
-		bfa_trc(rport->fcs, num_ents);
-		if (num_ents > 0) {
-			bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
-			bfa_trc(rport->fcs,
-				bfa_os_ntohs(rpsc2_acc->port_info[0].pid));
-			bfa_trc(rport->fcs,
-				bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
-			bfa_trc(rport->fcs,
-				bfa_os_ntohs(rpsc2_acc->port_info[0].index));
-			bfa_trc(rport->fcs,
-				rpsc2_acc->port_info[0].type);
-
-			if (rpsc2_acc->port_info[0].speed == 0) {
-				bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
-				return;
-			}
-
-			rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
-				bfa_os_ntohs(rpsc2_acc->port_info[0].speed));
-
-			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
-		}
-	} else {
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-		bfa_trc(rport->fcs, ls_rjt->reason_code);
-		bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
-		rport->stats.rpsc_rejects++;
-		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
-			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
-		else
-			bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
-	}
-}
diff --git a/drivers/scsi/bfa/scn.c b/drivers/scsi/bfa/scn.c
deleted file mode 100644
index 8a60129..0000000
--- a/drivers/scsi/bfa/scn.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include "fcs_lport.h"
-#include "fcs_rport.h"
-#include "fcs_ms.h"
-#include "fcs_trcmod.h"
-#include "fcs_fcxp.h"
-#include "fcs.h"
-#include "lport_priv.h"
-
-BFA_TRC_FILE(FCS, SCN);
-
-#define FC_QOS_RSCN_EVENT		0x0c
-#define FC_FABRIC_NAME_RSCN_EVENT	0x0d
-
-/*
- * forward declarations
- */
-static void     bfa_fcs_port_scn_send_scr(void *scn_cbarg,
-					  struct bfa_fcxp_s *fcxp_alloced);
-static void     bfa_fcs_port_scn_scr_response(void *fcsarg,
-					      struct bfa_fcxp_s *fcxp,
-					      void *cbarg,
-					      bfa_status_t req_status,
-					      u32 rsp_len,
-					      u32 resid_len,
-					      struct fchs_s *rsp_fchs);
-static void     bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
-					     struct fchs_s *rx_fchs);
-static void     bfa_fcs_port_scn_timeout(void *arg);
-
-/**
- *  fcs_scm_sm FCS SCN state machine
- */
-
-/**
- * VPort SCN State Machine events
- */
-enum port_scn_event {
-	SCNSM_EVENT_PORT_ONLINE = 1,
-	SCNSM_EVENT_PORT_OFFLINE = 2,
-	SCNSM_EVENT_RSP_OK = 3,
-	SCNSM_EVENT_RSP_ERROR = 4,
-	SCNSM_EVENT_TIMEOUT = 5,
-	SCNSM_EVENT_SCR_SENT = 6,
-};
-
-static void     bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
-					    enum port_scn_event event);
-static void     bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
-						enum port_scn_event event);
-static void     bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
-					enum port_scn_event event);
-static void     bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
-					      enum port_scn_event event);
-static void     bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
-					   enum port_scn_event event);
-
-/**
- * 		Starting state - awaiting link up.
- */
-static void
-bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn,
-			    enum port_scn_event event)
-{
-	switch (event) {
-	case SCNSM_EVENT_PORT_ONLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
-		bfa_fcs_port_scn_send_scr(scn, NULL);
-		break;
-
-	case SCNSM_EVENT_PORT_OFFLINE:
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn,
-				enum port_scn_event event)
-{
-	switch (event) {
-	case SCNSM_EVENT_SCR_SENT:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr);
-		break;
-
-	case SCNSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-		bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn,
-			enum port_scn_event event)
-{
-	struct bfa_fcs_port_s *port = scn->port;
-
-	switch (event) {
-	case SCNSM_EVENT_RSP_OK:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_online);
-		break;
-
-	case SCNSM_EVENT_RSP_ERROR:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr_retry);
-		bfa_timer_start(port->fcs->bfa, &scn->timer,
-				bfa_fcs_port_scn_timeout, scn,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case SCNSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-		bfa_fcxp_discard(scn->fcxp);
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn,
-			      enum port_scn_event event)
-{
-	switch (event) {
-	case SCNSM_EVENT_TIMEOUT:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr);
-		bfa_fcs_port_scn_send_scr(scn, NULL);
-		break;
-
-	case SCNSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-		bfa_timer_stop(&scn->timer);
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-static void
-bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn,
-			   enum port_scn_event event)
-{
-	switch (event) {
-	case SCNSM_EVENT_PORT_OFFLINE:
-		bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-		break;
-
-	default:
-		bfa_sm_fault(scn->port->fcs, event);
-	}
-}
-
-
-
-/**
- *  fcs_scn_private FCS SCN private functions
- */
-
-/**
- * This routine will be called to send a SCR command.
- */
-static void
-bfa_fcs_port_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
-{
-	struct bfa_fcs_port_scn_s *scn = scn_cbarg;
-	struct bfa_fcs_port_s *port = scn->port;
-	struct fchs_s          fchs;
-	int             len;
-	struct bfa_fcxp_s *fcxp;
-
-	bfa_trc(port->fcs, port->pid);
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp) {
-		bfa_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
-				    bfa_fcs_port_scn_send_scr, scn);
-		return;
-	}
-	scn->fcxp = fcxp;
-
-	/*
-	 * Handle VU registrations for Base port only
-	 */
-	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
-		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-				   bfa_lps_is_brcd_fabric(port->fabric->lps),
-				   port->pid, 0);
-	} else {
-		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), BFA_FALSE,
-				   port->pid, 0);
-	}
-
-	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
-		      FC_CLASS_3, len, &fchs, bfa_fcs_port_scn_scr_response,
-		      (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
-
-	bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
-}
-
-static void
-bfa_fcs_port_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
-			      void *cbarg, bfa_status_t req_status,
-			      u32 rsp_len, u32 resid_len,
-			      struct fchs_s *rsp_fchs)
-{
-	struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)cbarg;
-	struct bfa_fcs_port_s *port = scn->port;
-	struct fc_els_cmd_s   *els_cmd;
-	struct fc_ls_rjt_s    *ls_rjt;
-
-	bfa_trc(port->fcs, port->port_cfg.pwwn);
-
-	/*
-	 * Sanity Checks
-	 */
-	if (req_status != BFA_STATUS_OK) {
-		bfa_trc(port->fcs, req_status);
-		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
-		return;
-	}
-
-	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-	switch (els_cmd->els_code) {
-
-	case FC_ELS_ACC:
-		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
-		break;
-
-	case FC_ELS_LS_RJT:
-
-		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
-
-		bfa_trc(port->fcs, ls_rjt->reason_code);
-		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
-
-		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
-		break;
-
-	default:
-		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
-	}
-}
-
-/*
- * Send a LS Accept
- */
-static void
-bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port,
-			struct fchs_s *rx_fchs)
-{
-	struct fchs_s          fchs;
-	struct bfa_fcxp_s *fcxp;
-	struct bfa_rport_s *bfa_rport = NULL;
-	int             len;
-
-	bfa_trc(port->fcs, rx_fchs->s_id);
-
-	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
-	if (!fcxp)
-		return;
-
-	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
-			      bfa_fcs_port_get_fcid(port), rx_fchs->ox_id);
-
-	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
-		      BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
-		      FC_MAX_PDUSZ, 0);
-}
-
-/**
- *     This routine will be called by bfa_timer on timer timeouts.
- *
- * 	param[in] 	vport 			- pointer to bfa_fcs_port_t.
- * 	param[out]	vport_status 	- pointer to return vport status in
- *
- * 	return
- * 		void
- *
-*  	Special Considerations:
- *
- * 	note
- */
-static void
-bfa_fcs_port_scn_timeout(void *arg)
-{
-	struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)arg;
-
-	bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
-}
-
-
-
-/**
- *  fcs_scn_public FCS state change notification public interfaces
- */
-
-/*
- * Functions called by port/fab
- */
-void
-bfa_fcs_port_scn_init(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
-
-	scn->port = port;
-	bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline);
-}
-
-void
-bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
-
-	scn->port = port;
-	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
-}
-
-void
-bfa_fcs_port_scn_online(struct bfa_fcs_port_s *port)
-{
-	struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
-
-	scn->port = port;
-	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
-}
-
-static void
-bfa_fcs_port_scn_portid_rscn(struct bfa_fcs_port_s *port, u32 rpid)
-{
-	struct bfa_fcs_rport_s *rport;
-
-	bfa_trc(port->fcs, rpid);
-
-	/**
-	 * If this is an unknown device, then it just came online.
-	 * Otherwise let rport handle the RSCN event.
-	 */
-	rport = bfa_fcs_port_get_rport_by_pid(port, rpid);
-	if (rport == NULL) {
-		/*
-		 * If min cfg mode is enabled, we donot need to
-		 * discover any new rports.
-		 */
-		if (!__fcs_min_cfg(port->fcs))
-			rport = bfa_fcs_rport_create(port, rpid);
-	} else {
-		bfa_fcs_rport_scn(rport);
-	}
-}
-
-/**
- * rscn format based PID comparison
- */
-#define __fc_pid_match(__c0, __c1, __fmt)		\
-	(((__fmt) == FC_RSCN_FORMAT_FABRIC) ||		\
-	 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&		\
-	  ((__c0)[0] == (__c1)[0])) ||			\
-	 (((__fmt) == FC_RSCN_FORMAT_AREA) &&		\
-	  ((__c0)[0] == (__c1)[0]) &&			\
-	  ((__c0)[1] == (__c1)[1])))
-
-static void
-bfa_fcs_port_scn_multiport_rscn(struct bfa_fcs_port_s *port,
-			enum fc_rscn_format format, u32 rscn_pid)
-{
-	struct bfa_fcs_rport_s *rport;
-	struct list_head *qe, *qe_next;
-	u8        *c0, *c1;
-
-	bfa_trc(port->fcs, format);
-	bfa_trc(port->fcs, rscn_pid);
-
-	c0 = (u8 *) &rscn_pid;
-
-	list_for_each_safe(qe, qe_next, &port->rport_q) {
-		rport = (struct bfa_fcs_rport_s *)qe;
-		c1 = (u8 *) &rport->pid;
-		if (__fc_pid_match(c0, c1, format))
-			bfa_fcs_rport_scn(rport);
-	}
-}
-
-void
-bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
-			      u32 len)
-{
-	struct fc_rscn_pl_s   *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
-	int             num_entries;
-	u32        rscn_pid;
-	bfa_boolean_t   nsquery = BFA_FALSE;
-	int             i = 0;
-
-	num_entries =
-		(bfa_os_ntohs(rscn->payldlen) -
-		 sizeof(u32)) / sizeof(rscn->event[0]);
-
-	bfa_trc(port->fcs, num_entries);
-
-	port->stats.num_rscn++;
-
-	bfa_fcs_port_scn_send_ls_acc(port, fchs);
-
-	for (i = 0; i < num_entries; i++) {
-		rscn_pid = rscn->event[i].portid;
-
-		bfa_trc(port->fcs, rscn->event[i].format);
-		bfa_trc(port->fcs, rscn_pid);
-
-		switch (rscn->event[i].format) {
-		case FC_RSCN_FORMAT_PORTID:
-			if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
-				/*
-				 * Ignore this event. f/w would have processed
-				 * it
-				 */
-				bfa_trc(port->fcs, rscn_pid);
-			} else {
-				port->stats.num_portid_rscn++;
-				bfa_fcs_port_scn_portid_rscn(port, rscn_pid);
-			}
-			break;
-
-		case FC_RSCN_FORMAT_FABRIC:
-			if (rscn->event[i].qualifier ==
-			    FC_FABRIC_NAME_RSCN_EVENT) {
-				bfa_fcs_port_ms_fabric_rscn(port);
-				break;
-			}
-			/*
-			 * !!!!!!!!! Fall Through !!!!!!!!!!!!!
-			 */
-
-		case FC_RSCN_FORMAT_AREA:
-		case FC_RSCN_FORMAT_DOMAIN:
-			nsquery = BFA_TRUE;
-			bfa_fcs_port_scn_multiport_rscn(port,
-							rscn->event[i].format,
-							rscn_pid);
-			break;
-
-		default:
-			bfa_assert(0);
-			nsquery = BFA_TRUE;
-		}
-	}
-
-	/**
-	 * If any of area, domain or fabric RSCN is received, do a fresh discovery
-	 * to find new devices.
-	 */
-	if (nsquery)
-		bfa_fcs_port_ns_query(port);
-}
-
-
diff --git a/drivers/scsi/bfa/vfapi.c b/drivers/scsi/bfa/vfapi.c
deleted file mode 100644
index 391a479..0000000
--- a/drivers/scsi/bfa/vfapi.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  vfapi.c Fabric module implementation.
- */
-
-#include "fcs_fabric.h"
-#include "fcs_trcmod.h"
-
-BFA_TRC_FILE(FCS, VFAPI);
-
-/**
- *  fcs_vf_api virtual fabrics API
- */
-
-/**
- * 		Enable VF mode.
- *
- * @param[in]		fcs		fcs module instance
- * @param[in]		vf_id		default vf_id of port, FC_VF_ID_NULL
- * 					to use standard default vf_id of 1.
- *
- * @retval	BFA_STATUS_OK		vf mode is enabled
- * @retval	BFA_STATUS_BUSY		Port is active. Port must be disabled
- *					before VF mode can be enabled.
- */
-bfa_status_t
-bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id)
-{
-	return BFA_STATUS_OK;
-}
-
-/**
- * 		Disable VF mode.
- *
- * @param[in]		fcs		fcs module instance
- *
- * @retval	BFA_STATUS_OK		vf mode is disabled
- * @retval	BFA_STATUS_BUSY		VFs are present and being used. All
- * 					VFs must be deleted before disabling
- *					VF mode.
- */
-bfa_status_t
-bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs)
-{
-	return BFA_STATUS_OK;
-}
-
-/**
- * 		Create a new VF instance.
- *
- *  A new VF is created using the given VF configuration. A VF is identified
- *  by VF id. No duplicate VF creation is allowed with the same VF id. Once
- *  a VF is created, VF is automatically started after link initialization
- *  and EVFP exchange is completed.
- *
- * 	param[in] vf		- 	FCS vf data structure. Memory is
- *					allocated by caller (driver)
- * 	param[in] fcs 		- 	FCS module
- * 	param[in] vf_cfg	- 	VF configuration
- * 	param[in] vf_drv 	- 	Opaque handle back to the driver's
- *					virtual vf structure
- *
- * 	retval BFA_STATUS_OK VF creation is successful
- * 	retval BFA_STATUS_FAILED VF creation failed
- * 	retval BFA_STATUS_EEXIST A VF exists with the given vf_id
- */
-bfa_status_t
-bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, u16 vf_id,
-		  struct bfa_port_cfg_s *port_cfg, struct bfad_vf_s *vf_drv)
-{
-	bfa_trc(fcs, vf_id);
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Use this function to delete a BFA VF object. VF object should
- * 		be stopped before this function call.
- *
- * 	param[in] vf - pointer to bfa_vf_t.
- *
- * 	retval BFA_STATUS_OK	On vf deletion success
- * 	retval BFA_STATUS_BUSY VF is not in a stopped state
- * 	retval BFA_STATUS_INPROGRESS VF deletion in in progress
- */
-bfa_status_t
-bfa_fcs_vf_delete(bfa_fcs_vf_t *vf)
-{
-	bfa_trc(vf->fcs, vf->vf_id);
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Start participation in VF. This triggers login to the virtual fabric.
- *
- * 	param[in] vf - pointer to bfa_vf_t.
- *
- * 	return None
- */
-void
-bfa_fcs_vf_start(bfa_fcs_vf_t *vf)
-{
-	bfa_trc(vf->fcs, vf->vf_id);
-}
-
-/**
- *  	Logout with the virtual fabric.
- *
- * 	param[in] vf - pointer to bfa_vf_t.
- *
- * 	retval BFA_STATUS_OK 	On success.
- * 	retval BFA_STATUS_INPROGRESS VF is being stopped.
- */
-bfa_status_t
-bfa_fcs_vf_stop(bfa_fcs_vf_t *vf)
-{
-	bfa_trc(vf->fcs, vf->vf_id);
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Returns attributes of the given VF.
- *
- * 	param[in] 	vf			pointer to bfa_vf_t.
- * 	param[out] vf_attr 	vf attributes returned
- *
- * 	return None
- */
-void
-bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr)
-{
-	bfa_trc(vf->fcs, vf->vf_id);
-}
-
-/**
- * 		Return statistics associated with the given vf.
- *
- * 	param[in] 	vf			pointer to bfa_vf_t.
- * 	param[out] vf_stats 	vf statistics returned
- *
- *  @return None
- */
-void
-bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, struct bfa_vf_stats_s *vf_stats)
-{
-	bfa_os_memcpy(vf_stats, &vf->stats, sizeof(struct bfa_vf_stats_s));
-	return;
-}
-
-void
-/**
- * 		clear statistics associated with the given vf.
- *
- * 	param[in] 	vf			pointer to bfa_vf_t.
- *
- *  @return None
- */
-bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf)
-{
-	bfa_os_memset(&vf->stats, 0, sizeof(struct bfa_vf_stats_s));
-	return;
-}
-
-/**
- *  	Returns FCS vf structure for a given vf_id.
- *
- * 	param[in] 	vf_id		- VF_ID
- *
- * 	return
- * 		If lookup succeeds, retuns fcs vf object, otherwise returns NULL
- */
-bfa_fcs_vf_t   *
-bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
-{
-	bfa_trc(fcs, vf_id);
-	if (vf_id == FC_VF_ID_NULL)
-		return &fcs->fabric;
-
-	/**
-	 * @todo vf support
-	 */
-
-	return NULL;
-}
-
-/**
- *  	Returns driver VF structure for a given FCS vf.
- *
- * 	param[in] 	vf		- pointer to bfa_vf_t
- *
- * 	return Driver VF structure
- */
-struct bfad_vf_s      *
-bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf)
-{
-	bfa_assert(vf);
-	bfa_trc(vf->fcs, vf->vf_id);
-	return vf->vf_drv;
-}
-
-/**
- *  	Return the list of VFs configured.
- *
- * 	param[in]	fcs	fcs module instance
- * 	param[out] 	vf_ids	returned list of vf_ids
- * 	param[in,out] 	nvfs	in:size of vf_ids array,
- * 				out:total elements present,
- * 				actual elements returned is limited by the size
- *
- * 	return Driver VF structure
- */
-void
-bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
-{
-	bfa_trc(fcs, *nvfs);
-}
-
-/**
- *  	Return the list of all VFs visible from fabric.
- *
- * 	param[in]	fcs	fcs module instance
- * 	param[out] 	vf_ids	returned list of vf_ids
- * 	param[in,out] 	nvfs	in:size of vf_ids array,
- *				out:total elements present,
- * 				actual elements returned is limited by the size
- *
- * 	return Driver VF structure
- */
-void
-bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs)
-{
-	bfa_trc(fcs, *nvfs);
-}
-
-/**
- * 		Return the list of local logical ports present in the given VF.
- *
- * 	param[in]	vf	vf for which logical ports are returned
- * 	param[out] 	lpwwn	returned logical port wwn list
- * 	param[in,out] 	nlports	in:size of lpwwn list;
- *				out:total elements present,
- * 				actual elements returned is limited by the size
- *
- */
-void
-bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)
-{
-	struct list_head        *qe;
-	struct bfa_fcs_vport_s *vport;
-	int             i;
-	struct bfa_fcs_s      *fcs;
-
-	if (vf == NULL || lpwwn == NULL || *nlports == 0)
-		return;
-
-	fcs = vf->fcs;
-
-	bfa_trc(fcs, vf->vf_id);
-	bfa_trc(fcs, (u32) *nlports);
-
-	i = 0;
-	lpwwn[i++] = vf->bport.port_cfg.pwwn;
-
-	list_for_each(qe, &vf->vport_q) {
-		if (i >= *nlports)
-			break;
-
-		vport = (struct bfa_fcs_vport_s *) qe;
-		lpwwn[i++] = vport->lport.port_cfg.pwwn;
-	}
-
-	bfa_trc(fcs, i);
-	*nlports = i;
-	return;
-}
-
-
diff --git a/drivers/scsi/bfa/vport.c b/drivers/scsi/bfa/vport.c
deleted file mode 100644
index b378ec7..0000000
--- a/drivers/scsi/bfa/vport.c
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
- * All rights reserved
- * www.brocade.com
- *
- * Linux driver for Brocade Fibre Channel Host Bus Adapter.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License (GPL) 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.
- */
-
-/**
- *  bfa_fcs_vport.c FCS virtual port state machine
- */
-
-#include <bfa.h>
-#include <bfa_svc.h>
-#include <fcbuild.h>
-#include "fcs_fabric.h"
-#include "fcs_lport.h"
-#include "fcs_vport.h"
-#include "fcs_trcmod.h"
-#include "fcs.h"
-#include <aen/bfa_aen_lport.h>
-
-BFA_TRC_FILE(FCS, VPORT);
-
-#define __vport_fcs(__vp)       ((__vp)->lport.fcs)
-#define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
-#define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
-#define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
-#define __vport_fcid(__vp)      ((__vp)->lport.pid)
-#define __vport_fabric(__vp)    ((__vp)->lport.fabric)
-#define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
-
-#define BFA_FCS_VPORT_MAX_RETRIES  5
-/*
- * Forward declarations
- */
-static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
-static void     bfa_fcs_vport_timeout(void *vport_arg);
-static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
-static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
-
-/**
- *  fcs_vport_sm FCS virtual port state machine
- */
-
-/**
- * VPort State Machine events
- */
-enum bfa_fcs_vport_event {
-	BFA_FCS_VPORT_SM_CREATE = 1,	/*  vport create event */
-	BFA_FCS_VPORT_SM_DELETE = 2,	/*  vport delete event */
-	BFA_FCS_VPORT_SM_START = 3,	/*  vport start request */
-	BFA_FCS_VPORT_SM_STOP = 4,	/*  stop: unsupported */
-	BFA_FCS_VPORT_SM_ONLINE = 5,	/*  fabric online */
-	BFA_FCS_VPORT_SM_OFFLINE = 6,	/*  fabric offline event */
-	BFA_FCS_VPORT_SM_FRMSENT = 7,	/*  fdisc/logo sent events */
-	BFA_FCS_VPORT_SM_RSP_OK = 8,	/*  good response */
-	BFA_FCS_VPORT_SM_RSP_ERROR = 9,	/*  error/bad response */
-	BFA_FCS_VPORT_SM_TIMEOUT = 10,	/*  delay timer event */
-	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
-	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error */
-	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
-};
-
-static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
-					enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
-					 enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
-					 enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
-				       enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
-					     enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
-					enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
-					  enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
-					 enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
-				      enum bfa_fcs_vport_event event);
-static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
-				       enum bfa_fcs_vport_event event);
-
-static struct bfa_sm_table_s vport_sm_table[] = {
-	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
-	{BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
-	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
-	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
-	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
-	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
-	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
-	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
-	{BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
-	{BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
-};
-
-/**
- * Beginning state.
- */
-static void
-bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
-			enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_CREATE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
-		bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Created state - a start event is required to start up the state machine.
- */
-static void
-bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
-			 enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_START:
-		if (bfa_fcs_fabric_is_online(__vport_fabric(vport))
-		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
-			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
-			bfa_fcs_vport_do_fdisc(vport);
-		} else {
-			/**
-			 * Fabric is offline or not NPIV capable, stay in
-			 * offline state.
-			 */
-			vport->vport_stats.fab_no_npiv++;
-			bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		}
-		break;
-
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_ONLINE:
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		/**
-		 * Ignore ONLINE/OFFLINE events from fabric till vport is started.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Offline state - awaiting ONLINE event from fabric SM.
- */
-static void
-bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
-			 enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_ONLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
-		vport->fdisc_retries = 0;
-		bfa_fcs_vport_do_fdisc(vport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		/*
-		 * This can happen if the vport couldn't be initialzied due
-		 * the fact that the npiv was not enabled on the switch. In
-		 * that case we will put the vport in offline state. However,
-		 * the link can go down and cause the this event to be sent when
-		 * we are already offline. Ignore it.
-		 */
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * FDISC is sent and awaiting reply from fabric.
- */
-static void
-bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
-		       enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_lps_discard(vport->lps);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		bfa_lps_discard(vport->lps);
-		break;
-
-	case BFA_FCS_VPORT_SM_RSP_OK:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
-		bfa_fcs_port_online(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_RSP_ERROR:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
-		bfa_timer_start(__vport_bfa(vport), &vport->timer,
-				bfa_fcs_vport_timeout, vport,
-				BFA_FCS_RETRY_TIMEOUT);
-		break;
-
-	case BFA_FCS_VPORT_SM_RSP_FAILED:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		break;
-
-	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * FDISC attempt failed - a timer is active to retry FDISC.
- */
-static void
-bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
-			     enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_timer_stop(&vport->timer);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		bfa_timer_stop(&vport->timer);
-		break;
-
-	case BFA_FCS_VPORT_SM_TIMEOUT:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
-		vport->vport_stats.fdisc_retries++;
-		vport->fdisc_retries++;
-		bfa_fcs_vport_do_fdisc(vport);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Vport is online (FDISC is complete).
- */
-static void
-bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
-			enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
-		bfa_fcs_port_delete(&vport->lport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
-		bfa_lps_discard(vport->lps);
-		bfa_fcs_port_offline(&vport->lport);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Vport is being deleted - awaiting lport delete completion to send
- * LOGO to fabric.
- */
-static void
-bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
-			  enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		break;
-
-	case BFA_FCS_VPORT_SM_DELCOMP:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
-		bfa_fcs_vport_do_logo(vport);
-		break;
-
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Error State.
- * This state will be set when the Vport Creation fails due to errors like
- * Dup WWN. In this state only operation allowed is a Vport Delete.
- */
-static void
-bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
-		       enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELETE:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
-		bfa_fcs_port_delete(&vport->lport);
-
-		break;
-
-	default:
-		bfa_trc(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * Lport cleanup is in progress since vport is being deleted. Fabric is
- * offline, so no LOGO is needed to complete vport deletion.
- */
-static void
-bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
-			 enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_DELCOMP:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
-		bfa_fcs_vport_free(vport);
-		break;
-
-	case BFA_FCS_VPORT_SM_DELETE:
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-/**
- * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
- * is done.
- */
-static void
-bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
-		      enum bfa_fcs_vport_event event)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), event);
-
-	switch (event) {
-	case BFA_FCS_VPORT_SM_OFFLINE:
-		bfa_lps_discard(vport->lps);
-		/*
-		 * !!! fall through !!!
-		 */
-
-	case BFA_FCS_VPORT_SM_RSP_OK:
-	case BFA_FCS_VPORT_SM_RSP_ERROR:
-		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
-		bfa_fcs_vport_free(vport);
-		break;
-
-	case BFA_FCS_VPORT_SM_DELETE:
-		break;
-
-	default:
-		bfa_sm_fault(__vport_fcs(vport), event);
-	}
-}
-
-
-
-/**
- *  fcs_vport_private FCS virtual port private functions
- */
-
-/**
- * Send AEN notification
- */
-static void
-bfa_fcs_vport_aen_post(bfa_fcs_lport_t *port, enum bfa_lport_aen_event event)
-{
-	union bfa_aen_data_u aen_data;
-	struct bfa_log_mod_s *logmod = port->fcs->logm;
-	enum bfa_port_role role = port->port_cfg.roles;
-	wwn_t           lpwwn = bfa_fcs_port_get_pwwn(port);
-	char            lpwwn_ptr[BFA_STRING_32];
-	char           *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] =
-		{ "Initiator", "Target", "IPFC" };
-
-	wwn2str(lpwwn_ptr, lpwwn);
-
-	bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX);
-
-	bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, event), lpwwn_ptr,
-			role_str[role/2]);
-
-	aen_data.lport.vf_id = port->fabric->vf_id;
-	aen_data.lport.roles = role;
-	aen_data.lport.ppwwn =
-		bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs));
-	aen_data.lport.lpwwn = lpwwn;
-}
-
-/**
- * This routine will be called to send a FDISC command.
- */
-static void
-bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
-{
-	bfa_lps_fdisc(vport->lps, vport,
-		      bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
-		      __vport_pwwn(vport), __vport_nwwn(vport));
-	vport->vport_stats.fdisc_sent++;
-}
-
-static void
-bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
-{
-	u8         lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps);
-	u8         lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps);
-
-	bfa_trc(__vport_fcs(vport), lsrjt_rsn);
-	bfa_trc(__vport_fcs(vport), lsrjt_expl);
-
-	/*
-	 * For certain reason codes, we don't want to retry.
-	 */
-	switch (bfa_lps_get_lsrjt_expl(vport->lps)) {
-	case FC_LS_RJT_EXP_INV_PORT_NAME:	/* by brocade */
-	case FC_LS_RJT_EXP_INVALID_NPORT_ID:	/* by Cisco */
-		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
-			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-		else {
-			bfa_fcs_vport_aen_post(&vport->lport,
-					       BFA_LPORT_AEN_NPIV_DUP_WWN);
-			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
-		}
-		break;
-
-	case FC_LS_RJT_EXP_INSUFF_RES:
-		/*
-		 * This means max logins per port/switch setting on the
-		 * switch was exceeded.
-		 */
-		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
-			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-		else {
-			bfa_fcs_vport_aen_post(&vport->lport,
-					       BFA_LPORT_AEN_NPIV_FABRIC_MAX);
-			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
-		}
-		break;
-
-	default:
-		if (vport->fdisc_retries == 0)	/* Print only once */
-			bfa_fcs_vport_aen_post(&vport->lport,
-					       BFA_LPORT_AEN_NPIV_UNKNOWN);
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-	}
-}
-
-/**
- * 	Called to send a logout to the fabric. Used when a V-Port is
- * 	deleted/stopped.
- */
-static void
-bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
-{
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-
-	vport->vport_stats.logo_sent++;
-	bfa_lps_fdisclogo(vport->lps);
-}
-
-/**
- *     This routine will be called by bfa_timer on timer timeouts.
- *
- * 	param[in] 	vport 		- pointer to bfa_fcs_vport_t.
- * 	param[out]	vport_status 	- pointer to return vport status in
- *
- * 	return
- * 		void
- *
-* 	Special Considerations:
- *
- * 	note
- */
-static void
-bfa_fcs_vport_timeout(void *vport_arg)
-{
-	struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *)vport_arg;
-
-	vport->vport_stats.fdisc_timeouts++;
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
-}
-
-static void
-bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
-{
-	bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
-	bfa_fcb_vport_delete(vport->vport_drv);
-	bfa_lps_delete(vport->lps);
-}
-
-
-
-/**
- *  fcs_vport_public FCS virtual port public interfaces
- */
-
-/**
- * Online notification from fabric SM.
- */
-void
-bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
-{
-	vport->vport_stats.fab_online++;
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
-}
-
-/**
- * Offline notification from fabric SM.
- */
-void
-bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
-{
-	vport->vport_stats.fab_offline++;
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
-}
-
-/**
- * Cleanup notification from fabric SM on link timer expiry.
- */
-void
-bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
-{
-	vport->vport_stats.fab_cleanup++;
-}
-
-/**
- * delete notification from fabric SM. To be invoked from within FCS.
- */
-void
-bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
-{
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
-}
-
-/**
- * Delete completion callback from associated lport
- */
-void
-bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
-{
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
-}
-
-/**
- *  fcs_vport_api Virtual port API
- */
-
-/**
- *  	Use this function to instantiate a new FCS vport object. This
- * 	function will not trigger any HW initialization process (which will be
- * 	done in vport_start() call)
- *
- * 	param[in] vport	- 	pointer to bfa_fcs_vport_t. This space
- * 					needs to be allocated by the driver.
- * 	param[in] fcs 		- 	FCS instance
- * 	param[in] vport_cfg	- 	vport configuration
- * 	param[in] vf_id    	- 	VF_ID if vport is created within a VF.
- *                          		FC_VF_ID_NULL to specify base fabric.
- * 	param[in] vport_drv 	- 	Opaque handle back to the driver's vport
- * 					structure
- *
- * 	retval BFA_STATUS_OK - on success.
- * 	retval BFA_STATUS_FAILED - on failure.
- */
-bfa_status_t
-bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
-		     u16 vf_id, struct bfa_port_cfg_s *vport_cfg,
-		     struct bfad_vport_s *vport_drv)
-{
-	if (vport_cfg->pwwn == 0)
-		return BFA_STATUS_INVALID_WWN;
-
-	if (bfa_fcs_port_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
-		return BFA_STATUS_VPORT_WWN_BP;
-
-	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
-		return BFA_STATUS_VPORT_EXISTS;
-
-	if (bfa_fcs_fabric_vport_count(&fcs->fabric) ==
-		bfa_lps_get_max_vport(fcs->bfa))
-		return BFA_STATUS_VPORT_MAX;
-
-	vport->lps = bfa_lps_alloc(fcs->bfa);
-	if (!vport->lps)
-		return BFA_STATUS_VPORT_MAX;
-
-	vport->vport_drv = vport_drv;
-	vport_cfg->preboot_vp = BFA_FALSE;
-	bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
-
-	bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
-	bfa_fcs_lport_init(&vport->lport, vport_cfg);
-
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *      Use this function to instantiate a new FCS PBC vport object. This
- *      function will not trigger any HW initialization process (which will be
- *      done in vport_start() call)
- *
- *      param[in] vport        -       pointer to bfa_fcs_vport_t. This space
- *                                      needs to be allocated by the driver.
- *      param[in] fcs          -       FCS instance
- *      param[in] vport_cfg    -       vport configuration
- *      param[in] vf_id        -       VF_ID if vport is created within a VF.
- *                                      FC_VF_ID_NULL to specify base fabric.
- *      param[in] vport_drv    -       Opaque handle back to the driver's vport
- *                                      structure
- *
- *      retval BFA_STATUS_OK - on success.
- *      retval BFA_STATUS_FAILED - on failure.
- */
-bfa_status_t
-bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
-			uint16_t vf_id, struct bfa_port_cfg_s *vport_cfg,
-			struct bfad_vport_s *vport_drv)
-{
-	bfa_status_t rc;
-
-	rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
-	vport->lport.port_cfg.preboot_vp = BFA_TRUE;
-
-	return rc;
-}
-
-/**
- *  	Use this function initialize the vport.
- *
- *  @param[in] vport - pointer to bfa_fcs_vport_t.
- *
- *  @returns None
- */
-bfa_status_t
-bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
-{
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Use this function quiese the vport object. This function will return
- * 	immediately, when the vport is actually stopped, the
- * 	bfa_drv_vport_stop_cb() will be called.
- *
- * 	param[in] vport - pointer to bfa_fcs_vport_t.
- *
- * 	return None
- */
-bfa_status_t
-bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
-{
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Use this function to delete a vport object. Fabric object should
- * 		be stopped before this function call.
- *
- *	Donot invoke this from within FCS
- *
- * 	param[in] vport - pointer to bfa_fcs_vport_t.
- *
- * 	return     None
- */
-bfa_status_t
-bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
-{
-	if (vport->lport.port_cfg.preboot_vp)
-		return BFA_STATUS_PBC;
-
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
-
-	return BFA_STATUS_OK;
-}
-
-/**
- *  	Use this function to get vport's current status info.
- *
- * 	param[in] 	vport 		pointer to bfa_fcs_vport_t.
- * 	param[out]	attr 		pointer to return vport attributes
- *
- * 	return None
- */
-void
-bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
-		       struct bfa_vport_attr_s *attr)
-{
-	if (vport == NULL || attr == NULL)
-		return;
-
-	bfa_os_memset(attr, 0, sizeof(struct bfa_vport_attr_s));
-
-	bfa_fcs_port_get_attr(&vport->lport, &attr->port_attr);
-	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
-}
-
-/**
- *  	Use this function to get vport's statistics.
- *
- * 	param[in] 	vport 		pointer to bfa_fcs_vport_t.
- * 	param[out]	stats		pointer to return vport statistics in
- *
- * 	return None
- */
-void
-bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport,
-			struct bfa_vport_stats_s *stats)
-{
-	*stats = vport->vport_stats;
-}
-
-/**
- *  	Use this function to clear vport's statistics.
- *
- * 	param[in] 	vport 		pointer to bfa_fcs_vport_t.
- *
- * 	return None
- */
-void
-bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport)
-{
-	bfa_os_memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s));
-}
-
-/**
- *      Lookup a virtual port. Excludes base port from lookup.
- */
-struct bfa_fcs_vport_s *
-bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
-{
-	struct bfa_fcs_vport_s *vport;
-	struct bfa_fcs_fabric_s *fabric;
-
-	bfa_trc(fcs, vf_id);
-	bfa_trc(fcs, vpwwn);
-
-	fabric = bfa_fcs_vf_lookup(fcs, vf_id);
-	if (!fabric) {
-		bfa_trc(fcs, vf_id);
-		return NULL;
-	}
-
-	vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
-	return vport;
-}
-
-/**
- * FDISC Response
- */
-void
-bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
-{
-	struct bfa_fcs_vport_s *vport = uarg;
-
-	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
-	bfa_trc(__vport_fcs(vport), status);
-
-	switch (status) {
-	case BFA_STATUS_OK:
-		/*
-		 * Initialize the V-Port fields
-		 */
-		__vport_fcid(vport) = bfa_lps_get_pid(vport->lps);
-		vport->vport_stats.fdisc_accepts++;
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
-		break;
-
-	case BFA_STATUS_INVALID_MAC:
-		/*
-		 * Only for CNA
-		 */
-		vport->vport_stats.fdisc_acc_bad++;
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-
-		break;
-
-	case BFA_STATUS_EPROTOCOL:
-		switch (bfa_lps_get_extstatus(vport->lps)) {
-		case BFA_EPROTO_BAD_ACCEPT:
-			vport->vport_stats.fdisc_acc_bad++;
-			break;
-
-		case BFA_EPROTO_UNKNOWN_RSP:
-			vport->vport_stats.fdisc_unknown_rsp++;
-			break;
-
-		default:
-			break;
-		}
-
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-		break;
-
-	case BFA_STATUS_FABRIC_RJT:
-		vport->vport_stats.fdisc_rejects++;
-		bfa_fcs_vport_fdisc_rejected(vport);
-		break;
-
-	default:
-		vport->vport_stats.fdisc_rsp_err++;
-		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
-	}
-}
-
-/**
- * LOGO response
- */
-void
-bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
-{
-	struct bfa_fcs_vport_s *vport = uarg;
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
-}
-
-/**
- * Received clear virtual link
- */
-void
-bfa_cb_lps_cvl_event(void *bfad, void *uarg)
-{
-	struct bfa_fcs_vport_s *vport = uarg;
-
-	/* Send an Offline followed by an ONLINE */
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
-	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
-}
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 00c0335..b6345d9 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -753,7 +753,7 @@
 extern int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *conn,
 				    struct bnx2i_cmd *cmnd);
 extern int bnx2i_send_iscsi_nopout(struct bnx2i_conn *conn,
-				   struct iscsi_task *mtask, u32 ttt,
+				   struct iscsi_task *mtask,
 				   char *datap, int data_len, int unsol);
 extern int bnx2i_send_iscsi_logout(struct bnx2i_conn *conn,
 				   struct iscsi_task *mtask);
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index d23fc25..90cef71 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -385,7 +385,6 @@
 	struct bnx2i_cmd *bnx2i_cmd;
 	struct bnx2i_tmf_request *tmfabort_wqe;
 	u32 dword;
-	u32 scsi_lun[2];
 
 	bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
 	tmfabort_hdr = (struct iscsi_tm *)mtask->hdr;
@@ -393,38 +392,41 @@
 						bnx2i_conn->ep->qp.sq_prod_qe;
 
 	tmfabort_wqe->op_code = tmfabort_hdr->opcode;
-	tmfabort_wqe->op_attr = 0;
-	tmfabort_wqe->op_attr =
-		ISCSI_TMF_REQUEST_ALWAYS_ONE | ISCSI_TM_FUNC_ABORT_TASK;
+	tmfabort_wqe->op_attr = tmfabort_hdr->flags;
 
 	tmfabort_wqe->itt = (mtask->itt | (ISCSI_TASK_TYPE_MPATH << 14));
 	tmfabort_wqe->reserved2 = 0;
 	tmfabort_wqe->cmd_sn = be32_to_cpu(tmfabort_hdr->cmdsn);
 
-	ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt);
-	if (!ctask || !ctask->sc)
-		/*
-		 * the iscsi layer must have completed the cmd while this
-		 * was starting up.
-		 *
-		 * Note: In the case of a SCSI cmd timeout, the task's sc
-		 *       is still active; hence ctask->sc != 0
-		 *       In this case, the task must be aborted
-		 */
-		return 0;
+	switch (tmfabort_hdr->flags & ISCSI_FLAG_TM_FUNC_MASK) {
+	case ISCSI_TM_FUNC_ABORT_TASK:
+	case ISCSI_TM_FUNC_TASK_REASSIGN:
+		ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt);
+		if (!ctask || !ctask->sc)
+			/*
+			 * the iscsi layer must have completed the cmd while
+			 * was starting up.
+			 *
+			 * Note: In the case of a SCSI cmd timeout, the task's
+			 *       sc is still active; hence ctask->sc != 0
+			 *       In this case, the task must be aborted
+			 */
+			return 0;
 
-	ref_sc = ctask->sc;
-
-	/* Retrieve LUN directly from the ref_sc */
-	int_to_scsilun(ref_sc->device->lun, (struct scsi_lun *) scsi_lun);
-	tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
-	tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
-
-	if (ref_sc->sc_data_direction == DMA_TO_DEVICE)
-		dword = (ISCSI_TASK_TYPE_WRITE << ISCSI_CMD_REQUEST_TYPE_SHIFT);
-	else
-		dword = (ISCSI_TASK_TYPE_READ << ISCSI_CMD_REQUEST_TYPE_SHIFT);
-	tmfabort_wqe->ref_itt = (dword | (tmfabort_hdr->rtt & ISCSI_ITT_MASK));
+		ref_sc = ctask->sc;
+		if (ref_sc->sc_data_direction == DMA_TO_DEVICE)
+			dword = (ISCSI_TASK_TYPE_WRITE <<
+				 ISCSI_CMD_REQUEST_TYPE_SHIFT);
+		else
+			dword = (ISCSI_TASK_TYPE_READ <<
+				 ISCSI_CMD_REQUEST_TYPE_SHIFT);
+		tmfabort_wqe->ref_itt = (dword |
+					(tmfabort_hdr->rtt & ISCSI_ITT_MASK));
+		break;
+	default:
+		tmfabort_wqe->ref_itt = RESERVED_ITT;
+	}
+	memcpy(tmfabort_wqe->lun, tmfabort_hdr->lun, sizeof(struct scsi_lun));
 	tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn);
 
 	tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma;
@@ -464,7 +466,6 @@
  * @conn:		iscsi connection
  * @cmd:		driver command structure which is requesting
  *			a WQE to sent to chip for further processing
- * @ttt:		TTT to be used when building pdu header
  * @datap:		payload buffer pointer
  * @data_len:		payload data length
  * @unsol:		indicated whether nopout pdu is unsolicited pdu or
@@ -473,7 +474,7 @@
  * prepare and post a nopout request WQE to CNIC firmware
  */
 int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
-			    struct iscsi_task *task, u32 ttt,
+			    struct iscsi_task *task,
 			    char *datap, int data_len, int unsol)
 {
 	struct bnx2i_endpoint *ep = bnx2i_conn->ep;
@@ -498,7 +499,7 @@
 	nopout_wqe->itt = ((u16)task->itt |
 			   (ISCSI_TASK_TYPE_MPATH <<
 			    ISCSI_TMF_REQUEST_TYPE_SHIFT));
-	nopout_wqe->ttt = ttt;
+	nopout_wqe->ttt = nopout_hdr->ttt;
 	nopout_wqe->flags = 0;
 	if (!unsol)
 		nopout_wqe->flags = ISCSI_NOP_OUT_REQUEST_LOCAL_COMPLETION;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index a796f56..50c2aa3b 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -17,15 +17,17 @@
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME		"bnx2i"
-#define DRV_MODULE_VERSION	"2.1.2"
-#define DRV_MODULE_RELDATE	"Jun 28, 2010"
+#define DRV_MODULE_VERSION	"2.1.3"
+#define DRV_MODULE_RELDATE	"Aug 10, 2010"
 
 static char version[] __devinitdata =
 		"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
 		" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 
-MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com>");
+MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
+	      "Eddie Wai <eddie.wai@broadcom.com>");
+
 MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711"
 		   " iSCSI Driver");
 MODULE_LICENSE("GPL");
@@ -167,6 +169,38 @@
 
 
 /**
+ * bnx2i_chip_cleanup - local routine to handle chip cleanup
+ * @hba:	Adapter instance to register
+ *
+ * Driver checks if adapter still has any active connections before
+ *	executing the cleanup process
+ */
+static void bnx2i_chip_cleanup(struct bnx2i_hba *hba)
+{
+	struct bnx2i_endpoint *bnx2i_ep;
+	struct list_head *pos, *tmp;
+
+	if (hba->ofld_conns_active) {
+		/* Stage to force the disconnection
+		 * This is the case where the daemon is either slow or
+		 * not present
+		 */
+		printk(KERN_ALERT "bnx2i: (%s) chip cleanup for %d active "
+			"connections\n", hba->netdev->name,
+			hba->ofld_conns_active);
+		mutex_lock(&hba->net_dev_lock);
+		list_for_each_safe(pos, tmp, &hba->ep_active_list) {
+			bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link);
+			/* Clean up the chip only */
+			bnx2i_hw_ep_disconnect(bnx2i_ep);
+			bnx2i_ep->cm_sk = NULL;
+		}
+		mutex_unlock(&hba->net_dev_lock);
+	}
+}
+
+
+/**
  * bnx2i_stop - cnic callback to shutdown adapter instance
  * @handle:	transparent handle pointing to adapter structure
  *
@@ -176,8 +210,6 @@
 void bnx2i_stop(void *handle)
 {
 	struct bnx2i_hba *hba = handle;
-	struct list_head *pos, *tmp;
-	struct bnx2i_endpoint *bnx2i_ep;
 	int conns_active;
 
 	/* check if cleanup happened in GOING_DOWN context */
@@ -198,24 +230,7 @@
 		if (hba->ofld_conns_active == conns_active)
 			break;
 	}
-	if (hba->ofld_conns_active) {
-		/* Stage to force the disconnection
-		 * This is the case where the daemon is either slow or
-		 * not present
-		 */
-		printk(KERN_ALERT "bnx2i: Wait timeout, force all eps "
-			"to disconnect (%d)\n", hba->ofld_conns_active);
-		mutex_lock(&hba->net_dev_lock);
-		list_for_each_safe(pos, tmp, &hba->ep_active_list) {
-			bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link);
-			/* Clean up the chip only */
-			bnx2i_hw_ep_disconnect(bnx2i_ep);
-		}
-		mutex_unlock(&hba->net_dev_lock);
-		if (hba->ofld_conns_active)
-			printk(KERN_ERR "bnx2i: EP disconnect timeout (%d)!\n",
-				hba->ofld_conns_active);
-	}
+	bnx2i_chip_cleanup(hba);
 
 	/* This flag should be cleared last so that ep_disconnect() gracefully
 	 * cleans up connection context
@@ -457,6 +472,7 @@
 		adapter_count--;
 
 		if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
+			bnx2i_chip_cleanup(hba);
 			hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
 			clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
 		}
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index a46ccc3..fb50efb 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1078,11 +1078,9 @@
 		buf = bnx2i_conn->gen_pdu.req_buf;
 		if (data_len)
 			rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task,
-						     RESERVED_ITT,
 						     buf, data_len, 1);
 		else
 			rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task,
-						     RESERVED_ITT,
 						     NULL, 0, 1);
 		break;
 	case ISCSI_OP_LOGOUT:
@@ -1955,6 +1953,9 @@
 	if (!cnic)
 		return 0;
 
+	if (bnx2i_ep->state == EP_STATE_IDLE)
+		return 0;
+
 	if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
 		goto destroy_conn;
 
@@ -1998,11 +1999,13 @@
 	else
 		close_ret = cnic->cm_abort(bnx2i_ep->cm_sk);
 
+	/* No longer allow CFC delete if cm_close/abort fails the request */
 	if (close_ret)
-		bnx2i_ep->state = EP_STATE_DISCONN_COMPL;
-
-	/* wait for option-2 conn teardown */
-	wait_event_interruptible(bnx2i_ep->ofld_wait,
+		printk(KERN_ALERT "bnx2i: %s close/abort(%d) returned %d\n",
+			bnx2i_ep->hba->netdev->name, close, close_ret);
+	else
+		/* wait for option-2 conn teardown */
+		wait_event_interruptible(bnx2i_ep->ofld_wait,
 				 bnx2i_ep->state != EP_STATE_DISCONN_START);
 
 	if (signal_pending(current))
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index d653218..a15474e 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -22,7 +22,6 @@
 #include <linux/chio.h>			/* here are all the ioctls */
 #include <linux/mutex.h>
 #include <linux/idr.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 
 #include <scsi/scsi.h>
@@ -44,6 +43,7 @@
 MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER);
 
+static DEFINE_MUTEX(ch_mutex);
 static int init = 1;
 module_param(init, int, 0444);
 MODULE_PARM_DESC(init, \
@@ -581,19 +581,19 @@
 	scsi_changer *ch;
 	int minor = iminor(inode);
 
-	lock_kernel();
+	mutex_lock(&ch_mutex);
 	spin_lock(&ch_index_lock);
 	ch = idr_find(&ch_index_idr, minor);
 
 	if (NULL == ch || scsi_device_get(ch->device)) {
 		spin_unlock(&ch_index_lock);
-		unlock_kernel();
+		mutex_unlock(&ch_mutex);
 		return -ENXIO;
 	}
 	spin_unlock(&ch_index_lock);
 
 	file->private_data = ch;
-	unlock_kernel();
+	mutex_unlock(&ch_mutex);
 	return 0;
 }
 
@@ -981,6 +981,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ch_ioctl_compat,
 #endif
+	.llseek		= noop_llseek,
 };
 
 static int __init init_ch_module(void)
diff --git a/drivers/scsi/cxgb3i/Kbuild b/drivers/scsi/cxgb3i/Kbuild
deleted file mode 100644
index 70d060b..0000000
--- a/drivers/scsi/cxgb3i/Kbuild
+++ /dev/null
@@ -1,4 +0,0 @@
-EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
-
-cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o
-obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
diff --git a/drivers/scsi/cxgb3i/Kconfig b/drivers/scsi/cxgb3i/Kconfig
deleted file mode 100644
index bfdcaf5..0000000
--- a/drivers/scsi/cxgb3i/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config SCSI_CXGB3_ISCSI
-	tristate "Chelsio S3xx iSCSI support"
-	depends on CHELSIO_T3_DEPENDS
-	select CHELSIO_T3
-	select SCSI_ISCSI_ATTRS
-	---help---
-	This driver supports iSCSI offload for the Chelsio S3 series devices.
diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
deleted file mode 100644
index e3133b5..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * cxgb3i.h: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB3I_H__
-#define __CXGB3I_H__
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/netdevice.h>
-#include <linux/scatterlist.h>
-#include <linux/skbuff.h>
-#include <scsi/libiscsi_tcp.h>
-
-/* from cxgb3 LLD */
-#include "common.h"
-#include "t3_cpl.h"
-#include "t3cdev.h"
-#include "cxgb3_ctl_defs.h"
-#include "cxgb3_offload.h"
-#include "firmware_exports.h"
-
-#include "cxgb3i_offload.h"
-#include "cxgb3i_ddp.h"
-
-#define CXGB3I_SCSI_HOST_QDEPTH 1024
-#define CXGB3I_MAX_TARGET	CXGB3I_MAX_CONN
-#define CXGB3I_MAX_LUN		512
-#define ISCSI_PDU_NONPAYLOAD_MAX \
-	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + 2*ISCSI_DIGEST_SIZE)
-
-struct cxgb3i_adapter;
-struct cxgb3i_hba;
-struct cxgb3i_endpoint;
-
-/**
- * struct cxgb3i_hba - cxgb3i iscsi structure (per port)
- *
- * @snic:	cxgb3i adapter containing this port
- * @ndev:	pointer to netdev structure
- * @shost:	pointer to scsi host structure
- */
-struct cxgb3i_hba {
-	struct cxgb3i_adapter *snic;
-	struct net_device *ndev;
-	struct Scsi_Host *shost;
-};
-
-/**
- * struct cxgb3i_adapter - cxgb3i adapter structure (per pci)
- *
- * @listhead:	list head to link elements
- * @lock:	lock for this structure
- * @tdev:	pointer to t3cdev used by cxgb3 driver
- * @pdev:	pointer to pci dev
- * @hba_cnt:	# of hbas (the same as # of ports)
- * @hba:	all the hbas on this adapter
- * @flags:	bit flag for adapter event/status
- * @tx_max_size: max. tx packet size supported
- * @rx_max_size: max. rx packet size supported
- * @tag_format: ddp tag format settings
- */
-#define CXGB3I_ADAPTER_FLAG_RESET	0x1
-struct cxgb3i_adapter {
-	struct list_head list_head;
-	spinlock_t lock;
-	struct t3cdev *tdev;
-	struct pci_dev *pdev;
-	unsigned char hba_cnt;
-	struct cxgb3i_hba *hba[MAX_NPORTS];
-
-	unsigned int flags;
-	unsigned int tx_max_size;
-	unsigned int rx_max_size;
-
-	struct cxgb3i_tag_format tag_format;
-};
-
-/**
- * struct cxgb3i_conn - cxgb3i iscsi connection
- *
- * @listhead:	list head to link elements
- * @cep:	pointer to iscsi_endpoint structure
- * @conn:	pointer to iscsi_conn structure
- * @hba:	pointer to the hba this conn. is going through
- * @task_idx_bits: # of bits needed for session->cmds_max
- */
-struct cxgb3i_conn {
-	struct list_head list_head;
-	struct cxgb3i_endpoint *cep;
-	struct iscsi_conn *conn;
-	struct cxgb3i_hba *hba;
-	unsigned int task_idx_bits;
-};
-
-/**
- * struct cxgb3i_endpoint - iscsi tcp endpoint
- *
- * @c3cn:	the h/w tcp connection representation
- * @hba:	pointer to the hba this conn. is going through
- * @cconn:	pointer to the associated cxgb3i iscsi connection
- */
-struct cxgb3i_endpoint {
-	struct s3_conn *c3cn;
-	struct cxgb3i_hba *hba;
-	struct cxgb3i_conn *cconn;
-};
-
-/**
- * struct cxgb3i_task_data - private iscsi task data
- *
- * @nr_frags:	# of coalesced page frags (from scsi sgl)
- * @frags:	coalesced page frags (from scsi sgl)
- * @skb:	tx pdu skb
- * @offset:	data offset for the next pdu
- * @count:	max. possible pdu payload
- * @sgoffset:	offset to the first sg entry for a given offset
- */
-#define MAX_PDU_FRAGS	((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
-struct cxgb3i_task_data {
-	unsigned short nr_frags;
-	skb_frag_t frags[MAX_PDU_FRAGS];
-	struct sk_buff *skb;
-	unsigned int offset;
-	unsigned int count;
-	unsigned int sgoffset;
-};
-
-int cxgb3i_iscsi_init(void);
-void cxgb3i_iscsi_cleanup(void);
-
-struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *);
-void cxgb3i_adapter_open(struct t3cdev *);
-void cxgb3i_adapter_close(struct t3cdev *);
-
-struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *,
-				       struct net_device *);
-void cxgb3i_hba_host_remove(struct cxgb3i_hba *);
-
-int cxgb3i_pdu_init(void);
-void cxgb3i_pdu_cleanup(void);
-void cxgb3i_conn_cleanup_task(struct iscsi_task *);
-int cxgb3i_conn_alloc_pdu(struct iscsi_task *, u8);
-int cxgb3i_conn_init_pdu(struct iscsi_task *, unsigned int, unsigned int);
-int cxgb3i_conn_xmit_pdu(struct iscsi_task *);
-
-void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt);
-int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt);
-
-#endif
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
deleted file mode 100644
index be0e230..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * cxgb3i_ddp.c: Chelsio S3xx iSCSI DDP Manager.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/scatterlist.h>
-
-/* from cxgb3 LLD */
-#include "common.h"
-#include "t3_cpl.h"
-#include "t3cdev.h"
-#include "cxgb3_ctl_defs.h"
-#include "cxgb3_offload.h"
-#include "firmware_exports.h"
-
-#include "cxgb3i_ddp.h"
-
-#define ddp_log_error(fmt...) printk(KERN_ERR "cxgb3i_ddp: ERR! " fmt)
-#define ddp_log_warn(fmt...)  printk(KERN_WARNING "cxgb3i_ddp: WARN! " fmt)
-#define ddp_log_info(fmt...)  printk(KERN_INFO "cxgb3i_ddp: " fmt)
-
-#ifdef __DEBUG_CXGB3I_DDP__
-#define ddp_log_debug(fmt, args...) \
-	printk(KERN_INFO "cxgb3i_ddp: %s - " fmt, __func__ , ## args)
-#else
-#define ddp_log_debug(fmt...)
-#endif
-
-/*
- * iSCSI Direct Data Placement
- *
- * T3 h/w can directly place the iSCSI Data-In or Data-Out PDU's payload into
- * pre-posted final destination host-memory buffers based on the Initiator
- * Task Tag (ITT) in Data-In or Target Task Tag (TTT) in Data-Out PDUs.
- *
- * The host memory address is programmed into h/w in the format of pagepod
- * entries.
- * The location of the pagepod entry is encoded into ddp tag which is used or
- * is the base for ITT/TTT.
- */
-
-#define DDP_PGIDX_MAX		4
-#define DDP_THRESHOLD	2048
-static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
-static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
-static unsigned char page_idx = DDP_PGIDX_MAX;
-
-/*
- * functions to program the pagepod in h/w
- */
-static inline void ulp_mem_io_set_hdr(struct sk_buff *skb, unsigned int addr)
-{
-	struct ulp_mem_io *req = (struct ulp_mem_io *)skb->head;
-
-	req->wr.wr_lo = 0;
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS));
-	req->cmd_lock_addr = htonl(V_ULP_MEMIO_ADDR(addr >> 5) |
-				   V_ULPTX_CMD(ULP_MEM_WRITE));
-	req->len = htonl(V_ULP_MEMIO_DATA_LEN(PPOD_SIZE >> 5) |
-			 V_ULPTX_NFLITS((PPOD_SIZE >> 3) + 1));
-}
-
-static int set_ddp_map(struct cxgb3i_ddp_info *ddp, struct pagepod_hdr *hdr,
-		       unsigned int idx, unsigned int npods,
-		       struct cxgb3i_gather_list *gl)
-{
-	unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
-	int i;
-
-	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
-		struct sk_buff *skb = ddp->gl_skb[idx];
-		struct pagepod *ppod;
-		int j, pidx;
-
-		/* hold on to the skb until we clear the ddp mapping */
-		skb_get(skb);
-
-		ulp_mem_io_set_hdr(skb, pm_addr);
-		ppod = (struct pagepod *)
-		       (skb->head + sizeof(struct ulp_mem_io));
-		memcpy(&(ppod->hdr), hdr, sizeof(struct pagepod));
-		for (pidx = 4 * i, j = 0; j < 5; ++j, ++pidx)
-			ppod->addr[j] = pidx < gl->nelem ?
-				     cpu_to_be64(gl->phys_addr[pidx]) : 0UL;
-
-		skb->priority = CPL_PRIORITY_CONTROL;
-		cxgb3_ofld_send(ddp->tdev, skb);
-	}
-	return 0;
-}
-
-static void clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int tag,
-			 unsigned int idx, unsigned int npods)
-{
-	unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
-	int i;
-
-	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
-		struct sk_buff *skb = ddp->gl_skb[idx];
-
-		if (!skb) {
-			ddp_log_error("ddp tag 0x%x, 0x%x, %d/%u, skb NULL.\n",
-					tag, idx, i, npods);
-			continue;
-		}
-		ddp->gl_skb[idx] = NULL;
-		memset((skb->head + sizeof(struct ulp_mem_io)), 0, PPOD_SIZE);
-		ulp_mem_io_set_hdr(skb, pm_addr);
-		skb->priority = CPL_PRIORITY_CONTROL;
-		cxgb3_ofld_send(ddp->tdev, skb);
-	}
-}
-
-static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp,
-					  unsigned int start, unsigned int max,
-					  unsigned int count,
-					  struct cxgb3i_gather_list *gl)
-{
-	unsigned int i, j, k;
-
-	/* not enough entries */
-	if ((max - start) < count)
-		return -EBUSY;
-
-	max -= count;
-	spin_lock(&ddp->map_lock);
-	for (i = start; i < max;) {
-		for (j = 0, k = i; j < count; j++, k++) {
-			if (ddp->gl_map[k])
-				break;
-		}
-		if (j == count) {
-			for (j = 0, k = i; j < count; j++, k++)
-				ddp->gl_map[k] = gl;
-			spin_unlock(&ddp->map_lock);
-			return i;
-		}
-		i += j + 1;
-	}
-	spin_unlock(&ddp->map_lock);
-	return -EBUSY;
-}
-
-static inline void ddp_unmark_entries(struct cxgb3i_ddp_info *ddp,
-				      int start, int count)
-{
-	spin_lock(&ddp->map_lock);
-	memset(&ddp->gl_map[start], 0,
-	       count * sizeof(struct cxgb3i_gather_list *));
-	spin_unlock(&ddp->map_lock);
-}
-
-static inline void ddp_free_gl_skb(struct cxgb3i_ddp_info *ddp,
-				   int idx, int count)
-{
-	int i;
-
-	for (i = 0; i < count; i++, idx++)
-		if (ddp->gl_skb[idx]) {
-			kfree_skb(ddp->gl_skb[idx]);
-			ddp->gl_skb[idx] = NULL;
-		}
-}
-
-static inline int ddp_alloc_gl_skb(struct cxgb3i_ddp_info *ddp, int idx,
-				   int count, gfp_t gfp)
-{
-	int i;
-
-	for (i = 0; i < count; i++) {
-		struct sk_buff *skb = alloc_skb(sizeof(struct ulp_mem_io) +
-						PPOD_SIZE, gfp);
-		if (skb) {
-			ddp->gl_skb[idx + i] = skb;
-			skb_put(skb, sizeof(struct ulp_mem_io) + PPOD_SIZE);
-		} else {
-			ddp_free_gl_skb(ddp, idx, i);
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-/**
- * cxgb3i_ddp_find_page_index - return ddp page index for a given page size
- * @pgsz: page size
- * return the ddp page index, if no match is found return DDP_PGIDX_MAX.
- */
-int cxgb3i_ddp_find_page_index(unsigned long pgsz)
-{
-	int i;
-
-	for (i = 0; i < DDP_PGIDX_MAX; i++) {
-		if (pgsz == (1UL << ddp_page_shift[i]))
-			return i;
-	}
-	ddp_log_debug("ddp page size 0x%lx not supported.\n", pgsz);
-	return DDP_PGIDX_MAX;
-}
-
-/**
- * cxgb3i_ddp_adjust_page_table - adjust page table with PAGE_SIZE
- * return the ddp page index, if no match is found return DDP_PGIDX_MAX.
- */
-int cxgb3i_ddp_adjust_page_table(void)
-{
-	int i;
-	unsigned int base_order, order;
-
-	if (PAGE_SIZE < (1UL << ddp_page_shift[0])) {
-		ddp_log_info("PAGE_SIZE 0x%lx too small, min. 0x%lx.\n",
-				PAGE_SIZE, 1UL << ddp_page_shift[0]);
-		return -EINVAL;
-	}
-
-	base_order = get_order(1UL << ddp_page_shift[0]);
-	order = get_order(1 << PAGE_SHIFT);
-	for (i = 0; i < DDP_PGIDX_MAX; i++) {
-		/* first is the kernel page size, then just doubling the size */
-		ddp_page_order[i] = order - base_order + i;
-		ddp_page_shift[i] = PAGE_SHIFT + i;
-	}
-	return 0;
-}
-
-static inline void ddp_gl_unmap(struct pci_dev *pdev,
-				struct cxgb3i_gather_list *gl)
-{
-	int i;
-
-	for (i = 0; i < gl->nelem; i++)
-		pci_unmap_page(pdev, gl->phys_addr[i], PAGE_SIZE,
-			       PCI_DMA_FROMDEVICE);
-}
-
-static inline int ddp_gl_map(struct pci_dev *pdev,
-			     struct cxgb3i_gather_list *gl)
-{
-	int i;
-
-	for (i = 0; i < gl->nelem; i++) {
-		gl->phys_addr[i] = pci_map_page(pdev, gl->pages[i], 0,
-						PAGE_SIZE,
-						PCI_DMA_FROMDEVICE);
-		if (unlikely(pci_dma_mapping_error(pdev, gl->phys_addr[i])))
-			goto unmap;
-	}
-
-	return i;
-
-unmap:
-	if (i) {
-		unsigned int nelem = gl->nelem;
-
-		gl->nelem = i;
-		ddp_gl_unmap(pdev, gl);
-		gl->nelem = nelem;
-	}
-	return -ENOMEM;
-}
-
-/**
- * cxgb3i_ddp_make_gl - build ddp page buffer list
- * @xferlen: total buffer length
- * @sgl: page buffer scatter-gather list
- * @sgcnt: # of page buffers
- * @pdev: pci_dev, used for pci map
- * @gfp: allocation mode
- *
- * construct a ddp page buffer list from the scsi scattergather list.
- * coalesce buffers as much as possible, and obtain dma addresses for
- * each page.
- *
- * Return the cxgb3i_gather_list constructed from the page buffers if the
- * memory can be used for ddp. Return NULL otherwise.
- */
-struct cxgb3i_gather_list *cxgb3i_ddp_make_gl(unsigned int xferlen,
-					      struct scatterlist *sgl,
-					      unsigned int sgcnt,
-					      struct pci_dev *pdev,
-					      gfp_t gfp)
-{
-	struct cxgb3i_gather_list *gl;
-	struct scatterlist *sg = sgl;
-	struct page *sgpage = sg_page(sg);
-	unsigned int sglen = sg->length;
-	unsigned int sgoffset = sg->offset;
-	unsigned int npages = (xferlen + sgoffset + PAGE_SIZE - 1) >>
-			      PAGE_SHIFT;
-	int i = 1, j = 0;
-
-	if (xferlen < DDP_THRESHOLD) {
-		ddp_log_debug("xfer %u < threshold %u, no ddp.\n",
-			      xferlen, DDP_THRESHOLD);
-		return NULL;
-	}
-
-	gl = kzalloc(sizeof(struct cxgb3i_gather_list) +
-		     npages * (sizeof(dma_addr_t) + sizeof(struct page *)),
-		     gfp);
-	if (!gl)
-		return NULL;
-
-	gl->pages = (struct page **)&gl->phys_addr[npages];
-	gl->length = xferlen;
-	gl->offset = sgoffset;
-	gl->pages[0] = sgpage;
-
-	sg = sg_next(sg);
-	while (sg) {
-		struct page *page = sg_page(sg);
-
-		if (sgpage == page && sg->offset == sgoffset + sglen)
-			sglen += sg->length;
-		else {
-			/* make sure the sgl is fit for ddp:
-			 * each has the same page size, and
-			 * all of the middle pages are used completely
-			 */
-			if ((j && sgoffset) ||
-			    ((i != sgcnt - 1) &&
-			     ((sglen + sgoffset) & ~PAGE_MASK)))
-				goto error_out;
-
-			j++;
-			if (j == gl->nelem || sg->offset)
-				goto error_out;
-			gl->pages[j] = page;
-			sglen = sg->length;
-			sgoffset = sg->offset;
-			sgpage = page;
-		}
-		i++;
-		sg = sg_next(sg);
-	}
-	gl->nelem = ++j;
-
-	if (ddp_gl_map(pdev, gl) < 0)
-		goto error_out;
-
-	return gl;
-
-error_out:
-	kfree(gl);
-	return NULL;
-}
-
-/**
- * cxgb3i_ddp_release_gl - release a page buffer list
- * @gl: a ddp page buffer list
- * @pdev: pci_dev used for pci_unmap
- * free a ddp page buffer list resulted from cxgb3i_ddp_make_gl().
- */
-void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
-			   struct pci_dev *pdev)
-{
-	ddp_gl_unmap(pdev, gl);
-	kfree(gl);
-}
-
-/**
- * cxgb3i_ddp_tag_reserve - set up ddp for a data transfer
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @tformat: tag format
- * @tagp: contains s/w tag initially, will be updated with ddp/hw tag
- * @gl: the page momory list
- * @gfp: allocation mode
- *
- * ddp setup for a given page buffer list and construct the ddp tag.
- * return 0 if success, < 0 otherwise.
- */
-int cxgb3i_ddp_tag_reserve(struct t3cdev *tdev, unsigned int tid,
-			   struct cxgb3i_tag_format *tformat, u32 *tagp,
-			   struct cxgb3i_gather_list *gl, gfp_t gfp)
-{
-	struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
-	struct pagepod_hdr hdr;
-	unsigned int npods;
-	int idx = -1;
-	int err = -ENOMEM;
-	u32 sw_tag = *tagp;
-	u32 tag;
-
-	if (page_idx >= DDP_PGIDX_MAX || !ddp || !gl || !gl->nelem ||
-		gl->length < DDP_THRESHOLD) {
-		ddp_log_debug("pgidx %u, xfer %u/%u, NO ddp.\n",
-			      page_idx, gl->length, DDP_THRESHOLD);
-		return -EINVAL;
-	}
-
-	npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
-
-	if (ddp->idx_last == ddp->nppods)
-		idx = ddp_find_unused_entries(ddp, 0, ddp->nppods, npods, gl);
-	else {
-		idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1,
-					      ddp->nppods, npods, gl);
-		if (idx < 0 && ddp->idx_last >= npods) {
-			idx = ddp_find_unused_entries(ddp, 0,
-				min(ddp->idx_last + npods, ddp->nppods),
-						      npods, gl);
-		}
-	}
-	if (idx < 0) {
-		ddp_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n",
-			      gl->length, gl->nelem, npods);
-		return idx;
-	}
-
-	err = ddp_alloc_gl_skb(ddp, idx, npods, gfp);
-	if (err < 0)
-		goto unmark_entries;
-
-	tag = cxgb3i_ddp_tag_base(tformat, sw_tag);
-	tag |= idx << PPOD_IDX_SHIFT;
-
-	hdr.rsvd = 0;
-	hdr.vld_tid = htonl(F_PPOD_VALID | V_PPOD_TID(tid));
-	hdr.pgsz_tag_clr = htonl(tag & ddp->rsvd_tag_mask);
-	hdr.maxoffset = htonl(gl->length);
-	hdr.pgoffset = htonl(gl->offset);
-
-	err = set_ddp_map(ddp, &hdr, idx, npods, gl);
-	if (err < 0)
-		goto free_gl_skb;
-
-	ddp->idx_last = idx;
-	ddp_log_debug("xfer %u, gl %u,%u, tid 0x%x, 0x%x -> 0x%x(%u,%u).\n",
-		      gl->length, gl->nelem, gl->offset, tid, sw_tag, tag,
-		      idx, npods);
-	*tagp = tag;
-	return 0;
-
-free_gl_skb:
-	ddp_free_gl_skb(ddp, idx, npods);
-unmark_entries:
-	ddp_unmark_entries(ddp, idx, npods);
-	return err;
-}
-
-/**
- * cxgb3i_ddp_tag_release - release a ddp tag
- * @tdev: t3cdev adapter
- * @tag: ddp tag
- * ddp cleanup for a given ddp tag and release all the resources held
- */
-void cxgb3i_ddp_tag_release(struct t3cdev *tdev, u32 tag)
-{
-	struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
-	u32 idx;
-
-	if (!ddp) {
-		ddp_log_error("release ddp tag 0x%x, ddp NULL.\n", tag);
-		return;
-	}
-
-	idx = (tag >> PPOD_IDX_SHIFT) & ddp->idx_mask;
-	if (idx < ddp->nppods) {
-		struct cxgb3i_gather_list *gl = ddp->gl_map[idx];
-		unsigned int npods;
-
-		if (!gl || !gl->nelem) {
-			ddp_log_error("release 0x%x, idx 0x%x, gl 0x%p, %u.\n",
-				      tag, idx, gl, gl ? gl->nelem : 0);
-			return;
-		}
-		npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
-		ddp_log_debug("ddp tag 0x%x, release idx 0x%x, npods %u.\n",
-			      tag, idx, npods);
-		clear_ddp_map(ddp, tag, idx, npods);
-		ddp_unmark_entries(ddp, idx, npods);
-		cxgb3i_ddp_release_gl(gl, ddp->pdev);
-	} else
-		ddp_log_error("ddp tag 0x%x, idx 0x%x > max 0x%x.\n",
-			      tag, idx, ddp->nppods);
-}
-
-static int setup_conn_pgidx(struct t3cdev *tdev, unsigned int tid, int pg_idx,
-			    int reply)
-{
-	struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
-					GFP_KERNEL);
-	struct cpl_set_tcb_field *req;
-	u64 val = pg_idx < DDP_PGIDX_MAX ? pg_idx : 0;
-
-	if (!skb)
-		return -ENOMEM;
-
-	/* set up ulp submode and page size */
-	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	req->wr.wr_lo = 0;
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-	req->reply = V_NO_REPLY(reply ? 0 : 1);
-	req->cpu_idx = 0;
-	req->word = htons(31);
-	req->mask = cpu_to_be64(0xF0000000);
-	req->val = cpu_to_be64(val << 28);
-	skb->priority = CPL_PRIORITY_CONTROL;
-
-	cxgb3_ofld_send(tdev, skb);
-	return 0;
-}
-
-/**
- * cxgb3i_setup_conn_host_pagesize - setup the conn.'s ddp page size
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @reply: request reply from h/w
- * set up the ddp page size based on the host PAGE_SIZE for a connection
- * identified by tid
- */
-int cxgb3i_setup_conn_host_pagesize(struct t3cdev *tdev, unsigned int tid,
-				    int reply)
-{
-	return setup_conn_pgidx(tdev, tid, page_idx, reply);
-}
-
-/**
- * cxgb3i_setup_conn_pagesize - setup the conn.'s ddp page size
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @reply: request reply from h/w
- * @pgsz: ddp page size
- * set up the ddp page size for a connection identified by tid
- */
-int cxgb3i_setup_conn_pagesize(struct t3cdev *tdev, unsigned int tid,
-				int reply, unsigned long pgsz)
-{
-	int pgidx = cxgb3i_ddp_find_page_index(pgsz);
-
-	return setup_conn_pgidx(tdev, tid, pgidx, reply);
-}
-
-/**
- * cxgb3i_setup_conn_digest - setup conn. digest setting
- * @tdev: t3cdev adapter
- * @tid: connection id
- * @hcrc: header digest enabled
- * @dcrc: data digest enabled
- * @reply: request reply from h/w
- * set up the iscsi digest settings for a connection identified by tid
- */
-int cxgb3i_setup_conn_digest(struct t3cdev *tdev, unsigned int tid,
-			     int hcrc, int dcrc, int reply)
-{
-	struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
-					GFP_KERNEL);
-	struct cpl_set_tcb_field *req;
-	u64 val = (hcrc ? 1 : 0) | (dcrc ? 2 : 0);
-
-	if (!skb)
-		return -ENOMEM;
-
-	/* set up ulp submode and page size */
-	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	req->wr.wr_lo = 0;
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-	req->reply = V_NO_REPLY(reply ? 0 : 1);
-	req->cpu_idx = 0;
-	req->word = htons(31);
-	req->mask = cpu_to_be64(0x0F000000);
-	req->val = cpu_to_be64(val << 24);
-	skb->priority = CPL_PRIORITY_CONTROL;
-
-	cxgb3_ofld_send(tdev, skb);
-	return 0;
-}
-
-
-/**
- * cxgb3i_adapter_ddp_info - read the adapter's ddp information
- * @tdev: t3cdev adapter
- * @tformat: tag format
- * @txsz: max tx pdu payload size, filled in by this func.
- * @rxsz: max rx pdu payload size, filled in by this func.
- * setup the tag format for a given iscsi entity
- */
-int cxgb3i_adapter_ddp_info(struct t3cdev *tdev,
-			    struct cxgb3i_tag_format *tformat,
-			    unsigned int *txsz, unsigned int *rxsz)
-{
-	struct cxgb3i_ddp_info *ddp;
-	unsigned char idx_bits;
-
-	if (!tformat)
-		return -EINVAL;
-
-	if (!tdev->ulp_iscsi)
-		return -EINVAL;
-
-	ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
-
-	idx_bits = 32 - tformat->sw_bits;
-	tformat->rsvd_bits = ddp->idx_bits;
-	tformat->rsvd_shift = PPOD_IDX_SHIFT;
-	tformat->rsvd_mask = (1 << tformat->rsvd_bits) - 1;
-
-	ddp_log_info("tag format: sw %u, rsvd %u,%u, mask 0x%x.\n",
-		      tformat->sw_bits, tformat->rsvd_bits,
-		      tformat->rsvd_shift, tformat->rsvd_mask);
-
-	*txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
-			ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
-	*rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
-			ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
-	ddp_log_info("max payload size: %u/%u, %u/%u.\n",
-		     *txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz);
-	return 0;
-}
-
-/**
- * cxgb3i_ddp_cleanup - release the cxgb3 adapter's ddp resource
- * @tdev: t3cdev adapter
- * release all the resource held by the ddp pagepod manager for a given
- * adapter if needed
- */
-
-static void ddp_cleanup(struct kref *kref)
-{
-	struct cxgb3i_ddp_info *ddp = container_of(kref,
-						struct cxgb3i_ddp_info,
-						refcnt);
-	int i = 0;
-
-	ddp_log_info("kref release ddp 0x%p, t3dev 0x%p.\n", ddp, ddp->tdev);
-
-	ddp->tdev->ulp_iscsi = NULL;
-	while (i < ddp->nppods) {
-		struct cxgb3i_gather_list *gl = ddp->gl_map[i];
-		if (gl) {
-			int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
-					>> PPOD_PAGES_SHIFT;
-			ddp_log_info("t3dev 0x%p, ddp %d + %d.\n",
-					ddp->tdev, i, npods);
-			kfree(gl);
-			ddp_free_gl_skb(ddp, i, npods);
-			i += npods;
-		} else
-			i++;
-	}
-	cxgb3i_free_big_mem(ddp);
-}
-
-void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
-{
-	struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
-
-	ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp);
-	if (ddp)
-		kref_put(&ddp->refcnt, ddp_cleanup);
-}
-
-/**
- * ddp_init - initialize the cxgb3 adapter's ddp resource
- * @tdev: t3cdev adapter
- * initialize the ddp pagepod manager for a given adapter
- */
-static void ddp_init(struct t3cdev *tdev)
-{
-	struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
-	struct ulp_iscsi_info uinfo;
-	unsigned int ppmax, bits;
-	int i, err;
-
-	if (ddp) {
-		kref_get(&ddp->refcnt);
-		ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
-				tdev, tdev->ulp_iscsi);
-		return;
-	}
-
-	err = tdev->ctl(tdev, ULP_ISCSI_GET_PARAMS, &uinfo);
-	if (err < 0) {
-		ddp_log_error("%s, failed to get iscsi param err=%d.\n",
-				 tdev->name, err);
-		return;
-	}
-
-	ppmax = (uinfo.ulimit - uinfo.llimit + 1) >> PPOD_SIZE_SHIFT;
-	bits = __ilog2_u32(ppmax) + 1;
-	if (bits > PPOD_IDX_MAX_SIZE)
-		bits = PPOD_IDX_MAX_SIZE;
-	ppmax = (1 << (bits - 1)) - 1;
-
-	ddp = cxgb3i_alloc_big_mem(sizeof(struct cxgb3i_ddp_info) +
-				   ppmax *
-					(sizeof(struct cxgb3i_gather_list *) +
-					sizeof(struct sk_buff *)),
-				   GFP_KERNEL);
-	if (!ddp) {
-		ddp_log_warn("%s unable to alloc ddp 0x%d, ddp disabled.\n",
-			     tdev->name, ppmax);
-		return;
-	}
-	ddp->gl_map = (struct cxgb3i_gather_list **)(ddp + 1);
-	ddp->gl_skb = (struct sk_buff **)(((char *)ddp->gl_map) +
-					  ppmax *
-					  sizeof(struct cxgb3i_gather_list *));
-	spin_lock_init(&ddp->map_lock);
-	kref_init(&ddp->refcnt);
-
-	ddp->tdev = tdev;
-	ddp->pdev = uinfo.pdev;
-	ddp->max_txsz = min_t(unsigned int, uinfo.max_txsz, ULP2_MAX_PKT_SIZE);
-	ddp->max_rxsz = min_t(unsigned int, uinfo.max_rxsz, ULP2_MAX_PKT_SIZE);
-	ddp->llimit = uinfo.llimit;
-	ddp->ulimit = uinfo.ulimit;
-	ddp->nppods = ppmax;
-	ddp->idx_last = ppmax;
-	ddp->idx_bits = bits;
-	ddp->idx_mask = (1 << bits) - 1;
-	ddp->rsvd_tag_mask = (1 << (bits + PPOD_IDX_SHIFT)) - 1;
-
-	uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
-	for (i = 0; i < DDP_PGIDX_MAX; i++)
-		uinfo.pgsz_factor[i] = ddp_page_order[i];
-	uinfo.ulimit = uinfo.llimit + (ppmax << PPOD_SIZE_SHIFT);
-
-	err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo);
-	if (err < 0) {
-		ddp_log_warn("%s unable to set iscsi param err=%d, "
-			      "ddp disabled.\n", tdev->name, err);
-		goto free_ddp_map;
-	}
-
-	tdev->ulp_iscsi = ddp;
-
-	ddp_log_info("tdev 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u,"
-			" %u/%u.\n",
-			tdev, ppmax, ddp->idx_bits, ddp->idx_mask,
-			ddp->rsvd_tag_mask, ddp->max_txsz, uinfo.max_txsz,
-			ddp->max_rxsz, uinfo.max_rxsz);
-	return;
-
-free_ddp_map:
-	cxgb3i_free_big_mem(ddp);
-}
-
-/**
- * cxgb3i_ddp_init - initialize ddp functions
- */
-void cxgb3i_ddp_init(struct t3cdev *tdev)
-{
-	if (page_idx == DDP_PGIDX_MAX) {
-		page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
-
-		if (page_idx == DDP_PGIDX_MAX) {
-			ddp_log_info("system PAGE_SIZE %lu, update hw.\n",
-					PAGE_SIZE);
-			if (cxgb3i_ddp_adjust_page_table() < 0) {
-				ddp_log_info("PAGE_SIZE %lu, ddp disabled.\n",
-						PAGE_SIZE);
-				return;
-			}
-			page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
-		}
-		ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n",
-				PAGE_SIZE, page_idx);
-	}
-	ddp_init(tdev);
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h
deleted file mode 100644
index 6761b32..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * cxgb3i_ddp.h: Chelsio S3xx iSCSI DDP Manager.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB3I_ULP2_DDP_H__
-#define __CXGB3I_ULP2_DDP_H__
-
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-/**
- * struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity
- *
- * @sw_bits:	# of bits used by iscsi software layer
- * @rsvd_bits:	# of bits used by h/w
- * @rsvd_shift:	h/w bits shift left
- * @rsvd_mask:	reserved bit mask
- */
-struct cxgb3i_tag_format {
-	unsigned char sw_bits;
-	unsigned char rsvd_bits;
-	unsigned char rsvd_shift;
-	unsigned char filler[1];
-	u32 rsvd_mask;
-};
-
-/**
- * struct cxgb3i_gather_list - cxgb3i direct data placement memory
- *
- * @tag:	ddp tag
- * @length:	total data buffer length
- * @offset:	initial offset to the 1st page
- * @nelem:	# of pages
- * @pages:	page pointers
- * @phys_addr:	physical address
- */
-struct cxgb3i_gather_list {
-	u32 tag;
-	unsigned int length;
-	unsigned int offset;
-	unsigned int nelem;
-	struct page **pages;
-	dma_addr_t phys_addr[0];
-};
-
-/**
- * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload
- *
- * @list:	list head to link elements
- * @refcnt:	ref. count
- * @tdev:	pointer to t3cdev used by cxgb3 driver
- * @max_txsz:	max tx packet size for ddp
- * @max_rxsz:	max rx packet size for ddp
- * @llimit:	lower bound of the page pod memory
- * @ulimit:	upper bound of the page pod memory
- * @nppods:	# of page pod entries
- * @idx_last:	page pod entry last used
- * @idx_bits:	# of bits the pagepod index would take
- * @idx_mask:	pagepod index mask
- * @rsvd_tag_mask: tag mask
- * @map_lock:	lock to synchonize access to the page pod map
- * @gl_map:	ddp memory gather list
- * @gl_skb:	skb used to program the pagepod
- */
-struct cxgb3i_ddp_info {
-	struct list_head list;
-	struct kref refcnt;
-	struct t3cdev *tdev;
-	struct pci_dev *pdev;
-	unsigned int max_txsz;
-	unsigned int max_rxsz;
-	unsigned int llimit;
-	unsigned int ulimit;
-	unsigned int nppods;
-	unsigned int idx_last;
-	unsigned char idx_bits;
-	unsigned char filler[3];
-	u32 idx_mask;
-	u32 rsvd_tag_mask;
-	spinlock_t map_lock;
-	struct cxgb3i_gather_list **gl_map;
-	struct sk_buff **gl_skb;
-};
-
-#define ISCSI_PDU_NONPAYLOAD_LEN	312 /* bhs(48) + ahs(256) + digest(8) */
-#define ULP2_MAX_PKT_SIZE	16224
-#define ULP2_MAX_PDU_PAYLOAD	(ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
-#define PPOD_PAGES_MAX		4
-#define PPOD_PAGES_SHIFT	2	/* 4 pages per pod */
-
-/*
- * struct pagepod_hdr, pagepod - pagepod format
- */
-struct pagepod_hdr {
-	u32 vld_tid;
-	u32 pgsz_tag_clr;
-	u32 maxoffset;
-	u32 pgoffset;
-	u64 rsvd;
-};
-
-struct pagepod {
-	struct pagepod_hdr hdr;
-	u64 addr[PPOD_PAGES_MAX + 1];
-};
-
-#define PPOD_SIZE		sizeof(struct pagepod)	/* 64 */
-#define PPOD_SIZE_SHIFT		6
-
-#define PPOD_COLOR_SHIFT	0
-#define PPOD_COLOR_SIZE		6
-#define PPOD_COLOR_MASK		((1 << PPOD_COLOR_SIZE) - 1)
-
-#define PPOD_IDX_SHIFT		PPOD_COLOR_SIZE
-#define PPOD_IDX_MAX_SIZE	24
-
-#define S_PPOD_TID    0
-#define M_PPOD_TID    0xFFFFFF
-#define V_PPOD_TID(x) ((x) << S_PPOD_TID)
-
-#define S_PPOD_VALID    24
-#define V_PPOD_VALID(x) ((x) << S_PPOD_VALID)
-#define F_PPOD_VALID    V_PPOD_VALID(1U)
-
-#define S_PPOD_COLOR    0
-#define M_PPOD_COLOR    0x3F
-#define V_PPOD_COLOR(x) ((x) << S_PPOD_COLOR)
-
-#define S_PPOD_TAG    6
-#define M_PPOD_TAG    0xFFFFFF
-#define V_PPOD_TAG(x) ((x) << S_PPOD_TAG)
-
-#define S_PPOD_PGSZ    30
-#define M_PPOD_PGSZ    0x3
-#define V_PPOD_PGSZ(x) ((x) << S_PPOD_PGSZ)
-
-/*
- * large memory chunk allocation/release
- * use vmalloc() if kmalloc() fails
- */
-static inline void *cxgb3i_alloc_big_mem(unsigned int size,
-					 gfp_t gfp)
-{
-	void *p = kmalloc(size, gfp);
-	if (!p)
-		p = vmalloc(size);
-	if (p)
-		memset(p, 0, size);
-	return p;
-}
-
-static inline void cxgb3i_free_big_mem(void *addr)
-{
-	if (is_vmalloc_addr(addr))
-		vfree(addr);
-	else
-		kfree(addr);
-}
-
-/*
- * cxgb3i ddp tag are 32 bits, it consists of reserved bits used by h/w and
- * non-reserved bits that can be used by the iscsi s/w.
- * The reserved bits are identified by the rsvd_bits and rsvd_shift fields
- * in struct cxgb3i_tag_format.
- *
- * The upper most reserved bit can be used to check if a tag is ddp tag or not:
- * 	if the bit is 0, the tag is a valid ddp tag
- */
-
-/**
- * cxgb3i_is_ddp_tag - check if a given tag is a hw/ddp tag
- * @tformat: tag format information
- * @tag: tag to be checked
- *
- * return true if the tag is a ddp tag, false otherwise.
- */
-static inline int cxgb3i_is_ddp_tag(struct cxgb3i_tag_format *tformat, u32 tag)
-{
-	return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
-}
-
-/**
- * cxgb3i_sw_tag_usable - check if s/w tag has enough bits left for hw bits
- * @tformat: tag format information
- * @sw_tag: s/w tag to be checked
- *
- * return true if the tag can be used for hw ddp tag, false otherwise.
- */
-static inline int cxgb3i_sw_tag_usable(struct cxgb3i_tag_format *tformat,
-					u32 sw_tag)
-{
-	sw_tag >>= (32 - tformat->rsvd_bits);
-	return !sw_tag;
-}
-
-/**
- * cxgb3i_set_non_ddp_tag - mark a given s/w tag as an invalid ddp tag
- * @tformat: tag format information
- * @sw_tag: s/w tag to be checked
- *
- * insert 1 at the upper most reserved bit to mark it as an invalid ddp tag.
- */
-static inline u32 cxgb3i_set_non_ddp_tag(struct cxgb3i_tag_format *tformat,
-					 u32 sw_tag)
-{
-	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
-	u32 mask = (1 << shift) - 1;
-
-	if (sw_tag && (sw_tag & ~mask)) {
-		u32 v1 = sw_tag & ((1 << shift) - 1);
-		u32 v2 = (sw_tag >> (shift - 1)) << shift;
-
-		return v2 | v1 | 1 << shift;
-	}
-	return sw_tag | 1 << shift;
-}
-
-/**
- * cxgb3i_ddp_tag_base - shift s/w tag bits so that reserved bits are not used
- * @tformat: tag format information
- * @sw_tag: s/w tag to be checked
- */
-static inline u32 cxgb3i_ddp_tag_base(struct cxgb3i_tag_format *tformat,
-				      u32 sw_tag)
-{
-	u32 mask = (1 << tformat->rsvd_shift) - 1;
-
-	if (sw_tag && (sw_tag & ~mask)) {
-		u32 v1 = sw_tag & mask;
-		u32 v2 = sw_tag >> tformat->rsvd_shift;
-
-		v2 <<= tformat->rsvd_shift + tformat->rsvd_bits;
-		return v2 | v1;
-	}
-	return sw_tag;
-}
-
-/**
- * cxgb3i_tag_rsvd_bits - get the reserved bits used by the h/w
- * @tformat: tag format information
- * @tag: tag to be checked
- *
- * return the reserved bits in the tag
- */
-static inline u32 cxgb3i_tag_rsvd_bits(struct cxgb3i_tag_format *tformat,
-				       u32 tag)
-{
-	if (cxgb3i_is_ddp_tag(tformat, tag))
-		return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
-	return 0;
-}
-
-/**
- * cxgb3i_tag_nonrsvd_bits - get the non-reserved bits used by the s/w
- * @tformat: tag format information
- * @tag: tag to be checked
- *
- * return the non-reserved bits in the tag.
- */
-static inline u32 cxgb3i_tag_nonrsvd_bits(struct cxgb3i_tag_format *tformat,
-					  u32 tag)
-{
-	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
-	u32 v1, v2;
-
-	if (cxgb3i_is_ddp_tag(tformat, tag)) {
-		v1 = tag & ((1 << tformat->rsvd_shift) - 1);
-		v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
-	} else {
-		u32 mask = (1 << shift) - 1;
-
-		tag &= ~(1 << shift);
-		v1 = tag & mask;
-		v2 = (tag >> 1) & ~mask;
-	}
-	return v1 | v2;
-}
-
-int cxgb3i_ddp_tag_reserve(struct t3cdev *, unsigned int tid,
-			   struct cxgb3i_tag_format *, u32 *tag,
-			   struct cxgb3i_gather_list *, gfp_t gfp);
-void cxgb3i_ddp_tag_release(struct t3cdev *, u32 tag);
-
-struct cxgb3i_gather_list *cxgb3i_ddp_make_gl(unsigned int xferlen,
-				struct scatterlist *sgl,
-				unsigned int sgcnt,
-				struct pci_dev *pdev,
-				gfp_t gfp);
-void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
-				struct pci_dev *pdev);
-
-int cxgb3i_setup_conn_host_pagesize(struct t3cdev *, unsigned int tid,
-				    int reply);
-int cxgb3i_setup_conn_pagesize(struct t3cdev *, unsigned int tid, int reply,
-			       unsigned long pgsz);
-int cxgb3i_setup_conn_digest(struct t3cdev *, unsigned int tid,
-				int hcrc, int dcrc, int reply);
-int cxgb3i_ddp_find_page_index(unsigned long pgsz);
-int cxgb3i_adapter_ddp_info(struct t3cdev *, struct cxgb3i_tag_format *,
-			    unsigned int *txsz, unsigned int *rxsz);
-
-void cxgb3i_ddp_init(struct t3cdev *);
-void cxgb3i_ddp_cleanup(struct t3cdev *);
-#endif
diff --git a/drivers/scsi/cxgb3i/cxgb3i_init.c b/drivers/scsi/cxgb3i/cxgb3i_init.c
deleted file mode 100644
index 685af36..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_init.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/* cxgb3i_init.c: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include "cxgb3i.h"
-
-#define DRV_MODULE_NAME         "cxgb3i"
-#define DRV_MODULE_VERSION	"1.0.2"
-#define DRV_MODULE_RELDATE	"Mar. 2009"
-
-static char version[] =
-	"Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME
-	" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
-
-MODULE_AUTHOR("Karen Xie <kxie@chelsio.com>");
-MODULE_DESCRIPTION("Chelsio S3xx iSCSI Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_MODULE_VERSION);
-
-static void open_s3_dev(struct t3cdev *);
-static void close_s3_dev(struct t3cdev *);
-static void s3_event_handler(struct t3cdev *tdev, u32 event, u32 port);
-
-static cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
-static struct cxgb3_client t3c_client = {
-	.name = "iscsi_cxgb3",
-	.handlers = cxgb3i_cpl_handlers,
-	.add = open_s3_dev,
-	.remove = close_s3_dev,
-	.event_handler = s3_event_handler,
-};
-
-/**
- * open_s3_dev - register with cxgb3 LLD
- * @t3dev:	cxgb3 adapter instance
- */
-static void open_s3_dev(struct t3cdev *t3dev)
-{
-	static int vers_printed;
-
-	if (!vers_printed) {
-		printk(KERN_INFO "%s", version);
-		vers_printed = 1;
-	}
-
-	cxgb3i_ddp_init(t3dev);
-	cxgb3i_sdev_add(t3dev, &t3c_client);
-	cxgb3i_adapter_open(t3dev);
-}
-
-/**
- * close_s3_dev - de-register with cxgb3 LLD
- * @t3dev:	cxgb3 adapter instance
- */
-static void close_s3_dev(struct t3cdev *t3dev)
-{
-	cxgb3i_adapter_close(t3dev);
-	cxgb3i_sdev_remove(t3dev);
-	cxgb3i_ddp_cleanup(t3dev);
-}
-
-static void s3_event_handler(struct t3cdev *tdev, u32 event, u32 port)
-{
-	struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(tdev);
-
-	cxgb3i_log_info("snic 0x%p, tdev 0x%p, event 0x%x, port 0x%x.\n",
-			snic, tdev, event, port);
-	if (!snic)
-		return;
-
-	switch (event) {
-	case OFFLOAD_STATUS_DOWN:
-		snic->flags |= CXGB3I_ADAPTER_FLAG_RESET;
-		break;
-	case OFFLOAD_STATUS_UP:
-		snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
-		break;
-	}
-}
-
-/**
- * cxgb3i_init_module - module init entry point
- *
- * initialize any driver wide global data structures and register itself
- *	with the cxgb3 module
- */
-static int __init cxgb3i_init_module(void)
-{
-	int err;
-
-	err = cxgb3i_sdev_init(cxgb3i_cpl_handlers);
-	if (err < 0)
-		return err;
-
-	err = cxgb3i_iscsi_init();
-	if (err < 0)
-		return err;
-
-	err = cxgb3i_pdu_init();
-	if (err < 0) {
-		cxgb3i_iscsi_cleanup();
-		return err;
-	}
-
-	cxgb3_register_client(&t3c_client);
-
-	return 0;
-}
-
-/**
- * cxgb3i_exit_module - module cleanup/exit entry point
- *
- * go through the driver hba list and for each hba, release any resource held.
- *	and unregisters iscsi transport and the cxgb3 module
- */
-static void __exit cxgb3i_exit_module(void)
-{
-	cxgb3_unregister_client(&t3c_client);
-	cxgb3i_pdu_cleanup();
-	cxgb3i_iscsi_cleanup();
-	cxgb3i_sdev_cleanup();
-}
-
-module_init(cxgb3i_init_module);
-module_exit(cxgb3i_exit_module);
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
deleted file mode 100644
index 7b686ab..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+++ /dev/null
@@ -1,1018 +0,0 @@
-/* cxgb3i_iscsi.c: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, Inc.
- * Copyright (c) 2008 Mike Christie
- * Copyright (c) 2008 Red Hat, Inc.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/inet.h>
-#include <linux/slab.h>
-#include <linux/crypto.h>
-#include <linux/if_vlan.h>
-#include <net/dst.h>
-#include <net/tcp.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi.h>
-#include <scsi/iscsi_proto.h>
-#include <scsi/libiscsi.h>
-#include <scsi/scsi_transport_iscsi.h>
-
-#include "cxgb3i.h"
-#include "cxgb3i_pdu.h"
-
-#ifdef __DEBUG_CXGB3I_TAG__
-#define cxgb3i_tag_debug	cxgb3i_log_debug
-#else
-#define cxgb3i_tag_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_CXGB3I_API__
-#define cxgb3i_api_debug	cxgb3i_log_debug
-#else
-#define cxgb3i_api_debug(fmt...)
-#endif
-
-/*
- * align pdu size to multiple of 512 for better performance
- */
-#define align_pdu_size(n) do { n = (n) & (~511); } while (0)
-
-static struct scsi_transport_template *cxgb3i_scsi_transport;
-static struct scsi_host_template cxgb3i_host_template;
-static struct iscsi_transport cxgb3i_iscsi_transport;
-static unsigned char sw_tag_idx_bits;
-static unsigned char sw_tag_age_bits;
-
-static LIST_HEAD(cxgb3i_snic_list);
-static DEFINE_RWLOCK(cxgb3i_snic_rwlock);
-
-/**
- * cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev
- * @tdev: t3cdev pointer
- */
-struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev)
-{
-	struct cxgb3i_adapter *snic;
-
-	read_lock(&cxgb3i_snic_rwlock);
-	list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
-		if (snic->tdev == tdev) {
-			read_unlock(&cxgb3i_snic_rwlock);
-			return snic;
-		}
-	}
-	read_unlock(&cxgb3i_snic_rwlock);
-	return NULL;
-}
-
-static inline int adapter_update(struct cxgb3i_adapter *snic)
-{
-	cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n",
-			snic, snic->tdev);
-	return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format,
-					&snic->tx_max_size,
-					&snic->rx_max_size);
-}
-
-static int adapter_add(struct cxgb3i_adapter *snic)
-{
-	struct t3cdev *t3dev = snic->tdev;
-	struct adapter *adapter = tdev2adap(t3dev);
-	int i, err;
-
-	snic->pdev = adapter->pdev;
-	snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
-
-	err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format,
-				    &snic->tx_max_size,
-				    &snic->rx_max_size);
-	if (err < 0)
-		return err;
-
-	for_each_port(adapter, i) {
-		snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]);
-		if (!snic->hba[i])
-			return -EINVAL;
-	}
-	snic->hba_cnt = adapter->params.nports;
-
-	/* add to the list */
-	write_lock(&cxgb3i_snic_rwlock);
-	list_add_tail(&snic->list_head, &cxgb3i_snic_list);
-	write_unlock(&cxgb3i_snic_rwlock);
-
-	cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n",
-			t3dev, snic, snic->hba_cnt);
-	return 0;
-}
-
-/**
- * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
- * @t3dev: t3cdev adapter
- */
-void cxgb3i_adapter_open(struct t3cdev *t3dev)
-{
-	struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
-	int err;
-
-	if (snic)
-		err = adapter_update(snic);
-	else {
-		snic = kzalloc(sizeof(*snic), GFP_KERNEL);
-		if (snic) {
-			spin_lock_init(&snic->lock);
-			snic->tdev = t3dev;
-			err = adapter_add(snic);
-		} else
-			err = -ENOMEM;
-	}
-
-	if (err < 0) {
-		cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
-				snic, snic ? snic->flags : 0, t3dev, err);
-		if (snic) {
-			snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
-			cxgb3i_adapter_close(t3dev);
-		}
-	}
-}
-
-/**
- * cxgb3i_adapter_close - release the resources held and cleanup h/w settings
- * @t3dev: t3cdev adapter
- */
-void cxgb3i_adapter_close(struct t3cdev *t3dev)
-{
-	struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
-	int i;
-
-	if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) {
-		cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n",
-				t3dev, snic, snic ? snic->flags : 0);
-		return;
-	}
-
-	/* remove from the list */
-	write_lock(&cxgb3i_snic_rwlock);
-	list_del(&snic->list_head);
-	write_unlock(&cxgb3i_snic_rwlock);
-
-	for (i = 0; i < snic->hba_cnt; i++) {
-		if (snic->hba[i]) {
-			cxgb3i_hba_host_remove(snic->hba[i]);
-			snic->hba[i] = NULL;
-		}
-	}
-	cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n",
-			t3dev, snic, snic->hba_cnt);
-	kfree(snic);
-}
-
-/**
- * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
- * @t3dev: t3cdev adapter
- */
-static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
-{
-	struct cxgb3i_adapter *snic;
-	int i;
-
-	if (ndev->priv_flags & IFF_802_1Q_VLAN)
-		ndev = vlan_dev_real_dev(ndev);
-
-	read_lock(&cxgb3i_snic_rwlock);
-	list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
-		for (i = 0; i < snic->hba_cnt; i++) {
-			if (snic->hba[i]->ndev == ndev) {
-				read_unlock(&cxgb3i_snic_rwlock);
-				return snic->hba[i];
-			}
-		}
-	}
-	read_unlock(&cxgb3i_snic_rwlock);
-	return NULL;
-}
-
-/**
- * cxgb3i_hba_host_add - register a new host with scsi/iscsi
- * @snic: the cxgb3i adapter
- * @ndev: associated net_device
- */
-struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
-				       struct net_device *ndev)
-{
-	struct cxgb3i_hba *hba;
-	struct Scsi_Host *shost;
-	int err;
-
-	shost = iscsi_host_alloc(&cxgb3i_host_template,
-				 sizeof(struct cxgb3i_hba), 1);
-	if (!shost) {
-		cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n",
-				snic, ndev);
-		return NULL;
-	}
-
-	shost->transportt = cxgb3i_scsi_transport;
-	shost->max_lun = CXGB3I_MAX_LUN;
-	shost->max_id = CXGB3I_MAX_TARGET;
-	shost->max_channel = 0;
-	shost->max_cmd_len = 16;
-
-	hba = iscsi_host_priv(shost);
-	hba->snic = snic;
-	hba->ndev = ndev;
-	hba->shost = shost;
-
-	pci_dev_get(snic->pdev);
-	err = iscsi_host_add(shost, &snic->pdev->dev);
-	if (err) {
-		cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n",
-				snic, ndev);
-		goto pci_dev_put;
-	}
-
-	cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
-			 shost, hba, shost->host_no);
-
-	return hba;
-
-pci_dev_put:
-	pci_dev_put(snic->pdev);
-	scsi_host_put(shost);
-	return NULL;
-}
-
-/**
- * cxgb3i_hba_host_remove - de-register the host with scsi/iscsi
- * @hba: the cxgb3i hba
- */
-void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba)
-{
-	cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n",
-			 hba->shost, hba, hba->shost->host_no);
-	iscsi_host_remove(hba->shost);
-	pci_dev_put(hba->snic->pdev);
-	iscsi_host_free(hba->shost);
-}
-
-/**
- * cxgb3i_ep_connect - establish TCP connection to target portal
- * @shost:		scsi host to use
- * @dst_addr:		target IP address
- * @non_blocking:	blocking or non-blocking call
- *
- * Initiates a TCP/IP connection to the dst_addr
- */
-static struct iscsi_endpoint *cxgb3i_ep_connect(struct Scsi_Host *shost,
-						struct sockaddr *dst_addr,
-						int non_blocking)
-{
-	struct iscsi_endpoint *ep;
-	struct cxgb3i_endpoint *cep;
-	struct cxgb3i_hba *hba = NULL;
-	struct s3_conn *c3cn = NULL;
-	int err = 0;
-
-	if (shost)
-		hba = iscsi_host_priv(shost);
-
-	cxgb3i_api_debug("shost 0x%p, hba 0x%p.\n", shost, hba);
-
-	c3cn = cxgb3i_c3cn_create();
-	if (!c3cn) {
-		cxgb3i_log_info("ep connect OOM.\n");
-		err = -ENOMEM;
-		goto release_conn;
-	}
-
-	err = cxgb3i_c3cn_connect(hba ? hba->ndev : NULL, c3cn,
-				 (struct sockaddr_in *)dst_addr);
-	if (err < 0) {
-		cxgb3i_log_info("ep connect failed.\n");
-		goto release_conn;
-	}
-
-	hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev);
-	if (!hba) {
-		err = -ENOSPC;
-		cxgb3i_log_info("NOT going through cxgbi device.\n");
-		goto release_conn;
-	}
-
-	if (shost && hba != iscsi_host_priv(shost)) {
-		err = -ENOSPC;
-		cxgb3i_log_info("Could not connect through request host%u\n",
-				shost->host_no);
-		goto release_conn;
-	}
-
-	if (c3cn_is_closing(c3cn)) {
-		err = -ENOSPC;
-		cxgb3i_log_info("ep connect unable to connect.\n");
-		goto release_conn;
-	}
-
-	ep = iscsi_create_endpoint(sizeof(*cep));
-	if (!ep) {
-		err = -ENOMEM;
-		cxgb3i_log_info("iscsi alloc ep, OOM.\n");
-		goto release_conn;
-	}
-	cep = ep->dd_data;
-	cep->c3cn = c3cn;
-	cep->hba = hba;
-
-	cxgb3i_api_debug("ep 0x%p, 0x%p, c3cn 0x%p, hba 0x%p.\n",
-			  ep, cep, c3cn, hba);
-	return ep;
-
-release_conn:
-	cxgb3i_api_debug("conn 0x%p failed, release.\n", c3cn);
-	if (c3cn)
-		cxgb3i_c3cn_release(c3cn);
-	return ERR_PTR(err);
-}
-
-/**
- * cxgb3i_ep_poll - polls for TCP connection establishement
- * @ep:		TCP connection (endpoint) handle
- * @timeout_ms:	timeout value in milli secs
- *
- * polls for TCP connect request to complete
- */
-static int cxgb3i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
-{
-	struct cxgb3i_endpoint *cep = ep->dd_data;
-	struct s3_conn *c3cn = cep->c3cn;
-
-	if (!c3cn_is_established(c3cn))
-		return 0;
-	cxgb3i_api_debug("ep 0x%p, c3cn 0x%p established.\n", ep, c3cn);
-	return 1;
-}
-
-/**
- * cxgb3i_ep_disconnect - teardown TCP connection
- * @ep:		TCP connection (endpoint) handle
- *
- * teardown TCP connection
- */
-static void cxgb3i_ep_disconnect(struct iscsi_endpoint *ep)
-{
-	struct cxgb3i_endpoint *cep = ep->dd_data;
-	struct cxgb3i_conn *cconn = cep->cconn;
-
-	cxgb3i_api_debug("ep 0x%p, cep 0x%p.\n", ep, cep);
-
-	if (cconn && cconn->conn) {
-		/*
-		 * stop the xmit path so the xmit_pdu function is
-		 * not being called
-		 */
-		iscsi_suspend_tx(cconn->conn);
-
-		write_lock_bh(&cep->c3cn->callback_lock);
-		cep->c3cn->user_data = NULL;
-		cconn->cep = NULL;
-		write_unlock_bh(&cep->c3cn->callback_lock);
-	}
-
-	cxgb3i_api_debug("ep 0x%p, cep 0x%p, release c3cn 0x%p.\n",
-			 ep, cep, cep->c3cn);
-	cxgb3i_c3cn_release(cep->c3cn);
-	iscsi_destroy_endpoint(ep);
-}
-
-/**
- * cxgb3i_session_create - create a new iscsi session
- * @cmds_max:		max # of commands
- * @qdepth:		scsi queue depth
- * @initial_cmdsn:	initial iscsi CMDSN for this session
- *
- * Creates a new iSCSI session
- */
-static struct iscsi_cls_session *
-cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
-		      u32 initial_cmdsn)
-{
-	struct cxgb3i_endpoint *cep;
-	struct cxgb3i_hba *hba;
-	struct Scsi_Host *shost;
-	struct iscsi_cls_session *cls_session;
-	struct iscsi_session *session;
-
-	if (!ep) {
-		cxgb3i_log_error("%s, missing endpoint.\n", __func__);
-		return NULL;
-	}
-
-	cep = ep->dd_data;
-	hba = cep->hba;
-	shost = hba->shost;
-	cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep, cep, hba);
-	BUG_ON(hba != iscsi_host_priv(shost));
-
-	cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost,
-					  cmds_max, 0,
-					  sizeof(struct iscsi_tcp_task) +
-					  sizeof(struct cxgb3i_task_data),
-					  initial_cmdsn, ISCSI_MAX_TARGET);
-	if (!cls_session)
-		return NULL;
-	session = cls_session->dd_data;
-	if (iscsi_tcp_r2tpool_alloc(session))
-		goto remove_session;
-
-	return cls_session;
-
-remove_session:
-	iscsi_session_teardown(cls_session);
-	return NULL;
-}
-
-/**
- * cxgb3i_session_destroy - destroys iscsi session
- * @cls_session:	pointer to iscsi cls session
- *
- * Destroys an iSCSI session instance and releases its all resources held
- */
-static void cxgb3i_session_destroy(struct iscsi_cls_session *cls_session)
-{
-	cxgb3i_api_debug("sess 0x%p.\n", cls_session);
-	iscsi_tcp_r2tpool_free(cls_session->dd_data);
-	iscsi_session_teardown(cls_session);
-}
-
-/**
- * cxgb3i_conn_max_xmit_dlength -- calc the max. xmit pdu segment size
- * @conn: iscsi connection
- * check the max. xmit pdu payload, reduce it if needed
- */
-static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn)
-
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM);
-
-	max = min(cconn->hba->snic->tx_max_size, max);
-	if (conn->max_xmit_dlength)
-		conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
-	else
-		conn->max_xmit_dlength = max;
-	align_pdu_size(conn->max_xmit_dlength);
-	cxgb3i_api_debug("conn 0x%p, max xmit %u.\n",
-			 conn, conn->max_xmit_dlength);
-	return 0;
-}
-
-/**
- * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size
- * @conn: iscsi connection
- * return 0 if the value is valid, < 0 otherwise.
- */
-static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn)
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	unsigned int max = cconn->hba->snic->rx_max_size;
-
-	align_pdu_size(max);
-	if (conn->max_recv_dlength) {
-		if (conn->max_recv_dlength > max) {
-			cxgb3i_log_error("MaxRecvDataSegmentLength %u too big."
-					 " Need to be <= %u.\n",
-					 conn->max_recv_dlength, max);
-			return -EINVAL;
-		}
-		conn->max_recv_dlength = min(conn->max_recv_dlength, max);
-		align_pdu_size(conn->max_recv_dlength);
-	} else
-		conn->max_recv_dlength = max;
-	cxgb3i_api_debug("conn 0x%p, max recv %u.\n",
-			 conn, conn->max_recv_dlength);
-	return 0;
-}
-
-/**
- * cxgb3i_conn_create - create iscsi connection instance
- * @cls_session:	pointer to iscsi cls session
- * @cid:		iscsi cid
- *
- * Creates a new iSCSI connection instance for a given session
- */
-static struct iscsi_cls_conn *cxgb3i_conn_create(struct iscsi_cls_session
-						 *cls_session, u32 cid)
-{
-	struct iscsi_cls_conn *cls_conn;
-	struct iscsi_conn *conn;
-	struct iscsi_tcp_conn *tcp_conn;
-	struct cxgb3i_conn *cconn;
-
-	cxgb3i_api_debug("sess 0x%p, cid %u.\n", cls_session, cid);
-
-	cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid);
-	if (!cls_conn)
-		return NULL;
-	conn = cls_conn->dd_data;
-	tcp_conn = conn->dd_data;
-	cconn = tcp_conn->dd_data;
-
-	cconn->conn = conn;
-	return cls_conn;
-}
-
-/**
- * cxgb3i_conn_bind - binds iscsi sess, conn and endpoint together
- * @cls_session:	pointer to iscsi cls session
- * @cls_conn:		pointer to iscsi cls conn
- * @transport_eph:	64-bit EP handle
- * @is_leading:		leading connection on this session?
- *
- * Binds together an iSCSI session, an iSCSI connection and a
- *	TCP connection. This routine returns error code if the TCP
- *	connection does not belong on the device iSCSI sess/conn is bound
- */
-
-static int cxgb3i_conn_bind(struct iscsi_cls_session *cls_session,
-			    struct iscsi_cls_conn *cls_conn,
-			    u64 transport_eph, int is_leading)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic;
-	struct iscsi_endpoint *ep;
-	struct cxgb3i_endpoint *cep;
-	struct s3_conn *c3cn;
-	int err;
-
-	ep = iscsi_lookup_endpoint(transport_eph);
-	if (!ep)
-		return -EINVAL;
-
-	/* setup ddp pagesize */
-	cep = ep->dd_data;
-	c3cn = cep->c3cn;
-	snic = cep->hba->snic;
-	err = cxgb3i_setup_conn_host_pagesize(snic->tdev, c3cn->tid, 0);
-	if (err < 0)
-		return err;
-
-	cxgb3i_api_debug("ep 0x%p, cls sess 0x%p, cls conn 0x%p.\n",
-			 ep, cls_session, cls_conn);
-
-	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
-	if (err)
-		return -EINVAL;
-
-	/* calculate the tag idx bits needed for this conn based on cmds_max */
-	cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
-	cxgb3i_api_debug("session cmds_max 0x%x, bits %u.\n",
-			 conn->session->cmds_max, cconn->task_idx_bits);
-
-	read_lock(&c3cn->callback_lock);
-	c3cn->user_data = conn;
-	cconn->hba = cep->hba;
-	cconn->cep = cep;
-	cep->cconn = cconn;
-	read_unlock(&c3cn->callback_lock);
-
-	cxgb3i_conn_max_xmit_dlength(conn);
-	cxgb3i_conn_max_recv_dlength(conn);
-
-	spin_lock_bh(&conn->session->lock);
-	sprintf(conn->portal_address, "%pI4", &c3cn->daddr.sin_addr.s_addr);
-	conn->portal_port = ntohs(c3cn->daddr.sin_port);
-	spin_unlock_bh(&conn->session->lock);
-
-	/* init recv engine */
-	iscsi_tcp_hdr_recv_prep(tcp_conn);
-
-	return 0;
-}
-
-/**
- * cxgb3i_conn_get_param - return iscsi connection parameter to caller
- * @cls_conn:	pointer to iscsi cls conn
- * @param:	parameter type identifier
- * @buf:	buffer pointer
- *
- * returns iSCSI connection parameters
- */
-static int cxgb3i_conn_get_param(struct iscsi_cls_conn *cls_conn,
-				 enum iscsi_param param, char *buf)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	int len;
-
-	cxgb3i_api_debug("cls_conn 0x%p, param %d.\n", cls_conn, param);
-
-	switch (param) {
-	case ISCSI_PARAM_CONN_PORT:
-		spin_lock_bh(&conn->session->lock);
-		len = sprintf(buf, "%hu\n", conn->portal_port);
-		spin_unlock_bh(&conn->session->lock);
-		break;
-	case ISCSI_PARAM_CONN_ADDRESS:
-		spin_lock_bh(&conn->session->lock);
-		len = sprintf(buf, "%s\n", conn->portal_address);
-		spin_unlock_bh(&conn->session->lock);
-		break;
-	default:
-		return iscsi_conn_get_param(cls_conn, param, buf);
-	}
-
-	return len;
-}
-
-/**
- * cxgb3i_conn_set_param - set iscsi connection parameter
- * @cls_conn:	pointer to iscsi cls conn
- * @param:	parameter type identifier
- * @buf:	buffer pointer
- * @buflen:	buffer length
- *
- * set iSCSI connection parameters
- */
-static int cxgb3i_conn_set_param(struct iscsi_cls_conn *cls_conn,
-				 enum iscsi_param param, char *buf, int buflen)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_session *session = conn->session;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic = cconn->hba->snic;
-	struct s3_conn *c3cn = cconn->cep->c3cn;
-	int value, err = 0;
-
-	switch (param) {
-	case ISCSI_PARAM_HDRDGST_EN:
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err && conn->hdrdgst_en)
-			err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid,
-							conn->hdrdgst_en,
-							conn->datadgst_en, 0);
-		break;
-	case ISCSI_PARAM_DATADGST_EN:
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err && conn->datadgst_en)
-			err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid,
-							conn->hdrdgst_en,
-							conn->datadgst_en, 0);
-		break;
-	case ISCSI_PARAM_MAX_R2T:
-		sscanf(buf, "%d", &value);
-		if (value <= 0 || !is_power_of_2(value))
-			return -EINVAL;
-		if (session->max_r2t == value)
-			break;
-		iscsi_tcp_r2tpool_free(session);
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err && iscsi_tcp_r2tpool_alloc(session))
-			return -ENOMEM;
-	case ISCSI_PARAM_MAX_RECV_DLENGTH:
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err)
-			err = cxgb3i_conn_max_recv_dlength(conn);
-		break;
-	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
-		err = iscsi_set_param(cls_conn, param, buf, buflen);
-		if (!err)
-			err = cxgb3i_conn_max_xmit_dlength(conn);
-		break;
-	default:
-		return iscsi_set_param(cls_conn, param, buf, buflen);
-	}
-	return err;
-}
-
-/**
- * cxgb3i_host_set_param - configure host (adapter) related parameters
- * @shost:	scsi host pointer
- * @param:	parameter type identifier
- * @buf:	buffer pointer
- */
-static int cxgb3i_host_set_param(struct Scsi_Host *shost,
-				 enum iscsi_host_param param,
-				 char *buf, int buflen)
-{
-	struct cxgb3i_hba *hba = iscsi_host_priv(shost);
-
-	if (!hba->ndev) {
-		shost_printk(KERN_ERR, shost, "Could not set host param. "
-			     "Netdev for host not set.\n");
-		return -ENODEV;
-	}
-
-	cxgb3i_api_debug("param %d, buf %s.\n", param, buf);
-
-	switch (param) {
-	case ISCSI_HOST_PARAM_IPADDRESS:
-	{
-		__be32 addr = in_aton(buf);
-		cxgb3i_set_private_ipv4addr(hba->ndev, addr);
-		return 0;
-	}
-	case ISCSI_HOST_PARAM_HWADDRESS:
-	case ISCSI_HOST_PARAM_NETDEV_NAME:
-		/* ignore */
-		return 0;
-	default:
-		return iscsi_host_set_param(shost, param, buf, buflen);
-	}
-}
-
-/**
- * cxgb3i_host_get_param - returns host (adapter) related parameters
- * @shost:	scsi host pointer
- * @param:	parameter type identifier
- * @buf:	buffer pointer
- */
-static int cxgb3i_host_get_param(struct Scsi_Host *shost,
-				 enum iscsi_host_param param, char *buf)
-{
-	struct cxgb3i_hba *hba = iscsi_host_priv(shost);
-	int len = 0;
-
-	if (!hba->ndev) {
-		shost_printk(KERN_ERR, shost, "Could not set host param. "
-			     "Netdev for host not set.\n");
-		return -ENODEV;
-	}
-
-	cxgb3i_api_debug("hba %s, param %d.\n", hba->ndev->name, param);
-
-	switch (param) {
-	case ISCSI_HOST_PARAM_HWADDRESS:
-		len = sysfs_format_mac(buf, hba->ndev->dev_addr, 6);
-		break;
-	case ISCSI_HOST_PARAM_NETDEV_NAME:
-		len = sprintf(buf, "%s\n", hba->ndev->name);
-		break;
-	case ISCSI_HOST_PARAM_IPADDRESS:
-	{
-		__be32 addr;
-
-		addr = cxgb3i_get_private_ipv4addr(hba->ndev);
-		len = sprintf(buf, "%pI4", &addr);
-		break;
-	}
-	default:
-		return iscsi_host_get_param(shost, param, buf);
-	}
-	return len;
-}
-
-/**
- * cxgb3i_conn_get_stats - returns iSCSI stats
- * @cls_conn:	pointer to iscsi cls conn
- * @stats:	pointer to iscsi statistic struct
- */
-static void cxgb3i_conn_get_stats(struct iscsi_cls_conn *cls_conn,
-				  struct iscsi_stats *stats)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-
-	stats->txdata_octets = conn->txdata_octets;
-	stats->rxdata_octets = conn->rxdata_octets;
-	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
-	stats->dataout_pdus = conn->dataout_pdus_cnt;
-	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
-	stats->datain_pdus = conn->datain_pdus_cnt;
-	stats->r2t_pdus = conn->r2t_pdus_cnt;
-	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
-	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
-	stats->digest_err = 0;
-	stats->timeout_err = 0;
-	stats->custom_length = 1;
-	strcpy(stats->custom[0].desc, "eh_abort_cnt");
-	stats->custom[0].value = conn->eh_abort_cnt;
-}
-
-/**
- * cxgb3i_parse_itt - get the idx and age bits from a given tag
- * @conn:	iscsi connection
- * @itt:	itt tag
- * @idx:	task index, filled in by this function
- * @age:	session age, filled in by this function
- */
-static void cxgb3i_parse_itt(struct iscsi_conn *conn, itt_t itt,
-			     int *idx, int *age)
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic = cconn->hba->snic;
-	u32 tag = ntohl((__force u32) itt);
-	u32 sw_bits;
-
-	sw_bits = cxgb3i_tag_nonrsvd_bits(&snic->tag_format, tag);
-	if (idx)
-		*idx = sw_bits & ((1 << cconn->task_idx_bits) - 1);
-	if (age)
-		*age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK;
-
-	cxgb3i_tag_debug("parse tag 0x%x/0x%x, sw 0x%x, itt 0x%x, age 0x%x.\n",
-			 tag, itt, sw_bits, idx ? *idx : 0xFFFFF,
-			 age ? *age : 0xFF);
-}
-
-/**
- * cxgb3i_reserve_itt - generate tag for a give task
- * @task: iscsi task
- * @hdr_itt: tag, filled in by this function
- * Set up ddp for scsi read tasks if possible.
- */
-int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
-{
-	struct scsi_cmnd *sc = task->sc;
-	struct iscsi_conn *conn = task->conn;
-	struct iscsi_session *sess = conn->session;
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic = cconn->hba->snic;
-	struct cxgb3i_tag_format *tformat = &snic->tag_format;
-	u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt;
-	u32 tag;
-	int err = -EINVAL;
-
-	if (sc &&
-	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
-	    cxgb3i_sw_tag_usable(tformat, sw_tag)) {
-		struct s3_conn *c3cn = cconn->cep->c3cn;
-		struct cxgb3i_gather_list *gl;
-
-		gl = cxgb3i_ddp_make_gl(scsi_in(sc)->length,
-					scsi_in(sc)->table.sgl,
-					scsi_in(sc)->table.nents,
-					snic->pdev,
-					GFP_ATOMIC);
-		if (gl) {
-			tag = sw_tag;
-			err = cxgb3i_ddp_tag_reserve(snic->tdev, c3cn->tid,
-						     tformat, &tag,
-						     gl, GFP_ATOMIC);
-			if (err < 0)
-				cxgb3i_ddp_release_gl(gl, snic->pdev);
-		}
-	}
-
-	if (err < 0)
-		tag = cxgb3i_set_non_ddp_tag(tformat, sw_tag);
-	/* the itt need to sent in big-endian order */
-	*hdr_itt = (__force itt_t)htonl(tag);
-
-	cxgb3i_tag_debug("new tag 0x%x/0x%x (itt 0x%x, age 0x%x).\n",
-			 tag, *hdr_itt, task->itt, sess->age);
-	return 0;
-}
-
-/**
- * cxgb3i_release_itt - release the tag for a given task
- * @task:	iscsi task
- * @hdr_itt:	tag
- * If the tag is a ddp tag, release the ddp setup
- */
-void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt)
-{
-	struct scsi_cmnd *sc = task->sc;
-	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct cxgb3i_adapter *snic = cconn->hba->snic;
-	struct cxgb3i_tag_format *tformat = &snic->tag_format;
-	u32 tag = ntohl((__force u32)hdr_itt);
-
-	cxgb3i_tag_debug("release tag 0x%x.\n", tag);
-
-	if (sc &&
-	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
-	    cxgb3i_is_ddp_tag(tformat, tag))
-		cxgb3i_ddp_tag_release(snic->tdev, tag);
-}
-
-/**
- * cxgb3i_host_template -- Scsi_Host_Template structure
- *	used when registering with the scsi mid layer
- */
-static struct scsi_host_template cxgb3i_host_template = {
-	.module			= THIS_MODULE,
-	.name			= "Chelsio S3xx iSCSI Initiator",
-	.proc_name		= "cxgb3i",
-	.queuecommand		= iscsi_queuecommand,
-	.change_queue_depth	= iscsi_change_queue_depth,
-	.can_queue		= CXGB3I_SCSI_HOST_QDEPTH,
-	.sg_tablesize		= SG_ALL,
-	.max_sectors		= 0xFFFF,
-	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
-	.eh_abort_handler	= iscsi_eh_abort,
-	.eh_device_reset_handler = iscsi_eh_device_reset,
-	.eh_target_reset_handler = iscsi_eh_recover_target,
-	.target_alloc		= iscsi_target_alloc,
-	.use_clustering		= DISABLE_CLUSTERING,
-	.this_id		= -1,
-};
-
-static struct iscsi_transport cxgb3i_iscsi_transport = {
-	.owner			= THIS_MODULE,
-	.name			= "cxgb3i",
-	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
-				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
-				CAP_PADDING_OFFLOAD,
-	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
-				ISCSI_MAX_XMIT_DLENGTH |
-				ISCSI_HDRDGST_EN |
-				ISCSI_DATADGST_EN |
-				ISCSI_INITIAL_R2T_EN |
-				ISCSI_MAX_R2T |
-				ISCSI_IMM_DATA_EN |
-				ISCSI_FIRST_BURST |
-				ISCSI_MAX_BURST |
-				ISCSI_PDU_INORDER_EN |
-				ISCSI_DATASEQ_INORDER_EN |
-				ISCSI_ERL |
-				ISCSI_CONN_PORT |
-				ISCSI_CONN_ADDRESS |
-				ISCSI_EXP_STATSN |
-				ISCSI_PERSISTENT_PORT |
-				ISCSI_PERSISTENT_ADDRESS |
-				ISCSI_TARGET_NAME | ISCSI_TPGT |
-				ISCSI_USERNAME | ISCSI_PASSWORD |
-				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
-				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
-				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
-				ISCSI_PING_TMO | ISCSI_RECV_TMO |
-				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
-	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
-			ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_NETDEV_NAME,
-	.get_host_param		= cxgb3i_host_get_param,
-	.set_host_param		= cxgb3i_host_set_param,
-	/* session management */
-	.create_session		= cxgb3i_session_create,
-	.destroy_session	= cxgb3i_session_destroy,
-	.get_session_param	= iscsi_session_get_param,
-	/* connection management */
-	.create_conn		= cxgb3i_conn_create,
-	.bind_conn		= cxgb3i_conn_bind,
-	.destroy_conn		= iscsi_tcp_conn_teardown,
-	.start_conn		= iscsi_conn_start,
-	.stop_conn		= iscsi_conn_stop,
-	.get_conn_param		= cxgb3i_conn_get_param,
-	.set_param		= cxgb3i_conn_set_param,
-	.get_stats		= cxgb3i_conn_get_stats,
-	/* pdu xmit req. from user space */
-	.send_pdu		= iscsi_conn_send_pdu,
-	/* task */
-	.init_task		= iscsi_tcp_task_init,
-	.xmit_task		= iscsi_tcp_task_xmit,
-	.cleanup_task		= cxgb3i_conn_cleanup_task,
-
-	/* pdu */
-	.alloc_pdu		= cxgb3i_conn_alloc_pdu,
-	.init_pdu		= cxgb3i_conn_init_pdu,
-	.xmit_pdu		= cxgb3i_conn_xmit_pdu,
-	.parse_pdu_itt		= cxgb3i_parse_itt,
-
-	/* TCP connect/disconnect */
-	.ep_connect		= cxgb3i_ep_connect,
-	.ep_poll		= cxgb3i_ep_poll,
-	.ep_disconnect		= cxgb3i_ep_disconnect,
-	/* Error recovery timeout call */
-	.session_recovery_timedout = iscsi_session_recovery_timedout,
-};
-
-int cxgb3i_iscsi_init(void)
-{
-	sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
-	sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1;
-	cxgb3i_log_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n",
-			ISCSI_ITT_MASK, sw_tag_idx_bits,
-			ISCSI_AGE_MASK, sw_tag_age_bits);
-
-	cxgb3i_scsi_transport =
-	    iscsi_register_transport(&cxgb3i_iscsi_transport);
-	if (!cxgb3i_scsi_transport) {
-		cxgb3i_log_error("Could not register cxgb3i transport.\n");
-		return -ENODEV;
-	}
-	cxgb3i_api_debug("cxgb3i transport 0x%p.\n", cxgb3i_scsi_transport);
-	return 0;
-}
-
-void cxgb3i_iscsi_cleanup(void)
-{
-	if (cxgb3i_scsi_transport) {
-		cxgb3i_api_debug("cxgb3i transport 0x%p.\n",
-				 cxgb3i_scsi_transport);
-		iscsi_unregister_transport(&cxgb3i_iscsi_transport);
-	}
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
deleted file mode 100644
index 3ee13cf..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
+++ /dev/null
@@ -1,1944 +0,0 @@
-/*
- * cxgb3i_offload.c: Chelsio S3xx iscsi offloaded tcp connection management
- *
- * Copyright (C) 2003-2008 Chelsio Communications.  All rights reserved.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
- * release for licensing terms and conditions.
- *
- * Written by:	Dimitris Michailidis (dm@chelsio.com)
- *		Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/if_vlan.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-
-#include "cxgb3_defs.h"
-#include "cxgb3_ctl_defs.h"
-#include "firmware_exports.h"
-#include "cxgb3i_offload.h"
-#include "cxgb3i_pdu.h"
-#include "cxgb3i_ddp.h"
-
-#ifdef __DEBUG_C3CN_CONN__
-#define c3cn_conn_debug		cxgb3i_log_debug
-#else
-#define c3cn_conn_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_C3CN_TX__
-#define c3cn_tx_debug		cxgb3i_log_debug
-#else
-#define c3cn_tx_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_C3CN_RX__
-#define c3cn_rx_debug		cxgb3i_log_debug
-#else
-#define c3cn_rx_debug(fmt...)
-#endif
-
-/*
- * module parameters releated to offloaded iscsi connection
- */
-static int cxgb3_rcv_win = 256 * 1024;
-module_param(cxgb3_rcv_win, int, 0644);
-MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)");
-
-static int cxgb3_snd_win = 128 * 1024;
-module_param(cxgb3_snd_win, int, 0644);
-MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=128KB)");
-
-static int cxgb3_rx_credit_thres = 10 * 1024;
-module_param(cxgb3_rx_credit_thres, int, 0644);
-MODULE_PARM_DESC(rx_credit_thres,
-		 "RX credits return threshold in bytes (default=10KB)");
-
-static unsigned int cxgb3_max_connect = 8 * 1024;
-module_param(cxgb3_max_connect, uint, 0644);
-MODULE_PARM_DESC(cxgb3_max_connect, "Max. # of connections (default=8092)");
-
-static unsigned int cxgb3_sport_base = 20000;
-module_param(cxgb3_sport_base, uint, 0644);
-MODULE_PARM_DESC(cxgb3_sport_base, "starting port number (default=20000)");
-
-/*
- * cxgb3i tcp connection data(per adapter) list
- */
-static LIST_HEAD(cdata_list);
-static DEFINE_RWLOCK(cdata_rwlock);
-
-static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion);
-static void c3cn_release_offload_resources(struct s3_conn *c3cn);
-
-/*
- * iscsi source port management
- *
- * Find a free source port in the port allocation map. We use a very simple
- * rotor scheme to look for the next free port.
- *
- * If a source port has been specified make sure that it doesn't collide with
- * our normal source port allocation map.  If it's outside the range of our
- * allocation/deallocation scheme just let them use it.
- *
- * If the source port is outside our allocation range, the caller is
- * responsible for keeping track of their port usage.
- */
-static int c3cn_get_port(struct s3_conn *c3cn, struct cxgb3i_sdev_data *cdata)
-{
-	unsigned int start;
-	int idx;
-
-	if (!cdata)
-		goto error_out;
-
-	if (c3cn->saddr.sin_port) {
-		cxgb3i_log_error("connect, sin_port NON-ZERO %u.\n",
-				 c3cn->saddr.sin_port);
-		return -EADDRINUSE;
-	}
-
-	spin_lock_bh(&cdata->lock);
-	start = idx = cdata->sport_next;
-	do {
-		if (++idx >= cxgb3_max_connect)
-			idx = 0;
-		if (!cdata->sport_conn[idx]) {
-			c3cn->saddr.sin_port = htons(cxgb3_sport_base + idx);
-			cdata->sport_next = idx;
-			cdata->sport_conn[idx] = c3cn;
-			spin_unlock_bh(&cdata->lock);
-
-			c3cn_conn_debug("%s reserve port %u.\n",
-					cdata->cdev->name,
-					cxgb3_sport_base + idx);
-			return 0;
-		}
-	} while (idx != start);
-	spin_unlock_bh(&cdata->lock);
-
-error_out:
-	return -EADDRNOTAVAIL;
-}
-
-static void c3cn_put_port(struct s3_conn *c3cn)
-{
-	if (!c3cn->cdev)
-		return;
-
-	if (c3cn->saddr.sin_port) {
-		struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(c3cn->cdev);
-		int idx = ntohs(c3cn->saddr.sin_port) - cxgb3_sport_base;
-
-		c3cn->saddr.sin_port = 0;
-		if (idx < 0 || idx >= cxgb3_max_connect)
-			return;
-		spin_lock_bh(&cdata->lock);
-		cdata->sport_conn[idx] = NULL;
-		spin_unlock_bh(&cdata->lock);
-		c3cn_conn_debug("%s, release port %u.\n",
-				cdata->cdev->name, cxgb3_sport_base + idx);
-	}
-}
-
-static inline void c3cn_set_flag(struct s3_conn *c3cn, enum c3cn_flags flag)
-{
-	__set_bit(flag, &c3cn->flags);
-	c3cn_conn_debug("c3cn 0x%p, set %d, s %u, f 0x%lx.\n",
-			c3cn, flag, c3cn->state, c3cn->flags);
-}
-
-static inline void c3cn_clear_flag(struct s3_conn *c3cn, enum c3cn_flags flag)
-{
-	__clear_bit(flag, &c3cn->flags);
-	c3cn_conn_debug("c3cn 0x%p, clear %d, s %u, f 0x%lx.\n",
-			c3cn, flag, c3cn->state, c3cn->flags);
-}
-
-static inline int c3cn_flag(struct s3_conn *c3cn, enum c3cn_flags flag)
-{
-	if (c3cn == NULL)
-		return 0;
-	return test_bit(flag, &c3cn->flags);
-}
-
-static void c3cn_set_state(struct s3_conn *c3cn, int state)
-{
-	c3cn_conn_debug("c3cn 0x%p state -> %u.\n", c3cn, state);
-	c3cn->state = state;
-}
-
-static inline void c3cn_hold(struct s3_conn *c3cn)
-{
-	atomic_inc(&c3cn->refcnt);
-}
-
-static inline void c3cn_put(struct s3_conn *c3cn)
-{
-	if (atomic_dec_and_test(&c3cn->refcnt)) {
-		c3cn_conn_debug("free c3cn 0x%p, s %u, f 0x%lx.\n",
-				c3cn, c3cn->state, c3cn->flags);
-		kfree(c3cn);
-	}
-}
-
-static void c3cn_closed(struct s3_conn *c3cn)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			 c3cn, c3cn->state, c3cn->flags);
-
-	c3cn_put_port(c3cn);
-	c3cn_release_offload_resources(c3cn);
-	c3cn_set_state(c3cn, C3CN_STATE_CLOSED);
-	cxgb3i_conn_closing(c3cn);
-}
-
-/*
- * CPL (Chelsio Protocol Language) defines a message passing interface between
- * the host driver and T3 asic.
- * The section below implments CPLs that related to iscsi tcp connection
- * open/close/abort and data send/receive.
- */
-
-/*
- * CPL connection active open request: host ->
- */
-static unsigned int find_best_mtu(const struct t3c_data *d, unsigned short mtu)
-{
-	int i = 0;
-
-	while (i < d->nmtus - 1 && d->mtus[i + 1] <= mtu)
-		++i;
-	return i;
-}
-
-static unsigned int select_mss(struct s3_conn *c3cn, unsigned int pmtu)
-{
-	unsigned int idx;
-	struct dst_entry *dst = c3cn->dst_cache;
-	struct t3cdev *cdev = c3cn->cdev;
-	const struct t3c_data *td = T3C_DATA(cdev);
-	u16 advmss = dst_metric(dst, RTAX_ADVMSS);
-
-	if (advmss > pmtu - 40)
-		advmss = pmtu - 40;
-	if (advmss < td->mtus[0] - 40)
-		advmss = td->mtus[0] - 40;
-	idx = find_best_mtu(td, advmss + 40);
-	return idx;
-}
-
-static inline int compute_wscale(int win)
-{
-	int wscale = 0;
-	while (wscale < 14 && (65535<<wscale) < win)
-		wscale++;
-	return wscale;
-}
-
-static inline unsigned int calc_opt0h(struct s3_conn *c3cn)
-{
-	int wscale = compute_wscale(cxgb3_rcv_win);
-	return  V_KEEP_ALIVE(1) |
-		F_TCAM_BYPASS |
-		V_WND_SCALE(wscale) |
-		V_MSS_IDX(c3cn->mss_idx);
-}
-
-static inline unsigned int calc_opt0l(struct s3_conn *c3cn)
-{
-	return  V_ULP_MODE(ULP_MODE_ISCSI) |
-		V_RCV_BUFSIZ(cxgb3_rcv_win>>10);
-}
-
-static void make_act_open_req(struct s3_conn *c3cn, struct sk_buff *skb,
-			      unsigned int atid, const struct l2t_entry *e)
-{
-	struct cpl_act_open_req *req;
-
-	c3cn_conn_debug("c3cn 0x%p, atid 0x%x.\n", c3cn, atid);
-
-	skb->priority = CPL_PRIORITY_SETUP;
-	req = (struct cpl_act_open_req *)__skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	req->wr.wr_lo = 0;
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, atid));
-	req->local_port = c3cn->saddr.sin_port;
-	req->peer_port = c3cn->daddr.sin_port;
-	req->local_ip = c3cn->saddr.sin_addr.s_addr;
-	req->peer_ip = c3cn->daddr.sin_addr.s_addr;
-	req->opt0h = htonl(calc_opt0h(c3cn) | V_L2T_IDX(e->idx) |
-			   V_TX_CHANNEL(e->smt_idx));
-	req->opt0l = htonl(calc_opt0l(c3cn));
-	req->params = 0;
-	req->opt2 = 0;
-}
-
-static void fail_act_open(struct s3_conn *c3cn, int errno)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-	c3cn->err = errno;
-	c3cn_closed(c3cn);
-}
-
-static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
-{
-	struct s3_conn *c3cn = (struct s3_conn *)skb->sk;
-
-	c3cn_conn_debug("c3cn 0x%p, state %u.\n", c3cn, c3cn->state);
-
-	c3cn_hold(c3cn);
-	spin_lock_bh(&c3cn->lock);
-	if (c3cn->state == C3CN_STATE_CONNECTING)
-		fail_act_open(c3cn, -EHOSTUNREACH);
-	spin_unlock_bh(&c3cn->lock);
-	c3cn_put(c3cn);
-	__kfree_skb(skb);
-}
-
-/*
- * CPL connection close request: host ->
- *
- * Close a connection by sending a CPL_CLOSE_CON_REQ message and queue it to
- * the write queue (i.e., after any unsent txt data).
- */
-static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb,
-		       int flags)
-{
-	skb_tcp_seq(skb) = c3cn->write_seq;
-	skb_flags(skb) = flags;
-	__skb_queue_tail(&c3cn->write_queue, skb);
-}
-
-static void send_close_req(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb = c3cn->cpl_close;
-	struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
-	unsigned int tid = c3cn->tid;
-
-	c3cn_conn_debug("c3cn 0x%p, state 0x%x, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	c3cn->cpl_close = NULL;
-
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_CLOSE_CON));
-	req->wr.wr_lo = htonl(V_WR_TID(tid));
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
-	req->rsvd = htonl(c3cn->write_seq);
-
-	skb_entail(c3cn, skb, C3CB_FLAG_NO_APPEND);
-	if (c3cn->state != C3CN_STATE_CONNECTING)
-		c3cn_push_tx_frames(c3cn, 1);
-}
-
-/*
- * CPL connection abort request: host ->
- *
- * Send an ABORT_REQ message. Makes sure we do not send multiple ABORT_REQs
- * for the same connection and also that we do not try to send a message
- * after the connection has closed.
- */
-static void abort_arp_failure(struct t3cdev *cdev, struct sk_buff *skb)
-{
-	struct cpl_abort_req *req = cplhdr(skb);
-
-	c3cn_conn_debug("tdev 0x%p.\n", cdev);
-
-	req->cmd = CPL_ABORT_NO_RST;
-	cxgb3_ofld_send(cdev, skb);
-}
-
-static inline void c3cn_purge_write_queue(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb;
-
-	while ((skb = __skb_dequeue(&c3cn->write_queue)))
-		__kfree_skb(skb);
-}
-
-static void send_abort_req(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb = c3cn->cpl_abort_req;
-	struct cpl_abort_req *req;
-	unsigned int tid = c3cn->tid;
-
-	if (unlikely(c3cn->state == C3CN_STATE_ABORTING) || !skb ||
-		     !c3cn->cdev)
-		return;
-
-	c3cn_set_state(c3cn, C3CN_STATE_ABORTING);
-
-	c3cn_conn_debug("c3cn 0x%p, flag ABORT_RPL + ABORT_SHUT.\n", c3cn);
-
-	c3cn_set_flag(c3cn, C3CN_ABORT_RPL_PENDING);
-
-	/* Purge the send queue so we don't send anything after an abort. */
-	c3cn_purge_write_queue(c3cn);
-
-	c3cn->cpl_abort_req = NULL;
-	req = (struct cpl_abort_req *)skb->head;
-	memset(req, 0, sizeof(*req));
-
-	skb->priority = CPL_PRIORITY_DATA;
-	set_arp_failure_handler(skb, abort_arp_failure);
-
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ));
-	req->wr.wr_lo = htonl(V_WR_TID(tid));
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, tid));
-	req->rsvd0 = htonl(c3cn->snd_nxt);
-	req->rsvd1 = !c3cn_flag(c3cn, C3CN_TX_DATA_SENT);
-	req->cmd = CPL_ABORT_SEND_RST;
-
-	l2t_send(c3cn->cdev, skb, c3cn->l2t);
-}
-
-/*
- * CPL connection abort reply: host ->
- *
- * Send an ABORT_RPL message in response of the ABORT_REQ received.
- */
-static void send_abort_rpl(struct s3_conn *c3cn, int rst_status)
-{
-	struct sk_buff *skb = c3cn->cpl_abort_rpl;
-	struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
-
-	c3cn->cpl_abort_rpl = NULL;
-
-	skb->priority = CPL_PRIORITY_DATA;
-	memset(rpl, 0, sizeof(*rpl));
-	rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
-	rpl->wr.wr_lo = htonl(V_WR_TID(c3cn->tid));
-	OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, c3cn->tid));
-	rpl->cmd = rst_status;
-
-	cxgb3_ofld_send(c3cn->cdev, skb);
-}
-
-/*
- * CPL connection rx data ack: host ->
- * Send RX credits through an RX_DATA_ACK CPL message. Returns the number of
- * credits sent.
- */
-static u32 send_rx_credits(struct s3_conn *c3cn, u32 credits, u32 dack)
-{
-	struct sk_buff *skb;
-	struct cpl_rx_data_ack *req;
-
-	skb = alloc_skb(sizeof(*req), GFP_ATOMIC);
-	if (!skb)
-		return 0;
-
-	req = (struct cpl_rx_data_ack *)__skb_put(skb, sizeof(*req));
-	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
-	req->wr.wr_lo = 0;
-	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, c3cn->tid));
-	req->credit_dack = htonl(dack | V_RX_CREDITS(credits));
-	skb->priority = CPL_PRIORITY_ACK;
-	cxgb3_ofld_send(c3cn->cdev, skb);
-	return credits;
-}
-
-/*
- * CPL connection tx data: host ->
- *
- * Send iscsi PDU via TX_DATA CPL message. Returns the number of
- * credits sent.
- * Each TX_DATA consumes work request credit (wrs), so we need to keep track of
- * how many we've used so far and how many are pending (i.e., yet ack'ed by T3).
- */
-
-/*
- * For ULP connections HW may inserts digest bytes into the pdu. Those digest
- * bytes are not sent by the host but are part of the TCP payload and therefore
- * consume TCP sequence space.
- */
-static const unsigned int cxgb3_ulp_extra_len[] = { 0, 4, 4, 8 };
-static inline unsigned int ulp_extra_len(const struct sk_buff *skb)
-{
-	return cxgb3_ulp_extra_len[skb_ulp_mode(skb) & 3];
-}
-
-static unsigned int wrlen __read_mostly;
-
-/*
- * The number of WRs needed for an skb depends on the number of fragments
- * in the skb and whether it has any payload in its main body.  This maps the
- * length of the gather list represented by an skb into the # of necessary WRs.
- * The extra two fragments are for iscsi bhs and payload padding.
- */
-#define SKB_WR_LIST_SIZE	(MAX_SKB_FRAGS + 2)
-static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly;
-
-static void s3_init_wr_tab(unsigned int wr_len)
-{
-	int i;
-
-	if (skb_wrs[1])		/* already initialized */
-		return;
-
-	for (i = 1; i < SKB_WR_LIST_SIZE; i++) {
-		int sgl_len = (3 * i) / 2 + (i & 1);
-
-		sgl_len += 3;
-		skb_wrs[i] = (sgl_len <= wr_len
-			      ? 1 : 1 + (sgl_len - 2) / (wr_len - 1));
-	}
-
-	wrlen = wr_len * 8;
-}
-
-static inline void reset_wr_list(struct s3_conn *c3cn)
-{
-	c3cn->wr_pending_head = c3cn->wr_pending_tail = NULL;
-}
-
-/*
- * Add a WR to a connections's list of pending WRs.  This is a singly-linked
- * list of sk_buffs operating as a FIFO.  The head is kept in wr_pending_head
- * and the tail in wr_pending_tail.
- */
-static inline void enqueue_wr(struct s3_conn *c3cn,
-			      struct sk_buff *skb)
-{
-	skb_tx_wr_next(skb) = NULL;
-
-	/*
-	 * We want to take an extra reference since both us and the driver
-	 * need to free the packet before it's really freed. We know there's
-	 * just one user currently so we use atomic_set rather than skb_get
-	 * to avoid the atomic op.
-	 */
-	atomic_set(&skb->users, 2);
-
-	if (!c3cn->wr_pending_head)
-		c3cn->wr_pending_head = skb;
-	else
-		skb_tx_wr_next(c3cn->wr_pending_tail) = skb;
-	c3cn->wr_pending_tail = skb;
-}
-
-static int count_pending_wrs(struct s3_conn *c3cn)
-{
-	int n = 0;
-	const struct sk_buff *skb = c3cn->wr_pending_head;
-
-	while (skb) {
-		n += skb->csum;
-		skb = skb_tx_wr_next(skb);
-	}
-	return n;
-}
-
-static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn)
-{
-	return c3cn->wr_pending_head;
-}
-
-static inline void free_wr_skb(struct sk_buff *skb)
-{
-	kfree_skb(skb);
-}
-
-static inline struct sk_buff *dequeue_wr(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb = c3cn->wr_pending_head;
-
-	if (likely(skb)) {
-		/* Don't bother clearing the tail */
-		c3cn->wr_pending_head = skb_tx_wr_next(skb);
-		skb_tx_wr_next(skb) = NULL;
-	}
-	return skb;
-}
-
-static void purge_wr_queue(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb;
-	while ((skb = dequeue_wr(c3cn)) != NULL)
-		free_wr_skb(skb);
-}
-
-static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb,
-				   int len, int req_completion)
-{
-	struct tx_data_wr *req;
-
-	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_completion ? F_WR_COMPL : 0));
-	req->wr_lo = htonl(V_WR_TID(c3cn->tid));
-	req->sndseq = htonl(c3cn->snd_nxt);
-	/* len includes the length of any HW ULP additions */
-	req->len = htonl(len);
-	req->param = htonl(V_TX_PORT(c3cn->l2t->smt_idx));
-	/* V_TX_ULP_SUBMODE sets both the mode and submode */
-	req->flags = htonl(V_TX_ULP_SUBMODE(skb_ulp_mode(skb)) |
-			   V_TX_SHOVE((skb_peek(&c3cn->write_queue) ? 0 : 1)));
-
-	if (!c3cn_flag(c3cn, C3CN_TX_DATA_SENT)) {
-		req->flags |= htonl(V_TX_ACK_PAGES(2) | F_TX_INIT |
-				    V_TX_CPU_IDX(c3cn->qset));
-		/* Sendbuffer is in units of 32KB. */
-		req->param |= htonl(V_TX_SNDBUF(cxgb3_snd_win >> 15));
-		c3cn_set_flag(c3cn, C3CN_TX_DATA_SENT);
-	}
-}
-
-/**
- * c3cn_push_tx_frames -- start transmit
- * @c3cn: the offloaded connection
- * @req_completion: request wr_ack or not
- *
- * Prepends TX_DATA_WR or CPL_CLOSE_CON_REQ headers to buffers waiting in a
- * connection's send queue and sends them on to T3.  Must be called with the
- * connection's lock held.  Returns the amount of send buffer space that was
- * freed as a result of sending queued data to T3.
- */
-static void arp_failure_discard(struct t3cdev *cdev, struct sk_buff *skb)
-{
-	kfree_skb(skb);
-}
-
-static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion)
-{
-	int total_size = 0;
-	struct sk_buff *skb;
-	struct t3cdev *cdev;
-	struct cxgb3i_sdev_data *cdata;
-
-	if (unlikely(c3cn->state == C3CN_STATE_CONNECTING ||
-		     c3cn->state == C3CN_STATE_CLOSE_WAIT_1 ||
-		     c3cn->state >= C3CN_STATE_ABORTING)) {
-		c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n",
-			      c3cn, c3cn->state);
-		return 0;
-	}
-
-	cdev = c3cn->cdev;
-	cdata = CXGB3_SDEV_DATA(cdev);
-
-	while (c3cn->wr_avail
-	       && (skb = skb_peek(&c3cn->write_queue)) != NULL) {
-		int len = skb->len;	/* length before skb_push */
-		int frags = skb_shinfo(skb)->nr_frags + (len != skb->data_len);
-		int wrs_needed = skb_wrs[frags];
-
-		if (wrs_needed > 1 && len + sizeof(struct tx_data_wr) <= wrlen)
-			wrs_needed = 1;
-
-		WARN_ON(frags >= SKB_WR_LIST_SIZE || wrs_needed < 1);
-
-		if (c3cn->wr_avail < wrs_needed) {
-			c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, "
-				      "wr %d < %u.\n",
-				      c3cn, skb->len, skb->data_len, frags,
-				      wrs_needed, c3cn->wr_avail);
-			break;
-		}
-
-		__skb_unlink(skb, &c3cn->write_queue);
-		skb->priority = CPL_PRIORITY_DATA;
-		skb->csum = wrs_needed;	/* remember this until the WR_ACK */
-		c3cn->wr_avail -= wrs_needed;
-		c3cn->wr_unacked += wrs_needed;
-		enqueue_wr(c3cn, skb);
-
-		c3cn_tx_debug("c3cn 0x%p, enqueue, skb len %u/%u, frag %u, "
-				"wr %d, left %u, unack %u.\n",
-				c3cn, skb->len, skb->data_len, frags,
-				wrs_needed, c3cn->wr_avail, c3cn->wr_unacked);
-
-
-		if (likely(skb_flags(skb) & C3CB_FLAG_NEED_HDR)) {
-			if ((req_completion &&
-				c3cn->wr_unacked == wrs_needed) ||
-			    (skb_flags(skb) & C3CB_FLAG_COMPL) ||
-			    c3cn->wr_unacked >= c3cn->wr_max / 2) {
-				req_completion = 1;
-				c3cn->wr_unacked = 0;
-			}
-			len += ulp_extra_len(skb);
-			make_tx_data_wr(c3cn, skb, len, req_completion);
-			c3cn->snd_nxt += len;
-			skb_flags(skb) &= ~C3CB_FLAG_NEED_HDR;
-		}
-
-		total_size += skb->truesize;
-		set_arp_failure_handler(skb, arp_failure_discard);
-		l2t_send(cdev, skb, c3cn->l2t);
-	}
-	return total_size;
-}
-
-/*
- * process_cpl_msg: -> host
- * Top-level CPL message processing used by most CPL messages that
- * pertain to connections.
- */
-static inline void process_cpl_msg(void (*fn)(struct s3_conn *,
-					      struct sk_buff *),
-				   struct s3_conn *c3cn,
-				   struct sk_buff *skb)
-{
-	spin_lock_bh(&c3cn->lock);
-	fn(c3cn, skb);
-	spin_unlock_bh(&c3cn->lock);
-}
-
-/*
- * process_cpl_msg_ref: -> host
- * Similar to process_cpl_msg() but takes an extra connection reference around
- * the call to the handler.  Should be used if the handler may drop a
- * connection reference.
- */
-static inline void process_cpl_msg_ref(void (*fn) (struct s3_conn *,
-						   struct sk_buff *),
-				       struct s3_conn *c3cn,
-				       struct sk_buff *skb)
-{
-	c3cn_hold(c3cn);
-	process_cpl_msg(fn, c3cn, skb);
-	c3cn_put(c3cn);
-}
-
-/*
- * Process a CPL_ACT_ESTABLISH message: -> host
- * Updates connection state from an active establish CPL message.  Runs with
- * the connection lock held.
- */
-
-static inline void s3_free_atid(struct t3cdev *cdev, unsigned int tid)
-{
-	struct s3_conn *c3cn = cxgb3_free_atid(cdev, tid);
-	if (c3cn)
-		c3cn_put(c3cn);
-}
-
-static void c3cn_established(struct s3_conn *c3cn, u32 snd_isn,
-			     unsigned int opt)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u.\n", c3cn, c3cn->state);
-
-	c3cn->write_seq = c3cn->snd_nxt = c3cn->snd_una = snd_isn;
-
-	/*
-	 * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't
-	 * pass through opt0.
-	 */
-	if (cxgb3_rcv_win > (M_RCV_BUFSIZ << 10))
-		c3cn->rcv_wup -= cxgb3_rcv_win - (M_RCV_BUFSIZ << 10);
-
-	dst_confirm(c3cn->dst_cache);
-
-	smp_mb();
-
-	c3cn_set_state(c3cn, C3CN_STATE_ESTABLISHED);
-}
-
-static void process_act_establish(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_act_establish *req = cplhdr(skb);
-	u32 rcv_isn = ntohl(req->rcv_isn);	/* real RCV_ISN + 1 */
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (unlikely(c3cn->state != C3CN_STATE_CONNECTING))
-		cxgb3i_log_error("TID %u expected SYN_SENT, got EST., s %u\n",
-				 c3cn->tid, c3cn->state);
-
-	c3cn->copied_seq = c3cn->rcv_wup = c3cn->rcv_nxt = rcv_isn;
-	c3cn_established(c3cn, ntohl(req->snd_isn), ntohs(req->tcp_opt));
-
-	__kfree_skb(skb);
-
-	if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED)))
-		/* upper layer has requested closing */
-		send_abort_req(c3cn);
-	else {
-		if (skb_queue_len(&c3cn->write_queue))
-			c3cn_push_tx_frames(c3cn, 1);
-		cxgb3i_conn_tx_open(c3cn);
-	}
-}
-
-static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb,
-			    void *ctx)
-{
-	struct cpl_act_establish *req = cplhdr(skb);
-	unsigned int tid = GET_TID(req);
-	unsigned int atid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
-	struct s3_conn *c3cn = ctx;
-	struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(cdev);
-
-	c3cn_conn_debug("rcv, tid 0x%x, c3cn 0x%p, s %u, f 0x%lx.\n",
-			tid, c3cn, c3cn->state, c3cn->flags);
-
-	c3cn->tid = tid;
-	c3cn_hold(c3cn);
-	cxgb3_insert_tid(cdata->cdev, cdata->client, c3cn, tid);
-	s3_free_atid(cdev, atid);
-
-	c3cn->qset = G_QNUM(ntohl(skb->csum));
-
-	process_cpl_msg(process_act_establish, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process a CPL_ACT_OPEN_RPL message: -> host
- * Handle active open failures.
- */
-static int act_open_rpl_status_to_errno(int status)
-{
-	switch (status) {
-	case CPL_ERR_CONN_RESET:
-		return -ECONNREFUSED;
-	case CPL_ERR_ARP_MISS:
-		return -EHOSTUNREACH;
-	case CPL_ERR_CONN_TIMEDOUT:
-		return -ETIMEDOUT;
-	case CPL_ERR_TCAM_FULL:
-		return -ENOMEM;
-	case CPL_ERR_CONN_EXIST:
-		cxgb3i_log_error("ACTIVE_OPEN_RPL: 4-tuple in use\n");
-		return -EADDRINUSE;
-	default:
-		return -EIO;
-	}
-}
-
-static void act_open_retry_timer(unsigned long data)
-{
-	struct sk_buff *skb;
-	struct s3_conn *c3cn = (struct s3_conn *)data;
-
-	c3cn_conn_debug("c3cn 0x%p, state %u.\n", c3cn, c3cn->state);
-
-	spin_lock_bh(&c3cn->lock);
-	skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_ATOMIC);
-	if (!skb)
-		fail_act_open(c3cn, -ENOMEM);
-	else {
-		skb->sk = (struct sock *)c3cn;
-		set_arp_failure_handler(skb, act_open_req_arp_failure);
-		make_act_open_req(c3cn, skb, c3cn->tid, c3cn->l2t);
-		l2t_send(c3cn->cdev, skb, c3cn->l2t);
-	}
-	spin_unlock_bh(&c3cn->lock);
-	c3cn_put(c3cn);
-}
-
-static void process_act_open_rpl(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_act_open_rpl *rpl = cplhdr(skb);
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (rpl->status == CPL_ERR_CONN_EXIST &&
-	    c3cn->retry_timer.function != act_open_retry_timer) {
-		c3cn->retry_timer.function = act_open_retry_timer;
-		if (!mod_timer(&c3cn->retry_timer, jiffies + HZ / 2))
-			c3cn_hold(c3cn);
-	} else
-		fail_act_open(c3cn, act_open_rpl_status_to_errno(rpl->status));
-	__kfree_skb(skb);
-}
-
-static int do_act_open_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-	struct cpl_act_open_rpl *rpl = cplhdr(skb);
-
-	c3cn_conn_debug("rcv, status 0x%x, c3cn 0x%p, s %u, f 0x%lx.\n",
-			rpl->status, c3cn, c3cn->state, c3cn->flags);
-
-	if (rpl->status != CPL_ERR_TCAM_FULL &&
-	    rpl->status != CPL_ERR_CONN_EXIST &&
-	    rpl->status != CPL_ERR_ARP_MISS)
-		cxgb3_queue_tid_release(cdev, GET_TID(rpl));
-
-	process_cpl_msg_ref(process_act_open_rpl, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process PEER_CLOSE CPL messages: -> host
- * Handle peer FIN.
- */
-static void process_peer_close(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING))
-		goto out;
-
-	switch (c3cn->state) {
-	case C3CN_STATE_ESTABLISHED:
-		c3cn_set_state(c3cn, C3CN_STATE_PASSIVE_CLOSE);
-		break;
-	case C3CN_STATE_ACTIVE_CLOSE:
-		c3cn_set_state(c3cn, C3CN_STATE_CLOSE_WAIT_2);
-		break;
-	case C3CN_STATE_CLOSE_WAIT_1:
-		c3cn_closed(c3cn);
-		break;
-	case C3CN_STATE_ABORTING:
-		break;
-	default:
-		cxgb3i_log_error("%s: peer close, TID %u in bad state %u\n",
-				 c3cn->cdev->name, c3cn->tid, c3cn->state);
-	}
-
-	cxgb3i_conn_closing(c3cn);
-out:
-	__kfree_skb(skb);
-}
-
-static int do_peer_close(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-
-	c3cn_conn_debug("rcv, c3cn 0x%p, s %u, f 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-	process_cpl_msg_ref(process_peer_close, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process CLOSE_CONN_RPL CPL message: -> host
- * Process a peer ACK to our FIN.
- */
-static void process_close_con_rpl(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_close_con_rpl *rpl = cplhdr(skb);
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	c3cn->snd_una = ntohl(rpl->snd_nxt) - 1;	/* exclude FIN */
-
-	if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING))
-		goto out;
-
-	switch (c3cn->state) {
-	case C3CN_STATE_ACTIVE_CLOSE:
-		c3cn_set_state(c3cn, C3CN_STATE_CLOSE_WAIT_1);
-		break;
-	case C3CN_STATE_CLOSE_WAIT_1:
-	case C3CN_STATE_CLOSE_WAIT_2:
-		c3cn_closed(c3cn);
-		break;
-	case C3CN_STATE_ABORTING:
-		break;
-	default:
-		cxgb3i_log_error("%s: close_rpl, TID %u in bad state %u\n",
-				 c3cn->cdev->name, c3cn->tid, c3cn->state);
-	}
-
-out:
-	kfree_skb(skb);
-}
-
-static int do_close_con_rpl(struct t3cdev *cdev, struct sk_buff *skb,
-			    void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-
-	c3cn_conn_debug("rcv, c3cn 0x%p, s %u, f 0x%lx.\n",
-			 c3cn, c3cn->state, c3cn->flags);
-
-	process_cpl_msg_ref(process_close_con_rpl, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process ABORT_REQ_RSS CPL message: -> host
- * Process abort requests.  If we are waiting for an ABORT_RPL we ignore this
- * request except that we need to reply to it.
- */
-
-static int abort_status_to_errno(struct s3_conn *c3cn, int abort_reason,
-				 int *need_rst)
-{
-	switch (abort_reason) {
-	case CPL_ERR_BAD_SYN: /* fall through */
-	case CPL_ERR_CONN_RESET:
-		return c3cn->state > C3CN_STATE_ESTABLISHED ?
-			-EPIPE : -ECONNRESET;
-	case CPL_ERR_XMIT_TIMEDOUT:
-	case CPL_ERR_PERSIST_TIMEDOUT:
-	case CPL_ERR_FINWAIT2_TIMEDOUT:
-	case CPL_ERR_KEEPALIVE_TIMEDOUT:
-		return -ETIMEDOUT;
-	default:
-		return -EIO;
-	}
-}
-
-static void process_abort_req(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	int rst_status = CPL_ABORT_NO_RST;
-	const struct cpl_abort_req_rss *req = cplhdr(skb);
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (!c3cn_flag(c3cn, C3CN_ABORT_REQ_RCVD)) {
-		c3cn_set_flag(c3cn, C3CN_ABORT_REQ_RCVD);
-		c3cn_set_state(c3cn, C3CN_STATE_ABORTING);
-		__kfree_skb(skb);
-		return;
-	}
-
-	c3cn_clear_flag(c3cn, C3CN_ABORT_REQ_RCVD);
-	send_abort_rpl(c3cn, rst_status);
-
-	if (!c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING)) {
-		c3cn->err =
-		    abort_status_to_errno(c3cn, req->status, &rst_status);
-		c3cn_closed(c3cn);
-	}
-}
-
-static int do_abort_req(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	const struct cpl_abort_req_rss *req = cplhdr(skb);
-	struct s3_conn *c3cn = ctx;
-
-	c3cn_conn_debug("rcv, c3cn 0x%p, s 0x%x, f 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
-	    req->status == CPL_ERR_PERSIST_NEG_ADVICE) {
-		__kfree_skb(skb);
-		return 0;
-	}
-
-	process_cpl_msg_ref(process_abort_req, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process ABORT_RPL_RSS CPL message: -> host
- * Process abort replies.  We only process these messages if we anticipate
- * them as the coordination between SW and HW in this area is somewhat lacking
- * and sometimes we get ABORT_RPLs after we are done with the connection that
- * originated the ABORT_REQ.
- */
-static void process_abort_rpl(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-
-	if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING)) {
-		if (!c3cn_flag(c3cn, C3CN_ABORT_RPL_RCVD))
-			c3cn_set_flag(c3cn, C3CN_ABORT_RPL_RCVD);
-		else {
-			c3cn_clear_flag(c3cn, C3CN_ABORT_RPL_RCVD);
-			c3cn_clear_flag(c3cn, C3CN_ABORT_RPL_PENDING);
-			if (c3cn_flag(c3cn, C3CN_ABORT_REQ_RCVD))
-				cxgb3i_log_error("%s tid %u, ABORT_RPL_RSS\n",
-						 c3cn->cdev->name, c3cn->tid);
-			c3cn_closed(c3cn);
-		}
-	}
-	__kfree_skb(skb);
-}
-
-static int do_abort_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
-	struct s3_conn *c3cn = ctx;
-
-	c3cn_conn_debug("rcv, status 0x%x, c3cn 0x%p, s %u, 0x%lx.\n",
-			rpl->status, c3cn, c3cn ? c3cn->state : 0,
-			c3cn ? c3cn->flags : 0UL);
-
-	/*
-	 * Ignore replies to post-close aborts indicating that the abort was
-	 * requested too late.  These connections are terminated when we get
-	 * PEER_CLOSE or CLOSE_CON_RPL and by the time the abort_rpl_rss
-	 * arrives the TID is either no longer used or it has been recycled.
-	 */
-	if (rpl->status == CPL_ERR_ABORT_FAILED)
-		goto discard;
-
-	/*
-	 * Sometimes we've already closed the connection, e.g., a post-close
-	 * abort races with ABORT_REQ_RSS, the latter frees the connection
-	 * expecting the ABORT_REQ will fail with CPL_ERR_ABORT_FAILED,
-	 * but FW turns the ABORT_REQ into a regular one and so we get
-	 * ABORT_RPL_RSS with status 0 and no connection.
-	 */
-	if (!c3cn)
-		goto discard;
-
-	process_cpl_msg_ref(process_abort_rpl, c3cn, skb);
-	return 0;
-
-discard:
-	__kfree_skb(skb);
-	return 0;
-}
-
-/*
- * Process RX_ISCSI_HDR CPL message: -> host
- * Handle received PDUs, the payload could be DDP'ed. If not, the payload
- * follow after the bhs.
- */
-static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_iscsi_hdr *hdr_cpl = cplhdr(skb);
-	struct cpl_iscsi_hdr_norss data_cpl;
-	struct cpl_rx_data_ddp_norss ddp_cpl;
-	unsigned int hdr_len, data_len, status;
-	unsigned int len;
-	int err;
-
-	if (unlikely(c3cn->state >= C3CN_STATE_PASSIVE_CLOSE)) {
-		if (c3cn->state != C3CN_STATE_ABORTING)
-			send_abort_req(c3cn);
-		__kfree_skb(skb);
-		return;
-	}
-
-	skb_tcp_seq(skb) = ntohl(hdr_cpl->seq);
-	skb_flags(skb) = 0;
-
-	skb_reset_transport_header(skb);
-	__skb_pull(skb, sizeof(struct cpl_iscsi_hdr));
-
-	len = hdr_len = ntohs(hdr_cpl->len);
-	/* msg coalesce is off or not enough data received */
-	if (skb->len <= hdr_len) {
-		cxgb3i_log_error("%s: TID %u, ISCSI_HDR, skb len %u < %u.\n",
-				 c3cn->cdev->name, c3cn->tid,
-				 skb->len, hdr_len);
-		goto abort_conn;
-	}
-
-	err = skb_copy_bits(skb, skb->len - sizeof(ddp_cpl), &ddp_cpl,
-			    sizeof(ddp_cpl));
-	if (err < 0)
-		goto abort_conn;
-
-	skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY;
-	skb_rx_pdulen(skb) = ntohs(ddp_cpl.len);
-	skb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
-	status = ntohl(ddp_cpl.ddp_status);
-
-	c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n",
-		      skb, skb->len, skb_rx_pdulen(skb), status);
-
-	if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT))
-		skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR;
-	if (status & (1 << RX_DDP_STATUS_DCRC_SHIFT))
-		skb_ulp_mode(skb) |= ULP2_FLAG_DCRC_ERROR;
-	if (status & (1 << RX_DDP_STATUS_PAD_SHIFT))
-		skb_ulp_mode(skb) |= ULP2_FLAG_PAD_ERROR;
-
-	if (skb->len > (hdr_len + sizeof(ddp_cpl))) {
-		err = skb_copy_bits(skb, hdr_len, &data_cpl, sizeof(data_cpl));
-		if (err < 0)
-			goto abort_conn;
-		data_len = ntohs(data_cpl.len);
-		len += sizeof(data_cpl) + data_len;
-	} else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT))
-		skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED;
-
-	c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_rx_pdulen(skb);
-	__pskb_trim(skb, len);
-	__skb_queue_tail(&c3cn->receive_queue, skb);
-	cxgb3i_conn_pdu_ready(c3cn);
-
-	return;
-
-abort_conn:
-	send_abort_req(c3cn);
-	__kfree_skb(skb);
-}
-
-static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-
-	process_cpl_msg(process_rx_iscsi_hdr, c3cn, skb);
-	return 0;
-}
-
-/*
- * Process TX_DATA_ACK CPL messages: -> host
- * Process an acknowledgment of WR completion.  Advance snd_una and send the
- * next batch of work requests from the write queue.
- */
-static void check_wr_invariants(struct s3_conn *c3cn)
-{
-	int pending = count_pending_wrs(c3cn);
-
-	if (unlikely(c3cn->wr_avail + pending != c3cn->wr_max))
-		cxgb3i_log_error("TID %u: credit imbalance: avail %u, "
-				"pending %u, total should be %u\n",
-				c3cn->tid, c3cn->wr_avail, pending,
-				c3cn->wr_max);
-}
-
-static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct cpl_wr_ack *hdr = cplhdr(skb);
-	unsigned int credits = ntohs(hdr->credits);
-	u32 snd_una = ntohl(hdr->snd_una);
-
-	c3cn_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u.\n",
-			credits, c3cn->wr_avail, c3cn->wr_unacked,
-			c3cn->tid, c3cn->state);
-
-	c3cn->wr_avail += credits;
-	if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail)
-		c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail;
-
-	while (credits) {
-		struct sk_buff *p = peek_wr(c3cn);
-
-		if (unlikely(!p)) {
-			cxgb3i_log_error("%u WR_ACK credits for TID %u with "
-					 "nothing pending, state %u\n",
-					 credits, c3cn->tid, c3cn->state);
-			break;
-		}
-		if (unlikely(credits < p->csum)) {
-			struct tx_data_wr *w = cplhdr(p);
-			cxgb3i_log_error("TID %u got %u WR credits need %u, "
-					 "len %u, main body %u, frags %u, "
-					 "seq # %u, ACK una %u, ACK nxt %u, "
-					 "WR_AVAIL %u, WRs pending %u\n",
-					 c3cn->tid, credits, p->csum, p->len,
-					 p->len - p->data_len,
-					 skb_shinfo(p)->nr_frags,
-					 ntohl(w->sndseq), snd_una,
-					 ntohl(hdr->snd_nxt), c3cn->wr_avail,
-					 count_pending_wrs(c3cn) - credits);
-			p->csum -= credits;
-			break;
-		} else {
-			dequeue_wr(c3cn);
-			credits -= p->csum;
-			free_wr_skb(p);
-		}
-	}
-
-	check_wr_invariants(c3cn);
-
-	if (unlikely(before(snd_una, c3cn->snd_una))) {
-		cxgb3i_log_error("TID %u, unexpected sequence # %u in WR_ACK "
-				 "snd_una %u\n",
-				 c3cn->tid, snd_una, c3cn->snd_una);
-		goto out_free;
-	}
-
-	if (c3cn->snd_una != snd_una) {
-		c3cn->snd_una = snd_una;
-		dst_confirm(c3cn->dst_cache);
-	}
-
-	if (skb_queue_len(&c3cn->write_queue)) {
-		if (c3cn_push_tx_frames(c3cn, 0))
-			cxgb3i_conn_tx_open(c3cn);
-	} else
-		cxgb3i_conn_tx_open(c3cn);
-out_free:
-	__kfree_skb(skb);
-}
-
-static int do_wr_ack(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
-{
-	struct s3_conn *c3cn = ctx;
-
-	process_cpl_msg(process_wr_ack, c3cn, skb);
-	return 0;
-}
-
-/*
- * for each connection, pre-allocate skbs needed for close/abort requests. So
- * that we can service the request right away.
- */
-static void c3cn_free_cpl_skbs(struct s3_conn *c3cn)
-{
-	if (c3cn->cpl_close)
-		kfree_skb(c3cn->cpl_close);
-	if (c3cn->cpl_abort_req)
-		kfree_skb(c3cn->cpl_abort_req);
-	if (c3cn->cpl_abort_rpl)
-		kfree_skb(c3cn->cpl_abort_rpl);
-}
-
-static int c3cn_alloc_cpl_skbs(struct s3_conn *c3cn)
-{
-	c3cn->cpl_close = alloc_skb(sizeof(struct cpl_close_con_req),
-				   GFP_KERNEL);
-	if (!c3cn->cpl_close)
-		return -ENOMEM;
-	skb_put(c3cn->cpl_close, sizeof(struct cpl_close_con_req));
-
-	c3cn->cpl_abort_req = alloc_skb(sizeof(struct cpl_abort_req),
-					GFP_KERNEL);
-	if (!c3cn->cpl_abort_req)
-		goto free_cpl_skbs;
-	skb_put(c3cn->cpl_abort_req, sizeof(struct cpl_abort_req));
-
-	c3cn->cpl_abort_rpl = alloc_skb(sizeof(struct cpl_abort_rpl),
-					GFP_KERNEL);
-	if (!c3cn->cpl_abort_rpl)
-		goto free_cpl_skbs;
-	skb_put(c3cn->cpl_abort_rpl, sizeof(struct cpl_abort_rpl));
-
-	return 0;
-
-free_cpl_skbs:
-	c3cn_free_cpl_skbs(c3cn);
-	return -ENOMEM;
-}
-
-/**
- * c3cn_release_offload_resources - release offload resource
- * @c3cn: the offloaded iscsi tcp connection.
- * Release resources held by an offload connection (TID, L2T entry, etc.)
- */
-static void c3cn_release_offload_resources(struct s3_conn *c3cn)
-{
-	struct t3cdev *cdev = c3cn->cdev;
-	unsigned int tid = c3cn->tid;
-
-	c3cn->qset = 0;
-	c3cn_free_cpl_skbs(c3cn);
-
-	if (c3cn->wr_avail != c3cn->wr_max) {
-		purge_wr_queue(c3cn);
-		reset_wr_list(c3cn);
-	}
-
-	if (cdev) {
-		if (c3cn->l2t) {
-			l2t_release(L2DATA(cdev), c3cn->l2t);
-			c3cn->l2t = NULL;
-		}
-		if (c3cn->state == C3CN_STATE_CONNECTING)
-			/* we have ATID */
-			s3_free_atid(cdev, tid);
-		else {
-			/* we have TID */
-			cxgb3_remove_tid(cdev, (void *)c3cn, tid);
-			c3cn_put(c3cn);
-		}
-	}
-
-	c3cn->dst_cache = NULL;
-	c3cn->cdev = NULL;
-}
-
-/**
- * cxgb3i_c3cn_create - allocate and initialize an s3_conn structure
- * returns the s3_conn structure allocated.
- */
-struct s3_conn *cxgb3i_c3cn_create(void)
-{
-	struct s3_conn *c3cn;
-
-	c3cn = kzalloc(sizeof(*c3cn), GFP_KERNEL);
-	if (!c3cn)
-		return NULL;
-
-	/* pre-allocate close/abort cpl, so we don't need to wait for memory
-	   when close/abort is requested. */
-	if (c3cn_alloc_cpl_skbs(c3cn) < 0)
-		goto free_c3cn;
-
-	c3cn_conn_debug("alloc c3cn 0x%p.\n", c3cn);
-
-	c3cn->flags = 0;
-	spin_lock_init(&c3cn->lock);
-	atomic_set(&c3cn->refcnt, 1);
-	skb_queue_head_init(&c3cn->receive_queue);
-	skb_queue_head_init(&c3cn->write_queue);
-	setup_timer(&c3cn->retry_timer, NULL, (unsigned long)c3cn);
-	rwlock_init(&c3cn->callback_lock);
-
-	return c3cn;
-
-free_c3cn:
-	kfree(c3cn);
-	return NULL;
-}
-
-static void c3cn_active_close(struct s3_conn *c3cn)
-{
-	int data_lost;
-	int close_req = 0;
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			 c3cn, c3cn->state, c3cn->flags);
-
-	dst_confirm(c3cn->dst_cache);
-
-	c3cn_hold(c3cn);
-	spin_lock_bh(&c3cn->lock);
-
-	data_lost = skb_queue_len(&c3cn->receive_queue);
-	__skb_queue_purge(&c3cn->receive_queue);
-
-	switch (c3cn->state) {
-	case C3CN_STATE_CLOSED:
-	case C3CN_STATE_ACTIVE_CLOSE:
-	case C3CN_STATE_CLOSE_WAIT_1:
-	case C3CN_STATE_CLOSE_WAIT_2:
-	case C3CN_STATE_ABORTING:
-		/* nothing need to be done */
-		break;
-	case C3CN_STATE_CONNECTING:
-		/* defer until cpl_act_open_rpl or cpl_act_establish */
-		c3cn_set_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED);
-		break;
-	case C3CN_STATE_ESTABLISHED:
-		close_req = 1;
-		c3cn_set_state(c3cn, C3CN_STATE_ACTIVE_CLOSE);
-		break;
-	case C3CN_STATE_PASSIVE_CLOSE:
-		close_req = 1;
-		c3cn_set_state(c3cn, C3CN_STATE_CLOSE_WAIT_2);
-		break;
-	}
-
-	if (close_req) {
-		if (data_lost)
-			/* Unread data was tossed, zap the connection. */
-			send_abort_req(c3cn);
-		else
-			send_close_req(c3cn);
-	}
-
-	spin_unlock_bh(&c3cn->lock);
-	c3cn_put(c3cn);
-}
-
-/**
- * cxgb3i_c3cn_release - close and release an iscsi tcp connection and any
- * 	resource held
- * @c3cn: the iscsi tcp connection
- */
-void cxgb3i_c3cn_release(struct s3_conn *c3cn)
-{
-	c3cn_conn_debug("c3cn 0x%p, s %u, f 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-	if (unlikely(c3cn->state == C3CN_STATE_CONNECTING))
-		c3cn_set_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED);
-	else if (likely(c3cn->state != C3CN_STATE_CLOSED))
-		c3cn_active_close(c3cn);
-	c3cn_put(c3cn);
-}
-
-static int is_cxgb3_dev(struct net_device *dev)
-{
-	struct cxgb3i_sdev_data *cdata;
-	struct net_device *ndev = dev;
-
-	if (dev->priv_flags & IFF_802_1Q_VLAN)
-		ndev = vlan_dev_real_dev(dev);
-
-	write_lock(&cdata_rwlock);
-	list_for_each_entry(cdata, &cdata_list, list) {
-		struct adap_ports *ports = &cdata->ports;
-		int i;
-
-		for (i = 0; i < ports->nports; i++)
-			if (ndev == ports->lldevs[i]) {
-				write_unlock(&cdata_rwlock);
-				return 1;
-			}
-	}
-	write_unlock(&cdata_rwlock);
-	return 0;
-}
-
-/**
- * cxgb3_egress_dev - return the cxgb3 egress device
- * @root_dev: the root device anchoring the search
- * @c3cn: the connection used to determine egress port in bonding mode
- * @context: in bonding mode, indicates a connection set up or failover
- *
- * Return egress device or NULL if the egress device isn't one of our ports.
- */
-static struct net_device *cxgb3_egress_dev(struct net_device *root_dev,
-					   struct s3_conn *c3cn,
-					   int context)
-{
-	while (root_dev) {
-		if (root_dev->priv_flags & IFF_802_1Q_VLAN)
-			root_dev = vlan_dev_real_dev(root_dev);
-		else if (is_cxgb3_dev(root_dev))
-			return root_dev;
-		else
-			return NULL;
-	}
-	return NULL;
-}
-
-static struct rtable *find_route(struct net_device *dev,
-				 __be32 saddr, __be32 daddr,
-				 __be16 sport, __be16 dport)
-{
-	struct rtable *rt;
-	struct flowi fl = {
-		.oif = dev ? dev->ifindex : 0,
-		.nl_u = {
-			 .ip4_u = {
-				   .daddr = daddr,
-				   .saddr = saddr,
-				   .tos = 0 } },
-		.proto = IPPROTO_TCP,
-		.uli_u = {
-			  .ports = {
-				    .sport = sport,
-				    .dport = dport } } };
-
-	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
-		return NULL;
-	return rt;
-}
-
-/*
- * Assign offload parameters to some connection fields.
- */
-static void init_offload_conn(struct s3_conn *c3cn,
-			      struct t3cdev *cdev,
-			      struct dst_entry *dst)
-{
-	BUG_ON(c3cn->cdev != cdev);
-	c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs - 1;
-	c3cn->wr_unacked = 0;
-	c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst));
-
-	reset_wr_list(c3cn);
-}
-
-static int initiate_act_open(struct s3_conn *c3cn, struct net_device *dev)
-{
-	struct cxgb3i_sdev_data *cdata = NDEV2CDATA(dev);
-	struct t3cdev *cdev = cdata->cdev;
-	struct dst_entry *dst = c3cn->dst_cache;
-	struct sk_buff *skb;
-
-	c3cn_conn_debug("c3cn 0x%p, state %u, flag 0x%lx.\n",
-			c3cn, c3cn->state, c3cn->flags);
-	/*
-	 * Initialize connection data.  Note that the flags and ULP mode are
-	 * initialized higher up ...
-	 */
-	c3cn->dev = dev;
-	c3cn->cdev = cdev;
-	c3cn->tid = cxgb3_alloc_atid(cdev, cdata->client, c3cn);
-	if (c3cn->tid < 0)
-		goto out_err;
-
-	c3cn->qset = 0;
-	c3cn->l2t = t3_l2t_get(cdev, dst->neighbour, dev);
-	if (!c3cn->l2t)
-		goto free_tid;
-
-	skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_KERNEL);
-	if (!skb)
-		goto free_l2t;
-
-	skb->sk = (struct sock *)c3cn;
-	set_arp_failure_handler(skb, act_open_req_arp_failure);
-
-	c3cn_hold(c3cn);
-
-	init_offload_conn(c3cn, cdev, dst);
-	c3cn->err = 0;
-
-	make_act_open_req(c3cn, skb, c3cn->tid, c3cn->l2t);
-	l2t_send(cdev, skb, c3cn->l2t);
-	return 0;
-
-free_l2t:
-	l2t_release(L2DATA(cdev), c3cn->l2t);
-free_tid:
-	s3_free_atid(cdev, c3cn->tid);
-	c3cn->tid = 0;
-out_err:
-	return -EINVAL;
-}
-
-/**
- * cxgb3i_find_dev - find the interface associated with the given address
- * @ipaddr: ip address
- */
-static struct net_device *
-cxgb3i_find_dev(struct net_device *dev, __be32 ipaddr)
-{
-	struct flowi fl;
-	int err;
-	struct rtable *rt;
-
-	memset(&fl, 0, sizeof(fl));
-	fl.nl_u.ip4_u.daddr = ipaddr;
-
-	err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl);
-	if (!err)
-		return (&rt->dst)->dev;
-
-	return NULL;
-}
-
-/**
- * cxgb3i_c3cn_connect - initiates an iscsi tcp connection to a given address
- * @c3cn: the iscsi tcp connection
- * @usin: destination address
- *
- * return 0 if active open request is sent, < 0 otherwise.
- */
-int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn,
-			struct sockaddr_in *usin)
-{
-	struct rtable *rt;
-	struct cxgb3i_sdev_data *cdata;
-	struct t3cdev *cdev;
-	__be32 sipv4;
-	struct net_device *dstdev;
-	int err;
-
-	c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev);
-
-	if (usin->sin_family != AF_INET)
-		return -EAFNOSUPPORT;
-
-	c3cn->daddr.sin_port = usin->sin_port;
-	c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr;
-
-	dstdev = cxgb3i_find_dev(dev, usin->sin_addr.s_addr);
-	if (!dstdev || !is_cxgb3_dev(dstdev))
-		return -ENETUNREACH;
-
-	if (dstdev->priv_flags & IFF_802_1Q_VLAN)
-		dev = dstdev;
-
-	rt = find_route(dev, c3cn->saddr.sin_addr.s_addr,
-			c3cn->daddr.sin_addr.s_addr,
-			c3cn->saddr.sin_port,
-			c3cn->daddr.sin_port);
-	if (rt == NULL) {
-		c3cn_conn_debug("NO route to 0x%x, port %u, dev %s.\n",
-				c3cn->daddr.sin_addr.s_addr,
-				ntohs(c3cn->daddr.sin_port),
-				dev ? dev->name : "any");
-		return -ENETUNREACH;
-	}
-
-	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
-		c3cn_conn_debug("multi-cast route to 0x%x, port %u, dev %s.\n",
-				c3cn->daddr.sin_addr.s_addr,
-				ntohs(c3cn->daddr.sin_port),
-				dev ? dev->name : "any");
-		ip_rt_put(rt);
-		return -ENETUNREACH;
-	}
-
-	if (!c3cn->saddr.sin_addr.s_addr)
-		c3cn->saddr.sin_addr.s_addr = rt->rt_src;
-
-	/* now commit destination to connection */
-	c3cn->dst_cache = &rt->dst;
-
-	/* try to establish an offloaded connection */
-	dev = cxgb3_egress_dev(c3cn->dst_cache->dev, c3cn, 0);
-	if (dev == NULL) {
-		c3cn_conn_debug("c3cn 0x%p, egress dev NULL.\n", c3cn);
-		return -ENETUNREACH;
-	}
-	cdata = NDEV2CDATA(dev);
-	cdev = cdata->cdev;
-
-	/* get a source port if one hasn't been provided */
-	err = c3cn_get_port(c3cn, cdata);
-	if (err)
-		return err;
-
-	c3cn_conn_debug("c3cn 0x%p get port %u.\n",
-			c3cn, ntohs(c3cn->saddr.sin_port));
-
-	sipv4 = cxgb3i_get_private_ipv4addr(dev);
-	if (!sipv4) {
-		c3cn_conn_debug("c3cn 0x%p, iscsi ip not configured.\n", c3cn);
-		sipv4 = c3cn->saddr.sin_addr.s_addr;
-		cxgb3i_set_private_ipv4addr(dev, sipv4);
-	} else
-		c3cn->saddr.sin_addr.s_addr = sipv4;
-
-	c3cn_conn_debug("c3cn 0x%p, %pI4,%u-%pI4,%u SYN_SENT.\n",
-			c3cn,
-			&c3cn->saddr.sin_addr.s_addr,
-			ntohs(c3cn->saddr.sin_port),
-			&c3cn->daddr.sin_addr.s_addr,
-			ntohs(c3cn->daddr.sin_port));
-
-	c3cn_set_state(c3cn, C3CN_STATE_CONNECTING);
-	if (!initiate_act_open(c3cn, dev))
-		return 0;
-
-	/*
-	 * If we get here, we don't have an offload connection so simply
-	 * return a failure.
-	 */
-	err = -ENOTSUPP;
-
-	/*
-	 * This trashes the connection and releases the local port,
-	 * if necessary.
-	 */
-	c3cn_conn_debug("c3cn 0x%p -> CLOSED.\n", c3cn);
-	c3cn_set_state(c3cn, C3CN_STATE_CLOSED);
-	ip_rt_put(rt);
-	c3cn_put_port(c3cn);
-	return err;
-}
-
-/**
- * cxgb3i_c3cn_rx_credits - ack received tcp data.
- * @c3cn: iscsi tcp connection
- * @copied: # of bytes processed
- *
- * Called after some received data has been read.  It returns RX credits
- * to the HW for the amount of data processed.
- */
-void cxgb3i_c3cn_rx_credits(struct s3_conn *c3cn, int copied)
-{
-	struct t3cdev *cdev;
-	int must_send;
-	u32 credits, dack = 0;
-
-	if (c3cn->state != C3CN_STATE_ESTABLISHED)
-		return;
-
-	credits = c3cn->copied_seq - c3cn->rcv_wup;
-	if (unlikely(!credits))
-		return;
-
-	cdev = c3cn->cdev;
-
-	if (unlikely(cxgb3_rx_credit_thres == 0))
-		return;
-
-	dack = F_RX_DACK_CHANGE | V_RX_DACK_MODE(1);
-
-	/*
-	 * For coalescing to work effectively ensure the receive window has
-	 * at least 16KB left.
-	 */
-	must_send = credits + 16384 >= cxgb3_rcv_win;
-
-	if (must_send || credits >= cxgb3_rx_credit_thres)
-		c3cn->rcv_wup += send_rx_credits(c3cn, credits, dack);
-}
-
-/**
- * cxgb3i_c3cn_send_pdus - send the skbs containing iscsi pdus
- * @c3cn: iscsi tcp connection
- * @skb: skb contains the iscsi pdu
- *
- * Add a list of skbs to a connection send queue. The skbs must comply with
- * the max size limit of the device and have a headroom of at least
- * TX_HEADER_LEN bytes.
- * Return # of bytes queued.
- */
-int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb)
-{
-	struct sk_buff *next;
-	int err, copied = 0;
-
-	spin_lock_bh(&c3cn->lock);
-
-	if (c3cn->state != C3CN_STATE_ESTABLISHED) {
-		c3cn_tx_debug("c3cn 0x%p, not in est. state %u.\n",
-			      c3cn, c3cn->state);
-		err = -EAGAIN;
-		goto out_err;
-	}
-
-	if (c3cn->err) {
-		c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err);
-		err = -EPIPE;
-		goto out_err;
-	}
-
-	if (c3cn->write_seq - c3cn->snd_una >= cxgb3_snd_win) {
-		c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n",
-				c3cn, c3cn->write_seq, c3cn->snd_una,
-				cxgb3_snd_win);
-		err = -ENOBUFS;
-		goto out_err;
-	}
-
-	while (skb) {
-		int frags = skb_shinfo(skb)->nr_frags +
-				(skb->len != skb->data_len);
-
-		if (unlikely(skb_headroom(skb) < TX_HEADER_LEN)) {
-			c3cn_tx_debug("c3cn 0x%p, skb head.\n", c3cn);
-			err = -EINVAL;
-			goto out_err;
-		}
-
-		if (frags >= SKB_WR_LIST_SIZE) {
-			cxgb3i_log_error("c3cn 0x%p, tx frags %d, len %u,%u.\n",
-					 c3cn, skb_shinfo(skb)->nr_frags,
-					 skb->len, skb->data_len);
-			err = -EINVAL;
-			goto out_err;
-		}
-
-		next = skb->next;
-		skb->next = NULL;
-		skb_entail(c3cn, skb, C3CB_FLAG_NO_APPEND | C3CB_FLAG_NEED_HDR);
-		copied += skb->len;
-		c3cn->write_seq += skb->len + ulp_extra_len(skb);
-		skb = next;
-	}
-done:
-	if (likely(skb_queue_len(&c3cn->write_queue)))
-		c3cn_push_tx_frames(c3cn, 1);
-	spin_unlock_bh(&c3cn->lock);
-	return copied;
-
-out_err:
-	if (copied == 0 && err == -EPIPE)
-		copied = c3cn->err ? c3cn->err : -EPIPE;
-	else
-		copied = err;
-	goto done;
-}
-
-static void sdev_data_cleanup(struct cxgb3i_sdev_data *cdata)
-{
-	struct adap_ports *ports = &cdata->ports;
-	struct s3_conn *c3cn;
-	int i;
-
-	for (i = 0; i < cxgb3_max_connect; i++) {
-		if (cdata->sport_conn[i]) {
-			c3cn = cdata->sport_conn[i];
-			cdata->sport_conn[i] = NULL;
-
-			spin_lock_bh(&c3cn->lock);
-			c3cn->cdev = NULL;
-			c3cn_set_flag(c3cn, C3CN_OFFLOAD_DOWN);
-			c3cn_closed(c3cn);
-			spin_unlock_bh(&c3cn->lock);
-		}
-	}
-
-	for (i = 0; i < ports->nports; i++)
-		NDEV2CDATA(ports->lldevs[i]) = NULL;
-
-	cxgb3i_free_big_mem(cdata);
-}
-
-void cxgb3i_sdev_cleanup(void)
-{
-	struct cxgb3i_sdev_data *cdata;
-
-	write_lock(&cdata_rwlock);
-	list_for_each_entry(cdata, &cdata_list, list) {
-		list_del(&cdata->list);
-		sdev_data_cleanup(cdata);
-	}
-	write_unlock(&cdata_rwlock);
-}
-
-int cxgb3i_sdev_init(cxgb3_cpl_handler_func *cpl_handlers)
-{
-	cpl_handlers[CPL_ACT_ESTABLISH] = do_act_establish;
-	cpl_handlers[CPL_ACT_OPEN_RPL] = do_act_open_rpl;
-	cpl_handlers[CPL_PEER_CLOSE] = do_peer_close;
-	cpl_handlers[CPL_ABORT_REQ_RSS] = do_abort_req;
-	cpl_handlers[CPL_ABORT_RPL_RSS] = do_abort_rpl;
-	cpl_handlers[CPL_CLOSE_CON_RPL] = do_close_con_rpl;
-	cpl_handlers[CPL_TX_DMA_ACK] = do_wr_ack;
-	cpl_handlers[CPL_ISCSI_HDR] = do_iscsi_hdr;
-
-	if (cxgb3_max_connect > CXGB3I_MAX_CONN)
-		cxgb3_max_connect = CXGB3I_MAX_CONN;
-	return 0;
-}
-
-/**
- * cxgb3i_sdev_add - allocate and initialize resources for each adapter found
- * @cdev:	t3cdev adapter
- * @client:	cxgb3 driver client
- */
-void cxgb3i_sdev_add(struct t3cdev *cdev, struct cxgb3_client *client)
-{
-	struct cxgb3i_sdev_data *cdata;
-	struct ofld_page_info rx_page_info;
-	unsigned int wr_len;
-	int mapsize = cxgb3_max_connect * sizeof(struct s3_conn *);
-	int i;
-
-	cdata =  cxgb3i_alloc_big_mem(sizeof(*cdata) + mapsize, GFP_KERNEL);
-	if (!cdata) {
-		cxgb3i_log_warn("t3dev 0x%p, offload up, OOM %d.\n",
-				cdev, mapsize);
-		return;
-	}
-
-	if (cdev->ctl(cdev, GET_WR_LEN, &wr_len) < 0 ||
-	    cdev->ctl(cdev, GET_PORTS, &cdata->ports) < 0 ||
-	    cdev->ctl(cdev, GET_RX_PAGE_INFO, &rx_page_info) < 0) {
-		cxgb3i_log_warn("t3dev 0x%p, offload up, ioctl failed.\n",
-				cdev);
-		goto free_cdata;
-	}
-
-	s3_init_wr_tab(wr_len);
-
-	spin_lock_init(&cdata->lock);
-	INIT_LIST_HEAD(&cdata->list);
-	cdata->cdev = cdev;
-	cdata->client = client;
-
-	for (i = 0; i < cdata->ports.nports; i++)
-		NDEV2CDATA(cdata->ports.lldevs[i]) = cdata;
-
-	write_lock(&cdata_rwlock);
-	list_add_tail(&cdata->list, &cdata_list);
-	write_unlock(&cdata_rwlock);
-
-	cxgb3i_log_info("t3dev 0x%p, offload up, added.\n", cdev);
-	return;
-
-free_cdata:
-	cxgb3i_free_big_mem(cdata);
-}
-
-/**
- * cxgb3i_sdev_remove - free the allocated resources for the adapter
- * @cdev:	t3cdev adapter
- */
-void cxgb3i_sdev_remove(struct t3cdev *cdev)
-{
-	struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(cdev);
-
-	cxgb3i_log_info("t3dev 0x%p, offload down, remove.\n", cdev);
-
-	write_lock(&cdata_rwlock);
-	list_del(&cdata->list);
-	write_unlock(&cdata_rwlock);
-
-	sdev_data_cleanup(cdata);
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h
deleted file mode 100644
index 6a1d86b..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * cxgb3i_offload.h: Chelsio S3xx iscsi offloaded tcp connection management
- *
- * Copyright (C) 2003-2008 Chelsio Communications.  All rights reserved.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
- * release for licensing terms and conditions.
- *
- * Written by:	Dimitris Michailidis (dm@chelsio.com)
- *		Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef _CXGB3I_OFFLOAD_H
-#define _CXGB3I_OFFLOAD_H
-
-#include <linux/skbuff.h>
-#include <linux/in.h>
-
-#include "common.h"
-#include "adapter.h"
-#include "t3cdev.h"
-#include "cxgb3_offload.h"
-
-#define cxgb3i_log_error(fmt...) printk(KERN_ERR "cxgb3i: ERR! " fmt)
-#define cxgb3i_log_warn(fmt...)	 printk(KERN_WARNING "cxgb3i: WARN! " fmt)
-#define cxgb3i_log_info(fmt...)  printk(KERN_INFO "cxgb3i: " fmt)
-#define cxgb3i_log_debug(fmt, args...) \
-	printk(KERN_INFO "cxgb3i: %s - " fmt, __func__ , ## args)
-
-/**
- * struct s3_conn - an iscsi tcp connection structure
- *
- * @dev:	net device of with connection
- * @cdev:	adapter t3cdev for net device
- * @flags:	see c3cn_flags below
- * @tid:	connection id assigned by the h/w
- * @qset:	queue set used by connection
- * @mss_idx:	Maximum Segment Size table index
- * @l2t:	ARP resolution entry for offload packets
- * @wr_max:	maximum in-flight writes
- * @wr_avail:	number of writes available
- * @wr_unacked:	writes since last request for completion notification
- * @wr_pending_head: head of pending write queue
- * @wr_pending_tail: tail of pending write queue
- * @cpl_close:	skb for cpl_close_req
- * @cpl_abort_req: skb for cpl_abort_req
- * @cpl_abort_rpl: skb for cpl_abort_rpl
- * @lock:	connection status lock
- * @refcnt:	reference count on connection
- * @state:	connection state
- * @saddr:	source ip/port address
- * @daddr:	destination ip/port address
- * @dst_cache:	reference to destination route
- * @receive_queue: received PDUs
- * @write_queue: un-pushed pending writes
- * @retry_timer: retry timer for various operations
- * @err:	connection error status
- * @callback_lock: lock for opaque user context
- * @user_data:	opaque user context
- * @rcv_nxt:	next receive seq. #
- * @copied_seq:	head of yet unread data
- * @rcv_wup:	rcv_nxt on last window update sent
- * @snd_nxt:	next sequence we send
- * @snd_una:	first byte we want an ack for
- * @write_seq:	tail+1 of data held in send buffer
- */
-struct s3_conn {
-	struct net_device *dev;
-	struct t3cdev *cdev;
-	unsigned long flags;
-	int tid;
-	int qset;
-	int mss_idx;
-	struct l2t_entry *l2t;
-	int wr_max;
-	int wr_avail;
-	int wr_unacked;
-	struct sk_buff *wr_pending_head;
-	struct sk_buff *wr_pending_tail;
-	struct sk_buff *cpl_close;
-	struct sk_buff *cpl_abort_req;
-	struct sk_buff *cpl_abort_rpl;
-	spinlock_t lock;
-	atomic_t refcnt;
-	volatile unsigned int state;
-	struct sockaddr_in saddr;
-	struct sockaddr_in daddr;
-	struct dst_entry *dst_cache;
-	struct sk_buff_head receive_queue;
-	struct sk_buff_head write_queue;
-	struct timer_list retry_timer;
-	int err;
-	rwlock_t callback_lock;
-	void *user_data;
-
-	u32 rcv_nxt;
-	u32 copied_seq;
-	u32 rcv_wup;
-	u32 snd_nxt;
-	u32 snd_una;
-	u32 write_seq;
-};
-
-/*
- * connection state
- */
-enum conn_states {
-	C3CN_STATE_CONNECTING = 1,
-	C3CN_STATE_ESTABLISHED,
-	C3CN_STATE_ACTIVE_CLOSE,
-	C3CN_STATE_PASSIVE_CLOSE,
-	C3CN_STATE_CLOSE_WAIT_1,
-	C3CN_STATE_CLOSE_WAIT_2,
-	C3CN_STATE_ABORTING,
-	C3CN_STATE_CLOSED,
-};
-
-static inline unsigned int c3cn_is_closing(const struct s3_conn *c3cn)
-{
-	return c3cn->state >= C3CN_STATE_ACTIVE_CLOSE;
-}
-static inline unsigned int c3cn_is_established(const struct s3_conn *c3cn)
-{
-	return c3cn->state == C3CN_STATE_ESTABLISHED;
-}
-
-/*
- * Connection flags -- many to track some close related events.
- */
-enum c3cn_flags {
-	C3CN_ABORT_RPL_RCVD,	/* received one ABORT_RPL_RSS message */
-	C3CN_ABORT_REQ_RCVD,	/* received one ABORT_REQ_RSS message */
-	C3CN_ABORT_RPL_PENDING,	/* expecting an abort reply */
-	C3CN_TX_DATA_SENT,	/* already sent a TX_DATA WR */
-	C3CN_ACTIVE_CLOSE_NEEDED,	/* need to be closed */
-	C3CN_OFFLOAD_DOWN	/* offload function off */
-};
-
-/**
- * cxgb3i_sdev_data - Per adapter data.
- * Linked off of each Ethernet device port on the adapter.
- * Also available via the t3cdev structure since we have pointers to our port
- * net_device's there ...
- *
- * @list:	list head to link elements
- * @cdev:	t3cdev adapter
- * @client:	CPL client pointer
- * @ports:	array of adapter ports
- * @sport_next: next port
- * @sport_conn:	source port connection
- */
-struct cxgb3i_sdev_data {
-	struct list_head list;
-	struct t3cdev *cdev;
-	struct cxgb3_client *client;
-	struct adap_ports ports;
-	spinlock_t lock;
-	unsigned int sport_next;
-	struct s3_conn *sport_conn[0];
-};
-#define NDEV2CDATA(ndev) (*(struct cxgb3i_sdev_data **)&(ndev)->ec_ptr)
-#define CXGB3_SDEV_DATA(cdev) NDEV2CDATA((cdev)->lldev)
-
-void cxgb3i_sdev_cleanup(void);
-int cxgb3i_sdev_init(cxgb3_cpl_handler_func *);
-void cxgb3i_sdev_add(struct t3cdev *, struct cxgb3_client *);
-void cxgb3i_sdev_remove(struct t3cdev *);
-
-struct s3_conn *cxgb3i_c3cn_create(void);
-int cxgb3i_c3cn_connect(struct net_device *, struct s3_conn *,
-			struct sockaddr_in *);
-void cxgb3i_c3cn_rx_credits(struct s3_conn *, int);
-int cxgb3i_c3cn_send_pdus(struct s3_conn *, struct sk_buff *);
-void cxgb3i_c3cn_release(struct s3_conn *);
-
-/**
- * cxgb3_skb_cb - control block for received pdu state and ULP mode management.
- *
- * @flag:	see C3CB_FLAG_* below
- * @ulp_mode:	ULP mode/submode of sk_buff
- * @seq:	tcp sequence number
- */
-struct cxgb3_skb_rx_cb {
-	__u32 ddigest;			/* data digest */
-	__u32 pdulen;			/* recovered pdu length */
-};
-
-struct cxgb3_skb_tx_cb {
-	struct sk_buff *wr_next;	/* next wr */
-};
-
-struct cxgb3_skb_cb {
-	__u8 flags;
-	__u8 ulp_mode;
-	__u32 seq;
-	union {
-		struct cxgb3_skb_rx_cb rx;
-		struct cxgb3_skb_tx_cb tx;
-	};
-};
-
-#define CXGB3_SKB_CB(skb)	((struct cxgb3_skb_cb *)&((skb)->cb[0]))
-#define skb_flags(skb)		(CXGB3_SKB_CB(skb)->flags)
-#define skb_ulp_mode(skb)	(CXGB3_SKB_CB(skb)->ulp_mode)
-#define skb_tcp_seq(skb)	(CXGB3_SKB_CB(skb)->seq)
-#define skb_rx_ddigest(skb)	(CXGB3_SKB_CB(skb)->rx.ddigest)
-#define skb_rx_pdulen(skb)	(CXGB3_SKB_CB(skb)->rx.pdulen)
-#define skb_tx_wr_next(skb)	(CXGB3_SKB_CB(skb)->tx.wr_next)
-
-enum c3cb_flags {
-	C3CB_FLAG_NEED_HDR = 1 << 0,	/* packet needs a TX_DATA_WR header */
-	C3CB_FLAG_NO_APPEND = 1 << 1,	/* don't grow this skb */
-	C3CB_FLAG_COMPL = 1 << 2,	/* request WR completion */
-};
-
-/**
- * sge_opaque_hdr -
- * Opaque version of structure the SGE stores at skb->head of TX_DATA packets
- * and for which we must reserve space.
- */
-struct sge_opaque_hdr {
-	void *dev;
-	dma_addr_t addr[MAX_SKB_FRAGS + 1];
-};
-
-/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
-#define TX_HEADER_LEN \
-		(sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr))
-#define SKB_TX_HEADROOM		SKB_MAX_HEAD(TX_HEADER_LEN)
-
-/*
- * get and set private ip for iscsi traffic
- */
-#define cxgb3i_get_private_ipv4addr(ndev) \
-	(((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr)
-#define cxgb3i_set_private_ipv4addr(ndev, addr) \
-	(((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr) = addr
-
-/* max. connections per adapter */
-#define CXGB3I_MAX_CONN		16384
-#endif /* _CXGB3_OFFLOAD_H */
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
deleted file mode 100644
index dc5e3e7..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * cxgb3i_pdu.c: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, Inc.
- * Copyright (c) 2008 Mike Christie
- * Copyright (c) 2008 Red Hat, Inc.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/crypto.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_host.h>
-
-#include "cxgb3i.h"
-#include "cxgb3i_pdu.h"
-
-#ifdef __DEBUG_CXGB3I_RX__
-#define cxgb3i_rx_debug		cxgb3i_log_debug
-#else
-#define cxgb3i_rx_debug(fmt...)
-#endif
-
-#ifdef __DEBUG_CXGB3I_TX__
-#define cxgb3i_tx_debug		cxgb3i_log_debug
-#else
-#define cxgb3i_tx_debug(fmt...)
-#endif
-
-/* always allocate rooms for AHS */
-#define SKB_TX_PDU_HEADER_LEN	\
-	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
-static unsigned int skb_extra_headroom;
-static struct page *pad_page;
-
-/*
- * pdu receive, interact with libiscsi_tcp
- */
-static inline int read_pdu_skb(struct iscsi_conn *conn, struct sk_buff *skb,
-			       unsigned int offset, int offloaded)
-{
-	int status = 0;
-	int bytes_read;
-
-	bytes_read = iscsi_tcp_recv_skb(conn, skb, offset, offloaded, &status);
-	switch (status) {
-	case ISCSI_TCP_CONN_ERR:
-		return -EIO;
-	case ISCSI_TCP_SUSPENDED:
-		/* no transfer - just have caller flush queue */
-		return bytes_read;
-	case ISCSI_TCP_SKB_DONE:
-		/*
-		 * pdus should always fit in the skb and we should get
-		 * segment done notifcation.
-		 */
-		iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu or skb.");
-		return -EFAULT;
-	case ISCSI_TCP_SEGMENT_DONE:
-		return bytes_read;
-	default:
-		iscsi_conn_printk(KERN_ERR, conn, "Invalid iscsi_tcp_recv_skb "
-				  "status %d\n", status);
-		return -EINVAL;
-	}
-}
-
-static int cxgb3i_conn_read_pdu_skb(struct iscsi_conn *conn,
-				    struct sk_buff *skb)
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	bool offloaded = 0;
-	unsigned int offset;
-	int rc;
-
-	cxgb3i_rx_debug("conn 0x%p, skb 0x%p, len %u, flag 0x%x.\n",
-			conn, skb, skb->len, skb_ulp_mode(skb));
-
-	if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
-		iscsi_conn_failure(conn, ISCSI_ERR_PROTO);
-		return -EIO;
-	}
-
-	if (conn->hdrdgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_HCRC_ERROR)) {
-		iscsi_conn_failure(conn, ISCSI_ERR_HDR_DGST);
-		return -EIO;
-	}
-
-	if (conn->datadgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_DCRC_ERROR)) {
-		iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
-		return -EIO;
-	}
-
-	/* iscsi hdr */
-	rc = read_pdu_skb(conn, skb, 0, 0);
-	if (rc <= 0)
-		return rc;
-
-	if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
-		return 0;
-
-	offset = rc;
-	if (conn->hdrdgst_en)
-		offset += ISCSI_DIGEST_SIZE;
-
-	/* iscsi data */
-	if (skb_ulp_mode(skb) & ULP2_FLAG_DATA_DDPED) {
-		cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, ddp'ed, "
-				"itt 0x%x.\n",
-				skb,
-				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
-				tcp_conn->in.datalen,
-				ntohl(tcp_conn->in.hdr->itt));
-		offloaded = 1;
-	} else {
-		cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, NOT ddp'ed, "
-				"itt 0x%x.\n",
-				skb,
-				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
-				tcp_conn->in.datalen,
-				ntohl(tcp_conn->in.hdr->itt));
-		offset += sizeof(struct cpl_iscsi_hdr_norss);
-	}
-
-	rc = read_pdu_skb(conn, skb, offset, offloaded);
-	if (rc < 0)
-		return rc;
-	else
-		return 0;
-}
-
-/*
- * pdu transmit, interact with libiscsi_tcp
- */
-static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
-{
-	u8 submode = 0;
-
-	if (hcrc)
-		submode |= 1;
-	if (dcrc)
-		submode |= 2;
-	skb_ulp_mode(skb) = (ULP_MODE_ISCSI << 4) | submode;
-}
-
-void cxgb3i_conn_cleanup_task(struct iscsi_task *task)
-{
-	struct cxgb3i_task_data *tdata = task->dd_data +
-					sizeof(struct iscsi_tcp_task);
-
-	/* never reached the xmit task callout */
-	if (tdata->skb)
-		__kfree_skb(tdata->skb);
-	memset(tdata, 0, sizeof(struct cxgb3i_task_data));
-
-	/* MNC - Do we need a check in case this is called but
-	 * cxgb3i_conn_alloc_pdu has never been called on the task */
-	cxgb3i_release_itt(task, task->hdr_itt);
-	iscsi_tcp_cleanup_task(task);
-}
-
-static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
-				unsigned int offset, unsigned int *off,
-				struct scatterlist **sgp)
-{
-	int i;
-	struct scatterlist *sg;
-
-	for_each_sg(sgl, sg, sgcnt, i) {
-		if (offset < sg->length) {
-			*off = offset;
-			*sgp = sg;
-			return 0;
-		}
-		offset -= sg->length;
-	}
-	return -EFAULT;
-}
-
-static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
-				unsigned int dlen, skb_frag_t *frags,
-				int frag_max)
-{
-	unsigned int datalen = dlen;
-	unsigned int sglen = sg->length - sgoffset;
-	struct page *page = sg_page(sg);
-	int i;
-
-	i = 0;
-	do {
-		unsigned int copy;
-
-		if (!sglen) {
-			sg = sg_next(sg);
-			if (!sg) {
-				cxgb3i_log_error("%s, sg NULL, len %u/%u.\n",
-						 __func__, datalen, dlen);
-				return -EINVAL;
-			}
-			sgoffset = 0;
-			sglen = sg->length;
-			page = sg_page(sg);
-
-		}
-		copy = min(datalen, sglen);
-		if (i && page == frags[i - 1].page &&
-		    sgoffset + sg->offset ==
-			frags[i - 1].page_offset + frags[i - 1].size) {
-			frags[i - 1].size += copy;
-		} else {
-			if (i >= frag_max) {
-				cxgb3i_log_error("%s, too many pages %u, "
-						 "dlen %u.\n", __func__,
-						 frag_max, dlen);
-				return -EINVAL;
-			}
-
-			frags[i].page = page;
-			frags[i].page_offset = sg->offset + sgoffset;
-			frags[i].size = copy;
-			i++;
-		}
-		datalen -= copy;
-		sgoffset += copy;
-		sglen -= copy;
-	} while (datalen);
-
-	return i;
-}
-
-int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
-{
-	struct iscsi_conn *conn = task->conn;
-	struct iscsi_tcp_task *tcp_task = task->dd_data;
-	struct cxgb3i_task_data *tdata = task->dd_data + sizeof(*tcp_task);
-	struct scsi_cmnd *sc = task->sc;
-	int headroom = SKB_TX_PDU_HEADER_LEN;
-
-	tcp_task->dd_data = tdata;
-	task->hdr = NULL;
-
-	/* write command, need to send data pdus */
-	if (skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT ||
-	    (opcode == ISCSI_OP_SCSI_CMD &&
-	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
-		headroom += min(skb_extra_headroom, conn->max_xmit_dlength);
-
-	tdata->skb = alloc_skb(TX_HEADER_LEN + headroom, GFP_ATOMIC);
-	if (!tdata->skb)
-		return -ENOMEM;
-	skb_reserve(tdata->skb, TX_HEADER_LEN);
-
-	cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n",
-			task, opcode, tdata->skb);
-
-	task->hdr = (struct iscsi_hdr *)tdata->skb->data;
-	task->hdr_max = SKB_TX_PDU_HEADER_LEN;
-
-	/* data_out uses scsi_cmd's itt */
-	if (opcode != ISCSI_OP_SCSI_DATA_OUT)
-		cxgb3i_reserve_itt(task, &task->hdr->itt);
-
-	return 0;
-}
-
-int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
-			      unsigned int count)
-{
-	struct iscsi_conn *conn = task->conn;
-	struct iscsi_tcp_task *tcp_task = task->dd_data;
-	struct cxgb3i_task_data *tdata = tcp_task->dd_data;
-	struct sk_buff *skb = tdata->skb;
-	unsigned int datalen = count;
-	int i, padlen = iscsi_padding(count);
-	struct page *pg;
-
-	cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n",
-			task, task->sc, offset, count, skb);
-
-	skb_put(skb, task->hdr_len);
-	tx_skb_setmode(skb, conn->hdrdgst_en, datalen ? conn->datadgst_en : 0);
-	if (!count)
-		return 0;
-
-	if (task->sc) {
-		struct scsi_data_buffer *sdb = scsi_out(task->sc);
-		struct scatterlist *sg = NULL;
-		int err;
-
-		tdata->offset = offset;
-		tdata->count = count;
-		err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents,
-					tdata->offset, &tdata->sgoffset, &sg);
-		if (err < 0) {
-			cxgb3i_log_warn("tpdu, sgl %u, bad offset %u/%u.\n",
-					sdb->table.nents, tdata->offset,
-					sdb->length);
-			return err;
-		}
-		err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
-					tdata->frags, MAX_PDU_FRAGS);
-		if (err < 0) {
-			cxgb3i_log_warn("tpdu, sgl %u, bad offset %u + %u.\n",
-					sdb->table.nents, tdata->offset,
-					tdata->count);
-			return err;
-		}
-		tdata->nr_frags = err;
-
-		if (tdata->nr_frags > MAX_SKB_FRAGS ||
-		    (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
-			char *dst = skb->data + task->hdr_len;
-			skb_frag_t *frag = tdata->frags;
-
-			/* data fits in the skb's headroom */
-			for (i = 0; i < tdata->nr_frags; i++, frag++) {
-				char *src = kmap_atomic(frag->page,
-							KM_SOFTIRQ0);
-
-				memcpy(dst, src+frag->page_offset, frag->size);
-				dst += frag->size;
-				kunmap_atomic(src, KM_SOFTIRQ0);
-			}
-			if (padlen) {
-				memset(dst, 0, padlen);
-				padlen = 0;
-			}
-			skb_put(skb, count + padlen);
-		} else {
-			/* data fit into frag_list */
-			for (i = 0; i < tdata->nr_frags; i++)
-				get_page(tdata->frags[i].page);
-
-			memcpy(skb_shinfo(skb)->frags, tdata->frags,
-				sizeof(skb_frag_t) * tdata->nr_frags);
-			skb_shinfo(skb)->nr_frags = tdata->nr_frags;
-			skb->len += count;
-			skb->data_len += count;
-			skb->truesize += count;
-		}
-
-	} else {
-		pg = virt_to_page(task->data);
-
-		get_page(pg);
-		skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
-					count);
-		skb->len += count;
-		skb->data_len += count;
-		skb->truesize += count;
-	}
-
-	if (padlen) {
-		i = skb_shinfo(skb)->nr_frags;
-		get_page(pad_page);
-		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, pad_page, 0,
-				 padlen);
-
-		skb->data_len += padlen;
-		skb->truesize += padlen;
-		skb->len += padlen;
-	}
-
-	return 0;
-}
-
-int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
-{
-	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
-	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
-	struct iscsi_tcp_task *tcp_task = task->dd_data;
-	struct cxgb3i_task_data *tdata = tcp_task->dd_data;
-	struct sk_buff *skb = tdata->skb;
-	unsigned int datalen;
-	int err;
-
-	if (!skb)
-		return 0;
-
-	datalen = skb->data_len;
-	tdata->skb = NULL;
-	err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb);
-	if (err > 0) {
-		int pdulen = err;
-
-		cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
-				task, skb, skb->len, skb->data_len, err);
-
-		if (task->conn->hdrdgst_en)
-			pdulen += ISCSI_DIGEST_SIZE;
-		if (datalen && task->conn->datadgst_en)
-			pdulen += ISCSI_DIGEST_SIZE;
-
-		task->conn->txdata_octets += pdulen;
-		return 0;
-	}
-
-	if (err == -EAGAIN || err == -ENOBUFS) {
-		/* reset skb to send when we are called again */
-		tdata->skb = skb;
-		return err;
-	}
-
-	kfree_skb(skb);
-	cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
-			task->itt, skb, skb->len, skb->data_len, err);
-	iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
-	iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
-	return err;
-}
-
-int cxgb3i_pdu_init(void)
-{
-	if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS))
-		skb_extra_headroom = SKB_TX_HEADROOM;
-	pad_page = alloc_page(GFP_KERNEL);
-	if (!pad_page)
-		return -ENOMEM;
-	memset(page_address(pad_page), 0, PAGE_SIZE);
-	return 0;
-}
-
-void cxgb3i_pdu_cleanup(void)
-{
-	if (pad_page) {
-		__free_page(pad_page);
-		pad_page = NULL;
-	}
-}
-
-void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn)
-{
-	struct sk_buff *skb;
-	unsigned int read = 0;
-	struct iscsi_conn *conn = c3cn->user_data;
-	int err = 0;
-
-	cxgb3i_rx_debug("cn 0x%p.\n", c3cn);
-
-	read_lock(&c3cn->callback_lock);
-	if (unlikely(!conn || conn->suspend_rx)) {
-		cxgb3i_rx_debug("conn 0x%p, id %d, suspend_rx %lu!\n",
-				conn, conn ? conn->id : 0xFF,
-				conn ? conn->suspend_rx : 0xFF);
-		read_unlock(&c3cn->callback_lock);
-		return;
-	}
-	skb = skb_peek(&c3cn->receive_queue);
-	while (!err && skb) {
-		__skb_unlink(skb, &c3cn->receive_queue);
-		read += skb_rx_pdulen(skb);
-		cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n",
-				conn, c3cn, skb, skb_rx_pdulen(skb));
-		err = cxgb3i_conn_read_pdu_skb(conn, skb);
-		__kfree_skb(skb);
-		skb = skb_peek(&c3cn->receive_queue);
-	}
-	read_unlock(&c3cn->callback_lock);
-	c3cn->copied_seq += read;
-	cxgb3i_c3cn_rx_credits(c3cn, read);
-	conn->rxdata_octets += read;
-
-	if (err) {
-		cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err);
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-	}
-}
-
-void cxgb3i_conn_tx_open(struct s3_conn *c3cn)
-{
-	struct iscsi_conn *conn = c3cn->user_data;
-
-	cxgb3i_tx_debug("cn 0x%p.\n", c3cn);
-	if (conn) {
-		cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id);
-		iscsi_conn_queue_work(conn);
-	}
-}
-
-void cxgb3i_conn_closing(struct s3_conn *c3cn)
-{
-	struct iscsi_conn *conn;
-
-	read_lock(&c3cn->callback_lock);
-	conn = c3cn->user_data;
-	if (conn && c3cn->state != C3CN_STATE_ESTABLISHED)
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-	read_unlock(&c3cn->callback_lock);
-}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.h b/drivers/scsi/cxgb3i/cxgb3i_pdu.h
deleted file mode 100644
index 0770b23..0000000
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * cxgb3i_ulp2.h: Chelsio S3xx iSCSI driver.
- *
- * Copyright (c) 2008 Chelsio Communications, 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.
- *
- * Written by: Karen Xie (kxie@chelsio.com)
- */
-
-#ifndef __CXGB3I_ULP2_PDU_H__
-#define __CXGB3I_ULP2_PDU_H__
-
-struct cpl_iscsi_hdr_norss {
-	union opcode_tid ot;
-	u16 pdu_len_ddp;
-	u16 len;
-	u32 seq;
-	u16 urg;
-	u8 rsvd;
-	u8 status;
-};
-
-struct cpl_rx_data_ddp_norss {
-	union opcode_tid ot;
-	u16 urg;
-	u16 len;
-	u32 seq;
-	u32 nxt_seq;
-	u32 ulp_crc;
-	u32 ddp_status;
-};
-
-#define RX_DDP_STATUS_IPP_SHIFT		27	/* invalid pagepod */
-#define RX_DDP_STATUS_TID_SHIFT		26	/* tid mismatch */
-#define RX_DDP_STATUS_COLOR_SHIFT	25	/* color mismatch */
-#define RX_DDP_STATUS_OFFSET_SHIFT	24	/* offset mismatch */
-#define RX_DDP_STATUS_ULIMIT_SHIFT	23	/* ulimit error */
-#define RX_DDP_STATUS_TAG_SHIFT		22	/* tag mismatch */
-#define RX_DDP_STATUS_DCRC_SHIFT	21	/* dcrc error */
-#define RX_DDP_STATUS_HCRC_SHIFT	20	/* hcrc error */
-#define RX_DDP_STATUS_PAD_SHIFT		19	/* pad error */
-#define RX_DDP_STATUS_PPP_SHIFT		18	/* pagepod parity error */
-#define RX_DDP_STATUS_LLIMIT_SHIFT	17	/* llimit error */
-#define RX_DDP_STATUS_DDP_SHIFT		16	/* ddp'able */
-#define RX_DDP_STATUS_PMM_SHIFT		15	/* pagepod mismatch */
-
-#define ULP2_FLAG_DATA_READY		0x1
-#define ULP2_FLAG_DATA_DDPED		0x2
-#define ULP2_FLAG_HCRC_ERROR		0x10
-#define ULP2_FLAG_DCRC_ERROR		0x20
-#define ULP2_FLAG_PAD_ERROR		0x40
-
-void cxgb3i_conn_closing(struct s3_conn *c3cn);
-void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn);
-void cxgb3i_conn_tx_open(struct s3_conn *c3cn);
-#endif
diff --git a/drivers/scsi/cxgbi/Kconfig b/drivers/scsi/cxgbi/Kconfig
new file mode 100644
index 0000000..17eb5d5
--- /dev/null
+++ b/drivers/scsi/cxgbi/Kconfig
@@ -0,0 +1,2 @@
+source "drivers/scsi/cxgbi/cxgb3i/Kconfig"
+source "drivers/scsi/cxgbi/cxgb4i/Kconfig"
diff --git a/drivers/scsi/cxgbi/Makefile b/drivers/scsi/cxgbi/Makefile
new file mode 100644
index 0000000..86007e3
--- /dev/null
+++ b/drivers/scsi/cxgbi/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_SCSI_CXGB3_ISCSI)	+= libcxgbi.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB4_ISCSI)	+= libcxgbi.o cxgb4i/
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kbuild b/drivers/scsi/cxgbi/cxgb3i/Kbuild
new file mode 100644
index 0000000..09dbf9e
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/Kbuild
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
+
+obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig
new file mode 100644
index 0000000..5cf4e98
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig
@@ -0,0 +1,7 @@
+config SCSI_CXGB3_ISCSI
+	tristate "Chelsio T3 iSCSI support"
+	depends on CHELSIO_T3_DEPENDS
+	select CHELSIO_T3
+	select SCSI_ISCSI_ATTRS
+	---help---
+	  This driver supports iSCSI offload for the Chelsio T3 devices.
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
new file mode 100644
index 0000000..a129a17
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -0,0 +1,1465 @@
+/*
+ * cxgb3i_offload.c: Chelsio S3xx iscsi offloaded tcp connection management
+ *
+ * Copyright (C) 2003-2008 Chelsio Communications.  All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
+ * release for licensing terms and conditions.
+ *
+ * Written by:	Dimitris Michailidis (dm@chelsio.com)
+ *		Karen Xie (kxie@chelsio.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <scsi/scsi_host.h>
+
+#include "common.h"
+#include "t3_cpl.h"
+#include "t3cdev.h"
+#include "cxgb3_defs.h"
+#include "cxgb3_ctl_defs.h"
+#include "cxgb3_offload.h"
+#include "firmware_exports.h"
+#include "cxgb3i.h"
+
+static unsigned int dbg_level;
+#include "../libcxgbi.h"
+
+#define DRV_MODULE_NAME         "cxgb3i"
+#define DRV_MODULE_DESC         "Chelsio T3 iSCSI Driver"
+#define DRV_MODULE_VERSION	"2.0.0"
+#define DRV_MODULE_RELDATE	"Jun. 2010"
+
+static char version[] =
+	DRV_MODULE_DESC " " DRV_MODULE_NAME
+	" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Chelsio Communications, Inc.");
+MODULE_DESCRIPTION(DRV_MODULE_DESC);
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(dbg_level, uint, 0644);
+MODULE_PARM_DESC(dbg_level, "debug flag (default=0)");
+
+static int cxgb3i_rcv_win = 256 * 1024;
+module_param(cxgb3i_rcv_win, int, 0644);
+MODULE_PARM_DESC(cxgb3i_rcv_win, "TCP receive window in bytes (default=256KB)");
+
+static int cxgb3i_snd_win = 128 * 1024;
+module_param(cxgb3i_snd_win, int, 0644);
+MODULE_PARM_DESC(cxgb3i_snd_win, "TCP send window in bytes (default=128KB)");
+
+static int cxgb3i_rx_credit_thres = 10 * 1024;
+module_param(cxgb3i_rx_credit_thres, int, 0644);
+MODULE_PARM_DESC(rx_credit_thres,
+		 "RX credits return threshold in bytes (default=10KB)");
+
+static unsigned int cxgb3i_max_connect = 8 * 1024;
+module_param(cxgb3i_max_connect, uint, 0644);
+MODULE_PARM_DESC(cxgb3i_max_connect, "Max. # of connections (default=8092)");
+
+static unsigned int cxgb3i_sport_base = 20000;
+module_param(cxgb3i_sport_base, uint, 0644);
+MODULE_PARM_DESC(cxgb3i_sport_base, "starting port number (default=20000)");
+
+static void cxgb3i_dev_open(struct t3cdev *);
+static void cxgb3i_dev_close(struct t3cdev *);
+static void cxgb3i_dev_event_handler(struct t3cdev *, u32, u32);
+
+static struct cxgb3_client t3_client = {
+	.name = DRV_MODULE_NAME,
+	.handlers = cxgb3i_cpl_handlers,
+	.add = cxgb3i_dev_open,
+	.remove = cxgb3i_dev_close,
+	.event_handler = cxgb3i_dev_event_handler,
+};
+
+static struct scsi_host_template cxgb3i_host_template = {
+	.module		= THIS_MODULE,
+	.name		= DRV_MODULE_NAME,
+	.proc_name	= DRV_MODULE_NAME,
+	.can_queue	= CXGB3I_SCSI_HOST_QDEPTH,
+	.queuecommand	= iscsi_queuecommand,
+	.change_queue_depth = iscsi_change_queue_depth,
+	.sg_tablesize	= SG_ALL,
+	.max_sectors	= 0xFFFF,
+	.cmd_per_lun	= ISCSI_DEF_CMD_PER_LUN,
+	.eh_abort_handler = iscsi_eh_abort,
+	.eh_device_reset_handler = iscsi_eh_device_reset,
+	.eh_target_reset_handler = iscsi_eh_recover_target,
+	.target_alloc	= iscsi_target_alloc,
+	.use_clustering	= DISABLE_CLUSTERING,
+	.this_id	= -1,
+};
+
+static struct iscsi_transport cxgb3i_iscsi_transport = {
+	.owner		= THIS_MODULE,
+	.name		= DRV_MODULE_NAME,
+	/* owner and name should be set already */
+	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
+				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+				CAP_PADDING_OFFLOAD,
+	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
+				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+				ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+				ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+				ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+				ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+				ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
+				ISCSI_PERSISTENT_ADDRESS |
+				ISCSI_TARGET_NAME | ISCSI_TPGT |
+				ISCSI_USERNAME | ISCSI_PASSWORD |
+				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+				ISCSI_PING_TMO | ISCSI_RECV_TMO |
+				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+				ISCSI_HOST_INITIATOR_NAME |
+				ISCSI_HOST_NETDEV_NAME,
+	.get_host_param	= cxgbi_get_host_param,
+	.set_host_param	= cxgbi_set_host_param,
+	/* session management */
+	.create_session	= cxgbi_create_session,
+	.destroy_session	= cxgbi_destroy_session,
+	.get_session_param = iscsi_session_get_param,
+	/* connection management */
+	.create_conn	= cxgbi_create_conn,
+	.bind_conn	= cxgbi_bind_conn,
+	.destroy_conn	= iscsi_tcp_conn_teardown,
+	.start_conn	= iscsi_conn_start,
+	.stop_conn	= iscsi_conn_stop,
+	.get_conn_param	= cxgbi_get_conn_param,
+	.set_param	= cxgbi_set_conn_param,
+	.get_stats	= cxgbi_get_conn_stats,
+	/* pdu xmit req from user space */
+	.send_pdu	= iscsi_conn_send_pdu,
+	/* task */
+	.init_task	= iscsi_tcp_task_init,
+	.xmit_task	= iscsi_tcp_task_xmit,
+	.cleanup_task	= cxgbi_cleanup_task,
+	/* pdu */
+	.alloc_pdu	= cxgbi_conn_alloc_pdu,
+	.init_pdu	= cxgbi_conn_init_pdu,
+	.xmit_pdu	= cxgbi_conn_xmit_pdu,
+	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
+	/* TCP connect/disconnect */
+	.ep_connect	= cxgbi_ep_connect,
+	.ep_poll	= cxgbi_ep_poll,
+	.ep_disconnect	= cxgbi_ep_disconnect,
+	/* Error recovery timeout call */
+	.session_recovery_timedout = iscsi_session_recovery_timedout,
+};
+
+static struct scsi_transport_template *cxgb3i_stt;
+
+/*
+ * CPL (Chelsio Protocol Language) defines a message passing interface between
+ * the host driver and Chelsio asic.
+ * The section below implments CPLs that related to iscsi tcp connection
+ * open/close/abort and data send/receive.
+ */
+
+static int push_tx_frames(struct cxgbi_sock *csk, int req_completion);
+
+static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
+			      const struct l2t_entry *e)
+{
+	unsigned int wscale = cxgbi_sock_compute_wscale(cxgb3i_rcv_win);
+	struct cpl_act_open_req *req = (struct cpl_act_open_req *)skb->head;
+
+	skb->priority = CPL_PRIORITY_SETUP;
+
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, csk->atid));
+	req->local_port = csk->saddr.sin_port;
+	req->peer_port = csk->daddr.sin_port;
+	req->local_ip = csk->saddr.sin_addr.s_addr;
+	req->peer_ip = csk->daddr.sin_addr.s_addr;
+
+	req->opt0h = htonl(V_KEEP_ALIVE(1) | F_TCAM_BYPASS |
+			V_WND_SCALE(wscale) | V_MSS_IDX(csk->mss_idx) |
+			V_L2T_IDX(e->idx) | V_TX_CHANNEL(e->smt_idx));
+	req->opt0l = htonl(V_ULP_MODE(ULP2_MODE_ISCSI) |
+			V_RCV_BUFSIZ(cxgb3i_rcv_win>>10));
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, %pI4:%u-%pI4:%u, %u,%u,%u.\n",
+		csk, csk->state, csk->flags, csk->atid,
+		&req->local_ip, ntohs(req->local_port),
+		&req->peer_ip, ntohs(req->peer_port),
+		csk->mss_idx, e->idx, e->smt_idx);
+
+	l2t_send(csk->cdev->lldev, skb, csk->l2t);
+}
+
+static inline void act_open_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
+{
+	cxgbi_sock_act_open_req_arp_failure(NULL, skb);
+}
+
+/*
+ * CPL connection close request: host ->
+ *
+ * Close a connection by sending a CPL_CLOSE_CON_REQ message and queue it to
+ * the write queue (i.e., after any unsent txt data).
+ */
+static void send_close_req(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->cpl_close;
+	struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
+	unsigned int tid = csk->tid;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	csk->cpl_close = NULL;
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_CLOSE_CON));
+	req->wr.wr_lo = htonl(V_WR_TID(tid));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
+	req->rsvd = htonl(csk->write_seq);
+
+	cxgbi_sock_skb_entail(csk, skb);
+	if (csk->state >= CTP_ESTABLISHED)
+		push_tx_frames(csk, 1);
+}
+
+/*
+ * CPL connection abort request: host ->
+ *
+ * Send an ABORT_REQ message. Makes sure we do not send multiple ABORT_REQs
+ * for the same connection and also that we do not try to send a message
+ * after the connection has closed.
+ */
+static void abort_arp_failure(struct t3cdev *tdev, struct sk_buff *skb)
+{
+	struct cpl_abort_req *req = cplhdr(skb);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"t3dev 0x%p, tid %u, skb 0x%p.\n",
+		tdev, GET_TID(req), skb);
+	req->cmd = CPL_ABORT_NO_RST;
+	cxgb3_ofld_send(tdev, skb);
+}
+
+static void send_abort_req(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->cpl_abort_req;
+	struct cpl_abort_req *req;
+
+	if (unlikely(csk->state == CTP_ABORTING || !skb))
+		return;
+	cxgbi_sock_set_state(csk, CTP_ABORTING);
+	cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_PENDING);
+	/* Purge the send queue so we don't send anything after an abort. */
+	cxgbi_sock_purge_write_queue(csk);
+
+	csk->cpl_abort_req = NULL;
+	req = (struct cpl_abort_req *)skb->head;
+	skb->priority = CPL_PRIORITY_DATA;
+	set_arp_failure_handler(skb, abort_arp_failure);
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ));
+	req->wr.wr_lo = htonl(V_WR_TID(csk->tid));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ABORT_REQ, csk->tid));
+	req->rsvd0 = htonl(csk->snd_nxt);
+	req->rsvd1 = !cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT);
+	req->cmd = CPL_ABORT_SEND_RST;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, snd_nxt %u, 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, csk->snd_nxt,
+		req->rsvd1);
+
+	l2t_send(csk->cdev->lldev, skb, csk->l2t);
+}
+
+/*
+ * CPL connection abort reply: host ->
+ *
+ * Send an ABORT_RPL message in response of the ABORT_REQ received.
+ */
+static void send_abort_rpl(struct cxgbi_sock *csk, int rst_status)
+{
+	struct sk_buff *skb = csk->cpl_abort_rpl;
+	struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, status %d.\n",
+		csk, csk->state, csk->flags, csk->tid, rst_status);
+
+	csk->cpl_abort_rpl = NULL;
+	skb->priority = CPL_PRIORITY_DATA;
+	rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
+	rpl->wr.wr_lo = htonl(V_WR_TID(csk->tid));
+	OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, csk->tid));
+	rpl->cmd = rst_status;
+	cxgb3_ofld_send(csk->cdev->lldev, skb);
+}
+
+/*
+ * CPL connection rx data ack: host ->
+ * Send RX credits through an RX_DATA_ACK CPL message. Returns the number of
+ * credits sent.
+ */
+static u32 send_rx_credits(struct cxgbi_sock *csk, u32 credits)
+{
+	struct sk_buff *skb;
+	struct cpl_rx_data_ack *req;
+	u32 dack = F_RX_DACK_CHANGE | V_RX_DACK_MODE(1);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx,%u, credit %u, dack %u.\n",
+		csk, csk->state, csk->flags, csk->tid, credits, dack);
+
+	skb = alloc_wr(sizeof(*req), 0, GFP_ATOMIC);
+	if (!skb) {
+		pr_info("csk 0x%p, credit %u, OOM.\n", csk, credits);
+		return 0;
+	}
+	req = (struct cpl_rx_data_ack *)skb->head;
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_RX_DATA_ACK, csk->tid));
+	req->credit_dack = htonl(F_RX_DACK_CHANGE | V_RX_DACK_MODE(1) |
+				V_RX_CREDITS(credits));
+	skb->priority = CPL_PRIORITY_ACK;
+	cxgb3_ofld_send(csk->cdev->lldev, skb);
+	return credits;
+}
+
+/*
+ * CPL connection tx data: host ->
+ *
+ * Send iscsi PDU via TX_DATA CPL message. Returns the number of
+ * credits sent.
+ * Each TX_DATA consumes work request credit (wrs), so we need to keep track of
+ * how many we've used so far and how many are pending (i.e., yet ack'ed by T3).
+ */
+
+static unsigned int wrlen __read_mostly;
+static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly;
+
+static void init_wr_tab(unsigned int wr_len)
+{
+	int i;
+
+	if (skb_wrs[1])		/* already initialized */
+		return;
+	for (i = 1; i < SKB_WR_LIST_SIZE; i++) {
+		int sgl_len = (3 * i) / 2 + (i & 1);
+
+		sgl_len += 3;
+		skb_wrs[i] = (sgl_len <= wr_len
+			      ? 1 : 1 + (sgl_len - 2) / (wr_len - 1));
+	}
+	wrlen = wr_len * 8;
+}
+
+static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb,
+				   int len, int req_completion)
+{
+	struct tx_data_wr *req;
+	struct l2t_entry *l2t = csk->l2t;
+
+	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_completion ? F_WR_COMPL : 0));
+	req->wr_lo = htonl(V_WR_TID(csk->tid));
+	/* len includes the length of any HW ULP additions */
+	req->len = htonl(len);
+	/* V_TX_ULP_SUBMODE sets both the mode and submode */
+	req->flags = htonl(V_TX_ULP_SUBMODE(cxgbi_skcb_ulp_mode(skb)) |
+			   V_TX_SHOVE((skb_peek(&csk->write_queue) ? 0 : 1)));
+	req->sndseq = htonl(csk->snd_nxt);
+	req->param = htonl(V_TX_PORT(l2t->smt_idx));
+
+	if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) {
+		req->flags |= htonl(V_TX_ACK_PAGES(2) | F_TX_INIT |
+				    V_TX_CPU_IDX(csk->rss_qid));
+		/* sendbuffer is in units of 32KB. */
+		req->param |= htonl(V_TX_SNDBUF(cxgb3i_snd_win >> 15));
+		cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT);
+	}
+}
+
+/**
+ * push_tx_frames -- start transmit
+ * @c3cn: the offloaded connection
+ * @req_completion: request wr_ack or not
+ *
+ * Prepends TX_DATA_WR or CPL_CLOSE_CON_REQ headers to buffers waiting in a
+ * connection's send queue and sends them on to T3.  Must be called with the
+ * connection's lock held.  Returns the amount of send buffer space that was
+ * freed as a result of sending queued data to T3.
+ */
+
+static void arp_failure_skb_discard(struct t3cdev *dev, struct sk_buff *skb)
+{
+	kfree_skb(skb);
+}
+
+static int push_tx_frames(struct cxgbi_sock *csk, int req_completion)
+{
+	int total_size = 0;
+	struct sk_buff *skb;
+
+	if (unlikely(csk->state < CTP_ESTABLISHED ||
+		csk->state == CTP_CLOSE_WAIT_1 || csk->state >= CTP_ABORTING)) {
+			log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+				"csk 0x%p,%u,0x%lx,%u, in closing state.\n",
+				csk, csk->state, csk->flags, csk->tid);
+		return 0;
+	}
+
+	while (csk->wr_cred && (skb = skb_peek(&csk->write_queue)) != NULL) {
+		int len = skb->len;	/* length before skb_push */
+		int frags = skb_shinfo(skb)->nr_frags + (len != skb->data_len);
+		int wrs_needed = skb_wrs[frags];
+
+		if (wrs_needed > 1 && len + sizeof(struct tx_data_wr) <= wrlen)
+			wrs_needed = 1;
+
+		WARN_ON(frags >= SKB_WR_LIST_SIZE || wrs_needed < 1);
+
+		if (csk->wr_cred < wrs_needed) {
+			log_debug(1 << CXGBI_DBG_PDU_TX,
+				"csk 0x%p, skb len %u/%u, frag %u, wr %d<%u.\n",
+				csk, skb->len, skb->data_len, frags,
+				wrs_needed, csk->wr_cred);
+			break;
+		}
+
+		__skb_unlink(skb, &csk->write_queue);
+		skb->priority = CPL_PRIORITY_DATA;
+		skb->csum = wrs_needed;	/* remember this until the WR_ACK */
+		csk->wr_cred -= wrs_needed;
+		csk->wr_una_cred += wrs_needed;
+		cxgbi_sock_enqueue_wr(csk, skb);
+
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p, enqueue, skb len %u/%u, frag %u, wr %d, "
+			"left %u, unack %u.\n",
+			csk, skb->len, skb->data_len, frags, skb->csum,
+			csk->wr_cred, csk->wr_una_cred);
+
+		if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) {
+			if ((req_completion &&
+				csk->wr_una_cred == wrs_needed) ||
+			     csk->wr_una_cred >= csk->wr_max_cred / 2) {
+				req_completion = 1;
+				csk->wr_una_cred = 0;
+			}
+			len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+			make_tx_data_wr(csk, skb, len, req_completion);
+			csk->snd_nxt += len;
+			cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR);
+		}
+		total_size += skb->truesize;
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p, tid 0x%x, send skb 0x%p.\n",
+			csk, csk->tid, skb);
+		set_arp_failure_handler(skb, arp_failure_skb_discard);
+		l2t_send(csk->cdev->lldev, skb, csk->l2t);
+	}
+	return total_size;
+}
+
+/*
+ * Process a CPL_ACT_ESTABLISH message: -> host
+ * Updates connection state from an active establish CPL message.  Runs with
+ * the connection lock held.
+ */
+
+static inline void free_atid(struct cxgbi_sock *csk)
+{
+	if (cxgbi_sock_flag(csk, CTPF_HAS_ATID)) {
+		cxgb3_free_atid(csk->cdev->lldev, csk->atid);
+		cxgbi_sock_clear_flag(csk, CTPF_HAS_ATID);
+		cxgbi_sock_put(csk);
+	}
+}
+
+static int do_act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_act_establish *req = cplhdr(skb);
+	unsigned int tid = GET_TID(req);
+	unsigned int atid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
+	u32 rcv_isn = ntohl(req->rcv_isn);	/* real RCV_ISN + 1 */
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"atid 0x%x,tid 0x%x, csk 0x%p,%u,0x%lx, isn %u.\n",
+		atid, atid, csk, csk->state, csk->flags, rcv_isn);
+
+	cxgbi_sock_get(csk);
+	cxgbi_sock_set_flag(csk, CTPF_HAS_TID);
+	csk->tid = tid;
+	cxgb3_insert_tid(csk->cdev->lldev, &t3_client, csk, tid);
+
+	free_atid(csk);
+
+	csk->rss_qid = G_QNUM(ntohs(skb->csum));
+
+	spin_lock_bh(&csk->lock);
+	if (csk->retry_timer.function) {
+		del_timer(&csk->retry_timer);
+		csk->retry_timer.function = NULL;
+	}
+
+	if (unlikely(csk->state != CTP_ACTIVE_OPEN))
+		pr_info("csk 0x%p,%u,0x%lx,%u, got EST.\n",
+			csk, csk->state, csk->flags, csk->tid);
+
+	csk->copied_seq = csk->rcv_wup = csk->rcv_nxt = rcv_isn;
+	if (cxgb3i_rcv_win > (M_RCV_BUFSIZ << 10))
+		csk->rcv_wup -= cxgb3i_rcv_win - (M_RCV_BUFSIZ << 10);
+
+	cxgbi_sock_established(csk, ntohl(req->snd_isn), ntohs(req->tcp_opt));
+
+	if (unlikely(cxgbi_sock_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED)))
+		/* upper layer has requested closing */
+		send_abort_req(csk);
+	else {
+		if (skb_queue_len(&csk->write_queue))
+			push_tx_frames(csk, 1);
+		cxgbi_conn_tx_open(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process a CPL_ACT_OPEN_RPL message: -> host
+ * Handle active open failures.
+ */
+static int act_open_rpl_status_to_errno(int status)
+{
+	switch (status) {
+	case CPL_ERR_CONN_RESET:
+		return -ECONNREFUSED;
+	case CPL_ERR_ARP_MISS:
+		return -EHOSTUNREACH;
+	case CPL_ERR_CONN_TIMEDOUT:
+		return -ETIMEDOUT;
+	case CPL_ERR_TCAM_FULL:
+		return -ENOMEM;
+	case CPL_ERR_CONN_EXIST:
+		return -EADDRINUSE;
+	default:
+		return -EIO;
+	}
+}
+
+static void act_open_retry_timer(unsigned long data)
+{
+	struct sk_buff *skb;
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_ATOMIC);
+	if (!skb)
+		cxgbi_sock_fail_act_open(csk, -ENOMEM);
+	else {
+		skb->sk = (struct sock *)csk;
+		set_arp_failure_handler(skb, act_open_arp_failure);
+		send_act_open_req(csk, skb, csk->l2t);
+	}
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+
+static int do_act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_act_open_rpl *rpl = cplhdr(skb);
+
+	pr_info("csk 0x%p,%u,0x%lx,%u, status %u, %pI4:%u-%pI4:%u.\n",
+		csk, csk->state, csk->flags, csk->atid, rpl->status,
+		&csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
+		&csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port));
+
+	if (rpl->status != CPL_ERR_TCAM_FULL &&
+	    rpl->status != CPL_ERR_CONN_EXIST &&
+	    rpl->status != CPL_ERR_ARP_MISS)
+		cxgb3_queue_tid_release(tdev, GET_TID(rpl));
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	if (rpl->status == CPL_ERR_CONN_EXIST &&
+	    csk->retry_timer.function != act_open_retry_timer) {
+		csk->retry_timer.function = act_open_retry_timer;
+		mod_timer(&csk->retry_timer, jiffies + HZ / 2);
+	} else
+		cxgbi_sock_fail_act_open(csk,
+				act_open_rpl_status_to_errno(rpl->status));
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process PEER_CLOSE CPL messages: -> host
+ * Handle peer FIN.
+ */
+static int do_peer_close(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	cxgbi_sock_rcv_peer_close(csk);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process CLOSE_CONN_RPL CPL message: -> host
+ * Process a peer ACK to our FIN.
+ */
+static int do_close_con_rpl(struct t3cdev *cdev, struct sk_buff *skb,
+			    void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_close_con_rpl *rpl = cplhdr(skb);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, snxt %u.\n",
+		csk, csk->state, csk->flags, csk->tid, ntohl(rpl->snd_nxt));
+
+	cxgbi_sock_rcv_close_conn_rpl(csk, ntohl(rpl->snd_nxt));
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process ABORT_REQ_RSS CPL message: -> host
+ * Process abort requests.  If we are waiting for an ABORT_RPL we ignore this
+ * request except that we need to reply to it.
+ */
+
+static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason,
+				 int *need_rst)
+{
+	switch (abort_reason) {
+	case CPL_ERR_BAD_SYN: /* fall through */
+	case CPL_ERR_CONN_RESET:
+		return csk->state > CTP_ESTABLISHED ? -EPIPE : -ECONNRESET;
+	case CPL_ERR_XMIT_TIMEDOUT:
+	case CPL_ERR_PERSIST_TIMEDOUT:
+	case CPL_ERR_FINWAIT2_TIMEDOUT:
+	case CPL_ERR_KEEPALIVE_TIMEDOUT:
+		return -ETIMEDOUT;
+	default:
+		return -EIO;
+	}
+}
+
+static int do_abort_req(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+	const struct cpl_abort_req_rss *req = cplhdr(skb);
+	struct cxgbi_sock *csk = ctx;
+	int rst_status = CPL_ABORT_NO_RST;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
+	    req->status == CPL_ERR_PERSIST_NEG_ADVICE) {
+		goto done;
+	}
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (!cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD)) {
+		cxgbi_sock_set_flag(csk, CTPF_ABORT_REQ_RCVD);
+		cxgbi_sock_set_state(csk, CTP_ABORTING);
+		goto out;
+	}
+
+	cxgbi_sock_clear_flag(csk, CTPF_ABORT_REQ_RCVD);
+	send_abort_rpl(csk, rst_status);
+
+	if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
+		csk->err = abort_status_to_errno(csk, req->status, &rst_status);
+		cxgbi_sock_closed(csk);
+	}
+
+out:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+done:
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process ABORT_RPL_RSS CPL message: -> host
+ * Process abort replies.  We only process these messages if we anticipate
+ * them as the coordination between SW and HW in this area is somewhat lacking
+ * and sometimes we get ABORT_RPLs after we are done with the connection that
+ * originated the ABORT_REQ.
+ */
+static int do_abort_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+	struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
+	struct cxgbi_sock *csk = ctx;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"status 0x%x, csk 0x%p, s %u, 0x%lx.\n",
+		rpl->status, csk, csk ? csk->state : 0,
+		csk ? csk->flags : 0UL);
+	/*
+	 * Ignore replies to post-close aborts indicating that the abort was
+	 * requested too late.  These connections are terminated when we get
+	 * PEER_CLOSE or CLOSE_CON_RPL and by the time the abort_rpl_rss
+	 * arrives the TID is either no longer used or it has been recycled.
+	 */
+	if (rpl->status == CPL_ERR_ABORT_FAILED)
+		goto rel_skb;
+	/*
+	 * Sometimes we've already closed the connection, e.g., a post-close
+	 * abort races with ABORT_REQ_RSS, the latter frees the connection
+	 * expecting the ABORT_REQ will fail with CPL_ERR_ABORT_FAILED,
+	 * but FW turns the ABORT_REQ into a regular one and so we get
+	 * ABORT_RPL_RSS with status 0 and no connection.
+	 */
+	if (csk)
+		cxgbi_sock_rcv_abort_rpl(csk);
+rel_skb:
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process RX_ISCSI_HDR CPL message: -> host
+ * Handle received PDUs, the payload could be DDP'ed. If not, the payload
+ * follow after the bhs.
+ */
+static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_iscsi_hdr *hdr_cpl = cplhdr(skb);
+	struct cpl_iscsi_hdr_norss data_cpl;
+	struct cpl_rx_data_ddp_norss ddp_cpl;
+	unsigned int hdr_len, data_len, status;
+	unsigned int len;
+	int err;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx,%u, skb 0x%p,%u.\n",
+		csk, csk->state, csk->flags, csk->tid, skb, skb->len);
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CTP_PASSIVE_CLOSE)) {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		if (csk->state != CTP_ABORTING)
+			goto abort_conn;
+		else
+			goto discard;
+	}
+
+	cxgbi_skcb_tcp_seq(skb) = ntohl(hdr_cpl->seq);
+	cxgbi_skcb_flags(skb) = 0;
+
+	skb_reset_transport_header(skb);
+	__skb_pull(skb, sizeof(struct cpl_iscsi_hdr));
+
+	len = hdr_len = ntohs(hdr_cpl->len);
+	/* msg coalesce is off or not enough data received */
+	if (skb->len <= hdr_len) {
+		pr_err("%s: tid %u, CPL_ISCSI_HDR, skb len %u < %u.\n",
+			csk->cdev->ports[csk->port_id]->name, csk->tid,
+			skb->len, hdr_len);
+		goto abort_conn;
+	}
+	cxgbi_skcb_set_flag(skb, SKCBF_RX_COALESCED);
+
+	err = skb_copy_bits(skb, skb->len - sizeof(ddp_cpl), &ddp_cpl,
+			    sizeof(ddp_cpl));
+	if (err < 0) {
+		pr_err("%s: tid %u, copy cpl_ddp %u-%zu failed %d.\n",
+			csk->cdev->ports[csk->port_id]->name, csk->tid,
+			skb->len, sizeof(ddp_cpl), err);
+		goto abort_conn;
+	}
+
+	cxgbi_skcb_set_flag(skb, SKCBF_RX_STATUS);
+	cxgbi_skcb_rx_pdulen(skb) = ntohs(ddp_cpl.len);
+	cxgbi_skcb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
+	status = ntohl(ddp_cpl.ddp_status);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p, skb 0x%p,%u, pdulen %u, status 0x%x.\n",
+		csk, skb, skb->len, cxgbi_skcb_rx_pdulen(skb), status);
+
+	if (status & (1 << CPL_RX_DDP_STATUS_HCRC_SHIFT))
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_HCRC_ERR);
+	if (status & (1 << CPL_RX_DDP_STATUS_DCRC_SHIFT))
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_DCRC_ERR);
+	if (status & (1 << CPL_RX_DDP_STATUS_PAD_SHIFT))
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_PAD_ERR);
+
+	if (skb->len > (hdr_len + sizeof(ddp_cpl))) {
+		err = skb_copy_bits(skb, hdr_len, &data_cpl, sizeof(data_cpl));
+		if (err < 0) {
+			pr_err("%s: tid %u, cp %zu/%u failed %d.\n",
+				csk->cdev->ports[csk->port_id]->name,
+				csk->tid, sizeof(data_cpl), skb->len, err);
+			goto abort_conn;
+		}
+		data_len = ntohs(data_cpl.len);
+		log_debug(1 << CXGBI_DBG_DDP | 1 << CXGBI_DBG_PDU_RX,
+			"skb 0x%p, pdu not ddp'ed %u/%u, status 0x%x.\n",
+			skb, data_len, cxgbi_skcb_rx_pdulen(skb), status);
+		len += sizeof(data_cpl) + data_len;
+	} else if (status & (1 << CPL_RX_DDP_STATUS_DDP_SHIFT))
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_DATA_DDPD);
+
+	csk->rcv_nxt = ntohl(ddp_cpl.seq) + cxgbi_skcb_rx_pdulen(skb);
+	__pskb_trim(skb, len);
+	__skb_queue_tail(&csk->receive_queue, skb);
+	cxgbi_conn_pdu_ready(csk);
+
+	spin_unlock_bh(&csk->lock);
+	return 0;
+
+abort_conn:
+	send_abort_req(csk);
+discard:
+	spin_unlock_bh(&csk->lock);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * Process TX_DATA_ACK CPL messages: -> host
+ * Process an acknowledgment of WR completion.  Advance snd_una and send the
+ * next batch of work requests from the write queue.
+ */
+static int do_wr_ack(struct t3cdev *cdev, struct sk_buff *skb, void *ctx)
+{
+	struct cxgbi_sock *csk = ctx;
+	struct cpl_wr_ack *hdr = cplhdr(skb);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx,%u, cr %u.\n",
+		csk, csk->state, csk->flags, csk->tid, ntohs(hdr->credits));
+
+	cxgbi_sock_rcv_wr_ack(csk, ntohs(hdr->credits), ntohl(hdr->snd_una), 1);
+	__kfree_skb(skb);
+	return 0;
+}
+
+/*
+ * for each connection, pre-allocate skbs needed for close/abort requests. So
+ * that we can service the request right away.
+ */
+static int alloc_cpls(struct cxgbi_sock *csk)
+{
+	csk->cpl_close = alloc_wr(sizeof(struct cpl_close_con_req), 0,
+					GFP_KERNEL);
+	if (!csk->cpl_close)
+		return -ENOMEM;
+	csk->cpl_abort_req = alloc_wr(sizeof(struct cpl_abort_req), 0,
+					GFP_KERNEL);
+	if (!csk->cpl_abort_req)
+		goto free_cpl_skbs;
+
+	csk->cpl_abort_rpl = alloc_wr(sizeof(struct cpl_abort_rpl), 0,
+					GFP_KERNEL);
+	if (!csk->cpl_abort_rpl)
+		goto free_cpl_skbs;
+
+	return 0;
+
+free_cpl_skbs:
+	cxgbi_sock_free_cpl_skbs(csk);
+	return -ENOMEM;
+}
+
+/**
+ * release_offload_resources - release offload resource
+ * @c3cn: the offloaded iscsi tcp connection.
+ * Release resources held by an offload connection (TID, L2T entry, etc.)
+ */
+static void l2t_put(struct cxgbi_sock *csk)
+{
+	struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev;
+
+	if (csk->l2t) {
+		l2t_release(L2DATA(t3dev), csk->l2t);
+		csk->l2t = NULL;
+		cxgbi_sock_put(csk);
+	}
+}
+
+static void release_offload_resources(struct cxgbi_sock *csk)
+{
+	struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	csk->rss_qid = 0;
+	cxgbi_sock_free_cpl_skbs(csk);
+
+	if (csk->wr_cred != csk->wr_max_cred) {
+		cxgbi_sock_purge_wr_queue(csk);
+		cxgbi_sock_reset_wr_list(csk);
+	}
+	l2t_put(csk);
+	if (cxgbi_sock_flag(csk, CTPF_HAS_ATID))
+		free_atid(csk);
+	else if (cxgbi_sock_flag(csk, CTPF_HAS_TID)) {
+		cxgb3_remove_tid(t3dev, (void *)csk, csk->tid);
+		cxgbi_sock_clear_flag(csk, CTPF_HAS_TID);
+		cxgbi_sock_put(csk);
+	}
+	csk->dst = NULL;
+	csk->cdev = NULL;
+}
+
+static void update_address(struct cxgbi_hba *chba)
+{
+	if (chba->ipv4addr) {
+		if (chba->vdev &&
+		    chba->ipv4addr != cxgb3i_get_private_ipv4addr(chba->vdev)) {
+			cxgb3i_set_private_ipv4addr(chba->vdev, chba->ipv4addr);
+			cxgb3i_set_private_ipv4addr(chba->ndev, 0);
+			pr_info("%s set %pI4.\n",
+				chba->vdev->name, &chba->ipv4addr);
+		} else if (chba->ipv4addr !=
+				cxgb3i_get_private_ipv4addr(chba->ndev)) {
+			cxgb3i_set_private_ipv4addr(chba->ndev, chba->ipv4addr);
+			pr_info("%s set %pI4.\n",
+				chba->ndev->name, &chba->ipv4addr);
+		}
+	} else if (cxgb3i_get_private_ipv4addr(chba->ndev)) {
+		if (chba->vdev)
+			cxgb3i_set_private_ipv4addr(chba->vdev, 0);
+		cxgb3i_set_private_ipv4addr(chba->ndev, 0);
+	}
+}
+
+static int init_act_open(struct cxgbi_sock *csk)
+{
+	struct dst_entry *dst = csk->dst;
+	struct cxgbi_device *cdev = csk->cdev;
+	struct t3cdev *t3dev = (struct t3cdev *)cdev->lldev;
+	struct net_device *ndev = cdev->ports[csk->port_id];
+	struct cxgbi_hba *chba = cdev->hbas[csk->port_id];
+	struct sk_buff *skb = NULL;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx.\n", csk, csk->state, csk->flags);
+
+	update_address(chba);
+	if (chba->ipv4addr)
+		csk->saddr.sin_addr.s_addr = chba->ipv4addr;
+
+	csk->rss_qid = 0;
+	csk->l2t = t3_l2t_get(t3dev, dst->neighbour, ndev);
+	if (!csk->l2t) {
+		pr_err("NO l2t available.\n");
+		return -EINVAL;
+	}
+	cxgbi_sock_get(csk);
+
+	csk->atid = cxgb3_alloc_atid(t3dev, &t3_client, csk);
+	if (csk->atid < 0) {
+		pr_err("NO atid available.\n");
+		goto rel_resource;
+	}
+	cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
+	cxgbi_sock_get(csk);
+
+	skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_KERNEL);
+	if (!skb)
+		goto rel_resource;
+	skb->sk = (struct sock *)csk;
+	set_arp_failure_handler(skb, act_open_arp_failure);
+
+	csk->wr_max_cred = csk->wr_cred = T3C_DATA(t3dev)->max_wrs - 1;
+	csk->wr_una_cred = 0;
+	csk->mss_idx = cxgbi_sock_select_mss(csk, dst_mtu(dst));
+	cxgbi_sock_reset_wr_list(csk);
+	csk->err = 0;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, %pI4:%u-%pI4:%u.\n",
+		csk, csk->state, csk->flags,
+		&csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
+		&csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port));
+
+	cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
+	send_act_open_req(csk, skb, csk->l2t);
+	return 0;
+
+rel_resource:
+	if (skb)
+		__kfree_skb(skb);
+	return -EINVAL;
+}
+
+cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS] = {
+	[CPL_ACT_ESTABLISH] = do_act_establish,
+	[CPL_ACT_OPEN_RPL] = do_act_open_rpl,
+	[CPL_PEER_CLOSE] = do_peer_close,
+	[CPL_ABORT_REQ_RSS] = do_abort_req,
+	[CPL_ABORT_RPL_RSS] = do_abort_rpl,
+	[CPL_CLOSE_CON_RPL] = do_close_con_rpl,
+	[CPL_TX_DMA_ACK] = do_wr_ack,
+	[CPL_ISCSI_HDR] = do_iscsi_hdr,
+};
+
+/**
+ * cxgb3i_ofld_init - allocate and initialize resources for each adapter found
+ * @cdev:	cxgbi adapter
+ */
+int cxgb3i_ofld_init(struct cxgbi_device *cdev)
+{
+	struct t3cdev *t3dev = (struct t3cdev *)cdev->lldev;
+	struct adap_ports port;
+	struct ofld_page_info rx_page_info;
+	unsigned int wr_len;
+	int rc;
+
+	if (t3dev->ctl(t3dev, GET_WR_LEN, &wr_len) < 0 ||
+	    t3dev->ctl(t3dev, GET_PORTS, &port) < 0 ||
+	    t3dev->ctl(t3dev, GET_RX_PAGE_INFO, &rx_page_info) < 0) {
+		pr_warn("t3 0x%p, offload up, ioctl failed.\n", t3dev);
+		return -EINVAL;
+	}
+
+	if (cxgb3i_max_connect > CXGBI_MAX_CONN)
+		cxgb3i_max_connect = CXGBI_MAX_CONN;
+
+	rc = cxgbi_device_portmap_create(cdev, cxgb3i_sport_base,
+					cxgb3i_max_connect);
+	if (rc < 0)
+		return rc;
+
+	init_wr_tab(wr_len);
+	cdev->csk_release_offload_resources = release_offload_resources;
+	cdev->csk_push_tx_frames = push_tx_frames;
+	cdev->csk_send_abort_req = send_abort_req;
+	cdev->csk_send_close_req = send_close_req;
+	cdev->csk_send_rx_credits = send_rx_credits;
+	cdev->csk_alloc_cpls = alloc_cpls;
+	cdev->csk_init_act_open = init_act_open;
+
+	pr_info("cdev 0x%p, offload up, added.\n", cdev);
+	return 0;
+}
+
+/*
+ * functions to program the pagepod in h/w
+ */
+static inline void ulp_mem_io_set_hdr(struct sk_buff *skb, unsigned int addr)
+{
+	struct ulp_mem_io *req = (struct ulp_mem_io *)skb->head;
+
+	memset(req, 0, sizeof(*req));
+
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS));
+	req->cmd_lock_addr = htonl(V_ULP_MEMIO_ADDR(addr >> 5) |
+				   V_ULPTX_CMD(ULP_MEM_WRITE));
+	req->len = htonl(V_ULP_MEMIO_DATA_LEN(PPOD_SIZE >> 5) |
+			 V_ULPTX_NFLITS((PPOD_SIZE >> 3) + 1));
+}
+
+static int ddp_set_map(struct cxgbi_sock *csk, struct cxgbi_pagepod_hdr *hdr,
+			unsigned int idx, unsigned int npods,
+				struct cxgbi_gather_list *gl)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
+	int i;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"csk 0x%p, idx %u, npods %u, gl 0x%p.\n",
+		csk, idx, npods, gl);
+
+	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
+		struct sk_buff *skb = ddp->gl_skb[idx];
+
+		/* hold on to the skb until we clear the ddp mapping */
+		skb_get(skb);
+
+		ulp_mem_io_set_hdr(skb, pm_addr);
+		cxgbi_ddp_ppod_set((struct cxgbi_pagepod *)(skb->head +
+					sizeof(struct ulp_mem_io)),
+				   hdr, gl, i * PPOD_PAGES_MAX);
+		skb->priority = CPL_PRIORITY_CONTROL;
+		cxgb3_ofld_send(cdev->lldev, skb);
+	}
+	return 0;
+}
+
+static void ddp_clear_map(struct cxgbi_hba *chba, unsigned int tag,
+			  unsigned int idx, unsigned int npods)
+{
+	struct cxgbi_device *cdev = chba->cdev;
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
+	int i;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"cdev 0x%p, idx %u, npods %u, tag 0x%x.\n",
+		cdev, idx, npods, tag);
+
+	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
+		struct sk_buff *skb = ddp->gl_skb[idx];
+
+		if (!skb) {
+			pr_err("tag 0x%x, 0x%x, %d/%u, skb NULL.\n",
+				tag, idx, i, npods);
+			continue;
+		}
+		ddp->gl_skb[idx] = NULL;
+		memset(skb->head + sizeof(struct ulp_mem_io), 0, PPOD_SIZE);
+		ulp_mem_io_set_hdr(skb, pm_addr);
+		skb->priority = CPL_PRIORITY_CONTROL;
+		cxgb3_ofld_send(cdev->lldev, skb);
+	}
+}
+
+static void ddp_free_gl_skb(struct cxgbi_ddp_info *ddp, int idx, int cnt)
+{
+	int i;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"ddp 0x%p, idx %d, cnt %d.\n", ddp, idx, cnt);
+
+	for (i = 0; i < cnt; i++, idx++)
+		if (ddp->gl_skb[idx]) {
+			kfree_skb(ddp->gl_skb[idx]);
+			ddp->gl_skb[idx] = NULL;
+		}
+}
+
+static int ddp_alloc_gl_skb(struct cxgbi_ddp_info *ddp, int idx,
+				   int cnt, gfp_t gfp)
+{
+	int i;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"ddp 0x%p, idx %d, cnt %d.\n", ddp, idx, cnt);
+
+	for (i = 0; i < cnt; i++) {
+		struct sk_buff *skb = alloc_wr(sizeof(struct ulp_mem_io) +
+						PPOD_SIZE, 0, gfp);
+		if (skb)
+			ddp->gl_skb[idx + i] = skb;
+		else {
+			ddp_free_gl_skb(ddp, idx, i);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
+				       unsigned int tid, int pg_idx, bool reply)
+{
+	struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
+					GFP_KERNEL);
+	struct cpl_set_tcb_field *req;
+	u64 val = pg_idx < DDP_PGIDX_MAX ? pg_idx : 0;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"csk 0x%p, tid %u, pg_idx %d.\n", csk, tid, pg_idx);
+	if (!skb)
+		return -ENOMEM;
+
+	/* set up ulp submode and page size */
+	req = (struct cpl_set_tcb_field *)skb->head;
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+	req->reply = V_NO_REPLY(reply ? 0 : 1);
+	req->cpu_idx = 0;
+	req->word = htons(31);
+	req->mask = cpu_to_be64(0xF0000000);
+	req->val = cpu_to_be64(val << 28);
+	skb->priority = CPL_PRIORITY_CONTROL;
+
+	cxgb3_ofld_send(csk->cdev->lldev, skb);
+	return 0;
+}
+
+/**
+ * cxgb3i_setup_conn_digest - setup conn. digest setting
+ * @csk: cxgb tcp socket
+ * @tid: connection id
+ * @hcrc: header digest enabled
+ * @dcrc: data digest enabled
+ * @reply: request reply from h/w
+ * set up the iscsi digest settings for a connection identified by tid
+ */
+static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
+			     int hcrc, int dcrc, int reply)
+{
+	struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
+					GFP_KERNEL);
+	struct cpl_set_tcb_field *req;
+	u64 val = (hcrc ? 1 : 0) | (dcrc ? 2 : 0);
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"csk 0x%p, tid %u, crc %d,%d.\n", csk, tid, hcrc, dcrc);
+	if (!skb)
+		return -ENOMEM;
+
+	/* set up ulp submode and page size */
+	req = (struct cpl_set_tcb_field *)skb->head;
+	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+	req->reply = V_NO_REPLY(reply ? 0 : 1);
+	req->cpu_idx = 0;
+	req->word = htons(31);
+	req->mask = cpu_to_be64(0x0F000000);
+	req->val = cpu_to_be64(val << 24);
+	skb->priority = CPL_PRIORITY_CONTROL;
+
+	cxgb3_ofld_send(csk->cdev->lldev, skb);
+	return 0;
+}
+
+/**
+ * t3_ddp_cleanup - release the cxgb3 adapter's ddp resource
+ * @cdev: cxgb3i adapter
+ * release all the resource held by the ddp pagepod manager for a given
+ * adapter if needed
+ */
+
+static void t3_ddp_cleanup(struct cxgbi_device *cdev)
+{
+	struct t3cdev *tdev = (struct t3cdev *)cdev->lldev;
+
+	if (cxgbi_ddp_cleanup(cdev)) {
+		pr_info("t3dev 0x%p, ulp_iscsi no more user.\n", tdev);
+		tdev->ulp_iscsi = NULL;
+	}
+}
+
+/**
+ * ddp_init - initialize the cxgb3 adapter's ddp resource
+ * @cdev: cxgb3i adapter
+ * initialize the ddp pagepod manager for a given adapter
+ */
+static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
+{
+	struct t3cdev *tdev = (struct t3cdev *)cdev->lldev;
+	struct cxgbi_ddp_info *ddp = tdev->ulp_iscsi;
+	struct ulp_iscsi_info uinfo;
+	unsigned int pgsz_factor[4];
+	int err;
+
+	if (ddp) {
+		kref_get(&ddp->refcnt);
+		pr_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
+			tdev, tdev->ulp_iscsi);
+		cdev->ddp = ddp;
+		return -EALREADY;
+	}
+
+	err = tdev->ctl(tdev, ULP_ISCSI_GET_PARAMS, &uinfo);
+	if (err < 0) {
+		pr_err("%s, failed to get iscsi param err=%d.\n",
+			 tdev->name, err);
+		return err;
+	}
+
+	err = cxgbi_ddp_init(cdev, uinfo.llimit, uinfo.ulimit,
+			uinfo.max_txsz, uinfo.max_rxsz);
+	if (err < 0)
+		return err;
+
+	ddp = cdev->ddp;
+
+	uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
+	cxgbi_ddp_page_size_factor(pgsz_factor);
+	uinfo.ulimit = uinfo.llimit + (ddp->nppods << PPOD_SIZE_SHIFT);
+
+	err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo);
+	if (err < 0) {
+		pr_warn("%s unable to set iscsi param err=%d, ddp disabled.\n",
+			tdev->name, err);
+		cxgbi_ddp_cleanup(cdev);
+		return err;
+	}
+	tdev->ulp_iscsi = ddp;
+
+	cdev->csk_ddp_free_gl_skb = ddp_free_gl_skb;
+	cdev->csk_ddp_alloc_gl_skb = ddp_alloc_gl_skb;
+	cdev->csk_ddp_setup_digest = ddp_setup_conn_digest;
+	cdev->csk_ddp_setup_pgidx = ddp_setup_conn_pgidx;
+	cdev->csk_ddp_set = ddp_set_map;
+	cdev->csk_ddp_clear = ddp_clear_map;
+
+	pr_info("tdev 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u, "
+		"%u/%u.\n",
+		tdev, ddp->nppods, ddp->idx_bits, ddp->idx_mask,
+		ddp->rsvd_tag_mask, ddp->max_txsz, uinfo.max_txsz,
+		ddp->max_rxsz, uinfo.max_rxsz);
+	return 0;
+}
+
+static void cxgb3i_dev_close(struct t3cdev *t3dev)
+{
+	struct cxgbi_device *cdev = cxgbi_device_find_by_lldev(t3dev);
+
+	if (!cdev || cdev->flags & CXGBI_FLAG_ADAPTER_RESET) {
+		pr_info("0x%p close, f 0x%x.\n", cdev, cdev ? cdev->flags : 0);
+		return;
+	}
+
+	cxgbi_device_unregister(cdev);
+}
+
+/**
+ * cxgb3i_dev_open - init a t3 adapter structure and any h/w settings
+ * @t3dev: t3cdev adapter
+ */
+static void cxgb3i_dev_open(struct t3cdev *t3dev)
+{
+	struct cxgbi_device *cdev = cxgbi_device_find_by_lldev(t3dev);
+	struct adapter *adapter = tdev2adap(t3dev);
+	int i, err;
+
+	if (cdev) {
+		pr_info("0x%p, updating.\n", cdev);
+		return;
+	}
+
+	cdev = cxgbi_device_register(0, adapter->params.nports);
+	if (!cdev) {
+		pr_warn("device 0x%p register failed.\n", t3dev);
+		return;
+	}
+
+	cdev->flags = CXGBI_FLAG_DEV_T3 | CXGBI_FLAG_IPV4_SET;
+	cdev->lldev = t3dev;
+	cdev->pdev = adapter->pdev;
+	cdev->ports = adapter->port;
+	cdev->nports = adapter->params.nports;
+	cdev->mtus = adapter->params.mtus;
+	cdev->nmtus = NMTUS;
+	cdev->snd_win = cxgb3i_snd_win;
+	cdev->rcv_win = cxgb3i_rcv_win;
+	cdev->rx_credit_thres = cxgb3i_rx_credit_thres;
+	cdev->skb_tx_rsvd = CXGB3I_TX_HEADER_LEN;
+	cdev->skb_rx_extra = sizeof(struct cpl_iscsi_hdr_norss);
+	cdev->dev_ddp_cleanup = t3_ddp_cleanup;
+	cdev->itp = &cxgb3i_iscsi_transport;
+
+	err = cxgb3i_ddp_init(cdev);
+	if (err) {
+		pr_info("0x%p ddp init failed\n", cdev);
+		goto err_out;
+	}
+
+	err = cxgb3i_ofld_init(cdev);
+	if (err) {
+		pr_info("0x%p offload init failed\n", cdev);
+		goto err_out;
+	}
+
+	err = cxgbi_hbas_add(cdev, CXGB3I_MAX_LUN, CXGBI_MAX_CONN,
+				&cxgb3i_host_template, cxgb3i_stt);
+	if (err)
+		goto err_out;
+
+	for (i = 0; i < cdev->nports; i++)
+		cdev->hbas[i]->ipv4addr =
+			cxgb3i_get_private_ipv4addr(cdev->ports[i]);
+
+	pr_info("cdev 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
+		cdev, cdev ? cdev->flags : 0, t3dev, err);
+	return;
+
+err_out:
+	cxgbi_device_unregister(cdev);
+}
+
+static void cxgb3i_dev_event_handler(struct t3cdev *t3dev, u32 event, u32 port)
+{
+	struct cxgbi_device *cdev = cxgbi_device_find_by_lldev(t3dev);
+
+	log_debug(1 << CXGBI_DBG_TOE,
+		"0x%p, cdev 0x%p, event 0x%x, port 0x%x.\n",
+		t3dev, cdev, event, port);
+	if (!cdev)
+		return;
+
+	switch (event) {
+	case OFFLOAD_STATUS_DOWN:
+		cdev->flags |= CXGBI_FLAG_ADAPTER_RESET;
+		break;
+	case OFFLOAD_STATUS_UP:
+		cdev->flags &= ~CXGBI_FLAG_ADAPTER_RESET;
+		break;
+	}
+}
+
+/**
+ * cxgb3i_init_module - module init entry point
+ *
+ * initialize any driver wide global data structures and register itself
+ *	with the cxgb3 module
+ */
+static int __init cxgb3i_init_module(void)
+{
+	int rc;
+
+	printk(KERN_INFO "%s", version);
+
+	rc = cxgbi_iscsi_init(&cxgb3i_iscsi_transport, &cxgb3i_stt);
+	if (rc < 0)
+		return rc;
+
+	cxgb3_register_client(&t3_client);
+	return 0;
+}
+
+/**
+ * cxgb3i_exit_module - module cleanup/exit entry point
+ *
+ * go through the driver hba list and for each hba, release any resource held.
+ *	and unregisters iscsi transport and the cxgb3 module
+ */
+static void __exit cxgb3i_exit_module(void)
+{
+	cxgb3_unregister_client(&t3_client);
+	cxgbi_device_unregister_all(CXGBI_FLAG_DEV_T3);
+	cxgbi_iscsi_cleanup(&cxgb3i_iscsi_transport, &cxgb3i_stt);
+}
+
+module_init(cxgb3i_init_module);
+module_exit(cxgb3i_exit_module);
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
new file mode 100644
index 0000000..5f5e339
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
@@ -0,0 +1,51 @@
+/*
+ * cxgb3i.h: Chelsio S3xx iSCSI driver.
+ *
+ * Copyright (c) 2008 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ */
+
+#ifndef __CXGB3I_H__
+#define __CXGB3I_H__
+
+#define CXGB3I_SCSI_HOST_QDEPTH 1024
+#define CXGB3I_MAX_LUN		512
+#define ISCSI_PDU_NONPAYLOAD_MAX \
+	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + 2*ISCSI_DIGEST_SIZE)
+
+/*for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
+#define CXGB3I_TX_HEADER_LEN \
+	(sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr))
+
+extern cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
+
+#define cxgb3i_get_private_ipv4addr(ndev) \
+	(((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr)
+#define cxgb3i_set_private_ipv4addr(ndev, addr) \
+	(((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr) = addr
+
+struct cpl_iscsi_hdr_norss {
+	union opcode_tid ot;
+	u16 pdu_len_ddp;
+	u16 len;
+	u32 seq;
+	u16 urg;
+	u8 rsvd;
+	u8 status;
+};
+
+struct cpl_rx_data_ddp_norss {
+	union opcode_tid ot;
+	u16 urg;
+	u16 len;
+	u32 seq;
+	u32 nxt_seq;
+	u32 ulp_crc;
+	u32 ddp_status;
+};
+#endif
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kbuild b/drivers/scsi/cxgbi/cxgb4i/Kbuild
new file mode 100644
index 0000000..b9f4af7
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/Kbuild
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb4
+
+obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig
new file mode 100644
index 0000000..bb94b39
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -0,0 +1,7 @@
+config SCSI_CXGB4_ISCSI
+	tristate "Chelsio T4 iSCSI support"
+	depends on CHELSIO_T4_DEPENDS
+	select CHELSIO_T4
+	select SCSI_ISCSI_ATTRS
+	---help---
+	  This driver supports iSCSI offload for the Chelsio T4 devices.
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
new file mode 100644
index 0000000..99f2b8c
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -0,0 +1,1604 @@
+/*
+ * cxgb4i.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by:	Karen Xie (kxie@chelsio.com)
+ *		Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <scsi/scsi_host.h>
+#include <net/tcp.h>
+#include <net/dst.h>
+#include <linux/netdevice.h>
+
+#include "t4_msg.h"
+#include "cxgb4.h"
+#include "cxgb4_uld.h"
+#include "t4fw_api.h"
+#include "l2t.h"
+#include "cxgb4i.h"
+
+static unsigned int dbg_level;
+
+#include "../libcxgbi.h"
+
+#define	DRV_MODULE_NAME		"cxgb4i"
+#define DRV_MODULE_DESC		"Chelsio T4 iSCSI Driver"
+#define	DRV_MODULE_VERSION	"0.9.1"
+#define	DRV_MODULE_RELDATE	"Aug. 2010"
+
+static char version[] =
+	DRV_MODULE_DESC " " DRV_MODULE_NAME
+	" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Chelsio Communications, Inc.");
+MODULE_DESCRIPTION(DRV_MODULE_DESC);
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(dbg_level, uint, 0644);
+MODULE_PARM_DESC(dbg_level, "Debug flag (default=0)");
+
+static int cxgb4i_rcv_win = 256 * 1024;
+module_param(cxgb4i_rcv_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rcv_win, "TCP reveive window in bytes");
+
+static int cxgb4i_snd_win = 128 * 1024;
+module_param(cxgb4i_snd_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_snd_win, "TCP send window in bytes");
+
+static int cxgb4i_rx_credit_thres = 10 * 1024;
+module_param(cxgb4i_rx_credit_thres, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rx_credit_thres,
+		"RX credits return threshold in bytes (default=10KB)");
+
+static unsigned int cxgb4i_max_connect = (8 * 1024);
+module_param(cxgb4i_max_connect, uint, 0644);
+MODULE_PARM_DESC(cxgb4i_max_connect, "Maximum number of connections");
+
+static unsigned short cxgb4i_sport_base = 20000;
+module_param(cxgb4i_sport_base, ushort, 0644);
+MODULE_PARM_DESC(cxgb4i_sport_base, "Starting port number (default 20000)");
+
+typedef void (*cxgb4i_cplhandler_func)(struct cxgbi_device *, struct sk_buff *);
+
+static void *t4_uld_add(const struct cxgb4_lld_info *);
+static int t4_uld_rx_handler(void *, const __be64 *, const struct pkt_gl *);
+static int t4_uld_state_change(void *, enum cxgb4_state state);
+
+static const struct cxgb4_uld_info cxgb4i_uld_info = {
+	.name = DRV_MODULE_NAME,
+	.add = t4_uld_add,
+	.rx_handler = t4_uld_rx_handler,
+	.state_change = t4_uld_state_change,
+};
+
+static struct scsi_host_template cxgb4i_host_template = {
+	.module		= THIS_MODULE,
+	.name		= DRV_MODULE_NAME,
+	.proc_name	= DRV_MODULE_NAME,
+	.can_queue	= CXGB4I_SCSI_HOST_QDEPTH,
+	.queuecommand	= iscsi_queuecommand,
+	.change_queue_depth = iscsi_change_queue_depth,
+	.sg_tablesize	= SG_ALL,
+	.max_sectors	= 0xFFFF,
+	.cmd_per_lun	= ISCSI_DEF_CMD_PER_LUN,
+	.eh_abort_handler = iscsi_eh_abort,
+	.eh_device_reset_handler = iscsi_eh_device_reset,
+	.eh_target_reset_handler = iscsi_eh_recover_target,
+	.target_alloc	= iscsi_target_alloc,
+	.use_clustering	= DISABLE_CLUSTERING,
+	.this_id	= -1,
+};
+
+static struct iscsi_transport cxgb4i_iscsi_transport = {
+	.owner		= THIS_MODULE,
+	.name		= DRV_MODULE_NAME,
+	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
+				CAP_DATADGST | CAP_DIGEST_OFFLOAD |
+				CAP_PADDING_OFFLOAD,
+	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
+				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
+				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
+				ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST |
+				ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN |
+				ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL |
+				ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS |
+				ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT |
+				ISCSI_PERSISTENT_ADDRESS |
+				ISCSI_TARGET_NAME | ISCSI_TPGT |
+				ISCSI_USERNAME | ISCSI_PASSWORD |
+				ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
+				ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
+				ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO |
+				ISCSI_PING_TMO | ISCSI_RECV_TMO |
+				ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
+	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
+				ISCSI_HOST_INITIATOR_NAME |
+				ISCSI_HOST_NETDEV_NAME,
+	.get_host_param	= cxgbi_get_host_param,
+	.set_host_param	= cxgbi_set_host_param,
+	/* session management */
+	.create_session	= cxgbi_create_session,
+	.destroy_session	= cxgbi_destroy_session,
+	.get_session_param = iscsi_session_get_param,
+	/* connection management */
+	.create_conn	= cxgbi_create_conn,
+	.bind_conn		= cxgbi_bind_conn,
+	.destroy_conn	= iscsi_tcp_conn_teardown,
+	.start_conn		= iscsi_conn_start,
+	.stop_conn		= iscsi_conn_stop,
+	.get_conn_param	= cxgbi_get_conn_param,
+	.set_param	= cxgbi_set_conn_param,
+	.get_stats	= cxgbi_get_conn_stats,
+	/* pdu xmit req from user space */
+	.send_pdu	= iscsi_conn_send_pdu,
+	/* task */
+	.init_task	= iscsi_tcp_task_init,
+	.xmit_task	= iscsi_tcp_task_xmit,
+	.cleanup_task	= cxgbi_cleanup_task,
+	/* pdu */
+	.alloc_pdu	= cxgbi_conn_alloc_pdu,
+	.init_pdu	= cxgbi_conn_init_pdu,
+	.xmit_pdu	= cxgbi_conn_xmit_pdu,
+	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
+	/* TCP connect/disconnect */
+	.ep_connect	= cxgbi_ep_connect,
+	.ep_poll	= cxgbi_ep_poll,
+	.ep_disconnect	= cxgbi_ep_disconnect,
+	/* Error recovery timeout call */
+	.session_recovery_timedout = iscsi_session_recovery_timedout,
+};
+
+static struct scsi_transport_template *cxgb4i_stt;
+
+/*
+ * CPL (Chelsio Protocol Language) defines a message passing interface between
+ * the host driver and Chelsio asic.
+ * The section below implments CPLs that related to iscsi tcp connection
+ * open/close/abort and data send/receive.
+ */
+#define DIV_ROUND_UP(n, d)	(((n) + (d) - 1) / (d))
+#define RCV_BUFSIZ_MASK		0x3FFU
+#define MAX_IMM_TX_PKT_LEN	128
+
+static inline void set_queue(struct sk_buff *skb, unsigned int queue,
+				const struct cxgbi_sock *csk)
+{
+	skb->queue_mapping = queue;
+}
+
+static int push_tx_frames(struct cxgbi_sock *, int);
+
+/*
+ * is_ofld_imm - check whether a packet can be sent as immediate data
+ * @skb: the packet
+ *
+ * Returns true if a packet can be sent as an offload WR with immediate
+ * data.  We currently use the same limit as for Ethernet packets.
+ */
+static inline int is_ofld_imm(const struct sk_buff *skb)
+{
+	return skb->len <= (MAX_IMM_TX_PKT_LEN -
+			sizeof(struct fw_ofld_tx_data_wr));
+}
+
+static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
+				struct l2t_entry *e)
+{
+	struct cpl_act_open_req *req;
+	int wscale = cxgbi_sock_compute_wscale(csk->mss_idx);
+	unsigned long long opt0;
+	unsigned int opt2;
+	unsigned int qid_atid = ((unsigned int)csk->atid) |
+				 (((unsigned int)csk->rss_qid) << 14);
+
+	opt0 = KEEP_ALIVE(1) |
+		WND_SCALE(wscale) |
+		MSS_IDX(csk->mss_idx) |
+		L2T_IDX(((struct l2t_entry *)csk->l2t)->idx) |
+		TX_CHAN(csk->tx_chan) |
+		SMAC_SEL(csk->smac_idx) |
+		ULP_MODE(ULP_MODE_ISCSI) |
+		RCV_BUFSIZ(cxgb4i_rcv_win >> 10);
+	opt2 = RX_CHANNEL(0) |
+		RSS_QUEUE_VALID |
+		(1 << 20) | (1 << 22) |
+		RSS_QUEUE(csk->rss_qid);
+
+	set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id);
+	req = (struct cpl_act_open_req *)skb->head;
+
+	INIT_TP_WR(req, 0);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+					qid_atid));
+	req->local_port = csk->saddr.sin_port;
+	req->peer_port = csk->daddr.sin_port;
+	req->local_ip = csk->saddr.sin_addr.s_addr;
+	req->peer_ip = csk->daddr.sin_addr.s_addr;
+	req->opt0 = cpu_to_be64(opt0);
+	req->params = 0;
+	req->opt2 = cpu_to_be32(opt2);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, %pI4:%u-%pI4:%u, atid %d, qid %u.\n",
+		csk, &req->local_ip, ntohs(req->local_port),
+		&req->peer_ip, ntohs(req->peer_port),
+		csk->atid, csk->rss_qid);
+
+	cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+}
+
+static void send_close_req(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->cpl_close;
+	struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
+	unsigned int tid = csk->tid;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, tid %u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+	csk->cpl_close = NULL;
+	set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id);
+	INIT_TP_WR(req, tid);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
+	req->rsvd = 0;
+
+	cxgbi_sock_skb_entail(csk, skb);
+	if (csk->state >= CTP_ESTABLISHED)
+		push_tx_frames(csk, 1);
+}
+
+static void abort_arp_failure(void *handle, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)handle;
+	struct cpl_abort_req *req;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, tid %u, abort.\n",
+		csk, csk->state, csk->flags, csk->tid);
+	req = (struct cpl_abort_req *)skb->data;
+	req->cmd = CPL_ABORT_NO_RST;
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+}
+
+static void send_abort_req(struct cxgbi_sock *csk)
+{
+	struct cpl_abort_req *req;
+	struct sk_buff *skb = csk->cpl_abort_req;
+
+	if (unlikely(csk->state == CTP_ABORTING) || !skb || !csk->cdev)
+		return;
+	cxgbi_sock_set_state(csk, CTP_ABORTING);
+	cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_PENDING);
+	cxgbi_sock_purge_write_queue(csk);
+
+	csk->cpl_abort_req = NULL;
+	req = (struct cpl_abort_req *)skb->head;
+	set_queue(skb, CPL_PRIORITY_DATA, csk);
+	req->cmd = CPL_ABORT_SEND_RST;
+	t4_set_arp_err_handler(skb, csk, abort_arp_failure);
+	INIT_TP_WR(req, csk->tid);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, csk->tid));
+	req->rsvd0 = htonl(csk->snd_nxt);
+	req->rsvd1 = !cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, snd_nxt %u, 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, csk->snd_nxt,
+		req->rsvd1);
+
+	cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+}
+
+static void send_abort_rpl(struct cxgbi_sock *csk, int rst_status)
+{
+	struct sk_buff *skb = csk->cpl_abort_rpl;
+	struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u, status %d.\n",
+		csk, csk->state, csk->flags, csk->tid, rst_status);
+
+	csk->cpl_abort_rpl = NULL;
+	set_queue(skb, CPL_PRIORITY_DATA, csk);
+	INIT_TP_WR(rpl, csk->tid);
+	OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, csk->tid));
+	rpl->cmd = rst_status;
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+}
+
+/*
+ * CPL connection rx data ack: host ->
+ * Send RX credits through an RX_DATA_ACK CPL message. Returns the number of
+ * credits sent.
+ */
+static u32 send_rx_credits(struct cxgbi_sock *csk, u32 credits)
+{
+	struct sk_buff *skb;
+	struct cpl_rx_data_ack *req;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx,%u, credit %u.\n",
+		csk, csk->state, csk->flags, csk->tid, credits);
+
+	skb = alloc_wr(sizeof(*req), 0, GFP_ATOMIC);
+	if (!skb) {
+		pr_info("csk 0x%p, credit %u, OOM.\n", csk, credits);
+		return 0;
+	}
+	req = (struct cpl_rx_data_ack *)skb->head;
+
+	set_wr_txq(skb, CPL_PRIORITY_ACK, csk->port_id);
+	INIT_TP_WR(req, csk->tid);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK,
+				      csk->tid));
+	req->credit_dack = cpu_to_be32(RX_CREDITS(credits) | RX_FORCE_ACK(1));
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+	return credits;
+}
+
+/*
+ * sgl_len - calculates the size of an SGL of the given capacity
+ * @n: the number of SGL entries
+ * Calculates the number of flits needed for a scatter/gather list that
+ * can hold the given number of entries.
+ */
+static inline unsigned int sgl_len(unsigned int n)
+{
+	n--;
+	return (3 * n) / 2 + (n & 1) + 2;
+}
+
+/*
+ * calc_tx_flits_ofld - calculate # of flits for an offload packet
+ * @skb: the packet
+ *
+ * Returns the number of flits needed for the given offload packet.
+ * These packets are already fully constructed and no additional headers
+ * will be added.
+ */
+static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
+{
+	unsigned int flits, cnt;
+
+	if (is_ofld_imm(skb))
+		return DIV_ROUND_UP(skb->len, 8);
+	flits = skb_transport_offset(skb) / 8;
+	cnt = skb_shinfo(skb)->nr_frags;
+	if (skb->tail != skb->transport_header)
+		cnt++;
+	return flits + sgl_len(cnt);
+}
+
+static inline void send_tx_flowc_wr(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+	struct fw_flowc_wr *flowc;
+	int flowclen, i;
+
+	flowclen = 80;
+	skb = alloc_wr(flowclen, 0, GFP_ATOMIC);
+	flowc = (struct fw_flowc_wr *)skb->head;
+	flowc->op_to_nparams =
+		htonl(FW_WR_OP(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS(8));
+	flowc->flowid_len16 =
+		htonl(FW_WR_LEN16(DIV_ROUND_UP(72, 16)) |
+				FW_WR_FLOWID(csk->tid));
+	flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
+	flowc->mnemval[0].val = htonl(csk->cdev->pfvf);
+	flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
+	flowc->mnemval[1].val = htonl(csk->tx_chan);
+	flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
+	flowc->mnemval[2].val = htonl(csk->tx_chan);
+	flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID;
+	flowc->mnemval[3].val = htonl(csk->rss_qid);
+	flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT;
+	flowc->mnemval[4].val = htonl(csk->snd_nxt);
+	flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT;
+	flowc->mnemval[5].val = htonl(csk->rcv_nxt);
+	flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF;
+	flowc->mnemval[6].val = htonl(cxgb4i_snd_win);
+	flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS;
+	flowc->mnemval[7].val = htonl(csk->advmss);
+	flowc->mnemval[8].mnemonic = 0;
+	flowc->mnemval[8].val = 0;
+	for (i = 0; i < 9; i++) {
+		flowc->mnemval[i].r4[0] = 0;
+		flowc->mnemval[i].r4[1] = 0;
+		flowc->mnemval[i].r4[2] = 0;
+	}
+	set_queue(skb, CPL_PRIORITY_DATA, csk);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, tid 0x%x, %u,%u,%u,%u,%u,%u,%u.\n",
+		csk, csk->tid, 0, csk->tx_chan, csk->rss_qid,
+		csk->snd_nxt, csk->rcv_nxt, cxgb4i_snd_win,
+		csk->advmss);
+
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+}
+
+static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb,
+				   int dlen, int len, u32 credits, int compl)
+{
+	struct fw_ofld_tx_data_wr *req;
+	unsigned int submode = cxgbi_skcb_ulp_mode(skb) & 3;
+	unsigned int wr_ulp_mode = 0;
+
+	req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, sizeof(*req));
+
+	if (is_ofld_imm(skb)) {
+		req->op_to_immdlen = htonl(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+					FW_WR_COMPL(1) |
+					FW_WR_IMMDLEN(dlen));
+		req->flowid_len16 = htonl(FW_WR_FLOWID(csk->tid) |
+						FW_WR_LEN16(credits));
+	} else {
+		req->op_to_immdlen =
+			cpu_to_be32(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+					FW_WR_COMPL(1) |
+					FW_WR_IMMDLEN(0));
+		req->flowid_len16 =
+			cpu_to_be32(FW_WR_FLOWID(csk->tid) |
+					FW_WR_LEN16(credits));
+	}
+	if (submode)
+		wr_ulp_mode = FW_OFLD_TX_DATA_WR_ULPMODE(ULP2_MODE_ISCSI) |
+				FW_OFLD_TX_DATA_WR_ULPSUBMODE(submode);
+	req->tunnel_to_proxy = htonl(wr_ulp_mode) |
+		 FW_OFLD_TX_DATA_WR_SHOVE(skb_peek(&csk->write_queue) ? 0 : 1);
+	req->plen = htonl(len);
+	if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT))
+		cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT);
+}
+
+static void arp_failure_skb_discard(void *handle, struct sk_buff *skb)
+{
+	kfree_skb(skb);
+}
+
+static int push_tx_frames(struct cxgbi_sock *csk, int req_completion)
+{
+	int total_size = 0;
+	struct sk_buff *skb;
+
+	if (unlikely(csk->state < CTP_ESTABLISHED ||
+		csk->state == CTP_CLOSE_WAIT_1 || csk->state >= CTP_ABORTING)) {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK |
+			 1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, in closing state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		return 0;
+	}
+
+	while (csk->wr_cred && (skb = skb_peek(&csk->write_queue)) != NULL) {
+		int dlen = skb->len;
+		int len = skb->len;
+		unsigned int credits_needed;
+
+		skb_reset_transport_header(skb);
+		if (is_ofld_imm(skb))
+			credits_needed = DIV_ROUND_UP(dlen +
+					sizeof(struct fw_ofld_tx_data_wr), 16);
+		else
+			credits_needed = DIV_ROUND_UP(8*calc_tx_flits_ofld(skb)
+					+ sizeof(struct fw_ofld_tx_data_wr),
+					16);
+
+		if (csk->wr_cred < credits_needed) {
+			log_debug(1 << CXGBI_DBG_PDU_TX,
+				"csk 0x%p, skb %u/%u, wr %d < %u.\n",
+				csk, skb->len, skb->data_len,
+				credits_needed, csk->wr_cred);
+			break;
+		}
+		__skb_unlink(skb, &csk->write_queue);
+		set_queue(skb, CPL_PRIORITY_DATA, csk);
+		skb->csum = credits_needed;
+		csk->wr_cred -= credits_needed;
+		csk->wr_una_cred += credits_needed;
+		cxgbi_sock_enqueue_wr(csk, skb);
+
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p, skb %u/%u, wr %d, left %u, unack %u.\n",
+			csk, skb->len, skb->data_len, credits_needed,
+			csk->wr_cred, csk->wr_una_cred);
+
+		if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) {
+			if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) {
+				send_tx_flowc_wr(csk);
+				skb->csum += 5;
+				csk->wr_cred -= 5;
+				csk->wr_una_cred += 5;
+			}
+			len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+			make_tx_data_wr(csk, skb, dlen, len, credits_needed,
+					req_completion);
+			csk->snd_nxt += len;
+			cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR);
+		}
+		total_size += skb->truesize;
+		t4_set_arp_err_handler(skb, csk, arp_failure_skb_discard);
+
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, skb 0x%p, %u.\n",
+			csk, csk->state, csk->flags, csk->tid, skb, len);
+
+		cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
+	}
+	return total_size;
+}
+
+static inline void free_atid(struct cxgbi_sock *csk)
+{
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev);
+
+	if (cxgbi_sock_flag(csk, CTPF_HAS_ATID)) {
+		cxgb4_free_atid(lldi->tids, csk->atid);
+		cxgbi_sock_clear_flag(csk, CTPF_HAS_ATID);
+		cxgbi_sock_put(csk);
+	}
+}
+
+static void do_act_establish(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_act_establish *req = (struct cpl_act_establish *)skb->data;
+	unsigned short tcp_opt = ntohs(req->tcp_opt);
+	unsigned int tid = GET_TID(req);
+	unsigned int atid = GET_TID_TID(ntohl(req->tos_atid));
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+	u32 rcv_isn = be32_to_cpu(req->rcv_isn);
+
+	csk = lookup_atid(t, atid);
+	if (unlikely(!csk)) {
+		pr_err("NO conn. for atid %u, cdev 0x%p.\n", atid, cdev);
+		goto rel_skb;
+	}
+
+	if (csk->atid != atid) {
+		pr_err("bad conn atid %u, csk 0x%p,%u,0x%lx,tid %u, atid %u.\n",
+			atid, csk, csk->state, csk->flags, csk->tid, csk->atid);
+		goto rel_skb;
+	}
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, tid %u, atid %u, rseq %u.\n",
+		csk, csk->state, csk->flags, tid, atid, rcv_isn);
+
+	cxgbi_sock_get(csk);
+	csk->tid = tid;
+	cxgb4_insert_tid(lldi->tids, csk, tid);
+	cxgbi_sock_set_flag(csk, CTPF_HAS_TID);
+
+	free_atid(csk);
+
+	spin_lock_bh(&csk->lock);
+	if (unlikely(csk->state != CTP_ACTIVE_OPEN))
+		pr_info("csk 0x%p,%u,0x%lx,%u, got EST.\n",
+			csk, csk->state, csk->flags, csk->tid);
+
+	if (csk->retry_timer.function) {
+		del_timer(&csk->retry_timer);
+		csk->retry_timer.function = NULL;
+	}
+
+	csk->copied_seq = csk->rcv_wup = csk->rcv_nxt = rcv_isn;
+	/*
+	 * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't
+	 * pass through opt0.
+	 */
+	if (cxgb4i_rcv_win > (RCV_BUFSIZ_MASK << 10))
+		csk->rcv_wup -= cxgb4i_rcv_win - (RCV_BUFSIZ_MASK << 10);
+
+	csk->advmss = lldi->mtus[GET_TCPOPT_MSS(tcp_opt)] - 40;
+	if (GET_TCPOPT_TSTAMP(tcp_opt))
+		csk->advmss -= 12;
+	if (csk->advmss < 128)
+		csk->advmss = 128;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, mss_idx %u, advmss %u.\n",
+			csk, GET_TCPOPT_MSS(tcp_opt), csk->advmss);
+
+	cxgbi_sock_established(csk, ntohl(req->snd_isn), ntohs(req->tcp_opt));
+
+	if (unlikely(cxgbi_sock_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED)))
+		send_abort_req(csk);
+	else {
+		if (skb_queue_len(&csk->write_queue))
+			push_tx_frames(csk, 0);
+		cxgbi_conn_tx_open(csk);
+	}
+	spin_unlock_bh(&csk->lock);
+
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static int act_open_rpl_status_to_errno(int status)
+{
+	switch (status) {
+	case CPL_ERR_CONN_RESET:
+		return -ECONNREFUSED;
+	case CPL_ERR_ARP_MISS:
+		return -EHOSTUNREACH;
+	case CPL_ERR_CONN_TIMEDOUT:
+		return -ETIMEDOUT;
+	case CPL_ERR_TCAM_FULL:
+		return -ENOMEM;
+	case CPL_ERR_CONN_EXIST:
+		return -EADDRINUSE;
+	default:
+		return -EIO;
+	}
+}
+
+static void csk_act_open_retry_timer(unsigned long data)
+{
+	struct sk_buff *skb;
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_ATOMIC);
+	if (!skb)
+		cxgbi_sock_fail_act_open(csk, -ENOMEM);
+	else {
+		skb->sk = (struct sock *)csk;
+		t4_set_arp_err_handler(skb, csk,
+					cxgbi_sock_act_open_req_arp_failure);
+		send_act_open_req(csk, skb, csk->l2t);
+	}
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+
+static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_act_open_rpl *rpl = (struct cpl_act_open_rpl *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	unsigned int atid =
+		GET_TID_TID(GET_AOPEN_ATID(be32_to_cpu(rpl->atid_status)));
+	unsigned int status = GET_AOPEN_STATUS(be32_to_cpu(rpl->atid_status));
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_atid(t, atid);
+	if (unlikely(!csk)) {
+		pr_err("NO matching conn. atid %u, tid %u.\n", atid, tid);
+		goto rel_skb;
+	}
+
+	pr_info("%pI4:%u-%pI4:%u, atid %u,%u, status %u, csk 0x%p,%u,0x%lx.\n",
+		&csk->saddr.sin_addr.s_addr, ntohs(csk->saddr.sin_port),
+		&csk->daddr.sin_addr.s_addr, ntohs(csk->daddr.sin_port),
+		atid, tid, status, csk, csk->state, csk->flags);
+
+	if (status && status != CPL_ERR_TCAM_FULL &&
+	    status != CPL_ERR_CONN_EXIST &&
+	    status != CPL_ERR_ARP_MISS)
+		cxgb4_remove_tid(lldi->tids, csk->port_id, GET_TID(rpl));
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (status == CPL_ERR_CONN_EXIST &&
+	    csk->retry_timer.function != csk_act_open_retry_timer) {
+		csk->retry_timer.function = csk_act_open_retry_timer;
+		mod_timer(&csk->retry_timer, jiffies + HZ / 2);
+	} else
+		cxgbi_sock_fail_act_open(csk,
+					act_open_rpl_status_to_errno(status));
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_peer_close(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_peer_close *req = (struct cpl_peer_close *)skb->data;
+	unsigned int tid = GET_TID(req);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find connection for tid %u.\n", tid);
+		goto rel_skb;
+	}
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+	cxgbi_sock_rcv_peer_close(csk);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_close_con_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_close_con_rpl *rpl = (struct cpl_close_con_rpl *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find connection for tid %u.\n", tid);
+		goto rel_skb;
+	}
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+	cxgbi_sock_rcv_close_conn_rpl(csk, ntohl(rpl->snd_nxt));
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason,
+								int *need_rst)
+{
+	switch (abort_reason) {
+	case CPL_ERR_BAD_SYN: /* fall through */
+	case CPL_ERR_CONN_RESET:
+		return csk->state > CTP_ESTABLISHED ?
+			-EPIPE : -ECONNRESET;
+	case CPL_ERR_XMIT_TIMEDOUT:
+	case CPL_ERR_PERSIST_TIMEDOUT:
+	case CPL_ERR_FINWAIT2_TIMEDOUT:
+	case CPL_ERR_KEEPALIVE_TIMEDOUT:
+		return -ETIMEDOUT;
+	default:
+		return -EIO;
+	}
+}
+
+static void do_abort_req_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_abort_req_rss *req = (struct cpl_abort_req_rss *)skb->data;
+	unsigned int tid = GET_TID(req);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+	int rst_status = CPL_ABORT_NO_RST;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find connection for tid %u.\n", tid);
+		goto rel_skb;
+	}
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, tid %u, status 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, req->status);
+
+	if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
+	    req->status == CPL_ERR_PERSIST_NEG_ADVICE)
+		goto rel_skb;
+
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (!cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD)) {
+		cxgbi_sock_set_flag(csk, CTPF_ABORT_REQ_RCVD);
+		cxgbi_sock_set_state(csk, CTP_ABORTING);
+		goto done;
+	}
+
+	cxgbi_sock_clear_flag(csk, CTPF_ABORT_REQ_RCVD);
+	send_abort_rpl(csk, rst_status);
+
+	if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
+		csk->err = abort_status_to_errno(csk, req->status, &rst_status);
+		cxgbi_sock_closed(csk);
+	}
+done:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_abort_rpl_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_abort_rpl_rss *rpl = (struct cpl_abort_rpl_rss *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (!csk)
+		goto rel_skb;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"status 0x%x, csk 0x%p, s %u, 0x%lx.\n",
+		rpl->status, csk, csk ? csk->state : 0,
+		csk ? csk->flags : 0UL);
+
+	if (rpl->status == CPL_ERR_ABORT_FAILED)
+		goto rel_skb;
+
+	cxgbi_sock_rcv_abort_rpl(csk);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_rx_iscsi_hdr(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_iscsi_hdr *cpl = (struct cpl_iscsi_hdr *)skb->data;
+	unsigned short pdu_len_ddp = be16_to_cpu(cpl->pdu_len_ddp);
+	unsigned int tid = GET_TID(cpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find conn. for tid %u.\n", tid);
+		goto rel_skb;
+	}
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx, tid %u, skb 0x%p,%u, 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, skb, skb->len,
+		pdu_len_ddp);
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CTP_PASSIVE_CLOSE)) {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		if (csk->state != CTP_ABORTING)
+			goto abort_conn;
+		else
+			goto discard;
+	}
+
+	cxgbi_skcb_tcp_seq(skb) = ntohl(cpl->seq);
+	cxgbi_skcb_flags(skb) = 0;
+
+	skb_reset_transport_header(skb);
+	__skb_pull(skb, sizeof(*cpl));
+	__pskb_trim(skb, ntohs(cpl->len));
+
+	if (!csk->skb_ulp_lhdr) {
+		unsigned char *bhs;
+		unsigned int hlen, dlen;
+
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p,%u,0x%lx, tid %u, skb 0x%p header.\n",
+			csk, csk->state, csk->flags, csk->tid, skb);
+		csk->skb_ulp_lhdr = skb;
+		cxgbi_skcb_set_flag(skb, SKCBF_RX_HDR);
+
+		if (cxgbi_skcb_tcp_seq(skb) != csk->rcv_nxt) {
+			pr_info("tid %u, CPL_ISCSI_HDR, bad seq, 0x%x/0x%x.\n",
+				csk->tid, cxgbi_skcb_tcp_seq(skb),
+				csk->rcv_nxt);
+			goto abort_conn;
+		}
+
+		bhs = skb->data;
+		hlen = ntohs(cpl->len);
+		dlen = ntohl(*(unsigned int *)(bhs + 4)) & 0xFFFFFF;
+
+		if ((hlen + dlen) != ISCSI_PDU_LEN(pdu_len_ddp) - 40) {
+			pr_info("tid 0x%x, CPL_ISCSI_HDR, pdu len "
+				"mismatch %u != %u + %u, seq 0x%x.\n",
+				csk->tid, ISCSI_PDU_LEN(pdu_len_ddp) - 40,
+				hlen, dlen, cxgbi_skcb_tcp_seq(skb));
+			goto abort_conn;
+		}
+
+		cxgbi_skcb_rx_pdulen(skb) = (hlen + dlen + 3) & (~0x3);
+		if (dlen)
+			cxgbi_skcb_rx_pdulen(skb) += csk->dcrc_len;
+		csk->rcv_nxt += cxgbi_skcb_rx_pdulen(skb);
+
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, skb 0x%p, 0x%x,%u+%u,0x%x,0x%x.\n",
+			csk, skb, *bhs, hlen, dlen,
+			ntohl(*((unsigned int *)(bhs + 16))),
+			ntohl(*((unsigned int *)(bhs + 24))));
+
+	} else {
+		struct sk_buff *lskb = csk->skb_ulp_lhdr;
+
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_DATA);
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p,%u,0x%lx, skb 0x%p data, 0x%p.\n",
+			csk, csk->state, csk->flags, skb, lskb);
+	}
+
+	__skb_queue_tail(&csk->receive_queue, skb);
+	spin_unlock_bh(&csk->lock);
+	return;
+
+abort_conn:
+	send_abort_req(csk);
+discard:
+	spin_unlock_bh(&csk->lock);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_rx_data_ddp(struct cxgbi_device *cdev,
+				  struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct sk_buff *lskb;
+	struct cpl_rx_data_ddp *rpl = (struct cpl_rx_data_ddp *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+	unsigned int status = ntohl(rpl->ddpvld);
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk)) {
+		pr_err("can't find connection for tid %u.\n", tid);
+		goto rel_skb;
+	}
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lx, skb 0x%p,0x%x, lhdr 0x%p.\n",
+		csk, csk->state, csk->flags, skb, status, csk->skb_ulp_lhdr);
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CTP_PASSIVE_CLOSE)) {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		if (csk->state != CTP_ABORTING)
+			goto abort_conn;
+		else
+			goto discard;
+	}
+
+	if (!csk->skb_ulp_lhdr) {
+		pr_err("tid 0x%x, rcv RX_DATA_DDP w/o pdu bhs.\n", csk->tid);
+		goto abort_conn;
+	}
+
+	lskb = csk->skb_ulp_lhdr;
+	csk->skb_ulp_lhdr = NULL;
+
+	cxgbi_skcb_rx_ddigest(lskb) = ntohl(rpl->ulp_crc);
+
+	if (ntohs(rpl->len) != cxgbi_skcb_rx_pdulen(lskb))
+		pr_info("tid 0x%x, RX_DATA_DDP pdulen %u != %u.\n",
+			csk->tid, ntohs(rpl->len), cxgbi_skcb_rx_pdulen(lskb));
+
+	if (status & (1 << CPL_RX_DDP_STATUS_HCRC_SHIFT)) {
+		pr_info("csk 0x%p, lhdr 0x%p, status 0x%x, hcrc bad 0x%lx.\n",
+			csk, lskb, status, cxgbi_skcb_flags(lskb));
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_HCRC_ERR);
+	}
+	if (status & (1 << CPL_RX_DDP_STATUS_DCRC_SHIFT)) {
+		pr_info("csk 0x%p, lhdr 0x%p, status 0x%x, dcrc bad 0x%lx.\n",
+			csk, lskb, status, cxgbi_skcb_flags(lskb));
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_DCRC_ERR);
+	}
+	if (status & (1 << CPL_RX_DDP_STATUS_PAD_SHIFT)) {
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, lhdr 0x%p, status 0x%x, pad bad.\n",
+			csk, lskb, status);
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_PAD_ERR);
+	}
+	if ((status & (1 << CPL_RX_DDP_STATUS_DDP_SHIFT)) &&
+		!cxgbi_skcb_test_flag(lskb, SKCBF_RX_DATA)) {
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, lhdr 0x%p, 0x%x, data ddp'ed.\n",
+			csk, lskb, status);
+		cxgbi_skcb_set_flag(lskb, SKCBF_RX_DATA_DDPD);
+	}
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p, lskb 0x%p, f 0x%lx.\n",
+		csk, lskb, cxgbi_skcb_flags(lskb));
+
+	cxgbi_skcb_set_flag(lskb, SKCBF_RX_STATUS);
+	cxgbi_conn_pdu_ready(csk);
+	spin_unlock_bh(&csk->lock);
+	goto rel_skb;
+
+abort_conn:
+	send_abort_req(csk);
+discard:
+	spin_unlock_bh(&csk->lock);
+rel_skb:
+	__kfree_skb(skb);
+}
+
+static void do_fw4_ack(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_fw4_ack *rpl = (struct cpl_fw4_ack *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+
+	csk = lookup_tid(t, tid);
+	if (unlikely(!csk))
+		pr_err("can't find connection for tid %u.\n", tid);
+	else {
+		log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		cxgbi_sock_rcv_wr_ack(csk, rpl->credits, ntohl(rpl->snd_una),
+					rpl->seq_vld);
+	}
+	__kfree_skb(skb);
+}
+
+static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
+{
+	struct cpl_set_tcb_rpl *rpl = (struct cpl_set_tcb_rpl *)skb->data;
+	unsigned int tid = GET_TID(rpl);
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct tid_info *t = lldi->tids;
+	struct cxgbi_sock *csk;
+
+	csk = lookup_tid(t, tid);
+	if (!csk)
+		pr_err("can't find conn. for tid %u.\n", tid);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,%lx,%u, status 0x%x.\n",
+		csk, csk->state, csk->flags, csk->tid, rpl->status);
+
+	if (rpl->status != CPL_ERR_NONE)
+		pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n",
+			csk, tid, rpl->status);
+
+	__kfree_skb(skb);
+}
+
+static int alloc_cpls(struct cxgbi_sock *csk)
+{
+	csk->cpl_close = alloc_wr(sizeof(struct cpl_close_con_req),
+					0, GFP_KERNEL);
+	if (!csk->cpl_close)
+		return -ENOMEM;
+
+	csk->cpl_abort_req = alloc_wr(sizeof(struct cpl_abort_req),
+					0, GFP_KERNEL);
+	if (!csk->cpl_abort_req)
+		goto free_cpls;
+
+	csk->cpl_abort_rpl = alloc_wr(sizeof(struct cpl_abort_rpl),
+					0, GFP_KERNEL);
+	if (!csk->cpl_abort_rpl)
+		goto free_cpls;
+	return 0;
+
+free_cpls:
+	cxgbi_sock_free_cpl_skbs(csk);
+	return -ENOMEM;
+}
+
+static inline void l2t_put(struct cxgbi_sock *csk)
+{
+	if (csk->l2t) {
+		cxgb4_l2t_release(csk->l2t);
+		csk->l2t = NULL;
+		cxgbi_sock_put(csk);
+	}
+}
+
+static void release_offload_resources(struct cxgbi_sock *csk)
+{
+	struct cxgb4_lld_info *lldi;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	cxgbi_sock_free_cpl_skbs(csk);
+	if (csk->wr_cred != csk->wr_max_cred) {
+		cxgbi_sock_purge_wr_queue(csk);
+		cxgbi_sock_reset_wr_list(csk);
+	}
+
+	l2t_put(csk);
+	if (cxgbi_sock_flag(csk, CTPF_HAS_ATID))
+		free_atid(csk);
+	else if (cxgbi_sock_flag(csk, CTPF_HAS_TID)) {
+		lldi = cxgbi_cdev_priv(csk->cdev);
+		cxgb4_remove_tid(lldi->tids, 0, csk->tid);
+		cxgbi_sock_clear_flag(csk, CTPF_HAS_TID);
+		cxgbi_sock_put(csk);
+	}
+	csk->dst = NULL;
+	csk->cdev = NULL;
+}
+
+static int init_act_open(struct cxgbi_sock *csk)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct net_device *ndev = cdev->ports[csk->port_id];
+	struct port_info *pi = netdev_priv(ndev);
+	struct sk_buff *skb = NULL;
+	unsigned int step;
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx,%u.\n",
+		csk, csk->state, csk->flags, csk->tid);
+
+	csk->atid = cxgb4_alloc_atid(lldi->tids, csk);
+	if (csk->atid < 0) {
+		pr_err("%s, NO atid available.\n", ndev->name);
+		return -EINVAL;
+	}
+	cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
+	cxgbi_sock_get(csk);
+
+	csk->l2t = cxgb4_l2t_get(lldi->l2t, csk->dst->neighbour, ndev, 0);
+	if (!csk->l2t) {
+		pr_err("%s, cannot alloc l2t.\n", ndev->name);
+		goto rel_resource;
+	}
+	cxgbi_sock_get(csk);
+
+	skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_KERNEL);
+	if (!skb)
+		goto rel_resource;
+	skb->sk = (struct sock *)csk;
+	t4_set_arp_err_handler(skb, csk, cxgbi_sock_act_open_req_arp_failure);
+
+	if (!csk->mtu)
+		csk->mtu = dst_mtu(csk->dst);
+	cxgb4_best_mtu(lldi->mtus, csk->mtu, &csk->mss_idx);
+	csk->tx_chan = cxgb4_port_chan(ndev);
+	/* SMT two entries per row */
+	csk->smac_idx = ((cxgb4_port_viid(ndev) & 0x7F)) << 1;
+	step = lldi->ntxq / lldi->nchan;
+	csk->txq_idx = cxgb4_port_idx(ndev) * step;
+	step = lldi->nrxq / lldi->nchan;
+	csk->rss_qid = lldi->rxq_ids[cxgb4_port_idx(ndev) * step];
+	csk->wr_max_cred = csk->wr_cred = lldi->wr_cred;
+	csk->wr_una_cred = 0;
+	cxgbi_sock_reset_wr_list(csk);
+	csk->err = 0;
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,p%d,%s, %u,%u,%u, mss %u,%u, smac %u.\n",
+		csk, pi->port_id, ndev->name, csk->tx_chan,
+		csk->txq_idx, csk->rss_qid, csk->mtu, csk->mss_idx,
+		csk->smac_idx);
+
+	cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
+	send_act_open_req(csk, skb, csk->l2t);
+	return 0;
+
+rel_resource:
+	if (skb)
+		__kfree_skb(skb);
+	return -EINVAL;
+}
+
+cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = {
+	[CPL_ACT_ESTABLISH] = do_act_establish,
+	[CPL_ACT_OPEN_RPL] = do_act_open_rpl,
+	[CPL_PEER_CLOSE] = do_peer_close,
+	[CPL_ABORT_REQ_RSS] = do_abort_req_rss,
+	[CPL_ABORT_RPL_RSS] = do_abort_rpl_rss,
+	[CPL_CLOSE_CON_RPL] = do_close_con_rpl,
+	[CPL_FW4_ACK] = do_fw4_ack,
+	[CPL_ISCSI_HDR] = do_rx_iscsi_hdr,
+	[CPL_SET_TCB_RPL] = do_set_tcb_rpl,
+	[CPL_RX_DATA_DDP] = do_rx_data_ddp,
+};
+
+int cxgb4i_ofld_init(struct cxgbi_device *cdev)
+{
+	int rc;
+
+	if (cxgb4i_max_connect > CXGB4I_MAX_CONN)
+		cxgb4i_max_connect = CXGB4I_MAX_CONN;
+
+	rc = cxgbi_device_portmap_create(cdev, cxgb4i_sport_base,
+					cxgb4i_max_connect);
+	if (rc < 0)
+		return rc;
+
+	cdev->csk_release_offload_resources = release_offload_resources;
+	cdev->csk_push_tx_frames = push_tx_frames;
+	cdev->csk_send_abort_req = send_abort_req;
+	cdev->csk_send_close_req = send_close_req;
+	cdev->csk_send_rx_credits = send_rx_credits;
+	cdev->csk_alloc_cpls = alloc_cpls;
+	cdev->csk_init_act_open = init_act_open;
+
+	pr_info("cdev 0x%p, offload up, added.\n", cdev);
+	return 0;
+}
+
+/*
+ * functions to program the pagepod in h/w
+ */
+#define ULPMEM_IDATA_MAX_NPPODS	4 /* 256/PPOD_SIZE */
+static inline void ulp_mem_io_set_hdr(struct ulp_mem_io *req,
+				unsigned int wr_len, unsigned int dlen,
+				unsigned int pm_addr)
+{
+	struct ulptx_idata *idata = (struct ulptx_idata *)(req + 1);
+
+	INIT_ULPTX_WR(req, wr_len, 0, 0);
+	req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE) | (1 << 23));
+	req->dlen = htonl(ULP_MEMIO_DATA_LEN(dlen >> 5));
+	req->lock_addr = htonl(ULP_MEMIO_ADDR(pm_addr >> 5));
+	req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16));
+
+	idata->cmd_more = htonl(ULPTX_CMD(ULP_TX_SC_IMM));
+	idata->len = htonl(dlen);
+}
+
+static int ddp_ppod_write_idata(struct cxgbi_device *cdev, unsigned int port_id,
+				struct cxgbi_pagepod_hdr *hdr, unsigned int idx,
+				unsigned int npods,
+				struct cxgbi_gather_list *gl,
+				unsigned int gl_pidx)
+{
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	struct sk_buff *skb;
+	struct ulp_mem_io *req;
+	struct ulptx_idata *idata;
+	struct cxgbi_pagepod *ppod;
+	unsigned int pm_addr = idx * PPOD_SIZE + ddp->llimit;
+	unsigned int dlen = PPOD_SIZE * npods;
+	unsigned int wr_len = roundup(sizeof(struct ulp_mem_io) +
+				sizeof(struct ulptx_idata) + dlen, 16);
+	unsigned int i;
+
+	skb = alloc_wr(wr_len, 0, GFP_ATOMIC);
+	if (!skb) {
+		pr_err("cdev 0x%p, idx %u, npods %u, OOM.\n",
+			cdev, idx, npods);
+		return -ENOMEM;
+	}
+	req = (struct ulp_mem_io *)skb->head;
+	set_queue(skb, CPL_PRIORITY_CONTROL, NULL);
+
+	ulp_mem_io_set_hdr(req, wr_len, dlen, pm_addr);
+	idata = (struct ulptx_idata *)(req + 1);
+	ppod = (struct cxgbi_pagepod *)(idata + 1);
+
+	for (i = 0; i < npods; i++, ppod++, gl_pidx += PPOD_PAGES_MAX) {
+		if (!hdr && !gl)
+			cxgbi_ddp_ppod_clear(ppod);
+		else
+			cxgbi_ddp_ppod_set(ppod, hdr, gl, gl_pidx);
+	}
+
+	cxgb4_ofld_send(cdev->ports[port_id], skb);
+	return 0;
+}
+
+static int ddp_set_map(struct cxgbi_sock *csk, struct cxgbi_pagepod_hdr *hdr,
+			unsigned int idx, unsigned int npods,
+			struct cxgbi_gather_list *gl)
+{
+	unsigned int i, cnt;
+	int err = 0;
+
+	for (i = 0; i < npods; i += cnt, idx += cnt) {
+		cnt = npods - i;
+		if (cnt > ULPMEM_IDATA_MAX_NPPODS)
+			cnt = ULPMEM_IDATA_MAX_NPPODS;
+		err = ddp_ppod_write_idata(csk->cdev, csk->port_id, hdr,
+					idx, cnt, gl, 4 * i);
+		if (err < 0)
+			break;
+	}
+	return err;
+}
+
+static void ddp_clear_map(struct cxgbi_hba *chba, unsigned int tag,
+			  unsigned int idx, unsigned int npods)
+{
+	unsigned int i, cnt;
+	int err;
+
+	for (i = 0; i < npods; i += cnt, idx += cnt) {
+		cnt = npods - i;
+		if (cnt > ULPMEM_IDATA_MAX_NPPODS)
+			cnt = ULPMEM_IDATA_MAX_NPPODS;
+		err = ddp_ppod_write_idata(chba->cdev, chba->port_id, NULL,
+					idx, cnt, NULL, 0);
+		if (err < 0)
+			break;
+	}
+}
+
+static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
+				int pg_idx, bool reply)
+{
+	struct sk_buff *skb;
+	struct cpl_set_tcb_field *req;
+
+	if (!pg_idx || pg_idx >= DDP_PGIDX_MAX)
+		return 0;
+
+	skb = alloc_wr(sizeof(*req), 0, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	/*  set up ulp page size */
+	req = (struct cpl_set_tcb_field *)skb->head;
+	INIT_TP_WR(req, csk->tid);
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid));
+	req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+	req->word_cookie = htons(0);
+	req->mask = cpu_to_be64(0x3 << 8);
+	req->val = cpu_to_be64(pg_idx << 8);
+	set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->port_id);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx);
+
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+	return 0;
+}
+
+static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
+				 int hcrc, int dcrc, int reply)
+{
+	struct sk_buff *skb;
+	struct cpl_set_tcb_field *req;
+
+	if (!hcrc && !dcrc)
+		return 0;
+
+	skb = alloc_wr(sizeof(*req), 0, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	csk->hcrc_len = (hcrc ? 4 : 0);
+	csk->dcrc_len = (dcrc ? 4 : 0);
+	/*  set up ulp submode */
+	req = (struct cpl_set_tcb_field *)skb->head;
+	INIT_TP_WR(req, tid);
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+	req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+	req->word_cookie = htons(0);
+	req->mask = cpu_to_be64(0x3 << 4);
+	req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) |
+				(dcrc ? ULP_CRC_DATA : 0)) << 4);
+	set_wr_txq(skb, CPL_PRIORITY_CONTROL, csk->port_id);
+
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc);
+
+	cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
+	return 0;
+}
+
+static int cxgb4i_ddp_init(struct cxgbi_device *cdev)
+{
+	struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	unsigned int tagmask, pgsz_factor[4];
+	int err;
+
+	if (ddp) {
+		kref_get(&ddp->refcnt);
+		pr_warn("cdev 0x%p, ddp 0x%p already set up.\n",
+			cdev, cdev->ddp);
+		return -EALREADY;
+	}
+
+	err = cxgbi_ddp_init(cdev, lldi->vr->iscsi.start,
+			lldi->vr->iscsi.start + lldi->vr->iscsi.size - 1,
+			lldi->iscsi_iolen, lldi->iscsi_iolen);
+	if (err < 0)
+		return err;
+
+	ddp = cdev->ddp;
+
+	tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
+	cxgbi_ddp_page_size_factor(pgsz_factor);
+	cxgb4_iscsi_init(lldi->ports[0], tagmask, pgsz_factor);
+
+	cdev->csk_ddp_free_gl_skb = NULL;
+	cdev->csk_ddp_alloc_gl_skb = NULL;
+	cdev->csk_ddp_setup_digest = ddp_setup_conn_digest;
+	cdev->csk_ddp_setup_pgidx = ddp_setup_conn_pgidx;
+	cdev->csk_ddp_set = ddp_set_map;
+	cdev->csk_ddp_clear = ddp_clear_map;
+
+	pr_info("cxgb4i 0x%p tag: sw %u, rsvd %u,%u, mask 0x%x.\n",
+		cdev, cdev->tag_format.sw_bits, cdev->tag_format.rsvd_bits,
+		cdev->tag_format.rsvd_shift, cdev->tag_format.rsvd_mask);
+	pr_info("cxgb4i 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u, "
+		" %u/%u.\n",
+		cdev, ddp->nppods, ddp->idx_bits, ddp->idx_mask,
+		ddp->rsvd_tag_mask, ddp->max_txsz, lldi->iscsi_iolen,
+		ddp->max_rxsz, lldi->iscsi_iolen);
+	pr_info("cxgb4i 0x%p max payload size: %u/%u, %u/%u.\n",
+		cdev, cdev->tx_max_size, ddp->max_txsz, cdev->rx_max_size,
+		ddp->max_rxsz);
+	return 0;
+}
+
+static void *t4_uld_add(const struct cxgb4_lld_info *lldi)
+{
+	struct cxgbi_device *cdev;
+	struct port_info *pi;
+	int i, rc;
+
+	cdev = cxgbi_device_register(sizeof(*lldi), lldi->nports);
+	if (!cdev) {
+		pr_info("t4 device 0x%p, register failed.\n", lldi);
+		return NULL;
+	}
+	pr_info("0x%p,0x%x, ports %u,%s, chan %u, q %u,%u, wr %u.\n",
+		cdev, lldi->adapter_type, lldi->nports,
+		lldi->ports[0]->name, lldi->nchan, lldi->ntxq,
+		lldi->nrxq, lldi->wr_cred);
+	for (i = 0; i < lldi->nrxq; i++)
+		log_debug(1 << CXGBI_DBG_DEV,
+			"t4 0x%p, rxq id #%d: %u.\n",
+			cdev, i, lldi->rxq_ids[i]);
+
+	memcpy(cxgbi_cdev_priv(cdev), lldi, sizeof(*lldi));
+	cdev->flags = CXGBI_FLAG_DEV_T4;
+	cdev->pdev = lldi->pdev;
+	cdev->ports = lldi->ports;
+	cdev->nports = lldi->nports;
+	cdev->mtus = lldi->mtus;
+	cdev->nmtus = NMTUS;
+	cdev->snd_win = cxgb4i_snd_win;
+	cdev->rcv_win = cxgb4i_rcv_win;
+	cdev->rx_credit_thres = cxgb4i_rx_credit_thres;
+	cdev->skb_tx_rsvd = CXGB4I_TX_HEADER_LEN;
+	cdev->skb_rx_extra = sizeof(struct cpl_iscsi_hdr);
+	cdev->itp = &cxgb4i_iscsi_transport;
+
+	cdev->pfvf = FW_VIID_PFN_GET(cxgb4_port_viid(lldi->ports[0])) << 8;
+	pr_info("cdev 0x%p,%s, pfvf %u.\n",
+		cdev, lldi->ports[0]->name, cdev->pfvf);
+
+	rc = cxgb4i_ddp_init(cdev);
+	if (rc) {
+		pr_info("t4 0x%p ddp init failed.\n", cdev);
+		goto err_out;
+	}
+	rc = cxgb4i_ofld_init(cdev);
+	if (rc) {
+		pr_info("t4 0x%p ofld init failed.\n", cdev);
+		goto err_out;
+	}
+
+	rc = cxgbi_hbas_add(cdev, CXGB4I_MAX_LUN, CXGBI_MAX_CONN,
+				&cxgb4i_host_template, cxgb4i_stt);
+	if (rc)
+		goto err_out;
+
+	for (i = 0; i < cdev->nports; i++) {
+		pi = netdev_priv(lldi->ports[i]);
+		cdev->hbas[i]->port_id = pi->port_id;
+	}
+	return cdev;
+
+err_out:
+	cxgbi_device_unregister(cdev);
+	return ERR_PTR(-ENOMEM);
+}
+
+#define RX_PULL_LEN	128
+static int t4_uld_rx_handler(void *handle, const __be64 *rsp,
+				const struct pkt_gl *pgl)
+{
+	const struct cpl_act_establish *rpl;
+	struct sk_buff *skb;
+	unsigned int opc;
+	struct cxgbi_device *cdev = handle;
+
+	if (pgl == NULL) {
+		unsigned int len = 64 - sizeof(struct rsp_ctrl) - 8;
+
+		skb = alloc_wr(len, 0, GFP_ATOMIC);
+		if (!skb)
+			goto nomem;
+		skb_copy_to_linear_data(skb, &rsp[1], len);
+	} else {
+		if (unlikely(*(u8 *)rsp != *(u8 *)pgl->va)) {
+			pr_info("? FL 0x%p,RSS%#llx,FL %#llx,len %u.\n",
+				pgl->va, be64_to_cpu(*rsp),
+				be64_to_cpu(*(u64 *)pgl->va),
+				pgl->tot_len);
+			return 0;
+		}
+		skb = cxgb4_pktgl_to_skb(pgl, RX_PULL_LEN, RX_PULL_LEN);
+		if (unlikely(!skb))
+			goto nomem;
+	}
+
+	rpl = (struct cpl_act_establish *)skb->data;
+	opc = rpl->ot.opcode;
+	log_debug(1 << CXGBI_DBG_TOE,
+		"cdev %p, opcode 0x%x(0x%x,0x%x), skb %p.\n",
+		 cdev, opc, rpl->ot.opcode_tid, ntohl(rpl->ot.opcode_tid), skb);
+	if (cxgb4i_cplhandlers[opc])
+		cxgb4i_cplhandlers[opc](cdev, skb);
+	else {
+		pr_err("No handler for opcode 0x%x.\n", opc);
+		__kfree_skb(skb);
+	}
+	return 0;
+nomem:
+	log_debug(1 << CXGBI_DBG_TOE, "OOM bailing out.\n");
+	return 1;
+}
+
+static int t4_uld_state_change(void *handle, enum cxgb4_state state)
+{
+	struct cxgbi_device *cdev = handle;
+
+	switch (state) {
+	case CXGB4_STATE_UP:
+		pr_info("cdev 0x%p, UP.\n", cdev);
+		/* re-initialize */
+		break;
+	case CXGB4_STATE_START_RECOVERY:
+		pr_info("cdev 0x%p, RECOVERY.\n", cdev);
+		/* close all connections */
+		break;
+	case CXGB4_STATE_DOWN:
+		pr_info("cdev 0x%p, DOWN.\n", cdev);
+		break;
+	case CXGB4_STATE_DETACH:
+		pr_info("cdev 0x%p, DETACH.\n", cdev);
+		break;
+	default:
+		pr_info("cdev 0x%p, unknown state %d.\n", cdev, state);
+		break;
+	}
+	return 0;
+}
+
+static int __init cxgb4i_init_module(void)
+{
+	int rc;
+
+	printk(KERN_INFO "%s", version);
+
+	rc = cxgbi_iscsi_init(&cxgb4i_iscsi_transport, &cxgb4i_stt);
+	if (rc < 0)
+		return rc;
+	cxgb4_register_uld(CXGB4_ULD_ISCSI, &cxgb4i_uld_info);
+	return 0;
+}
+
+static void __exit cxgb4i_exit_module(void)
+{
+	cxgb4_unregister_uld(CXGB4_ULD_ISCSI);
+	cxgbi_device_unregister_all(CXGBI_FLAG_DEV_T4);
+	cxgbi_iscsi_cleanup(&cxgb4i_iscsi_transport, &cxgb4i_stt);
+}
+
+module_init(cxgb4i_init_module);
+module_exit(cxgb4i_exit_module);
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.h b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.h
new file mode 100644
index 0000000..1096026
--- /dev/null
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.h
@@ -0,0 +1,43 @@
+/*
+ * cxgb4i.h: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Written by: Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#ifndef	__CXGB4I_H__
+#define	__CXGB4I_H__
+
+#define	CXGB4I_SCSI_HOST_QDEPTH	1024
+#define	CXGB4I_MAX_CONN		16384
+#define	CXGB4I_MAX_TARGET	CXGB4I_MAX_CONN
+#define	CXGB4I_MAX_LUN		0x1000
+
+/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
+#define CXGB4I_TX_HEADER_LEN \
+	(sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr))
+
+struct ulptx_idata {
+	__be32 cmd_more;
+	__be32 len;
+};
+
+struct cpl_rx_data_ddp {
+	union opcode_tid ot;
+	__be16 urg;
+	__be16 len;
+	__be32 seq;
+	union {
+		__be32 nxt_seq;
+		__be32 ddp_report;
+	};
+	__be32 ulp_crc;
+	__be32 ddpvld;
+};
+#endif	/* __CXGB4I_H__ */
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
new file mode 100644
index 0000000..be56617
--- /dev/null
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -0,0 +1,2612 @@
+/*
+ * libcxgbi.c: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Written by: Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/skbuff.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/pci.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <linux/if_vlan.h>
+#include <linux/inet.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <linux/inetdevice.h>	/* ip_dev_find */
+#include <net/tcp.h>
+
+static unsigned int dbg_level;
+
+#include "libcxgbi.h"
+
+#define DRV_MODULE_NAME		"libcxgbi"
+#define DRV_MODULE_DESC		"Chelsio iSCSI driver library"
+#define DRV_MODULE_VERSION	"0.9.0"
+#define DRV_MODULE_RELDATE	"Jun. 2010"
+
+MODULE_AUTHOR("Chelsio Communications, Inc.");
+MODULE_DESCRIPTION(DRV_MODULE_DESC);
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(dbg_level, uint, 0644);
+MODULE_PARM_DESC(dbg_level, "libiscsi debug level (default=0)");
+
+
+/*
+ * cxgbi device management
+ * maintains a list of the cxgbi devices
+ */
+static LIST_HEAD(cdev_list);
+static DEFINE_MUTEX(cdev_mutex);
+
+int cxgbi_device_portmap_create(struct cxgbi_device *cdev, unsigned int base,
+				unsigned int max_conn)
+{
+	struct cxgbi_ports_map *pmap = &cdev->pmap;
+
+	pmap->port_csk = cxgbi_alloc_big_mem(max_conn *
+					     sizeof(struct cxgbi_sock *),
+					     GFP_KERNEL);
+	if (!pmap->port_csk) {
+		pr_warn("cdev 0x%p, portmap OOM %u.\n", cdev, max_conn);
+		return -ENOMEM;
+	}
+
+	pmap->max_connect = max_conn;
+	pmap->sport_base = base;
+	spin_lock_init(&pmap->lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_portmap_create);
+
+void cxgbi_device_portmap_cleanup(struct cxgbi_device *cdev)
+{
+	struct cxgbi_ports_map *pmap = &cdev->pmap;
+	struct cxgbi_sock *csk;
+	int i;
+
+	for (i = 0; i < pmap->max_connect; i++) {
+		if (pmap->port_csk[i]) {
+			csk = pmap->port_csk[i];
+			pmap->port_csk[i] = NULL;
+			log_debug(1 << CXGBI_DBG_SOCK,
+				"csk 0x%p, cdev 0x%p, offload down.\n",
+				csk, cdev);
+			spin_lock_bh(&csk->lock);
+			cxgbi_sock_set_flag(csk, CTPF_OFFLOAD_DOWN);
+			cxgbi_sock_closed(csk);
+			spin_unlock_bh(&csk->lock);
+			cxgbi_sock_put(csk);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_portmap_cleanup);
+
+static inline void cxgbi_device_destroy(struct cxgbi_device *cdev)
+{
+	log_debug(1 << CXGBI_DBG_DEV,
+		"cdev 0x%p, p# %u.\n", cdev, cdev->nports);
+	cxgbi_hbas_remove(cdev);
+	cxgbi_device_portmap_cleanup(cdev);
+	if (cdev->dev_ddp_cleanup)
+		cdev->dev_ddp_cleanup(cdev);
+	else
+		cxgbi_ddp_cleanup(cdev);
+	if (cdev->ddp)
+		cxgbi_ddp_cleanup(cdev);
+	if (cdev->pmap.max_connect)
+		cxgbi_free_big_mem(cdev->pmap.port_csk);
+	kfree(cdev);
+}
+
+struct cxgbi_device *cxgbi_device_register(unsigned int extra,
+					   unsigned int nports)
+{
+	struct cxgbi_device *cdev;
+
+	cdev = kzalloc(sizeof(*cdev) + extra + nports *
+			(sizeof(struct cxgbi_hba *) +
+			 sizeof(struct net_device *)),
+			GFP_KERNEL);
+	if (!cdev) {
+		pr_warn("nport %d, OOM.\n", nports);
+		return NULL;
+	}
+	cdev->ports = (struct net_device **)(cdev + 1);
+	cdev->hbas = (struct cxgbi_hba **)(((char*)cdev->ports) + nports *
+						sizeof(struct net_device *));
+	if (extra)
+		cdev->dd_data = ((char *)cdev->hbas) +
+				nports * sizeof(struct cxgbi_hba *);
+	spin_lock_init(&cdev->pmap.lock);
+
+	mutex_lock(&cdev_mutex);
+	list_add_tail(&cdev->list_head, &cdev_list);
+	mutex_unlock(&cdev_mutex);
+
+	log_debug(1 << CXGBI_DBG_DEV,
+		"cdev 0x%p, p# %u.\n", cdev, nports);
+	return cdev;
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_register);
+
+void cxgbi_device_unregister(struct cxgbi_device *cdev)
+{
+	log_debug(1 << CXGBI_DBG_DEV,
+		"cdev 0x%p, p# %u,%s.\n",
+		cdev, cdev->nports, cdev->nports ? cdev->ports[0]->name : "");
+	mutex_lock(&cdev_mutex);
+	list_del(&cdev->list_head);
+	mutex_unlock(&cdev_mutex);
+	cxgbi_device_destroy(cdev);
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_unregister);
+
+void cxgbi_device_unregister_all(unsigned int flag)
+{
+	struct cxgbi_device *cdev, *tmp;
+
+	mutex_lock(&cdev_mutex);
+	list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+		if ((cdev->flags & flag) == flag) {
+			log_debug(1 << CXGBI_DBG_DEV,
+				"cdev 0x%p, p# %u,%s.\n",
+				cdev, cdev->nports, cdev->nports ?
+				 cdev->ports[0]->name : "");
+			list_del(&cdev->list_head);
+			cxgbi_device_destroy(cdev);
+		}
+	}
+	mutex_unlock(&cdev_mutex);
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_unregister_all);
+
+struct cxgbi_device *cxgbi_device_find_by_lldev(void *lldev)
+{
+	struct cxgbi_device *cdev, *tmp;
+
+	mutex_lock(&cdev_mutex);
+	list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+		if (cdev->lldev == lldev) {
+			mutex_unlock(&cdev_mutex);
+			return cdev;
+		}
+	}
+	mutex_unlock(&cdev_mutex);
+	log_debug(1 << CXGBI_DBG_DEV,
+		"lldev 0x%p, NO match found.\n", lldev);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(cxgbi_device_find_by_lldev);
+
+static struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *ndev,
+							int *port)
+{
+	struct net_device *vdev = NULL;
+	struct cxgbi_device *cdev, *tmp;
+	int i;
+
+	if (ndev->priv_flags & IFF_802_1Q_VLAN) {
+		vdev = ndev;
+		ndev = vlan_dev_real_dev(ndev);
+		log_debug(1 << CXGBI_DBG_DEV,
+			"vlan dev %s -> %s.\n", vdev->name, ndev->name);
+	}
+
+	mutex_lock(&cdev_mutex);
+	list_for_each_entry_safe(cdev, tmp, &cdev_list, list_head) {
+		for (i = 0; i < cdev->nports; i++) {
+			if (ndev == cdev->ports[i]) {
+				cdev->hbas[i]->vdev = vdev;
+				mutex_unlock(&cdev_mutex);
+				if (port)
+					*port = i;
+				return cdev;
+			}
+		}
+	}
+	mutex_unlock(&cdev_mutex);
+	log_debug(1 << CXGBI_DBG_DEV,
+		"ndev 0x%p, %s, NO match found.\n", ndev, ndev->name);
+	return NULL;
+}
+
+void cxgbi_hbas_remove(struct cxgbi_device *cdev)
+{
+	int i;
+	struct cxgbi_hba *chba;
+
+	log_debug(1 << CXGBI_DBG_DEV,
+		"cdev 0x%p, p#%u.\n", cdev, cdev->nports);
+
+	for (i = 0; i < cdev->nports; i++) {
+		chba = cdev->hbas[i];
+		if (chba) {
+			cdev->hbas[i] = NULL;
+			iscsi_host_remove(chba->shost);
+			pci_dev_put(cdev->pdev);
+			iscsi_host_free(chba->shost);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_hbas_remove);
+
+int cxgbi_hbas_add(struct cxgbi_device *cdev, unsigned int max_lun,
+		unsigned int max_id, struct scsi_host_template *sht,
+		struct scsi_transport_template *stt)
+{
+	struct cxgbi_hba *chba;
+	struct Scsi_Host *shost;
+	int i, err;
+
+	log_debug(1 << CXGBI_DBG_DEV, "cdev 0x%p, p#%u.\n", cdev, cdev->nports);
+
+	for (i = 0; i < cdev->nports; i++) {
+		shost = iscsi_host_alloc(sht, sizeof(*chba), 1);
+		if (!shost) {
+			pr_info("0x%p, p%d, %s, host alloc failed.\n",
+				cdev, i, cdev->ports[i]->name);
+			err = -ENOMEM;
+			goto err_out;
+		}
+
+		shost->transportt = stt;
+		shost->max_lun = max_lun;
+		shost->max_id = max_id;
+		shost->max_channel = 0;
+		shost->max_cmd_len = 16;
+
+		chba = iscsi_host_priv(shost);
+		chba->cdev = cdev;
+		chba->ndev = cdev->ports[i];
+		chba->shost = shost;
+
+		log_debug(1 << CXGBI_DBG_DEV,
+			"cdev 0x%p, p#%d %s: chba 0x%p.\n",
+			cdev, i, cdev->ports[i]->name, chba);
+
+		pci_dev_get(cdev->pdev);
+		err = iscsi_host_add(shost, &cdev->pdev->dev);
+		if (err) {
+			pr_info("cdev 0x%p, p#%d %s, host add failed.\n",
+				cdev, i, cdev->ports[i]->name);
+			pci_dev_put(cdev->pdev);
+			scsi_host_put(shost);
+			goto  err_out;
+		}
+
+		cdev->hbas[i] = chba;
+	}
+
+	return 0;
+
+err_out:
+	cxgbi_hbas_remove(cdev);
+	return err;
+}
+EXPORT_SYMBOL_GPL(cxgbi_hbas_add);
+
+/*
+ * iSCSI offload
+ *
+ * - source port management
+ *   To find a free source port in the port allocation map we use a very simple
+ *   rotor scheme to look for the next free port.
+ *
+ *   If a source port has been specified make sure that it doesn't collide with
+ *   our normal source port allocation map.  If it's outside the range of our
+ *   allocation/deallocation scheme just let them use it.
+ *
+ *   If the source port is outside our allocation range, the caller is
+ *   responsible for keeping track of their port usage.
+ */
+static int sock_get_port(struct cxgbi_sock *csk)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_ports_map *pmap = &cdev->pmap;
+	unsigned int start;
+	int idx;
+
+	if (!pmap->max_connect) {
+		pr_err("cdev 0x%p, p#%u %s, NO port map.\n",
+			   cdev, csk->port_id, cdev->ports[csk->port_id]->name);
+		return -EADDRNOTAVAIL;
+	}
+
+	if (csk->saddr.sin_port) {
+		pr_err("source port NON-ZERO %u.\n",
+			ntohs(csk->saddr.sin_port));
+		return -EADDRINUSE;
+	}
+
+	spin_lock_bh(&pmap->lock);
+	if (pmap->used >= pmap->max_connect) {
+		spin_unlock_bh(&pmap->lock);
+		pr_info("cdev 0x%p, p#%u %s, ALL ports used.\n",
+			cdev, csk->port_id, cdev->ports[csk->port_id]->name);
+		return -EADDRNOTAVAIL;
+	}
+
+	start = idx = pmap->next;
+	do {
+		if (++idx >= pmap->max_connect)
+			idx = 0;
+		if (!pmap->port_csk[idx]) {
+			pmap->used++;
+			csk->saddr.sin_port =
+				htons(pmap->sport_base + idx);
+			pmap->next = idx;
+			pmap->port_csk[idx] = csk;
+			spin_unlock_bh(&pmap->lock);
+			cxgbi_sock_get(csk);
+			log_debug(1 << CXGBI_DBG_SOCK,
+				"cdev 0x%p, p#%u %s, p %u, %u.\n",
+				cdev, csk->port_id,
+				cdev->ports[csk->port_id]->name,
+				pmap->sport_base + idx, pmap->next);
+			return 0;
+		}
+	} while (idx != start);
+	spin_unlock_bh(&pmap->lock);
+
+	/* should not happen */
+	pr_warn("cdev 0x%p, p#%u %s, next %u?\n",
+		cdev, csk->port_id, cdev->ports[csk->port_id]->name,
+		pmap->next);
+	return -EADDRNOTAVAIL;
+}
+
+static void sock_put_port(struct cxgbi_sock *csk)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_ports_map *pmap = &cdev->pmap;
+
+	if (csk->saddr.sin_port) {
+		int idx = ntohs(csk->saddr.sin_port) - pmap->sport_base;
+
+		csk->saddr.sin_port = 0;
+		if (idx < 0 || idx >= pmap->max_connect) {
+			pr_err("cdev 0x%p, p#%u %s, port %u OOR.\n",
+				cdev, csk->port_id,
+				cdev->ports[csk->port_id]->name,
+				ntohs(csk->saddr.sin_port));
+			return;
+		}
+
+		spin_lock_bh(&pmap->lock);
+		pmap->port_csk[idx] = NULL;
+		pmap->used--;
+		spin_unlock_bh(&pmap->lock);
+
+		log_debug(1 << CXGBI_DBG_SOCK,
+			"cdev 0x%p, p#%u %s, release %u.\n",
+			cdev, csk->port_id, cdev->ports[csk->port_id]->name,
+			pmap->sport_base + idx);
+
+		cxgbi_sock_put(csk);
+	}
+}
+
+/*
+ * iscsi tcp connection
+ */
+void cxgbi_sock_free_cpl_skbs(struct cxgbi_sock *csk)
+{
+	if (csk->cpl_close) {
+		kfree_skb(csk->cpl_close);
+		csk->cpl_close = NULL;
+	}
+	if (csk->cpl_abort_req) {
+		kfree_skb(csk->cpl_abort_req);
+		csk->cpl_abort_req = NULL;
+	}
+	if (csk->cpl_abort_rpl) {
+		kfree_skb(csk->cpl_abort_rpl);
+		csk->cpl_abort_rpl = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_free_cpl_skbs);
+
+static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev)
+{
+	struct cxgbi_sock *csk = kzalloc(sizeof(*csk), GFP_NOIO);
+
+	if (!csk) {
+		pr_info("alloc csk %zu failed.\n", sizeof(*csk));
+		return NULL;
+	}
+
+	if (cdev->csk_alloc_cpls(csk) < 0) {
+		pr_info("csk 0x%p, alloc cpls failed.\n", csk);
+		kfree(csk);
+		return NULL;
+	}
+
+	spin_lock_init(&csk->lock);
+	kref_init(&csk->refcnt);
+	skb_queue_head_init(&csk->receive_queue);
+	skb_queue_head_init(&csk->write_queue);
+	setup_timer(&csk->retry_timer, NULL, (unsigned long)csk);
+	rwlock_init(&csk->callback_lock);
+	csk->cdev = cdev;
+	csk->flags = 0;
+	cxgbi_sock_set_state(csk, CTP_CLOSED);
+
+	log_debug(1 << CXGBI_DBG_SOCK, "cdev 0x%p, new csk 0x%p.\n", cdev, csk);
+
+	return csk;
+}
+
+static struct rtable *find_route_ipv4(__be32 saddr, __be32 daddr,
+					__be16 sport, __be16 dport, u8 tos)
+{
+	struct rtable *rt;
+	struct flowi fl = {
+		.oif = 0,
+		.nl_u = {
+			.ip4_u = {
+				.daddr = daddr,
+				.saddr = saddr,
+				.tos = tos }
+			},
+		.proto = IPPROTO_TCP,
+		.uli_u = {
+			.ports = {
+				.sport = sport,
+				.dport = dport }
+			}
+	};
+
+	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
+		return NULL;
+
+	return rt;
+}
+
+static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
+{
+	struct sockaddr_in *daddr = (struct sockaddr_in *)dst_addr;
+	struct dst_entry *dst;
+	struct net_device *ndev;
+	struct cxgbi_device *cdev;
+	struct rtable *rt = NULL;
+	struct cxgbi_sock *csk = NULL;
+	unsigned int mtu = 0;
+	int port = 0xFFFF;
+	int err = 0;
+
+	if (daddr->sin_family != AF_INET) {
+		pr_info("address family 0x%x NOT supported.\n",
+			daddr->sin_family);
+		err = -EAFNOSUPPORT;
+		goto err_out;
+	}
+
+	rt = find_route_ipv4(0, daddr->sin_addr.s_addr, 0, daddr->sin_port, 0);
+	if (!rt) {
+		pr_info("no route to ipv4 0x%x, port %u.\n",
+			daddr->sin_addr.s_addr, daddr->sin_port);
+		err = -ENETUNREACH;
+		goto err_out;
+	}
+	dst = &rt->dst;
+	ndev = dst->neighbour->dev;
+
+	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
+		pr_info("multi-cast route %pI4, port %u, dev %s.\n",
+			&daddr->sin_addr.s_addr, ntohs(daddr->sin_port),
+			ndev->name);
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+
+	if (ndev->flags & IFF_LOOPBACK) {
+		ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr);
+		mtu = ndev->mtu;
+		pr_info("rt dev %s, loopback -> %s, mtu %u.\n",
+			dst->neighbour->dev->name, ndev->name, mtu);
+	}
+
+	cdev = cxgbi_device_find_by_netdev(ndev, &port);
+	if (!cdev) {
+		pr_info("dst %pI4, %s, NOT cxgbi device.\n",
+			&daddr->sin_addr.s_addr, ndev->name);
+		err = -ENETUNREACH;
+		goto rel_rt;
+	}
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"route to %pI4 :%u, ndev p#%d,%s, cdev 0x%p.\n",
+		&daddr->sin_addr.s_addr, ntohs(daddr->sin_port),
+			   port, ndev->name, cdev);
+
+	csk = cxgbi_sock_create(cdev);
+	if (!csk) {
+		err = -ENOMEM;
+		goto rel_rt;
+	}
+	csk->cdev = cdev;
+	csk->port_id = port;
+	csk->mtu = mtu;
+	csk->dst = dst;
+	csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr;
+	csk->daddr.sin_port = daddr->sin_port;
+	csk->saddr.sin_addr.s_addr = rt->rt_src;
+
+	return csk;
+
+rel_rt:
+	ip_rt_put(rt);
+	if (csk)
+		cxgbi_sock_closed(csk);
+err_out:
+	return ERR_PTR(err);
+}
+
+void cxgbi_sock_established(struct cxgbi_sock *csk, unsigned int snd_isn,
+			unsigned int opt)
+{
+	csk->write_seq = csk->snd_nxt = csk->snd_una = snd_isn;
+	dst_confirm(csk->dst);
+	smp_mb();
+	cxgbi_sock_set_state(csk, CTP_ESTABLISHED);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_established);
+
+static void cxgbi_inform_iscsi_conn_closing(struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"csk 0x%p, state %u, flags 0x%lx, conn 0x%p.\n",
+		csk, csk->state, csk->flags, csk->user_data);
+
+	if (csk->state != CTP_ESTABLISHED) {
+		read_lock_bh(&csk->callback_lock);
+		if (csk->user_data)
+			iscsi_conn_failure(csk->user_data,
+					ISCSI_ERR_CONN_FAILED);
+		read_unlock_bh(&csk->callback_lock);
+	}
+}
+
+void cxgbi_sock_closed(struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	cxgbi_sock_set_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED);
+	if (csk->state == CTP_ACTIVE_OPEN || csk->state == CTP_CLOSED)
+		return;
+	if (csk->saddr.sin_port)
+		sock_put_port(csk);
+	if (csk->dst)
+		dst_release(csk->dst);
+	csk->cdev->csk_release_offload_resources(csk);
+	cxgbi_sock_set_state(csk, CTP_CLOSED);
+	cxgbi_inform_iscsi_conn_closing(csk);
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_closed);
+
+static void need_active_close(struct cxgbi_sock *csk)
+{
+	int data_lost;
+	int close_req = 0;
+
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	spin_lock_bh(&csk->lock);
+	dst_confirm(csk->dst);
+	data_lost = skb_queue_len(&csk->receive_queue);
+	__skb_queue_purge(&csk->receive_queue);
+
+	if (csk->state == CTP_ACTIVE_OPEN)
+		cxgbi_sock_set_flag(csk, CTPF_ACTIVE_CLOSE_NEEDED);
+	else if (csk->state == CTP_ESTABLISHED) {
+		close_req = 1;
+		cxgbi_sock_set_state(csk, CTP_ACTIVE_CLOSE);
+	} else if (csk->state == CTP_PASSIVE_CLOSE) {
+		close_req = 1;
+		cxgbi_sock_set_state(csk, CTP_CLOSE_WAIT_2);
+	}
+
+	if (close_req) {
+		if (data_lost)
+			csk->cdev->csk_send_abort_req(csk);
+		else
+			csk->cdev->csk_send_close_req(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+}
+
+void cxgbi_sock_fail_act_open(struct cxgbi_sock *csk, int errno)
+{
+	pr_info("csk 0x%p,%u,%lx, %pI4:%u-%pI4:%u, err %d.\n",
+			csk, csk->state, csk->flags,
+			&csk->saddr.sin_addr.s_addr, csk->saddr.sin_port,
+			&csk->daddr.sin_addr.s_addr, csk->daddr.sin_port,
+			errno);
+
+	cxgbi_sock_set_state(csk, CTP_CONNECTING);
+	csk->err = errno;
+	cxgbi_sock_closed(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_fail_act_open);
+
+void cxgbi_sock_act_open_req_arp_failure(void *handle, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)skb->sk;
+
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	if (csk->state == CTP_ACTIVE_OPEN)
+		cxgbi_sock_fail_act_open(csk, -EHOSTUNREACH);
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+	__kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_act_open_req_arp_failure);
+
+void cxgbi_sock_rcv_abort_rpl(struct cxgbi_sock *csk)
+{
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+	if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
+		if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_RCVD))
+			cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_RCVD);
+		else {
+			cxgbi_sock_clear_flag(csk, CTPF_ABORT_RPL_RCVD);
+			cxgbi_sock_clear_flag(csk, CTPF_ABORT_RPL_PENDING);
+			if (cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD))
+				pr_err("csk 0x%p,%u,0x%lx,%u,ABT_RPL_RSS.\n",
+					csk, csk->state, csk->flags, csk->tid);
+			cxgbi_sock_closed(csk);
+		}
+	}
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_abort_rpl);
+
+void cxgbi_sock_rcv_peer_close(struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING))
+		goto done;
+
+	switch (csk->state) {
+	case CTP_ESTABLISHED:
+		cxgbi_sock_set_state(csk, CTP_PASSIVE_CLOSE);
+		break;
+	case CTP_ACTIVE_CLOSE:
+		cxgbi_sock_set_state(csk, CTP_CLOSE_WAIT_2);
+		break;
+	case CTP_CLOSE_WAIT_1:
+		cxgbi_sock_closed(csk);
+		break;
+	case CTP_ABORTING:
+		break;
+	default:
+		pr_err("csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+	}
+	cxgbi_inform_iscsi_conn_closing(csk);
+done:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_peer_close);
+
+void cxgbi_sock_rcv_close_conn_rpl(struct cxgbi_sock *csk, u32 snd_nxt)
+{
+	log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
+		csk, (csk)->state, (csk)->flags, (csk)->tid);
+	cxgbi_sock_get(csk);
+	spin_lock_bh(&csk->lock);
+
+	csk->snd_una = snd_nxt - 1;
+	if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING))
+		goto done;
+
+	switch (csk->state) {
+	case CTP_ACTIVE_CLOSE:
+		cxgbi_sock_set_state(csk, CTP_CLOSE_WAIT_1);
+		break;
+	case CTP_CLOSE_WAIT_1:
+	case CTP_CLOSE_WAIT_2:
+		cxgbi_sock_closed(csk);
+		break;
+	case CTP_ABORTING:
+		break;
+	default:
+		pr_err("csk 0x%p,%u,0x%lx,%u, bad state.\n",
+			csk, csk->state, csk->flags, csk->tid);
+	}
+done:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_close_conn_rpl);
+
+void cxgbi_sock_rcv_wr_ack(struct cxgbi_sock *csk, unsigned int credits,
+			   unsigned int snd_una, int seq_chk)
+{
+	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
+			"csk 0x%p,%u,0x%lx,%u, cr %u,%u+%u, snd_una %u,%d.\n",
+			csk, csk->state, csk->flags, csk->tid, credits,
+			csk->wr_cred, csk->wr_una_cred, snd_una, seq_chk);
+
+	spin_lock_bh(&csk->lock);
+
+	csk->wr_cred += credits;
+	if (csk->wr_una_cred > csk->wr_max_cred - csk->wr_cred)
+		csk->wr_una_cred = csk->wr_max_cred - csk->wr_cred;
+
+	while (credits) {
+		struct sk_buff *p = cxgbi_sock_peek_wr(csk);
+
+		if (unlikely(!p)) {
+			pr_err("csk 0x%p,%u,0x%lx,%u, cr %u,%u+%u, empty.\n",
+				csk, csk->state, csk->flags, csk->tid, credits,
+				csk->wr_cred, csk->wr_una_cred);
+			break;
+		}
+
+		if (unlikely(credits < p->csum)) {
+			pr_warn("csk 0x%p,%u,0x%lx,%u, cr %u,%u+%u, < %u.\n",
+				csk, csk->state, csk->flags, csk->tid,
+				credits, csk->wr_cred, csk->wr_una_cred,
+				p->csum);
+			p->csum -= credits;
+			break;
+		} else {
+			cxgbi_sock_dequeue_wr(csk);
+			credits -= p->csum;
+			kfree_skb(p);
+		}
+	}
+
+	cxgbi_sock_check_wr_invariants(csk);
+
+	if (seq_chk) {
+		if (unlikely(before(snd_una, csk->snd_una))) {
+			pr_warn("csk 0x%p,%u,0x%lx,%u, snd_una %u/%u.",
+				csk, csk->state, csk->flags, csk->tid, snd_una,
+				csk->snd_una);
+			goto done;
+		}
+
+		if (csk->snd_una != snd_una) {
+			csk->snd_una = snd_una;
+			dst_confirm(csk->dst);
+		}
+	}
+
+	if (skb_queue_len(&csk->write_queue)) {
+		if (csk->cdev->csk_push_tx_frames(csk, 0))
+			cxgbi_conn_tx_open(csk);
+	} else
+		cxgbi_conn_tx_open(csk);
+done:
+	spin_unlock_bh(&csk->lock);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_rcv_wr_ack);
+
+static unsigned int cxgbi_sock_find_best_mtu(struct cxgbi_sock *csk,
+					     unsigned short mtu)
+{
+	int i = 0;
+
+	while (i < csk->cdev->nmtus - 1 && csk->cdev->mtus[i + 1] <= mtu)
+		++i;
+
+	return i;
+}
+
+unsigned int cxgbi_sock_select_mss(struct cxgbi_sock *csk, unsigned int pmtu)
+{
+	unsigned int idx;
+	struct dst_entry *dst = csk->dst;
+
+	csk->advmss = dst_metric(dst, RTAX_ADVMSS);
+
+	if (csk->advmss > pmtu - 40)
+		csk->advmss = pmtu - 40;
+	if (csk->advmss < csk->cdev->mtus[0] - 40)
+		csk->advmss = csk->cdev->mtus[0] - 40;
+	idx = cxgbi_sock_find_best_mtu(csk, csk->advmss + 40);
+
+	return idx;
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_select_mss);
+
+void cxgbi_sock_skb_entail(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+	cxgbi_skcb_tcp_seq(skb) = csk->write_seq;
+	__skb_queue_tail(&csk->write_queue, skb);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_skb_entail);
+
+void cxgbi_sock_purge_wr_queue(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+
+	while ((skb = cxgbi_sock_dequeue_wr(csk)) != NULL)
+		kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_purge_wr_queue);
+
+void cxgbi_sock_check_wr_invariants(const struct cxgbi_sock *csk)
+{
+	int pending = cxgbi_sock_count_pending_wrs(csk);
+
+	if (unlikely(csk->wr_cred + pending != csk->wr_max_cred))
+		pr_err("csk 0x%p, tid %u, credit %u + %u != %u.\n",
+			csk, csk->tid, csk->wr_cred, pending, csk->wr_max_cred);
+}
+EXPORT_SYMBOL_GPL(cxgbi_sock_check_wr_invariants);
+
+static int cxgbi_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct sk_buff *next;
+	int err, copied = 0;
+
+	spin_lock_bh(&csk->lock);
+
+	if (csk->state != CTP_ESTABLISHED) {
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, EAGAIN.\n",
+			csk, csk->state, csk->flags, csk->tid);
+		err = -EAGAIN;
+		goto out_err;
+	}
+
+	if (csk->err) {
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, EPIPE %d.\n",
+			csk, csk->state, csk->flags, csk->tid, csk->err);
+		err = -EPIPE;
+		goto out_err;
+	}
+
+	if (csk->write_seq - csk->snd_una >= cdev->snd_win) {
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"csk 0x%p,%u,0x%lx,%u, FULL %u-%u >= %u.\n",
+			csk, csk->state, csk->flags, csk->tid, csk->write_seq,
+			csk->snd_una, cdev->snd_win);
+		err = -ENOBUFS;
+		goto out_err;
+	}
+
+	while (skb) {
+		int frags = skb_shinfo(skb)->nr_frags +
+				(skb->len != skb->data_len);
+
+		if (unlikely(skb_headroom(skb) < cdev->skb_tx_rsvd)) {
+			pr_err("csk 0x%p, skb head %u < %u.\n",
+				csk, skb_headroom(skb), cdev->skb_tx_rsvd);
+			err = -EINVAL;
+			goto out_err;
+		}
+
+		if (frags >= SKB_WR_LIST_SIZE) {
+			pr_err("csk 0x%p, frags %d, %u,%u >%u.\n",
+				csk, skb_shinfo(skb)->nr_frags, skb->len,
+				skb->data_len, (uint)(SKB_WR_LIST_SIZE));
+			err = -EINVAL;
+			goto out_err;
+		}
+
+		next = skb->next;
+		skb->next = NULL;
+		cxgbi_skcb_set_flag(skb, SKCBF_TX_NEED_HDR);
+		cxgbi_sock_skb_entail(csk, skb);
+		copied += skb->len;
+		csk->write_seq += skb->len +
+				cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+		skb = next;
+	}
+done:
+	if (likely(skb_queue_len(&csk->write_queue)))
+		cdev->csk_push_tx_frames(csk, 1);
+	spin_unlock_bh(&csk->lock);
+	return copied;
+
+out_err:
+	if (copied == 0 && err == -EPIPE)
+		copied = csk->err ? csk->err : -EPIPE;
+	else
+		copied = err;
+	goto done;
+}
+
+/*
+ * Direct Data Placement -
+ * Directly place the iSCSI Data-In or Data-Out PDU's payload into pre-posted
+ * final destination host-memory buffers based on the Initiator Task Tag (ITT)
+ * in Data-In or Target Task Tag (TTT) in Data-Out PDUs.
+ * The host memory address is programmed into h/w in the format of pagepod
+ * entries.
+ * The location of the pagepod entry is encoded into ddp tag which is used as
+ * the base for ITT/TTT.
+ */
+
+static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
+static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
+static unsigned char page_idx = DDP_PGIDX_MAX;
+
+static unsigned char sw_tag_idx_bits;
+static unsigned char sw_tag_age_bits;
+
+/*
+ * Direct-Data Placement page size adjustment
+ */
+static int ddp_adjust_page_table(void)
+{
+	int i;
+	unsigned int base_order, order;
+
+	if (PAGE_SIZE < (1UL << ddp_page_shift[0])) {
+		pr_info("PAGE_SIZE 0x%lx too small, min 0x%lx\n",
+			PAGE_SIZE, 1UL << ddp_page_shift[0]);
+		return -EINVAL;
+	}
+
+	base_order = get_order(1UL << ddp_page_shift[0]);
+	order = get_order(1UL << PAGE_SHIFT);
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++) {
+		/* first is the kernel page size, then just doubling */
+		ddp_page_order[i] = order - base_order + i;
+		ddp_page_shift[i] = PAGE_SHIFT + i;
+	}
+	return 0;
+}
+
+static int ddp_find_page_index(unsigned long pgsz)
+{
+	int i;
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++) {
+		if (pgsz == (1UL << ddp_page_shift[i]))
+			return i;
+	}
+	pr_info("ddp page size %lu not supported.\n", pgsz);
+	return DDP_PGIDX_MAX;
+}
+
+static void ddp_setup_host_page_size(void)
+{
+	if (page_idx == DDP_PGIDX_MAX) {
+		page_idx = ddp_find_page_index(PAGE_SIZE);
+
+		if (page_idx == DDP_PGIDX_MAX) {
+			pr_info("system PAGE %lu, update hw.\n", PAGE_SIZE);
+			if (ddp_adjust_page_table() < 0) {
+				pr_info("PAGE %lu, disable ddp.\n", PAGE_SIZE);
+				return;
+			}
+			page_idx = ddp_find_page_index(PAGE_SIZE);
+		}
+		pr_info("system PAGE %lu, ddp idx %u.\n", PAGE_SIZE, page_idx);
+	}
+}
+
+void cxgbi_ddp_page_size_factor(int *pgsz_factor)
+{
+	int i;
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++)
+		pgsz_factor[i] = ddp_page_order[i];
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_page_size_factor);
+
+/*
+ * DDP setup & teardown
+ */
+
+void cxgbi_ddp_ppod_set(struct cxgbi_pagepod *ppod,
+			struct cxgbi_pagepod_hdr *hdr,
+			struct cxgbi_gather_list *gl, unsigned int gidx)
+{
+	int i;
+
+	memcpy(ppod, hdr, sizeof(*hdr));
+	for (i = 0; i < (PPOD_PAGES_MAX + 1); i++, gidx++) {
+		ppod->addr[i] = gidx < gl->nelem ?
+				cpu_to_be64(gl->phys_addr[gidx]) : 0ULL;
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_ppod_set);
+
+void cxgbi_ddp_ppod_clear(struct cxgbi_pagepod *ppod)
+{
+	memset(ppod, 0, sizeof(*ppod));
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_ppod_clear);
+
+static inline int ddp_find_unused_entries(struct cxgbi_ddp_info *ddp,
+					unsigned int start, unsigned int max,
+					unsigned int count,
+					struct cxgbi_gather_list *gl)
+{
+	unsigned int i, j, k;
+
+	/*  not enough entries */
+	if ((max - start) < count) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"NOT enough entries %u+%u < %u.\n", start, count, max);
+		return -EBUSY;
+	}
+
+	max -= count;
+	spin_lock(&ddp->map_lock);
+	for (i = start; i < max;) {
+		for (j = 0, k = i; j < count; j++, k++) {
+			if (ddp->gl_map[k])
+				break;
+		}
+		if (j == count) {
+			for (j = 0, k = i; j < count; j++, k++)
+				ddp->gl_map[k] = gl;
+			spin_unlock(&ddp->map_lock);
+			return i;
+		}
+		i += j + 1;
+	}
+	spin_unlock(&ddp->map_lock);
+	log_debug(1 << CXGBI_DBG_DDP,
+		"NO suitable entries %u available.\n", count);
+	return -EBUSY;
+}
+
+static inline void ddp_unmark_entries(struct cxgbi_ddp_info *ddp,
+						int start, int count)
+{
+	spin_lock(&ddp->map_lock);
+	memset(&ddp->gl_map[start], 0,
+		count * sizeof(struct cxgbi_gather_list *));
+	spin_unlock(&ddp->map_lock);
+}
+
+static inline void ddp_gl_unmap(struct pci_dev *pdev,
+					struct cxgbi_gather_list *gl)
+{
+	int i;
+
+	for (i = 0; i < gl->nelem; i++)
+		dma_unmap_page(&pdev->dev, gl->phys_addr[i], PAGE_SIZE,
+				PCI_DMA_FROMDEVICE);
+}
+
+static inline int ddp_gl_map(struct pci_dev *pdev,
+				    struct cxgbi_gather_list *gl)
+{
+	int i;
+
+	for (i = 0; i < gl->nelem; i++) {
+		gl->phys_addr[i] = dma_map_page(&pdev->dev, gl->pages[i], 0,
+						PAGE_SIZE,
+						PCI_DMA_FROMDEVICE);
+		if (unlikely(dma_mapping_error(&pdev->dev, gl->phys_addr[i]))) {
+			log_debug(1 << CXGBI_DBG_DDP,
+				"page %d 0x%p, 0x%p dma mapping err.\n",
+				i, gl->pages[i], pdev);
+			goto unmap;
+		}
+	}
+	return i;
+unmap:
+	if (i) {
+		unsigned int nelem = gl->nelem;
+
+		gl->nelem = i;
+		ddp_gl_unmap(pdev, gl);
+		gl->nelem = nelem;
+	}
+	return -EINVAL;
+}
+
+static void ddp_release_gl(struct cxgbi_gather_list *gl,
+				  struct pci_dev *pdev)
+{
+	ddp_gl_unmap(pdev, gl);
+	kfree(gl);
+}
+
+static struct cxgbi_gather_list *ddp_make_gl(unsigned int xferlen,
+						    struct scatterlist *sgl,
+						    unsigned int sgcnt,
+						    struct pci_dev *pdev,
+						    gfp_t gfp)
+{
+	struct cxgbi_gather_list *gl;
+	struct scatterlist *sg = sgl;
+	struct page *sgpage = sg_page(sg);
+	unsigned int sglen = sg->length;
+	unsigned int sgoffset = sg->offset;
+	unsigned int npages = (xferlen + sgoffset + PAGE_SIZE - 1) >>
+				PAGE_SHIFT;
+	int i = 1, j = 0;
+
+	if (xferlen < DDP_THRESHOLD) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"xfer %u < threshold %u, no ddp.\n",
+			xferlen, DDP_THRESHOLD);
+		return NULL;
+	}
+
+	gl = kzalloc(sizeof(struct cxgbi_gather_list) +
+		     npages * (sizeof(dma_addr_t) +
+		     sizeof(struct page *)), gfp);
+	if (!gl) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"xfer %u, %u pages, OOM.\n", xferlen, npages);
+		return NULL;
+	}
+
+	 log_debug(1 << CXGBI_DBG_DDP,
+		"xfer %u, sgl %u, gl max %u.\n", xferlen, sgcnt, npages);
+
+	gl->pages = (struct page **)&gl->phys_addr[npages];
+	gl->nelem = npages;
+	gl->length = xferlen;
+	gl->offset = sgoffset;
+	gl->pages[0] = sgpage;
+
+	for (i = 1, sg = sg_next(sgl), j = 0; i < sgcnt;
+		i++, sg = sg_next(sg)) {
+		struct page *page = sg_page(sg);
+
+		if (sgpage == page && sg->offset == sgoffset + sglen)
+			sglen += sg->length;
+		else {
+			/*  make sure the sgl is fit for ddp:
+			 *  each has the same page size, and
+			 *  all of the middle pages are used completely
+			 */
+			if ((j && sgoffset) || ((i != sgcnt - 1) &&
+			    ((sglen + sgoffset) & ~PAGE_MASK))) {
+				log_debug(1 << CXGBI_DBG_DDP,
+					"page %d/%u, %u + %u.\n",
+					i, sgcnt, sgoffset, sglen);
+				goto error_out;
+			}
+
+			j++;
+			if (j == gl->nelem || sg->offset) {
+				log_debug(1 << CXGBI_DBG_DDP,
+					"page %d/%u, offset %u.\n",
+					j, gl->nelem, sg->offset);
+				goto error_out;
+			}
+			gl->pages[j] = page;
+			sglen = sg->length;
+			sgoffset = sg->offset;
+			sgpage = page;
+		}
+	}
+	gl->nelem = ++j;
+
+	if (ddp_gl_map(pdev, gl) < 0)
+		goto error_out;
+
+	return gl;
+
+error_out:
+	kfree(gl);
+	return NULL;
+}
+
+static void ddp_tag_release(struct cxgbi_hba *chba, u32 tag)
+{
+	struct cxgbi_device *cdev = chba->cdev;
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	u32 idx;
+
+	idx = (tag >> PPOD_IDX_SHIFT) & ddp->idx_mask;
+	if (idx < ddp->nppods) {
+		struct cxgbi_gather_list *gl = ddp->gl_map[idx];
+		unsigned int npods;
+
+		if (!gl || !gl->nelem) {
+			pr_warn("tag 0x%x, idx %u, gl 0x%p, %u.\n",
+				tag, idx, gl, gl ? gl->nelem : 0);
+			return;
+		}
+		npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+		log_debug(1 << CXGBI_DBG_DDP,
+			"tag 0x%x, release idx %u, npods %u.\n",
+			tag, idx, npods);
+		cdev->csk_ddp_clear(chba, tag, idx, npods);
+		ddp_unmark_entries(ddp, idx, npods);
+		ddp_release_gl(gl, ddp->pdev);
+	} else
+		pr_warn("tag 0x%x, idx %u > max %u.\n", tag, idx, ddp->nppods);
+}
+
+static int ddp_tag_reserve(struct cxgbi_sock *csk, unsigned int tid,
+			   u32 sw_tag, u32 *tagp, struct cxgbi_gather_list *gl,
+			   gfp_t gfp)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+	struct cxgbi_tag_format *tformat = &cdev->tag_format;
+	struct cxgbi_pagepod_hdr hdr;
+	unsigned int npods;
+	int idx = -1;
+	int err = -ENOMEM;
+	u32 tag;
+
+	npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+	if (ddp->idx_last == ddp->nppods)
+		idx = ddp_find_unused_entries(ddp, 0, ddp->nppods,
+							npods, gl);
+	else {
+		idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1,
+							ddp->nppods, npods,
+							gl);
+		if (idx < 0 && ddp->idx_last >= npods) {
+			idx = ddp_find_unused_entries(ddp, 0,
+				min(ddp->idx_last + npods, ddp->nppods),
+							npods, gl);
+		}
+	}
+	if (idx < 0) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"xferlen %u, gl %u, npods %u NO DDP.\n",
+			gl->length, gl->nelem, npods);
+		return idx;
+	}
+
+	if (cdev->csk_ddp_alloc_gl_skb) {
+		err = cdev->csk_ddp_alloc_gl_skb(ddp, idx, npods, gfp);
+		if (err < 0)
+			goto unmark_entries;
+	}
+
+	tag = cxgbi_ddp_tag_base(tformat, sw_tag);
+	tag |= idx << PPOD_IDX_SHIFT;
+
+	hdr.rsvd = 0;
+	hdr.vld_tid = htonl(PPOD_VALID_FLAG | PPOD_TID(tid));
+	hdr.pgsz_tag_clr = htonl(tag & ddp->rsvd_tag_mask);
+	hdr.max_offset = htonl(gl->length);
+	hdr.page_offset = htonl(gl->offset);
+
+	err = cdev->csk_ddp_set(csk, &hdr, idx, npods, gl);
+	if (err < 0) {
+		if (cdev->csk_ddp_free_gl_skb)
+			cdev->csk_ddp_free_gl_skb(ddp, idx, npods);
+		goto unmark_entries;
+	}
+
+	ddp->idx_last = idx;
+	log_debug(1 << CXGBI_DBG_DDP,
+		"xfer %u, gl %u,%u, tid 0x%x, tag 0x%x->0x%x(%u,%u).\n",
+		gl->length, gl->nelem, gl->offset, tid, sw_tag, tag, idx,
+		npods);
+	*tagp = tag;
+	return 0;
+
+unmark_entries:
+	ddp_unmark_entries(ddp, idx, npods);
+	return err;
+}
+
+int cxgbi_ddp_reserve(struct cxgbi_sock *csk, unsigned int *tagp,
+			unsigned int sw_tag, unsigned int xferlen,
+			struct scatterlist *sgl, unsigned int sgcnt, gfp_t gfp)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct cxgbi_tag_format *tformat = &cdev->tag_format;
+	struct cxgbi_gather_list *gl;
+	int err;
+
+	if (page_idx >= DDP_PGIDX_MAX || !cdev->ddp ||
+	    xferlen < DDP_THRESHOLD) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"pgidx %u, xfer %u, NO ddp.\n", page_idx, xferlen);
+		return -EINVAL;
+	}
+
+	if (!cxgbi_sw_tag_usable(tformat, sw_tag)) {
+		log_debug(1 << CXGBI_DBG_DDP,
+			"sw_tag 0x%x NOT usable.\n", sw_tag);
+		return -EINVAL;
+	}
+
+	gl = ddp_make_gl(xferlen, sgl, sgcnt, cdev->pdev, gfp);
+	if (!gl)
+		return -ENOMEM;
+
+	err = ddp_tag_reserve(csk, csk->tid, sw_tag, tagp, gl, gfp);
+	if (err < 0)
+		ddp_release_gl(gl, cdev->pdev);
+
+	return err;
+}
+
+static void ddp_destroy(struct kref *kref)
+{
+	struct cxgbi_ddp_info *ddp = container_of(kref,
+						struct cxgbi_ddp_info,
+						refcnt);
+	struct cxgbi_device *cdev = ddp->cdev;
+	int i = 0;
+
+	pr_info("kref 0, destroy ddp 0x%p, cdev 0x%p.\n", ddp, cdev);
+
+	while (i < ddp->nppods) {
+		struct cxgbi_gather_list *gl = ddp->gl_map[i];
+
+		if (gl) {
+			int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
+					>> PPOD_PAGES_SHIFT;
+			pr_info("cdev 0x%p, ddp %d + %d.\n", cdev, i, npods);
+			kfree(gl);
+			if (cdev->csk_ddp_free_gl_skb)
+				cdev->csk_ddp_free_gl_skb(ddp, i, npods);
+			i += npods;
+		} else
+			i++;
+	}
+	cxgbi_free_big_mem(ddp);
+}
+
+int cxgbi_ddp_cleanup(struct cxgbi_device *cdev)
+{
+	struct cxgbi_ddp_info *ddp = cdev->ddp;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"cdev 0x%p, release ddp 0x%p.\n", cdev, ddp);
+	cdev->ddp = NULL;
+	if (ddp)
+		return kref_put(&ddp->refcnt, ddp_destroy);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_cleanup);
+
+int cxgbi_ddp_init(struct cxgbi_device *cdev,
+		   unsigned int llimit, unsigned int ulimit,
+		   unsigned int max_txsz, unsigned int max_rxsz)
+{
+	struct cxgbi_ddp_info *ddp;
+	unsigned int ppmax, bits;
+
+	ppmax = (ulimit - llimit + 1) >> PPOD_SIZE_SHIFT;
+	bits = __ilog2_u32(ppmax) + 1;
+	if (bits > PPOD_IDX_MAX_SIZE)
+		bits = PPOD_IDX_MAX_SIZE;
+	ppmax = (1 << (bits - 1)) - 1;
+
+	ddp = cxgbi_alloc_big_mem(sizeof(struct cxgbi_ddp_info) +
+				ppmax * (sizeof(struct cxgbi_gather_list *) +
+					 sizeof(struct sk_buff *)),
+				GFP_KERNEL);
+	if (!ddp) {
+		pr_warn("cdev 0x%p, ddp ppmax %u OOM.\n", cdev, ppmax);
+		return -ENOMEM;
+	}
+	ddp->gl_map = (struct cxgbi_gather_list **)(ddp + 1);
+	ddp->gl_skb = (struct sk_buff **)(((char *)ddp->gl_map) +
+				ppmax * sizeof(struct cxgbi_gather_list *));
+	cdev->ddp = ddp;
+
+	spin_lock_init(&ddp->map_lock);
+	kref_init(&ddp->refcnt);
+
+	ddp->cdev = cdev;
+	ddp->pdev = cdev->pdev;
+	ddp->llimit = llimit;
+	ddp->ulimit = ulimit;
+	ddp->max_txsz = min_t(unsigned int, max_txsz, ULP2_MAX_PKT_SIZE);
+	ddp->max_rxsz = min_t(unsigned int, max_rxsz, ULP2_MAX_PKT_SIZE);
+	ddp->nppods = ppmax;
+	ddp->idx_last = ppmax;
+	ddp->idx_bits = bits;
+	ddp->idx_mask = (1 << bits) - 1;
+	ddp->rsvd_tag_mask = (1 << (bits + PPOD_IDX_SHIFT)) - 1;
+
+	cdev->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
+	cdev->tag_format.rsvd_bits = ddp->idx_bits;
+	cdev->tag_format.rsvd_shift = PPOD_IDX_SHIFT;
+	cdev->tag_format.rsvd_mask = (1 << cdev->tag_format.rsvd_bits) - 1;
+
+	pr_info("%s tag format, sw %u, rsvd %u,%u, mask 0x%x.\n",
+		cdev->ports[0]->name, cdev->tag_format.sw_bits,
+		cdev->tag_format.rsvd_bits, cdev->tag_format.rsvd_shift,
+		cdev->tag_format.rsvd_mask);
+
+	cdev->tx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+				ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
+	cdev->rx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+				ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"%s max payload size: %u/%u, %u/%u.\n",
+		cdev->ports[0]->name, cdev->tx_max_size, ddp->max_txsz,
+		cdev->rx_max_size, ddp->max_rxsz);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_ddp_init);
+
+/*
+ * APIs interacting with open-iscsi libraries
+ */
+
+static unsigned char padding[4];
+
+static void task_release_itt(struct iscsi_task *task, itt_t hdr_itt)
+{
+	struct scsi_cmnd *sc = task->sc;
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_hba *chba = cconn->chba;
+	struct cxgbi_tag_format *tformat = &chba->cdev->tag_format;
+	u32 tag = ntohl((__force u32)hdr_itt);
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		   "cdev 0x%p, release tag 0x%x.\n", chba->cdev, tag);
+	if (sc &&
+	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) &&
+	    cxgbi_is_ddp_tag(tformat, tag))
+		ddp_tag_release(chba, tag);
+}
+
+static int task_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
+{
+	struct scsi_cmnd *sc = task->sc;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_session *sess = conn->session;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_hba *chba = cconn->chba;
+	struct cxgbi_tag_format *tformat = &chba->cdev->tag_format;
+	u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt;
+	u32 tag = 0;
+	int err = -EINVAL;
+
+	if (sc &&
+	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE)) {
+		err = cxgbi_ddp_reserve(cconn->cep->csk, &tag, sw_tag,
+					scsi_in(sc)->length,
+					scsi_in(sc)->table.sgl,
+					scsi_in(sc)->table.nents,
+					GFP_ATOMIC);
+		if (err < 0)
+			log_debug(1 << CXGBI_DBG_DDP,
+				"csk 0x%p, R task 0x%p, %u,%u, no ddp.\n",
+				cconn->cep->csk, task, scsi_in(sc)->length,
+				scsi_in(sc)->table.nents);
+	}
+
+	if (err < 0)
+		tag = cxgbi_set_non_ddp_tag(tformat, sw_tag);
+	/*  the itt need to sent in big-endian order */
+	*hdr_itt = (__force itt_t)htonl(tag);
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"cdev 0x%p, task 0x%p, 0x%x(0x%x,0x%x)->0x%x/0x%x.\n",
+		chba->cdev, task, sw_tag, task->itt, sess->age, tag, *hdr_itt);
+	return 0;
+}
+
+void cxgbi_parse_pdu_itt(struct iscsi_conn *conn, itt_t itt, int *idx, int *age)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	u32 tag = ntohl((__force u32) itt);
+	u32 sw_bits;
+
+	sw_bits = cxgbi_tag_nonrsvd_bits(&cdev->tag_format, tag);
+	if (idx)
+		*idx = sw_bits & ((1 << cconn->task_idx_bits) - 1);
+	if (age)
+		*age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK;
+
+	log_debug(1 << CXGBI_DBG_DDP,
+		"cdev 0x%p, tag 0x%x/0x%x, -> 0x%x(0x%x,0x%x).\n",
+		cdev, tag, itt, sw_bits, idx ? *idx : 0xFFFFF,
+		age ? *age : 0xFF);
+}
+EXPORT_SYMBOL_GPL(cxgbi_parse_pdu_itt);
+
+void cxgbi_conn_tx_open(struct cxgbi_sock *csk)
+{
+	struct iscsi_conn *conn = csk->user_data;
+
+	if (conn) {
+		log_debug(1 << CXGBI_DBG_SOCK,
+			"csk 0x%p, cid %d.\n", csk, conn->id);
+		iscsi_conn_queue_work(conn);
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_tx_open);
+
+/*
+ * pdu receive, interact with libiscsi_tcp
+ */
+static inline int read_pdu_skb(struct iscsi_conn *conn,
+			       struct sk_buff *skb,
+			       unsigned int offset,
+			       int offloaded)
+{
+	int status = 0;
+	int bytes_read;
+
+	bytes_read = iscsi_tcp_recv_skb(conn, skb, offset, offloaded, &status);
+	switch (status) {
+	case ISCSI_TCP_CONN_ERR:
+		pr_info("skb 0x%p, off %u, %d, TCP_ERR.\n",
+			  skb, offset, offloaded);
+		return -EIO;
+	case ISCSI_TCP_SUSPENDED:
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"skb 0x%p, off %u, %d, TCP_SUSPEND, rc %d.\n",
+			skb, offset, offloaded, bytes_read);
+		/* no transfer - just have caller flush queue */
+		return bytes_read;
+	case ISCSI_TCP_SKB_DONE:
+		pr_info("skb 0x%p, off %u, %d, TCP_SKB_DONE.\n",
+			skb, offset, offloaded);
+		/*
+		 * pdus should always fit in the skb and we should get
+		 * segment done notifcation.
+		 */
+		iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu or skb.");
+		return -EFAULT;
+	case ISCSI_TCP_SEGMENT_DONE:
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"skb 0x%p, off %u, %d, TCP_SEG_DONE, rc %d.\n",
+			skb, offset, offloaded, bytes_read);
+		return bytes_read;
+	default:
+		pr_info("skb 0x%p, off %u, %d, invalid status %d.\n",
+			skb, offset, offloaded, status);
+		return -EINVAL;
+	}
+}
+
+static int skb_read_pdu_bhs(struct iscsi_conn *conn, struct sk_buff *skb)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"conn 0x%p, skb 0x%p, len %u, flag 0x%lx.\n",
+		conn, skb, skb->len, cxgbi_skcb_flags(skb));
+
+	if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
+		pr_info("conn 0x%p, skb 0x%p, not hdr.\n", conn, skb);
+		iscsi_conn_failure(conn, ISCSI_ERR_PROTO);
+		return -EIO;
+	}
+
+	if (conn->hdrdgst_en &&
+	    cxgbi_skcb_test_flag(skb, SKCBF_RX_HCRC_ERR)) {
+		pr_info("conn 0x%p, skb 0x%p, hcrc.\n", conn, skb);
+		iscsi_conn_failure(conn, ISCSI_ERR_HDR_DGST);
+		return -EIO;
+	}
+
+	return read_pdu_skb(conn, skb, 0, 0);
+}
+
+static int skb_read_pdu_data(struct iscsi_conn *conn, struct sk_buff *lskb,
+			     struct sk_buff *skb, unsigned int offset)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	bool offloaded = 0;
+	int opcode = tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK;
+
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"conn 0x%p, skb 0x%p, len %u, flag 0x%lx.\n",
+		conn, skb, skb->len, cxgbi_skcb_flags(skb));
+
+	if (conn->datadgst_en &&
+	    cxgbi_skcb_test_flag(lskb, SKCBF_RX_DCRC_ERR)) {
+		pr_info("conn 0x%p, skb 0x%p, dcrc 0x%lx.\n",
+			conn, lskb, cxgbi_skcb_flags(lskb));
+		iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
+		return -EIO;
+	}
+
+	if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
+		return 0;
+
+	/* coalesced, add header digest length */
+	if (lskb == skb && conn->hdrdgst_en)
+		offset += ISCSI_DIGEST_SIZE;
+
+	if (cxgbi_skcb_test_flag(lskb, SKCBF_RX_DATA_DDPD))
+		offloaded = 1;
+
+	if (opcode == ISCSI_OP_SCSI_DATA_IN)
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"skb 0x%p, op 0x%x, itt 0x%x, %u %s ddp'ed.\n",
+			skb, opcode, ntohl(tcp_conn->in.hdr->itt),
+			tcp_conn->in.datalen, offloaded ? "is" : "not");
+
+	return read_pdu_skb(conn, skb, offset, offloaded);
+}
+
+static void csk_return_rx_credits(struct cxgbi_sock *csk, int copied)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	int must_send;
+	u32 credits;
+
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p,%u,0x%lu,%u, seq %u, wup %u, thre %u, %u.\n",
+		csk, csk->state, csk->flags, csk->tid, csk->copied_seq,
+		csk->rcv_wup, cdev->rx_credit_thres,
+		cdev->rcv_win);
+
+	if (csk->state != CTP_ESTABLISHED)
+		return;
+
+	credits = csk->copied_seq - csk->rcv_wup;
+	if (unlikely(!credits))
+		return;
+	if (unlikely(cdev->rx_credit_thres == 0))
+		return;
+
+	must_send = credits + 16384 >= cdev->rcv_win;
+	if (must_send || credits >= cdev->rx_credit_thres)
+		csk->rcv_wup += cdev->csk_send_rx_credits(csk, credits);
+}
+
+void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
+{
+	struct cxgbi_device *cdev = csk->cdev;
+	struct iscsi_conn *conn = csk->user_data;
+	struct sk_buff *skb;
+	unsigned int read = 0;
+	int err = 0;
+
+	log_debug(1 << CXGBI_DBG_PDU_RX,
+		"csk 0x%p, conn 0x%p.\n", csk, conn);
+
+	if (unlikely(!conn || conn->suspend_rx)) {
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, conn 0x%p, id %d, suspend_rx %lu!\n",
+			csk, conn, conn ? conn->id : 0xFF,
+			conn ? conn->suspend_rx : 0xFF);
+		return;
+	}
+
+	while (!err) {
+		skb = skb_peek(&csk->receive_queue);
+		if (!skb ||
+		    !(cxgbi_skcb_test_flag(skb, SKCBF_RX_STATUS))) {
+			if (skb)
+				log_debug(1 << CXGBI_DBG_PDU_RX,
+					"skb 0x%p, NOT ready 0x%lx.\n",
+					skb, cxgbi_skcb_flags(skb));
+			break;
+		}
+		__skb_unlink(skb, &csk->receive_queue);
+
+		read += cxgbi_skcb_rx_pdulen(skb);
+		log_debug(1 << CXGBI_DBG_PDU_RX,
+			"csk 0x%p, skb 0x%p,%u,f 0x%lx, pdu len %u.\n",
+			csk, skb, skb->len, cxgbi_skcb_flags(skb),
+			cxgbi_skcb_rx_pdulen(skb));
+
+		if (cxgbi_skcb_test_flag(skb, SKCBF_RX_COALESCED)) {
+			err = skb_read_pdu_bhs(conn, skb);
+			if (err < 0) {
+				pr_err("coalesced bhs, csk 0x%p, skb 0x%p,%u, "
+					"f 0x%lx, plen %u.\n",
+					csk, skb, skb->len,
+					cxgbi_skcb_flags(skb),
+					cxgbi_skcb_rx_pdulen(skb));
+				goto skb_done;
+			}
+			err = skb_read_pdu_data(conn, skb, skb,
+						err + cdev->skb_rx_extra);
+			if (err < 0)
+				pr_err("coalesced data, csk 0x%p, skb 0x%p,%u, "
+					"f 0x%lx, plen %u.\n",
+					csk, skb, skb->len,
+					cxgbi_skcb_flags(skb),
+					cxgbi_skcb_rx_pdulen(skb));
+		} else {
+			err = skb_read_pdu_bhs(conn, skb);
+			if (err < 0) {
+				pr_err("bhs, csk 0x%p, skb 0x%p,%u, "
+					"f 0x%lx, plen %u.\n",
+					csk, skb, skb->len,
+					cxgbi_skcb_flags(skb),
+					cxgbi_skcb_rx_pdulen(skb));
+				goto skb_done;
+			}
+
+			if (cxgbi_skcb_test_flag(skb, SKCBF_RX_DATA)) {
+				struct sk_buff *dskb;
+
+				dskb = skb_peek(&csk->receive_queue);
+				if (!dskb) {
+					pr_err("csk 0x%p, skb 0x%p,%u, f 0x%lx,"
+						" plen %u, NO data.\n",
+						csk, skb, skb->len,
+						cxgbi_skcb_flags(skb),
+						cxgbi_skcb_rx_pdulen(skb));
+					err = -EIO;
+					goto skb_done;
+				}
+				__skb_unlink(dskb, &csk->receive_queue);
+
+				err = skb_read_pdu_data(conn, skb, dskb, 0);
+				if (err < 0)
+					pr_err("data, csk 0x%p, skb 0x%p,%u, "
+						"f 0x%lx, plen %u, dskb 0x%p,"
+						"%u.\n",
+						csk, skb, skb->len,
+						cxgbi_skcb_flags(skb),
+						cxgbi_skcb_rx_pdulen(skb),
+						dskb, dskb->len);
+				__kfree_skb(dskb);
+			} else
+				err = skb_read_pdu_data(conn, skb, skb, 0);
+		}
+skb_done:
+		__kfree_skb(skb);
+
+		if (err < 0)
+			break;
+	}
+
+	log_debug(1 << CXGBI_DBG_PDU_RX, "csk 0x%p, read %u.\n", csk, read);
+	if (read) {
+		csk->copied_seq += read;
+		csk_return_rx_credits(csk, read);
+		conn->rxdata_octets += read;
+	}
+
+	if (err < 0) {
+		pr_info("csk 0x%p, 0x%p, rx failed %d, read %u.\n",
+			csk, conn, err, read);
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_pdu_ready);
+
+static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
+				unsigned int offset, unsigned int *off,
+				struct scatterlist **sgp)
+{
+	int i;
+	struct scatterlist *sg;
+
+	for_each_sg(sgl, sg, sgcnt, i) {
+		if (offset < sg->length) {
+			*off = offset;
+			*sgp = sg;
+			return 0;
+		}
+		offset -= sg->length;
+	}
+	return -EFAULT;
+}
+
+static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
+				unsigned int dlen, skb_frag_t *frags,
+				int frag_max)
+{
+	unsigned int datalen = dlen;
+	unsigned int sglen = sg->length - sgoffset;
+	struct page *page = sg_page(sg);
+	int i;
+
+	i = 0;
+	do {
+		unsigned int copy;
+
+		if (!sglen) {
+			sg = sg_next(sg);
+			if (!sg) {
+				pr_warn("sg %d NULL, len %u/%u.\n",
+					i, datalen, dlen);
+				return -EINVAL;
+			}
+			sgoffset = 0;
+			sglen = sg->length;
+			page = sg_page(sg);
+
+		}
+		copy = min(datalen, sglen);
+		if (i && page == frags[i - 1].page &&
+		    sgoffset + sg->offset ==
+			frags[i - 1].page_offset + frags[i - 1].size) {
+			frags[i - 1].size += copy;
+		} else {
+			if (i >= frag_max) {
+				pr_warn("too many pages %u, dlen %u.\n",
+					frag_max, dlen);
+				return -EINVAL;
+			}
+
+			frags[i].page = page;
+			frags[i].page_offset = sg->offset + sgoffset;
+			frags[i].size = copy;
+			i++;
+		}
+		datalen -= copy;
+		sgoffset += copy;
+		sglen -= copy;
+	} while (datalen);
+
+	return i;
+}
+
+int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_tcp_task *tcp_task = task->dd_data;
+	struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+	struct scsi_cmnd *sc = task->sc;
+	int headroom = SKB_TX_ISCSI_PDU_HEADER_MAX;
+
+	tcp_task->dd_data = tdata;
+	task->hdr = NULL;
+
+	if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) &&
+	    (opcode == ISCSI_OP_SCSI_DATA_OUT ||
+	     (opcode == ISCSI_OP_SCSI_CMD &&
+	      (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
+		/* data could goes into skb head */
+		headroom += min_t(unsigned int,
+				SKB_MAX_HEAD(cdev->skb_tx_rsvd),
+				conn->max_xmit_dlength);
+
+	tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC);
+	if (!tdata->skb) {
+		pr_warn("alloc skb %u+%u, opcode 0x%x failed.\n",
+			cdev->skb_tx_rsvd, headroom, opcode);
+		return -ENOMEM;
+	}
+
+	skb_reserve(tdata->skb, cdev->skb_tx_rsvd);
+	task->hdr = (struct iscsi_hdr *)tdata->skb->data;
+	task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */
+
+	/* data_out uses scsi_cmd's itt */
+	if (opcode != ISCSI_OP_SCSI_DATA_OUT)
+		task_reserve_itt(task, &task->hdr->itt);
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+		"task 0x%p, op 0x%x, skb 0x%p,%u+%u/%u, itt 0x%x.\n",
+		task, opcode, tdata->skb, cdev->skb_tx_rsvd, headroom,
+		conn->max_xmit_dlength, ntohl(task->hdr->itt));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_alloc_pdu);
+
+static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
+{
+	u8 submode = 0;
+
+	if (hcrc)
+		submode |= 1;
+	if (dcrc)
+		submode |= 2;
+	cxgbi_skcb_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode;
+}
+
+int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
+			      unsigned int count)
+{
+	struct iscsi_conn *conn = task->conn;
+	struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+	struct sk_buff *skb = tdata->skb;
+	unsigned int datalen = count;
+	int i, padlen = iscsi_padding(count);
+	struct page *pg;
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+		"task 0x%p,0x%p, skb 0x%p, 0x%x,0x%x,0x%x, %u+%u.\n",
+		task, task->sc, skb, (*skb->data) & ISCSI_OPCODE_MASK,
+		ntohl(task->cmdsn), ntohl(task->hdr->itt), offset, count);
+
+	skb_put(skb, task->hdr_len);
+	tx_skb_setmode(skb, conn->hdrdgst_en, datalen ? conn->datadgst_en : 0);
+	if (!count)
+		return 0;
+
+	if (task->sc) {
+		struct scsi_data_buffer *sdb = scsi_out(task->sc);
+		struct scatterlist *sg = NULL;
+		int err;
+
+		tdata->offset = offset;
+		tdata->count = count;
+		err = sgl_seek_offset(
+					sdb->table.sgl, sdb->table.nents,
+					tdata->offset, &tdata->sgoffset, &sg);
+		if (err < 0) {
+			pr_warn("tpdu, sgl %u, bad offset %u/%u.\n",
+				sdb->table.nents, tdata->offset, sdb->length);
+			return err;
+		}
+		err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
+					tdata->frags, MAX_PDU_FRAGS);
+		if (err < 0) {
+			pr_warn("tpdu, sgl %u, bad offset %u + %u.\n",
+				sdb->table.nents, tdata->offset, tdata->count);
+			return err;
+		}
+		tdata->nr_frags = err;
+
+		if (tdata->nr_frags > MAX_SKB_FRAGS ||
+		    (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
+			char *dst = skb->data + task->hdr_len;
+			skb_frag_t *frag = tdata->frags;
+
+			/* data fits in the skb's headroom */
+			for (i = 0; i < tdata->nr_frags; i++, frag++) {
+				char *src = kmap_atomic(frag->page,
+							KM_SOFTIRQ0);
+
+				memcpy(dst, src+frag->page_offset, frag->size);
+				dst += frag->size;
+				kunmap_atomic(src, KM_SOFTIRQ0);
+			}
+			if (padlen) {
+				memset(dst, 0, padlen);
+				padlen = 0;
+			}
+			skb_put(skb, count + padlen);
+		} else {
+			/* data fit into frag_list */
+			for (i = 0; i < tdata->nr_frags; i++)
+				get_page(tdata->frags[i].page);
+
+			memcpy(skb_shinfo(skb)->frags, tdata->frags,
+				sizeof(skb_frag_t) * tdata->nr_frags);
+			skb_shinfo(skb)->nr_frags = tdata->nr_frags;
+			skb->len += count;
+			skb->data_len += count;
+			skb->truesize += count;
+		}
+
+	} else {
+		pg = virt_to_page(task->data);
+
+		get_page(pg);
+		skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
+					count);
+		skb->len += count;
+		skb->data_len += count;
+		skb->truesize += count;
+	}
+
+	if (padlen) {
+		i = skb_shinfo(skb)->nr_frags;
+		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+				virt_to_page(padding), offset_in_page(padding),
+				padlen);
+
+		skb->data_len += padlen;
+		skb->truesize += padlen;
+		skb->len += padlen;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_init_pdu);
+
+int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+	struct sk_buff *skb = tdata->skb;
+	unsigned int datalen;
+	int err;
+
+	if (!skb) {
+		log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+			"task 0x%p, skb NULL.\n", task);
+		return 0;
+	}
+
+	datalen = skb->data_len;
+	tdata->skb = NULL;
+	err = cxgbi_sock_send_pdus(cconn->cep->csk, skb);
+	if (err > 0) {
+		int pdulen = err;
+
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"task 0x%p,0x%p, skb 0x%p, len %u/%u, rv %d.\n",
+			task, task->sc, skb, skb->len, skb->data_len, err);
+
+		if (task->conn->hdrdgst_en)
+			pdulen += ISCSI_DIGEST_SIZE;
+
+		if (datalen && task->conn->datadgst_en)
+			pdulen += ISCSI_DIGEST_SIZE;
+
+		task->conn->txdata_octets += pdulen;
+		return 0;
+	}
+
+	if (err == -EAGAIN || err == -ENOBUFS) {
+		log_debug(1 << CXGBI_DBG_PDU_TX,
+			"task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n",
+			task, skb, skb->len, skb->data_len, err);
+		/* reset skb to send when we are called again */
+		tdata->skb = skb;
+		return err;
+	}
+
+	kfree_skb(skb);
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+		"itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+		task->itt, skb, skb->len, skb->data_len, err);
+	iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
+	iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+	return err;
+}
+EXPORT_SYMBOL_GPL(cxgbi_conn_xmit_pdu);
+
+void cxgbi_cleanup_task(struct iscsi_task *task)
+{
+	struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"task 0x%p, skb 0x%p, itt 0x%x.\n",
+		task, tdata->skb, task->hdr_itt);
+
+	/*  never reached the xmit task callout */
+	if (tdata->skb)
+		__kfree_skb(tdata->skb);
+	memset(tdata, 0, sizeof(*tdata));
+
+	task_release_itt(task, task->hdr_itt);
+	iscsi_tcp_cleanup_task(task);
+}
+EXPORT_SYMBOL_GPL(cxgbi_cleanup_task);
+
+void cxgbi_get_conn_stats(struct iscsi_cls_conn *cls_conn,
+				struct iscsi_stats *stats)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+
+	stats->txdata_octets = conn->txdata_octets;
+	stats->rxdata_octets = conn->rxdata_octets;
+	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
+	stats->dataout_pdus = conn->dataout_pdus_cnt;
+	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
+	stats->datain_pdus = conn->datain_pdus_cnt;
+	stats->r2t_pdus = conn->r2t_pdus_cnt;
+	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+	stats->digest_err = 0;
+	stats->timeout_err = 0;
+	stats->custom_length = 1;
+	strcpy(stats->custom[0].desc, "eh_abort_cnt");
+	stats->custom[0].value = conn->eh_abort_cnt;
+}
+EXPORT_SYMBOL_GPL(cxgbi_get_conn_stats);
+
+static int cxgbi_conn_max_xmit_dlength(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	unsigned int headroom = SKB_MAX_HEAD(cdev->skb_tx_rsvd);
+	unsigned int max_def = 512 * MAX_SKB_FRAGS;
+	unsigned int max = max(max_def, headroom);
+
+	max = min(cconn->chba->cdev->tx_max_size, max);
+	if (conn->max_xmit_dlength)
+		conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
+	else
+		conn->max_xmit_dlength = max;
+	cxgbi_align_pdu_size(conn->max_xmit_dlength);
+
+	return 0;
+}
+
+static int cxgbi_conn_max_recv_dlength(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	unsigned int max = cconn->chba->cdev->rx_max_size;
+
+	cxgbi_align_pdu_size(max);
+
+	if (conn->max_recv_dlength) {
+		if (conn->max_recv_dlength > max) {
+			pr_err("MaxRecvDataSegmentLength %u > %u.\n",
+				conn->max_recv_dlength, max);
+			return -EINVAL;
+		}
+		conn->max_recv_dlength = min(conn->max_recv_dlength, max);
+		cxgbi_align_pdu_size(conn->max_recv_dlength);
+	} else
+		conn->max_recv_dlength = max;
+
+	return 0;
+}
+
+int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
+			enum iscsi_param param, char *buf, int buflen)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_session *session = conn->session;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_sock *csk = cconn->cep->csk;
+	int value, err = 0;
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"cls_conn 0x%p, param %d, buf(%d) %s.\n",
+		cls_conn, param, buflen, buf);
+
+	switch (param) {
+	case ISCSI_PARAM_HDRDGST_EN:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && conn->hdrdgst_en)
+			err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
+							conn->hdrdgst_en,
+							conn->datadgst_en, 0);
+		break;
+	case ISCSI_PARAM_DATADGST_EN:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && conn->datadgst_en)
+			err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
+							conn->hdrdgst_en,
+							conn->datadgst_en, 0);
+		break;
+	case ISCSI_PARAM_MAX_R2T:
+		sscanf(buf, "%d", &value);
+		if (value <= 0 || !is_power_of_2(value))
+			return -EINVAL;
+		if (session->max_r2t == value)
+			break;
+		iscsi_tcp_r2tpool_free(session);
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && iscsi_tcp_r2tpool_alloc(session))
+			return -ENOMEM;
+	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err)
+			err = cxgbi_conn_max_recv_dlength(conn);
+		break;
+	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err)
+			err = cxgbi_conn_max_xmit_dlength(conn);
+		break;
+	default:
+		return iscsi_set_param(cls_conn, param, buf, buflen);
+	}
+	return err;
+}
+EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
+
+int cxgbi_get_conn_param(struct iscsi_cls_conn *cls_conn,
+			enum iscsi_param param, char *buf)
+{
+	struct iscsi_conn *iconn = cls_conn->dd_data;
+	int len;
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"cls_conn 0x%p, param %d.\n", cls_conn, param);
+
+	switch (param) {
+	case ISCSI_PARAM_CONN_PORT:
+		spin_lock_bh(&iconn->session->lock);
+		len = sprintf(buf, "%hu\n", iconn->portal_port);
+		spin_unlock_bh(&iconn->session->lock);
+		break;
+	case ISCSI_PARAM_CONN_ADDRESS:
+		spin_lock_bh(&iconn->session->lock);
+		len = sprintf(buf, "%s\n", iconn->portal_address);
+		spin_unlock_bh(&iconn->session->lock);
+		break;
+	default:
+		return iscsi_conn_get_param(cls_conn, param, buf);
+	}
+	return len;
+}
+EXPORT_SYMBOL_GPL(cxgbi_get_conn_param);
+
+struct iscsi_cls_conn *
+cxgbi_create_conn(struct iscsi_cls_session *cls_session, u32 cid)
+{
+	struct iscsi_cls_conn *cls_conn;
+	struct iscsi_conn *conn;
+	struct iscsi_tcp_conn *tcp_conn;
+	struct cxgbi_conn *cconn;
+
+	cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid);
+	if (!cls_conn)
+		return NULL;
+
+	conn = cls_conn->dd_data;
+	tcp_conn = conn->dd_data;
+	cconn = tcp_conn->dd_data;
+	cconn->iconn = conn;
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"cid %u(0x%x), cls 0x%p,0x%p, conn 0x%p,0x%p,0x%p.\n",
+		cid, cid, cls_session, cls_conn, conn, tcp_conn, cconn);
+
+	return cls_conn;
+}
+EXPORT_SYMBOL_GPL(cxgbi_create_conn);
+
+int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
+				struct iscsi_cls_conn *cls_conn,
+				u64 transport_eph, int is_leading)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct iscsi_endpoint *ep;
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_sock *csk;
+	int err;
+
+	ep = iscsi_lookup_endpoint(transport_eph);
+	if (!ep)
+		return -EINVAL;
+
+	/*  setup ddp pagesize */
+	cep = ep->dd_data;
+	csk = cep->csk;
+	err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid, page_idx, 0);
+	if (err < 0)
+		return err;
+
+	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+	if (err)
+		return -EINVAL;
+
+	/*  calculate the tag idx bits needed for this conn based on cmds_max */
+	cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
+
+	write_lock_bh(&csk->callback_lock);
+	csk->user_data = conn;
+	cconn->chba = cep->chba;
+	cconn->cep = cep;
+	cep->cconn = cconn;
+	write_unlock_bh(&csk->callback_lock);
+
+	cxgbi_conn_max_xmit_dlength(conn);
+	cxgbi_conn_max_recv_dlength(conn);
+
+	spin_lock_bh(&conn->session->lock);
+	sprintf(conn->portal_address, "%pI4", &csk->daddr.sin_addr.s_addr);
+	conn->portal_port = ntohs(csk->daddr.sin_port);
+	spin_unlock_bh(&conn->session->lock);
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"cls 0x%p,0x%p, ep 0x%p, cconn 0x%p, csk 0x%p.\n",
+		cls_session, cls_conn, ep, cconn, csk);
+	/*  init recv engine */
+	iscsi_tcp_hdr_recv_prep(tcp_conn);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_bind_conn);
+
+struct iscsi_cls_session *cxgbi_create_session(struct iscsi_endpoint *ep,
+						u16 cmds_max, u16 qdepth,
+						u32 initial_cmdsn)
+{
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_hba *chba;
+	struct Scsi_Host *shost;
+	struct iscsi_cls_session *cls_session;
+	struct iscsi_session *session;
+
+	if (!ep) {
+		pr_err("missing endpoint.\n");
+		return NULL;
+	}
+
+	cep = ep->dd_data;
+	chba = cep->chba;
+	shost = chba->shost;
+
+	BUG_ON(chba != iscsi_host_priv(shost));
+
+	cls_session = iscsi_session_setup(chba->cdev->itp, shost,
+					cmds_max, 0,
+					sizeof(struct iscsi_tcp_task) +
+					sizeof(struct cxgbi_task_data),
+					initial_cmdsn, ISCSI_MAX_TARGET);
+	if (!cls_session)
+		return NULL;
+
+	session = cls_session->dd_data;
+	if (iscsi_tcp_r2tpool_alloc(session))
+		goto remove_session;
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"ep 0x%p, cls sess 0x%p.\n", ep, cls_session);
+	return cls_session;
+
+remove_session:
+	iscsi_session_teardown(cls_session);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(cxgbi_create_session);
+
+void cxgbi_destroy_session(struct iscsi_cls_session *cls_session)
+{
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"cls sess 0x%p.\n", cls_session);
+
+	iscsi_tcp_r2tpool_free(cls_session->dd_data);
+	iscsi_session_teardown(cls_session);
+}
+EXPORT_SYMBOL_GPL(cxgbi_destroy_session);
+
+int cxgbi_set_host_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+			char *buf, int buflen)
+{
+	struct cxgbi_hba *chba = iscsi_host_priv(shost);
+
+	if (!chba->ndev) {
+		shost_printk(KERN_ERR, shost, "Could not get host param. "
+				"netdev for host not set.\n");
+		return -ENODEV;
+	}
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"shost 0x%p, hba 0x%p,%s, param %d, buf(%d) %s.\n",
+		shost, chba, chba->ndev->name, param, buflen, buf);
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_IPADDRESS:
+	{
+		__be32 addr = in_aton(buf);
+		log_debug(1 << CXGBI_DBG_ISCSI,
+			"hba %s, req. ipv4 %pI4.\n", chba->ndev->name, &addr);
+		cxgbi_set_iscsi_ipv4(chba, addr);
+		return 0;
+	}
+	case ISCSI_HOST_PARAM_HWADDRESS:
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		return 0;
+	default:
+		return iscsi_host_set_param(shost, param, buf, buflen);
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_set_host_param);
+
+int cxgbi_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param,
+			char *buf)
+{
+	struct cxgbi_hba *chba = iscsi_host_priv(shost);
+	int len = 0;
+
+	if (!chba->ndev) {
+		shost_printk(KERN_ERR, shost, "Could not get host param. "
+				"netdev for host not set.\n");
+		return -ENODEV;
+	}
+
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"shost 0x%p, hba 0x%p,%s, param %d.\n",
+		shost, chba, chba->ndev->name, param);
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_HWADDRESS:
+		len = sysfs_format_mac(buf, chba->ndev->dev_addr, 6);
+		break;
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		len = sprintf(buf, "%s\n", chba->ndev->name);
+		break;
+	case ISCSI_HOST_PARAM_IPADDRESS:
+	{
+		__be32 addr;
+
+		addr = cxgbi_get_iscsi_ipv4(chba);
+		len = sprintf(buf, "%pI4", &addr);
+		log_debug(1 << CXGBI_DBG_ISCSI,
+			"hba %s, ipv4 %pI4.\n", chba->ndev->name, &addr);
+		break;
+	}
+	default:
+		return iscsi_host_get_param(shost, param, buf);
+	}
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(cxgbi_get_host_param);
+
+struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *shost,
+					struct sockaddr *dst_addr,
+					int non_blocking)
+{
+	struct iscsi_endpoint *ep;
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_hba *hba = NULL;
+	struct cxgbi_sock *csk;
+	int err = -EINVAL;
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_SOCK,
+		"shost 0x%p, non_blocking %d, dst_addr 0x%p.\n",
+		shost, non_blocking, dst_addr);
+
+	if (shost) {
+		hba = iscsi_host_priv(shost);
+		if (!hba) {
+			pr_info("shost 0x%p, priv NULL.\n", shost);
+			goto err_out;
+		}
+	}
+
+	csk = cxgbi_check_route(dst_addr);
+	if (IS_ERR(csk))
+		return (struct iscsi_endpoint *)csk;
+	cxgbi_sock_get(csk);
+
+	if (!hba)
+		hba = csk->cdev->hbas[csk->port_id];
+	else if (hba != csk->cdev->hbas[csk->port_id]) {
+		pr_info("Could not connect through requested host %u"
+			"hba 0x%p != 0x%p (%u).\n",
+			shost->host_no, hba,
+			csk->cdev->hbas[csk->port_id], csk->port_id);
+		err = -ENOSPC;
+		goto release_conn;
+	}
+
+	err = sock_get_port(csk);
+	if (err)
+		goto release_conn;
+
+	cxgbi_sock_set_state(csk, CTP_CONNECTING);
+	err = csk->cdev->csk_init_act_open(csk);
+	if (err)
+		goto release_conn;
+
+	if (cxgbi_sock_is_closing(csk)) {
+		err = -ENOSPC;
+		pr_info("csk 0x%p is closing.\n", csk);
+		goto release_conn;
+	}
+
+	ep = iscsi_create_endpoint(sizeof(*cep));
+	if (!ep) {
+		err = -ENOMEM;
+		pr_info("iscsi alloc ep, OOM.\n");
+		goto release_conn;
+	}
+
+	cep = ep->dd_data;
+	cep->csk = csk;
+	cep->chba = hba;
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_SOCK,
+		"ep 0x%p, cep 0x%p, csk 0x%p, hba 0x%p,%s.\n",
+		ep, cep, csk, hba, hba->ndev->name);
+	return ep;
+
+release_conn:
+	cxgbi_sock_put(csk);
+	cxgbi_sock_closed(csk);
+err_out:
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(cxgbi_ep_connect);
+
+int cxgbi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+{
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_sock *csk = cep->csk;
+
+	if (!cxgbi_sock_is_established(csk))
+		return 0;
+	return 1;
+}
+EXPORT_SYMBOL_GPL(cxgbi_ep_poll);
+
+void cxgbi_ep_disconnect(struct iscsi_endpoint *ep)
+{
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_conn *cconn = cep->cconn;
+	struct cxgbi_sock *csk = cep->csk;
+
+	log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_SOCK,
+		"ep 0x%p, cep 0x%p, cconn 0x%p, csk 0x%p,%u,0x%lx.\n",
+		ep, cep, cconn, csk, csk->state, csk->flags);
+
+	if (cconn && cconn->iconn) {
+		iscsi_suspend_tx(cconn->iconn);
+		write_lock_bh(&csk->callback_lock);
+		cep->csk->user_data = NULL;
+		cconn->cep = NULL;
+		write_unlock_bh(&csk->callback_lock);
+	}
+	iscsi_destroy_endpoint(ep);
+
+	if (likely(csk->state >= CTP_ESTABLISHED))
+		need_active_close(csk);
+	else
+		cxgbi_sock_closed(csk);
+
+	cxgbi_sock_put(csk);
+}
+EXPORT_SYMBOL_GPL(cxgbi_ep_disconnect);
+
+int cxgbi_iscsi_init(struct iscsi_transport *itp,
+			struct scsi_transport_template **stt)
+{
+	*stt = iscsi_register_transport(itp);
+	if (*stt == NULL) {
+		pr_err("unable to register %s transport 0x%p.\n",
+			itp->name, itp);
+		return -ENODEV;
+	}
+	log_debug(1 << CXGBI_DBG_ISCSI,
+		"%s, registered iscsi transport 0x%p.\n",
+		itp->name, stt);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cxgbi_iscsi_init);
+
+void cxgbi_iscsi_cleanup(struct iscsi_transport *itp,
+			struct scsi_transport_template **stt)
+{
+	if (*stt) {
+		log_debug(1 << CXGBI_DBG_ISCSI,
+			"de-register transport 0x%p, %s, stt 0x%p.\n",
+			itp, itp->name, *stt);
+		*stt = NULL;
+		iscsi_unregister_transport(itp);
+	}
+}
+EXPORT_SYMBOL_GPL(cxgbi_iscsi_cleanup);
+
+static int __init libcxgbi_init_module(void)
+{
+	sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
+	sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1;
+
+	pr_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n",
+		ISCSI_ITT_MASK, sw_tag_idx_bits,
+		ISCSI_AGE_MASK, sw_tag_age_bits);
+
+	ddp_setup_host_page_size();
+	return 0;
+}
+
+static void __exit libcxgbi_exit_module(void)
+{
+	cxgbi_device_unregister_all(0xFF);
+	return;
+}
+
+module_init(libcxgbi_init_module);
+module_exit(libcxgbi_exit_module);
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
new file mode 100644
index 0000000..c57d59d
--- /dev/null
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -0,0 +1,745 @@
+/*
+ * libcxgbi.h: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, 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.
+ *
+ * Written by: Karen Xie (kxie@chelsio.com)
+ * Written by: Rakesh Ranjan (rranjan@chelsio.com)
+ */
+
+#ifndef	__LIBCXGBI_H__
+#define	__LIBCXGBI_H__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <scsi/scsi_device.h>
+#include <scsi/libiscsi_tcp.h>
+
+enum cxgbi_dbg_flag {
+	CXGBI_DBG_ISCSI,
+	CXGBI_DBG_DDP,
+	CXGBI_DBG_TOE,
+	CXGBI_DBG_SOCK,
+
+	CXGBI_DBG_PDU_TX,
+	CXGBI_DBG_PDU_RX,
+	CXGBI_DBG_DEV,
+};
+
+#define log_debug(level, fmt, ...)	\
+	do {	\
+		if (dbg_level & (level)) \
+			pr_info(fmt, ##__VA_ARGS__); \
+	} while (0)
+
+/* max. connections per adapter */
+#define CXGBI_MAX_CONN		16384
+
+/* always allocate rooms for AHS */
+#define SKB_TX_ISCSI_PDU_HEADER_MAX	\
+	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
+
+#define	ISCSI_PDU_NONPAYLOAD_LEN	312 /* bhs(48) + ahs(256) + digest(8)*/
+
+/*
+ * align pdu size to multiple of 512 for better performance
+ */
+#define cxgbi_align_pdu_size(n) do { n = (n) & (~511); } while (0)
+
+#define ULP2_MODE_ISCSI		2
+
+#define ULP2_MAX_PKT_SIZE	16224
+#define ULP2_MAX_PDU_PAYLOAD	\
+	(ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
+
+/*
+ * For iscsi connections HW may inserts digest bytes into the pdu. Those digest
+ * bytes are not sent by the host but are part of the TCP payload and therefore
+ * consume TCP sequence space.
+ */
+static const unsigned int ulp2_extra_len[] = { 0, 4, 4, 8 };
+static inline unsigned int cxgbi_ulp_extra_len(int submode)
+{
+	return ulp2_extra_len[submode & 3];
+}
+
+/*
+ * struct pagepod_hdr, pagepod - pagepod format
+ */
+
+#define CPL_RX_DDP_STATUS_DDP_SHIFT	16 /* ddp'able */
+#define CPL_RX_DDP_STATUS_PAD_SHIFT	19 /* pad error */
+#define CPL_RX_DDP_STATUS_HCRC_SHIFT	20 /* hcrc error */
+#define CPL_RX_DDP_STATUS_DCRC_SHIFT	21 /* dcrc error */
+
+struct cxgbi_pagepod_hdr {
+	u32 vld_tid;
+	u32 pgsz_tag_clr;
+	u32 max_offset;
+	u32 page_offset;
+	u64 rsvd;
+};
+
+#define PPOD_PAGES_MAX			4
+struct cxgbi_pagepod {
+	struct cxgbi_pagepod_hdr hdr;
+	u64 addr[PPOD_PAGES_MAX + 1];
+};
+
+struct cxgbi_tag_format {
+	unsigned char sw_bits;
+	unsigned char rsvd_bits;
+	unsigned char rsvd_shift;
+	unsigned char filler[1];
+	u32 rsvd_mask;
+};
+
+struct cxgbi_gather_list {
+	unsigned int tag;
+	unsigned int length;
+	unsigned int offset;
+	unsigned int nelem;
+	struct page **pages;
+	dma_addr_t phys_addr[0];
+};
+
+struct cxgbi_ddp_info {
+	struct kref refcnt;
+	struct cxgbi_device *cdev;
+	struct pci_dev *pdev;
+	unsigned int max_txsz;
+	unsigned int max_rxsz;
+	unsigned int llimit;
+	unsigned int ulimit;
+	unsigned int nppods;
+	unsigned int idx_last;
+	unsigned char idx_bits;
+	unsigned char filler[3];
+	unsigned int idx_mask;
+	unsigned int rsvd_tag_mask;
+	spinlock_t map_lock;
+	struct cxgbi_gather_list **gl_map;
+	struct sk_buff **gl_skb;
+};
+
+#define DDP_PGIDX_MAX		4
+#define DDP_THRESHOLD		2048
+
+#define PPOD_PAGES_SHIFT	2       /*  4 pages per pod */
+
+#define PPOD_SIZE               sizeof(struct cxgbi_pagepod)  /*  64 */
+#define PPOD_SIZE_SHIFT         6
+
+#define ULPMEM_DSGL_MAX_NPPODS	16	/*  1024/PPOD_SIZE */
+#define ULPMEM_IDATA_MAX_NPPODS	4	/*  256/PPOD_SIZE */
+#define PCIE_MEMWIN_MAX_NPPODS	16	/*  1024/PPOD_SIZE */
+
+#define PPOD_COLOR_SHIFT	0
+#define PPOD_COLOR(x)		((x) << PPOD_COLOR_SHIFT)
+
+#define PPOD_IDX_SHIFT          6
+#define PPOD_IDX_MAX_SIZE       24
+
+#define PPOD_TID_SHIFT		0
+#define PPOD_TID(x)		((x) << PPOD_TID_SHIFT)
+
+#define PPOD_TAG_SHIFT		6
+#define PPOD_TAG(x)		((x) << PPOD_TAG_SHIFT)
+
+#define PPOD_VALID_SHIFT	24
+#define PPOD_VALID(x)		((x) << PPOD_VALID_SHIFT)
+#define PPOD_VALID_FLAG		PPOD_VALID(1U)
+
+/*
+ * sge_opaque_hdr -
+ * Opaque version of structure the SGE stores at skb->head of TX_DATA packets
+ * and for which we must reserve space.
+ */
+struct sge_opaque_hdr {
+	void *dev;
+	dma_addr_t addr[MAX_SKB_FRAGS + 1];
+};
+
+struct cxgbi_sock {
+	struct cxgbi_device *cdev;
+
+	int tid;
+	int atid;
+	unsigned long flags;
+	unsigned int mtu;
+	unsigned short rss_qid;
+	unsigned short txq_idx;
+	unsigned short advmss;
+	unsigned int tx_chan;
+	unsigned int rx_chan;
+	unsigned int mss_idx;
+	unsigned int smac_idx;
+	unsigned char port_id;
+	int wr_max_cred;
+	int wr_cred;
+	int wr_una_cred;
+	unsigned char hcrc_len;
+	unsigned char dcrc_len;
+
+	void *l2t;
+	struct sk_buff *wr_pending_head;
+	struct sk_buff *wr_pending_tail;
+	struct sk_buff *cpl_close;
+	struct sk_buff *cpl_abort_req;
+	struct sk_buff *cpl_abort_rpl;
+	struct sk_buff *skb_ulp_lhdr;
+	spinlock_t lock;
+	struct kref refcnt;
+	unsigned int state;
+	struct sockaddr_in saddr;
+	struct sockaddr_in daddr;
+	struct dst_entry *dst;
+	struct sk_buff_head receive_queue;
+	struct sk_buff_head write_queue;
+	struct timer_list retry_timer;
+	int err;
+	rwlock_t callback_lock;
+	void *user_data;
+
+	u32 rcv_nxt;
+	u32 copied_seq;
+	u32 rcv_wup;
+	u32 snd_nxt;
+	u32 snd_una;
+	u32 write_seq;
+};
+
+/*
+ * connection states
+ */
+enum cxgbi_sock_states{
+	CTP_CLOSED,
+	CTP_CONNECTING,
+	CTP_ACTIVE_OPEN,
+	CTP_ESTABLISHED,
+	CTP_ACTIVE_CLOSE,
+	CTP_PASSIVE_CLOSE,
+	CTP_CLOSE_WAIT_1,
+	CTP_CLOSE_WAIT_2,
+	CTP_ABORTING,
+};
+
+/*
+ * Connection flags -- many to track some close related events.
+ */
+enum cxgbi_sock_flags {
+	CTPF_ABORT_RPL_RCVD,	/*received one ABORT_RPL_RSS message */
+	CTPF_ABORT_REQ_RCVD,	/*received one ABORT_REQ_RSS message */
+	CTPF_ABORT_RPL_PENDING,	/* expecting an abort reply */
+	CTPF_TX_DATA_SENT,	/* already sent a TX_DATA WR */
+	CTPF_ACTIVE_CLOSE_NEEDED,/* need to be closed */
+	CTPF_HAS_ATID,		/* reserved atid */
+	CTPF_HAS_TID,		/* reserved hw tid */
+	CTPF_OFFLOAD_DOWN,	/* offload function off */
+};
+
+struct cxgbi_skb_rx_cb {
+	__u32 ddigest;
+	__u32 pdulen;
+};
+
+struct cxgbi_skb_tx_cb {
+	void *l2t;
+	struct sk_buff *wr_next;
+};
+
+enum cxgbi_skcb_flags {
+	SKCBF_TX_NEED_HDR,	/* packet needs a header */
+	SKCBF_RX_COALESCED,	/* received whole pdu */
+	SKCBF_RX_HDR,		/* recieved pdu header */
+	SKCBF_RX_DATA,		/* recieved pdu payload */
+	SKCBF_RX_STATUS,	/* recieved ddp status */
+	SKCBF_RX_DATA_DDPD,	/* pdu payload ddp'd */
+	SKCBF_RX_HCRC_ERR,	/* header digest error */
+	SKCBF_RX_DCRC_ERR,	/* data digest error */
+	SKCBF_RX_PAD_ERR,	/* padding byte error */
+};
+
+struct cxgbi_skb_cb {
+	unsigned char ulp_mode;
+	unsigned long flags;
+	unsigned int seq;
+	union {
+		struct cxgbi_skb_rx_cb rx;
+		struct cxgbi_skb_tx_cb tx;
+	};
+};
+
+#define CXGBI_SKB_CB(skb)	((struct cxgbi_skb_cb *)&((skb)->cb[0]))
+#define cxgbi_skcb_flags(skb)		(CXGBI_SKB_CB(skb)->flags)
+#define cxgbi_skcb_ulp_mode(skb)	(CXGBI_SKB_CB(skb)->ulp_mode)
+#define cxgbi_skcb_tcp_seq(skb)		(CXGBI_SKB_CB(skb)->seq)
+#define cxgbi_skcb_rx_ddigest(skb)	(CXGBI_SKB_CB(skb)->rx.ddigest)
+#define cxgbi_skcb_rx_pdulen(skb)	(CXGBI_SKB_CB(skb)->rx.pdulen)
+#define cxgbi_skcb_tx_wr_next(skb)	(CXGBI_SKB_CB(skb)->tx.wr_next)
+
+static inline void cxgbi_skcb_set_flag(struct sk_buff *skb,
+					enum cxgbi_skcb_flags flag)
+{
+	__set_bit(flag, &(cxgbi_skcb_flags(skb)));
+}
+
+static inline void cxgbi_skcb_clear_flag(struct sk_buff *skb,
+					enum cxgbi_skcb_flags flag)
+{
+	__clear_bit(flag, &(cxgbi_skcb_flags(skb)));
+}
+
+static inline int cxgbi_skcb_test_flag(struct sk_buff *skb,
+					enum cxgbi_skcb_flags flag)
+{
+	return test_bit(flag, &(cxgbi_skcb_flags(skb)));
+}
+
+static inline void cxgbi_sock_set_flag(struct cxgbi_sock *csk,
+					enum cxgbi_sock_flags flag)
+{
+	__set_bit(flag, &csk->flags);
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, bit %d.\n",
+		csk, csk->state, csk->flags, flag);
+}
+
+static inline void cxgbi_sock_clear_flag(struct cxgbi_sock *csk,
+					enum cxgbi_sock_flags flag)
+{
+	__clear_bit(flag, &csk->flags);
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, bit %d.\n",
+		csk, csk->state, csk->flags, flag);
+}
+
+static inline int cxgbi_sock_flag(struct cxgbi_sock *csk,
+				enum cxgbi_sock_flags flag)
+{
+	if (csk == NULL)
+		return 0;
+	return test_bit(flag, &csk->flags);
+}
+
+static inline void cxgbi_sock_set_state(struct cxgbi_sock *csk, int state)
+{
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"csk 0x%p,%u,0x%lx, state -> %u.\n",
+		csk, csk->state, csk->flags, state);
+	csk->state = state;
+}
+
+static inline void cxgbi_sock_free(struct kref *kref)
+{
+	struct cxgbi_sock *csk = container_of(kref,
+						struct cxgbi_sock,
+						refcnt);
+	if (csk) {
+		log_debug(1 << CXGBI_DBG_SOCK,
+			"free csk 0x%p, state %u, flags 0x%lx\n",
+			csk, csk->state, csk->flags);
+		kfree(csk);
+	}
+}
+
+static inline void __cxgbi_sock_put(const char *fn, struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"%s, put csk 0x%p, ref %u-1.\n",
+		fn, csk, atomic_read(&csk->refcnt.refcount));
+	kref_put(&csk->refcnt, cxgbi_sock_free);
+}
+#define cxgbi_sock_put(csk)	__cxgbi_sock_put(__func__, csk)
+
+static inline void __cxgbi_sock_get(const char *fn, struct cxgbi_sock *csk)
+{
+	log_debug(1 << CXGBI_DBG_SOCK,
+		"%s, get csk 0x%p, ref %u+1.\n",
+		fn, csk, atomic_read(&csk->refcnt.refcount));
+	kref_get(&csk->refcnt);
+}
+#define cxgbi_sock_get(csk)	__cxgbi_sock_get(__func__, csk)
+
+static inline int cxgbi_sock_is_closing(struct cxgbi_sock *csk)
+{
+	return csk->state >= CTP_ACTIVE_CLOSE;
+}
+
+static inline int cxgbi_sock_is_established(struct cxgbi_sock *csk)
+{
+	return csk->state == CTP_ESTABLISHED;
+}
+
+static inline void cxgbi_sock_purge_write_queue(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+
+	while ((skb = __skb_dequeue(&csk->write_queue)))
+		__kfree_skb(skb);
+}
+
+static inline unsigned int cxgbi_sock_compute_wscale(unsigned int win)
+{
+	unsigned int wscale = 0;
+
+	while (wscale < 14 && (65535 << wscale) < win)
+		wscale++;
+	return wscale;
+}
+
+static inline struct sk_buff *alloc_wr(int wrlen, int dlen, gfp_t gfp)
+{
+	struct sk_buff *skb = alloc_skb(wrlen + dlen, gfp);
+
+	if (skb) {
+		__skb_put(skb, wrlen);
+		memset(skb->head, 0, wrlen + dlen);
+	} else
+		pr_info("alloc cpl wr skb %u+%u, OOM.\n", wrlen, dlen);
+	return skb;
+}
+
+
+/*
+ * The number of WRs needed for an skb depends on the number of fragments
+ * in the skb and whether it has any payload in its main body.  This maps the
+ * length of the gather list represented by an skb into the # of necessary WRs.
+ * The extra two fragments are for iscsi bhs and payload padding.
+ */
+#define SKB_WR_LIST_SIZE	 (MAX_SKB_FRAGS + 2)
+
+static inline void cxgbi_sock_reset_wr_list(struct cxgbi_sock *csk)
+{
+	csk->wr_pending_head = csk->wr_pending_tail = NULL;
+}
+
+static inline void cxgbi_sock_enqueue_wr(struct cxgbi_sock *csk,
+					  struct sk_buff *skb)
+{
+	cxgbi_skcb_tx_wr_next(skb) = NULL;
+	/*
+	 * We want to take an extra reference since both us and the driver
+	 * need to free the packet before it's really freed. We know there's
+	 * just one user currently so we use atomic_set rather than skb_get
+	 * to avoid the atomic op.
+	 */
+	atomic_set(&skb->users, 2);
+
+	if (!csk->wr_pending_head)
+		csk->wr_pending_head = skb;
+	else
+		cxgbi_skcb_tx_wr_next(csk->wr_pending_tail) = skb;
+	csk->wr_pending_tail = skb;
+}
+
+static inline int cxgbi_sock_count_pending_wrs(const struct cxgbi_sock *csk)
+{
+	int n = 0;
+	const struct sk_buff *skb = csk->wr_pending_head;
+
+	while (skb) {
+		n += skb->csum;
+		skb = cxgbi_skcb_tx_wr_next(skb);
+	}
+	return n;
+}
+
+static inline struct sk_buff *cxgbi_sock_peek_wr(const struct cxgbi_sock *csk)
+{
+	return csk->wr_pending_head;
+}
+
+static inline struct sk_buff *cxgbi_sock_dequeue_wr(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->wr_pending_head;
+
+	if (likely(skb)) {
+		csk->wr_pending_head = cxgbi_skcb_tx_wr_next(skb);
+		cxgbi_skcb_tx_wr_next(skb) = NULL;
+	}
+	return skb;
+}
+
+void cxgbi_sock_check_wr_invariants(const struct cxgbi_sock *);
+void cxgbi_sock_purge_wr_queue(struct cxgbi_sock *);
+void cxgbi_sock_skb_entail(struct cxgbi_sock *, struct sk_buff *);
+void cxgbi_sock_fail_act_open(struct cxgbi_sock *, int);
+void cxgbi_sock_act_open_req_arp_failure(void *, struct sk_buff *);
+void cxgbi_sock_closed(struct cxgbi_sock *);
+void cxgbi_sock_established(struct cxgbi_sock *, unsigned int, unsigned int);
+void cxgbi_sock_rcv_abort_rpl(struct cxgbi_sock *);
+void cxgbi_sock_rcv_peer_close(struct cxgbi_sock *);
+void cxgbi_sock_rcv_close_conn_rpl(struct cxgbi_sock *, u32);
+void cxgbi_sock_rcv_wr_ack(struct cxgbi_sock *, unsigned int, unsigned int,
+				int);
+unsigned int cxgbi_sock_select_mss(struct cxgbi_sock *, unsigned int);
+void cxgbi_sock_free_cpl_skbs(struct cxgbi_sock *);
+
+struct cxgbi_hba {
+	struct net_device *ndev;
+	struct net_device *vdev;	/* vlan dev */
+	struct Scsi_Host *shost;
+	struct cxgbi_device *cdev;
+	__be32 ipv4addr;
+	unsigned char port_id;
+};
+
+struct cxgbi_ports_map {
+	unsigned int max_connect;
+	unsigned int used;
+	unsigned short sport_base;
+	spinlock_t lock;
+	unsigned int next;
+	struct cxgbi_sock **port_csk;
+};
+
+#define CXGBI_FLAG_DEV_T3		0x1
+#define CXGBI_FLAG_DEV_T4		0x2
+#define CXGBI_FLAG_ADAPTER_RESET	0x4
+#define CXGBI_FLAG_IPV4_SET		0x10
+struct cxgbi_device {
+	struct list_head list_head;
+	unsigned int flags;
+	struct net_device **ports;
+	void *lldev;
+	struct cxgbi_hba **hbas;
+	const unsigned short *mtus;
+	unsigned char nmtus;
+	unsigned char nports;
+	struct pci_dev *pdev;
+	struct dentry *debugfs_root;
+	struct iscsi_transport *itp;
+
+	unsigned int pfvf;
+	unsigned int snd_win;
+	unsigned int rcv_win;
+	unsigned int rx_credit_thres;
+	unsigned int skb_tx_rsvd;
+	unsigned int skb_rx_extra;	/* for msg coalesced mode */
+	unsigned int tx_max_size;
+	unsigned int rx_max_size;
+	struct cxgbi_ports_map pmap;
+	struct cxgbi_tag_format tag_format;
+	struct cxgbi_ddp_info *ddp;
+
+	void (*dev_ddp_cleanup)(struct cxgbi_device *);
+	void (*csk_ddp_free_gl_skb)(struct cxgbi_ddp_info *, int, int);
+	int (*csk_ddp_alloc_gl_skb)(struct cxgbi_ddp_info *, int, int, gfp_t);
+	int (*csk_ddp_set)(struct cxgbi_sock *, struct cxgbi_pagepod_hdr *,
+				unsigned int, unsigned int,
+				struct cxgbi_gather_list *);
+	void (*csk_ddp_clear)(struct cxgbi_hba *,
+				unsigned int, unsigned int, unsigned int);
+	int (*csk_ddp_setup_digest)(struct cxgbi_sock *,
+				unsigned int, int, int, int);
+	int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *,
+				unsigned int, int, bool);
+
+	void (*csk_release_offload_resources)(struct cxgbi_sock *);
+	int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
+	u32 (*csk_send_rx_credits)(struct cxgbi_sock *, u32);
+	int (*csk_push_tx_frames)(struct cxgbi_sock *, int);
+	void (*csk_send_abort_req)(struct cxgbi_sock *);
+	void (*csk_send_close_req)(struct cxgbi_sock *);
+	int (*csk_alloc_cpls)(struct cxgbi_sock *);
+	int (*csk_init_act_open)(struct cxgbi_sock *);
+
+	void *dd_data;
+};
+#define cxgbi_cdev_priv(cdev)	((cdev)->dd_data)
+
+struct cxgbi_conn {
+	struct cxgbi_endpoint *cep;
+	struct iscsi_conn *iconn;
+	struct cxgbi_hba *chba;
+	u32 task_idx_bits;
+};
+
+struct cxgbi_endpoint {
+	struct cxgbi_conn *cconn;
+	struct cxgbi_hba *chba;
+	struct cxgbi_sock *csk;
+};
+
+#define MAX_PDU_FRAGS	((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
+struct cxgbi_task_data {
+	unsigned short nr_frags;
+	skb_frag_t frags[MAX_PDU_FRAGS];
+	struct sk_buff *skb;
+	unsigned int offset;
+	unsigned int count;
+	unsigned int sgoffset;
+};
+#define iscsi_task_cxgbi_data(task) \
+	((task)->dd_data + sizeof(struct iscsi_tcp_task))
+
+static inline int cxgbi_is_ddp_tag(struct cxgbi_tag_format *tformat, u32 tag)
+{
+	return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
+}
+
+static inline int cxgbi_sw_tag_usable(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	sw_tag >>= (32 - tformat->rsvd_bits);
+	return !sw_tag;
+}
+
+static inline u32 cxgbi_set_non_ddp_tag(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+	u32 mask = (1 << shift) - 1;
+
+	if (sw_tag && (sw_tag & ~mask)) {
+		u32 v1 = sw_tag & ((1 << shift) - 1);
+		u32 v2 = (sw_tag >> (shift - 1)) << shift;
+
+		return v2 | v1 | 1 << shift;
+	}
+
+	return sw_tag | 1 << shift;
+}
+
+static inline u32 cxgbi_ddp_tag_base(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	u32 mask = (1 << tformat->rsvd_shift) - 1;
+
+	if (sw_tag && (sw_tag & ~mask)) {
+		u32 v1 = sw_tag & mask;
+		u32 v2 = sw_tag >> tformat->rsvd_shift;
+
+		v2 <<= tformat->rsvd_bits + tformat->rsvd_shift;
+
+		return v2 | v1;
+	}
+
+	return sw_tag;
+}
+
+static inline u32 cxgbi_tag_rsvd_bits(struct cxgbi_tag_format *tformat,
+					u32 tag)
+{
+	if (cxgbi_is_ddp_tag(tformat, tag))
+		return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
+
+	return 0;
+}
+
+static inline u32 cxgbi_tag_nonrsvd_bits(struct cxgbi_tag_format *tformat,
+					u32 tag)
+{
+	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+	u32 v1, v2;
+
+	if (cxgbi_is_ddp_tag(tformat, tag)) {
+		v1 = tag & ((1 << tformat->rsvd_shift) - 1);
+		v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
+	} else {
+		u32 mask = (1 << shift) - 1;
+		tag &= ~(1 << shift);
+		v1 = tag & mask;
+		v2 = (tag >> 1) & ~mask;
+	}
+	return v1 | v2;
+}
+
+static inline void *cxgbi_alloc_big_mem(unsigned int size,
+					gfp_t gfp)
+{
+	void *p = kmalloc(size, gfp);
+	if (!p)
+		p = vmalloc(size);
+	if (p)
+		memset(p, 0, size);
+	return p;
+}
+
+static inline void cxgbi_free_big_mem(void *addr)
+{
+	if (is_vmalloc_addr(addr))
+		vfree(addr);
+	else
+		kfree(addr);
+}
+
+static inline void cxgbi_set_iscsi_ipv4(struct cxgbi_hba *chba, __be32 ipaddr)
+{
+	if (chba->cdev->flags & CXGBI_FLAG_IPV4_SET)
+		chba->ipv4addr = ipaddr;
+	else
+		pr_info("set iscsi ipv4 NOT supported, using %s ipv4.\n",
+			chba->ndev->name);
+}
+
+static inline __be32 cxgbi_get_iscsi_ipv4(struct cxgbi_hba *chba)
+{
+	return chba->ipv4addr;
+}
+
+struct cxgbi_device *cxgbi_device_register(unsigned int, unsigned int);
+void cxgbi_device_unregister(struct cxgbi_device *);
+void cxgbi_device_unregister_all(unsigned int flag);
+struct cxgbi_device *cxgbi_device_find_by_lldev(void *);
+int cxgbi_hbas_add(struct cxgbi_device *, unsigned int, unsigned int,
+			struct scsi_host_template *,
+			struct scsi_transport_template *);
+void cxgbi_hbas_remove(struct cxgbi_device *);
+
+int cxgbi_device_portmap_create(struct cxgbi_device *cdev, unsigned int base,
+			unsigned int max_conn);
+void cxgbi_device_portmap_cleanup(struct cxgbi_device *cdev);
+
+void cxgbi_conn_tx_open(struct cxgbi_sock *);
+void cxgbi_conn_pdu_ready(struct cxgbi_sock *);
+int cxgbi_conn_alloc_pdu(struct iscsi_task *, u8);
+int cxgbi_conn_init_pdu(struct iscsi_task *, unsigned int , unsigned int);
+int cxgbi_conn_xmit_pdu(struct iscsi_task *);
+
+void cxgbi_cleanup_task(struct iscsi_task *task);
+
+void cxgbi_get_conn_stats(struct iscsi_cls_conn *, struct iscsi_stats *);
+int cxgbi_set_conn_param(struct iscsi_cls_conn *,
+			enum iscsi_param, char *, int);
+int cxgbi_get_conn_param(struct iscsi_cls_conn *, enum iscsi_param, char *);
+struct iscsi_cls_conn *cxgbi_create_conn(struct iscsi_cls_session *, u32);
+int cxgbi_bind_conn(struct iscsi_cls_session *,
+			struct iscsi_cls_conn *, u64, int);
+void cxgbi_destroy_session(struct iscsi_cls_session *);
+struct iscsi_cls_session *cxgbi_create_session(struct iscsi_endpoint *,
+			u16, u16, u32);
+int cxgbi_set_host_param(struct Scsi_Host *,
+			enum iscsi_host_param, char *, int);
+int cxgbi_get_host_param(struct Scsi_Host *, enum iscsi_host_param, char *);
+struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *,
+			struct sockaddr *, int);
+int cxgbi_ep_poll(struct iscsi_endpoint *, int);
+void cxgbi_ep_disconnect(struct iscsi_endpoint *);
+
+int cxgbi_iscsi_init(struct iscsi_transport *,
+			struct scsi_transport_template **);
+void cxgbi_iscsi_cleanup(struct iscsi_transport *,
+			struct scsi_transport_template **);
+void cxgbi_parse_pdu_itt(struct iscsi_conn *, itt_t, int *, int *);
+int cxgbi_ddp_init(struct cxgbi_device *, unsigned int, unsigned int,
+			unsigned int, unsigned int);
+int cxgbi_ddp_cleanup(struct cxgbi_device *);
+void cxgbi_ddp_page_size_factor(int *);
+void cxgbi_ddp_ppod_clear(struct cxgbi_pagepod *);
+void cxgbi_ddp_ppod_set(struct cxgbi_pagepod *, struct cxgbi_pagepod_hdr *,
+			struct cxgbi_gather_list *, unsigned int);
+#endif	/*__LIBCXGBI_H__*/
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 1a970a7..6b72932 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -1,7 +1,7 @@
 /*
  * Generic SCSI-3 ALUA SCSI Device Handler
  *
- * Copyright (C) 2007, 2008 Hannes Reinecke, SUSE Linux Products GmbH.
+ * Copyright (C) 2007-2010 Hannes Reinecke, SUSE Linux Products GmbH.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,17 +20,19 @@
  *
  */
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_dh.h>
 
 #define ALUA_DH_NAME "alua"
-#define ALUA_DH_VER "1.2"
+#define ALUA_DH_VER "1.3"
 
 #define TPGS_STATE_OPTIMIZED		0x0
 #define TPGS_STATE_NONOPTIMIZED		0x1
 #define TPGS_STATE_STANDBY		0x2
 #define TPGS_STATE_UNAVAILABLE		0x3
+#define TPGS_STATE_LBA_DEPENDENT	0x4
 #define TPGS_STATE_OFFLINE		0xe
 #define TPGS_STATE_TRANSITIONING	0xf
 
@@ -39,6 +41,7 @@
 #define TPGS_SUPPORT_NONOPTIMIZED	0x02
 #define TPGS_SUPPORT_STANDBY		0x04
 #define TPGS_SUPPORT_UNAVAILABLE	0x08
+#define TPGS_SUPPORT_LBA_DEPENDENT	0x10
 #define TPGS_SUPPORT_OFFLINE		0x40
 #define TPGS_SUPPORT_TRANSITION		0x80
 
@@ -460,6 +463,8 @@
 		return 'S';
 	case TPGS_STATE_UNAVAILABLE:
 		return 'U';
+	case TPGS_STATE_LBA_DEPENDENT:
+		return 'L';
 	case TPGS_STATE_OFFLINE:
 		return 'O';
 	case TPGS_STATE_TRANSITIONING:
@@ -542,7 +547,9 @@
 	int len, k, off, valid_states = 0;
 	char *ucp;
 	unsigned err;
+	unsigned long expiry, interval = 10;
 
+	expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT);
  retry:
 	err = submit_rtpg(sdev, h);
 
@@ -553,7 +560,7 @@
 			return SCSI_DH_IO;
 
 		err = alua_check_sense(sdev, &sense_hdr);
-		if (err == ADD_TO_MLQUEUE)
+		if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry))
 			goto retry;
 		sdev_printk(KERN_INFO, sdev,
 			    "%s: rtpg sense code %02x/%02x/%02x\n",
@@ -587,38 +594,37 @@
 	}
 
 	sdev_printk(KERN_INFO, sdev,
-		    "%s: port group %02x state %c supports %c%c%c%c%c%c\n",
+		    "%s: port group %02x state %c supports %c%c%c%c%c%c%c\n",
 		    ALUA_DH_NAME, h->group_id, print_alua_state(h->state),
 		    valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
 		    valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
+		    valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
 		    valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
 		    valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
 		    valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
 		    valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
 
-	if (h->tpgs & TPGS_MODE_EXPLICIT) {
-		switch (h->state) {
-		case TPGS_STATE_TRANSITIONING:
+	switch (h->state) {
+	case TPGS_STATE_TRANSITIONING:
+		if (time_before(jiffies, expiry)) {
 			/* State transition, retry */
+			interval *= 10;
+			msleep(interval);
 			goto retry;
-			break;
-		case TPGS_STATE_OFFLINE:
-			/* Path is offline, fail */
-			err = SCSI_DH_DEV_OFFLINED;
-			break;
-		default:
-			break;
 		}
-	} else {
-		/* Only Implicit ALUA support */
-		if (h->state == TPGS_STATE_OPTIMIZED ||
-		    h->state == TPGS_STATE_NONOPTIMIZED ||
-		    h->state == TPGS_STATE_STANDBY)
-			/* Useable path if active */
-			err = SCSI_DH_OK;
-		else
-			/* Path unuseable for unavailable/offline */
-			err = SCSI_DH_DEV_OFFLINED;
+		/* Transitioning time exceeded, set port to standby */
+		err = SCSI_DH_RETRY;
+		h->state = TPGS_STATE_STANDBY;
+		break;
+	case TPGS_STATE_OFFLINE:
+	case TPGS_STATE_UNAVAILABLE:
+		/* Path unuseable for unavailable/offline */
+		err = SCSI_DH_DEV_OFFLINED;
+		break;
+	default:
+		/* Useable path if active */
+		err = SCSI_DH_OK;
+		break;
 	}
 	return err;
 }
@@ -672,7 +678,9 @@
 			goto out;
 	}
 
-	if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED) {
+	if (h->tpgs & TPGS_MODE_EXPLICIT &&
+	    h->state != TPGS_STATE_OPTIMIZED &&
+	    h->state != TPGS_STATE_LBA_DEPENDENT) {
 		h->callback_fn = fn;
 		h->callback_data = data;
 		err = submit_stpg(h);
@@ -698,8 +706,11 @@
 	struct alua_dh_data *h = get_alua_data(sdev);
 	int ret = BLKPREP_OK;
 
-	if (h->state != TPGS_STATE_OPTIMIZED &&
-	    h->state != TPGS_STATE_NONOPTIMIZED) {
+	if (h->state == TPGS_STATE_TRANSITIONING)
+		ret = BLKPREP_DEFER;
+	else if (h->state != TPGS_STATE_OPTIMIZED &&
+		 h->state != TPGS_STATE_NONOPTIMIZED &&
+		 h->state != TPGS_STATE_LBA_DEPENDENT) {
 		ret = BLKPREP_KILL;
 		req->cmd_flags |= REQ_QUIET;
 	}
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index ffc1edf..23dec00 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -49,7 +49,6 @@
 #include <linux/kernel.h>	/* for printk */
 #include <linux/sched.h>
 #include <linux/reboot.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
 
@@ -76,6 +75,7 @@
  * Needed for our management apps
  *============================================================================
  */
+static DEFINE_MUTEX(adpt_mutex);
 static dpt_sig_S DPTI_sig = {
 	{'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION,
 #ifdef __i386__
@@ -126,6 +126,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= compat_adpt_ioctl,
 #endif
+	.llseek		= noop_llseek,
 };
 
 /* Structures and definitions for synchronous message posting.
@@ -1732,12 +1733,12 @@
 	int minor;
 	adpt_hba* pHba;
 
-	lock_kernel();
+	mutex_lock(&adpt_mutex);
 	//TODO check for root access
 	//
 	minor = iminor(inode);
 	if (minor >= hba_count) {
-		unlock_kernel();
+		mutex_unlock(&adpt_mutex);
 		return -ENXIO;
 	}
 	mutex_lock(&adpt_configuration_lock);
@@ -1748,7 +1749,7 @@
 	}
 	if (pHba == NULL) {
 		mutex_unlock(&adpt_configuration_lock);
-		unlock_kernel();
+		mutex_unlock(&adpt_mutex);
 		return -ENXIO;
 	}
 
@@ -1759,7 +1760,7 @@
 
 	pHba->in_use = 1;
 	mutex_unlock(&adpt_configuration_lock);
-	unlock_kernel();
+	mutex_unlock(&adpt_mutex);
 
 	return 0;
 }
@@ -2160,9 +2161,9 @@
  
 	inode = file->f_dentry->d_inode;
  
-	lock_kernel();
+	mutex_lock(&adpt_mutex);
 	ret = adpt_ioctl(inode, file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&adpt_mutex);
 
 	return ret;
 }
@@ -2176,7 +2177,7 @@
  
 	inode = file->f_dentry->d_inode;
  
-	lock_kernel();
+	mutex_lock(&adpt_mutex);
  
 	switch(cmd) {
 		case DPT_SIGNATURE:
@@ -2194,7 +2195,7 @@
 			ret =  -ENOIOCTLCMD;
 	}
  
-	unlock_kernel();
+	mutex_unlock(&adpt_mutex);
  
 	return ret;
 }
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 9eb7a9e..bb63f1a 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -80,8 +80,6 @@
 static int fnic_slave_alloc(struct scsi_device *sdev)
 {
 	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
-	struct fc_lport *lp = shost_priv(sdev->host);
-	struct fnic *fnic = lport_priv(lp);
 
 	sdev->tagged_supported = 1;
 
@@ -89,8 +87,6 @@
 		return -ENXIO;
 
 	scsi_activate_tcq(sdev, FNIC_DFLT_QUEUE_DEPTH);
-	rport->dev_loss_tmo = fnic->config.port_down_timeout / 1000;
-
 	return 0;
 }
 
@@ -113,6 +109,15 @@
 	.shost_attrs = fnic_attrs,
 };
 
+static void
+fnic_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
+{
+	if (timeout)
+		rport->dev_loss_tmo = timeout;
+	else
+		rport->dev_loss_tmo = 1;
+}
+
 static void fnic_get_host_speed(struct Scsi_Host *shost);
 static struct scsi_transport_template *fnic_fc_transport;
 static struct fc_host_statistics *fnic_get_stats(struct Scsi_Host *);
@@ -140,6 +145,7 @@
 	.show_starget_port_name = 1,
 	.show_starget_port_id = 1,
 	.show_rport_dev_loss_tmo = 1,
+	.set_rport_dev_loss_tmo = fnic_set_rport_dev_loss_tmo,
 	.issue_fc_host_lip = fnic_reset,
 	.get_fc_host_stats = fnic_get_stats,
 	.dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
@@ -706,6 +712,7 @@
 		goto err_out_free_exch_mgr;
 	}
 	fc_host_maxframe_size(lp->host) = lp->mfs;
+	fc_host_dev_loss_tmo(lp->host) = fnic->config.port_down_timeout / 1000;
 
 	sprintf(fc_host_symbolic_name(lp->host),
 		DRV_NAME " v" DRV_VERSION " over %s", fnic->name);
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index b860d65..5a3f931 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -120,7 +120,7 @@
 #include <linux/timer.h>
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 
 #ifdef GDTH_RTC
@@ -140,6 +140,7 @@
 #include <scsi/scsi_host.h>
 #include "gdth.h"
 
+static DEFINE_MUTEX(gdth_mutex);
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(u32 size, u32 *cyls, int *heads, int *secs);
 static irqreturn_t gdth_interrupt(int irq, void *dev_id);
@@ -372,6 +373,7 @@
     .unlocked_ioctl   = gdth_unlocked_ioctl,
     .open    = gdth_open,
     .release = gdth_close,
+    .llseek = noop_llseek,
 };
 
 #include "gdth_proc.h"
@@ -4042,12 +4044,12 @@
 {
     gdth_ha_str *ha;
 
-    lock_kernel();
+    mutex_lock(&gdth_mutex);
     list_for_each_entry(ha, &gdth_instances, list) {
         if (!ha->sdev)
             ha->sdev = scsi_get_host_dev(ha->shost);
     }
-    unlock_kernel();
+    mutex_unlock(&gdth_mutex);
 
     TRACE(("gdth_open()\n"));
     return 0;
@@ -4615,9 +4617,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&gdth_mutex);
 	ret = gdth_ioctl(file, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&gdth_mutex);
 
 	return ret;
 }
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 8a8f803..4f7a582 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -376,6 +376,7 @@
 	shost->this_id = sht->this_id;
 	shost->can_queue = sht->can_queue;
 	shost->sg_tablesize = sht->sg_tablesize;
+	shost->sg_prot_tablesize = sht->sg_prot_tablesize;
 	shost->cmd_per_lun = sht->cmd_per_lun;
 	shost->unchecked_isa_dma = sht->unchecked_isa_dma;
 	shost->use_clustering = sht->use_clustering;
@@ -411,9 +412,7 @@
 
 	device_initialize(&shost->shost_gendev);
 	dev_set_name(&shost->shost_gendev, "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);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 9f75a6d..00d08b2 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -50,7 +50,6 @@
 static unsigned int max_targets = IBMVFC_MAX_TARGETS;
 static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT;
 static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
-static unsigned int dev_loss_tmo = IBMVFC_DEV_LOSS_TMO;
 static unsigned int ibmvfc_debug = IBMVFC_DEBUG;
 static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL;
 static LIST_HEAD(ibmvfc_head);
@@ -84,11 +83,6 @@
 module_param_named(debug, ibmvfc_debug, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Enable driver debug information. "
 		 "[Default=" __stringify(IBMVFC_DEBUG) "]");
-module_param_named(dev_loss_tmo, dev_loss_tmo, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(dev_loss_tmo, "Maximum number of seconds that the FC "
-		 "transport should insulate the loss of a remote port. Once this "
-		 "value is exceeded, the scsi target is removed. "
-		 "[Default=" __stringify(IBMVFC_DEV_LOSS_TMO) "]");
 module_param_named(log_level, log_level, uint, 0);
 MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. "
 		 "[Default=" __stringify(IBMVFC_DEFAULT_LOG_LEVEL) "]");
@@ -2496,41 +2490,66 @@
 	LEAVE;
 }
 
-static const struct {
-	enum ibmvfc_async_event ae;
-	const char *desc;
-} ae_desc [] = {
-	{ IBMVFC_AE_ELS_PLOGI,		"PLOGI" },
-	{ IBMVFC_AE_ELS_LOGO,		"LOGO" },
-	{ IBMVFC_AE_ELS_PRLO,		"PRLO" },
-	{ IBMVFC_AE_SCN_NPORT,		"N-Port SCN" },
-	{ IBMVFC_AE_SCN_GROUP,		"Group SCN" },
-	{ IBMVFC_AE_SCN_DOMAIN,		"Domain SCN" },
-	{ IBMVFC_AE_SCN_FABRIC,		"Fabric SCN" },
-	{ IBMVFC_AE_LINK_UP,		"Link Up" },
-	{ IBMVFC_AE_LINK_DOWN,		"Link Down" },
-	{ IBMVFC_AE_LINK_DEAD,		"Link Dead" },
-	{ IBMVFC_AE_HALT,			"Halt" },
-	{ IBMVFC_AE_RESUME,		"Resume" },
-	{ IBMVFC_AE_ADAPTER_FAILED,	"Adapter Failed" },
+static const struct ibmvfc_async_desc ae_desc [] = {
+	{ IBMVFC_AE_ELS_PLOGI,		"PLOGI",		IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_ELS_LOGO,		"LOGO",		IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_ELS_PRLO,		"PRLO",		IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_SCN_NPORT,		"N-Port SCN",	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_SCN_GROUP,		"Group SCN",	IBMVFC_DEFAULT_LOG_LEVEL + 1 },
+	{ IBMVFC_AE_SCN_DOMAIN,		"Domain SCN",	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_SCN_FABRIC,		"Fabric SCN",	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_LINK_UP,		"Link Up",		IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_LINK_DOWN,		"Link Down",	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_LINK_DEAD,		"Link Dead",	IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_HALT,			"Halt",		IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_RESUME,		"Resume",		IBMVFC_DEFAULT_LOG_LEVEL },
+	{ IBMVFC_AE_ADAPTER_FAILED,	"Adapter Failed",	IBMVFC_DEFAULT_LOG_LEVEL },
 };
 
-static const char *unknown_ae = "Unknown async";
+static const struct ibmvfc_async_desc unknown_ae = {
+	0, "Unknown async", IBMVFC_DEFAULT_LOG_LEVEL
+};
 
 /**
  * ibmvfc_get_ae_desc - Get text description for async event
  * @ae:	async event
  *
  **/
-static const char *ibmvfc_get_ae_desc(u64 ae)
+static const struct ibmvfc_async_desc *ibmvfc_get_ae_desc(u64 ae)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(ae_desc); i++)
 		if (ae_desc[i].ae == ae)
-			return ae_desc[i].desc;
+			return &ae_desc[i];
 
-	return unknown_ae;
+	return &unknown_ae;
+}
+
+static const struct {
+	enum ibmvfc_ae_link_state state;
+	const char *desc;
+} link_desc [] = {
+	{ IBMVFC_AE_LS_LINK_UP,		" link up" },
+	{ IBMVFC_AE_LS_LINK_BOUNCED,	" link bounced" },
+	{ IBMVFC_AE_LS_LINK_DOWN,	" link down" },
+	{ IBMVFC_AE_LS_LINK_DEAD,	" link dead" },
+};
+
+/**
+ * ibmvfc_get_link_state - Get text description for link state
+ * @state:	link state
+ *
+ **/
+static const char *ibmvfc_get_link_state(enum ibmvfc_ae_link_state state)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(link_desc); i++)
+		if (link_desc[i].state == state)
+			return link_desc[i].desc;
+
+	return "";
 }
 
 /**
@@ -2542,11 +2561,12 @@
 static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
 				struct ibmvfc_host *vhost)
 {
-	const char *desc = ibmvfc_get_ae_desc(crq->event);
+	const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(crq->event);
 	struct ibmvfc_target *tgt;
 
-	ibmvfc_log(vhost, 3, "%s event received. scsi_id: %llx, wwpn: %llx,"
-		   " node_name: %llx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name);
+	ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx,"
+		   " node_name: %llx%s\n", desc->desc, crq->scsi_id, crq->wwpn, crq->node_name,
+		   ibmvfc_get_link_state(crq->link_state));
 
 	switch (crq->event) {
 	case IBMVFC_AE_RESUME:
@@ -2788,7 +2808,6 @@
 static int ibmvfc_slave_configure(struct scsi_device *sdev)
 {
 	struct Scsi_Host *shost = sdev->host;
-	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
 	unsigned long flags = 0;
 
 	spin_lock_irqsave(shost->host_lock, flags);
@@ -2800,8 +2819,6 @@
 		scsi_activate_tcq(sdev, sdev->queue_depth);
 	} else
 		scsi_deactivate_tcq(sdev, sdev->queue_depth);
-
-	rport->dev_loss_tmo = dev_loss_tmo;
 	spin_unlock_irqrestore(shost->host_lock, flags);
 	return 0;
 }
@@ -4285,8 +4302,10 @@
 		spin_unlock_irqrestore(vhost->host->host_lock, flags);
 		rc = ibmvfc_reset_crq(vhost);
 		spin_lock_irqsave(vhost->host->host_lock, flags);
-		if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
-		    (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
+		if (rc == H_CLOSED)
+			vio_enable_interrupts(to_vio_dev(vhost->dev));
+		else if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
+			 (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
 			ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
 			dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc);
 		}
@@ -4744,6 +4763,8 @@
 	if ((rc = scsi_add_host(shost, dev)))
 		goto release_event_pool;
 
+	fc_host_dev_loss_tmo(shost) = IBMVFC_DEV_LOSS_TMO;
+
 	if ((rc = ibmvfc_create_trace_file(&shost->shost_dev.kobj,
 					   &ibmvfc_trace_attr))) {
 		dev_err(dev, "Failed to create trace file. rc=%d\n", rc);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 608af39..ef663e7 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -541,6 +541,12 @@
 	IBMVFC_AE_ADAPTER_FAILED	= 0x1000,
 };
 
+struct ibmvfc_async_desc {
+	enum ibmvfc_async_event ae;
+	const char *desc;
+	int log_level;
+};
+
 struct ibmvfc_crq {
 	volatile u8 valid;
 	volatile u8 format;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5256858..df9a12c 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -1096,6 +1096,7 @@
 		res->bus = cfgtew->u.cfgte->res_addr.bus;
 		res->target = cfgtew->u.cfgte->res_addr.target;
 		res->lun = cfgtew->u.cfgte->res_addr.lun;
+		res->lun_wwn = get_unaligned_be64(cfgtew->u.cfgte->lun_wwn);
 	}
 
 	ipr_update_ata_class(res, proto);
@@ -1142,7 +1143,7 @@
 	int i;
 	char *p = buffer;
 
-	res_path[0] = '\0';
+	*p = '\0';
 	p += snprintf(p, buffer + len - p, "%02X", res_path[0]);
 	for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++)
 		p += snprintf(p, buffer + len - p, "-%02X", res_path[i]);
@@ -1670,7 +1671,7 @@
 
 	array_entry = error->array_member;
 	num_entries = min_t(u32, be32_to_cpu(error->num_entries),
-			    sizeof(error->array_member));
+			    ARRAY_SIZE(error->array_member));
 
 	for (i = 0; i < num_entries; i++, array_entry++) {
 		if (!memcmp(array_entry->vpd.vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN))
@@ -2151,8 +2152,8 @@
 	ipr_err_separator;
 
 	array_entry = error->array_member;
-	num_entries = min_t(u32, be32_to_cpu(error->num_entries),
-			    sizeof(error->array_member));
+	num_entries = min_t(u32, error->num_entries,
+			    ARRAY_SIZE(error->array_member));
 
 	for (i = 0; i < num_entries; i++, array_entry++) {
 
@@ -2166,10 +2167,10 @@
 
 		ipr_err("Array Member %d:\n", i);
 		ipr_log_ext_vpd(&array_entry->vpd);
-		ipr_err("Current Location: %s",
+		ipr_err("Current Location: %s\n",
 			 ipr_format_res_path(array_entry->res_path, buffer,
 					     sizeof(buffer)));
-		ipr_err("Expected Location: %s",
+		ipr_err("Expected Location: %s\n",
 			 ipr_format_res_path(array_entry->expected_res_path,
 					     buffer, sizeof(buffer)));
 
@@ -4089,6 +4090,7 @@
 /**
  * ipr_show_adapter_handle - Show the adapter's resource handle for this device
  * @dev:	device struct
+ * @attr:	device attribute structure
  * @buf:	buffer
  *
  * Return value:
@@ -4122,6 +4124,7 @@
  * ipr_show_resource_path - Show the resource path or the resource address for
  *			    this device.
  * @dev:	device struct
+ * @attr:	device attribute structure
  * @buf:	buffer
  *
  * Return value:
@@ -4159,8 +4162,45 @@
 };
 
 /**
+ * ipr_show_device_id - Show the device_id for this device.
+ * @dev:	device struct
+ * @attr:	device attribute structure
+ * @buf:	buffer
+ *
+ * Return value:
+ *	number of bytes printed to buffer
+ **/
+static ssize_t ipr_show_device_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
+	struct ipr_resource_entry *res;
+	unsigned long lock_flags = 0;
+	ssize_t len = -ENXIO;
+
+	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+	res = (struct ipr_resource_entry *)sdev->hostdata;
+	if (res && ioa_cfg->sis64)
+		len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->dev_id);
+	else if (res)
+		len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->lun_wwn);
+
+	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+	return len;
+}
+
+static struct device_attribute ipr_device_id_attr = {
+	.attr = {
+		.name =		"device_id",
+		.mode =		S_IRUGO,
+	},
+	.show = ipr_show_device_id
+};
+
+/**
  * ipr_show_resource_type - Show the resource type for this device.
  * @dev:	device struct
+ * @attr:	device attribute structure
  * @buf:	buffer
  *
  * Return value:
@@ -4195,6 +4235,7 @@
 static struct device_attribute *ipr_dev_attrs[] = {
 	&ipr_adapter_handle_attr,
 	&ipr_resource_path_attr,
+	&ipr_device_id_attr,
 	&ipr_resource_type_attr,
 	NULL,
 };
@@ -4898,39 +4939,15 @@
 /**
  * ipr_handle_other_interrupt - Handle "other" interrupts
  * @ioa_cfg:	ioa config struct
+ * @int_reg:	interrupt register
  *
  * Return value:
  * 	IRQ_NONE / IRQ_HANDLED
  **/
-static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg)
+static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg,
+					      volatile u32 int_reg)
 {
 	irqreturn_t rc = IRQ_HANDLED;
-	volatile u32 int_reg, int_mask_reg;
-
-	int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
-	int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
-
-	/* If an interrupt on the adapter did not occur, ignore it.
-	 * Or in the case of SIS 64, check for a stage change interrupt.
-	 */
-	if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) {
-		if (ioa_cfg->sis64) {
-			int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
-			int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
-			if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
-
-				/* clear stage change */
-				writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
-				int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
-				list_del(&ioa_cfg->reset_cmd->queue);
-				del_timer(&ioa_cfg->reset_cmd->timer);
-				ipr_reset_ioa_job(ioa_cfg->reset_cmd);
-				return IRQ_HANDLED;
-			}
-		}
-
-		return IRQ_NONE;
-	}
 
 	if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) {
 		/* Mask the interrupt */
@@ -4991,7 +5008,7 @@
 {
 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp;
 	unsigned long lock_flags = 0;
-	volatile u32 int_reg;
+	volatile u32 int_reg, int_mask_reg;
 	u32 ioasc;
 	u16 cmd_index;
 	int num_hrrq = 0;
@@ -5006,6 +5023,33 @@
 		return IRQ_NONE;
 	}
 
+	int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32);
+	int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
+
+	/* If an interrupt on the adapter did not occur, ignore it.
+	 * Or in the case of SIS 64, check for a stage change interrupt.
+	 */
+	if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) {
+		if (ioa_cfg->sis64) {
+			int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+			int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
+			if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) {
+
+				/* clear stage change */
+				writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg);
+				int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg;
+				list_del(&ioa_cfg->reset_cmd->queue);
+				del_timer(&ioa_cfg->reset_cmd->timer);
+				ipr_reset_ioa_job(ioa_cfg->reset_cmd);
+				spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+				return IRQ_HANDLED;
+			}
+		}
+
+		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+		return IRQ_NONE;
+	}
+
 	while (1) {
 		ipr_cmd = NULL;
 
@@ -5045,7 +5089,7 @@
 			/* Clear the PCI interrupt */
 			do {
 				writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32);
-				int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32);
+				int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg;
 			} while (int_reg & IPR_PCII_HRRQ_UPDATED &&
 					num_hrrq++ < IPR_MAX_HRRQ_RETRIES);
 
@@ -5060,7 +5104,7 @@
 	}
 
 	if (unlikely(rc == IRQ_NONE))
-		rc = ipr_handle_other_interrupt(ioa_cfg);
+		rc = ipr_handle_other_interrupt(ioa_cfg, int_reg);
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 	return rc;
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 4d31625..aa8bb2f 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -26,6 +26,7 @@
 #ifndef _IPR_H
 #define _IPR_H
 
+#include <asm/unaligned.h>
 #include <linux/types.h>
 #include <linux/completion.h>
 #include <linux/libata.h>
@@ -37,8 +38,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.5.0"
-#define IPR_DRIVER_DATE "(February 11, 2010)"
+#define IPR_DRIVER_VERSION "2.5.1"
+#define IPR_DRIVER_DATE "(August 10, 2010)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -318,6 +319,11 @@
 	__be32 wwid[2];
 }__attribute__((packed));
 
+struct ipr_ext_vpd64 {
+	struct ipr_vpd vpd;
+	__be32 wwid[4];
+}__attribute__((packed));
+
 struct ipr_std_inq_data {
 	u8 peri_qual_dev_type;
 #define IPR_STD_INQ_PERI_QUAL(peri) ((peri) >> 5)
@@ -372,7 +378,7 @@
 
 	struct ipr_res_addr res_addr;
 	__be32 res_handle;
-	__be32 reserved4[2];
+	__be32 lun_wwn[2];
 	struct ipr_std_inq_data std_inq_data;
 }__attribute__ ((packed, aligned (4)));
 
@@ -394,7 +400,7 @@
 	__be64 res_path;
 	struct ipr_std_inq_data std_inq_data;
 	u8 reserved2[4];
-	__be64 reserved3[2]; // description text
+	__be64 reserved3[2];
 	u8 reserved4[8];
 }__attribute__ ((packed, aligned (8)));
 
@@ -913,7 +919,7 @@
 	u8 array_id;
 	u8 last_res_path[8];
 	u8 protection_level[8];
-	struct ipr_ext_vpd array_vpd;
+	struct ipr_ext_vpd64 array_vpd;
 	u8 description[16];
 	u8 reserved2[3];
 	u8 num_entries;
@@ -1210,6 +1216,7 @@
 
 	__be32 res_handle;
 	__be64 dev_id;
+	__be64 lun_wwn;
 	struct scsi_lun dev_lun;
 	u8 res_path[8];
 
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 042153c..e1a395b 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -162,6 +162,10 @@
 	unsigned int xfer = 0;
 	unsigned int si;
 
+	/* If the device fell off, no sense in issuing commands */
+	if (dev->gone)
+		return AC_ERR_SYSTEM;
+
 	task = sas_alloc_task(GFP_ATOMIC);
 	if (!task)
 		return AC_ERR_SYSTEM;
@@ -347,6 +351,7 @@
 static struct ata_port_operations sas_sata_ops = {
 	.phy_reset		= sas_ata_phy_reset,
 	.post_internal_cmd	= sas_ata_post_internal,
+	.qc_defer               = ata_std_qc_defer,
 	.qc_prep		= ata_noop_qc_prep,
 	.qc_issue		= sas_ata_qc_issue,
 	.qc_fill_rtf		= sas_ata_qc_fill_rtf,
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 83dd507..505ffe35 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -175,10 +175,10 @@
 	switch (resp->result) {
 	case SMP_RESP_PHY_VACANT:
 		phy->phy_state = PHY_VACANT;
-		return;
+		break;
 	default:
 		phy->phy_state = PHY_NOT_PRESENT;
-		return;
+		break;
 	case SMP_RESP_FUNC_ACC:
 		phy->phy_state = PHY_EMPTY; /* do not know yet */
 		break;
@@ -209,7 +209,10 @@
 	phy->phy->negotiated_linkrate = phy->linkrate;
 
 	if (!rediscover)
-		sas_phy_add(phy->phy);
+		if (sas_phy_add(phy->phy)) {
+			sas_phy_free(phy->phy);
+			return;
+		}
 
 	SAS_DPRINTK("ex %016llx phy%02d:%c attached: %016llx\n",
 		    SAS_ADDR(dev->sas_addr), phy->phy_id,
@@ -1724,6 +1727,7 @@
 	struct domain_device *child, *n;
 
 	list_for_each_entry_safe(child, n, &ex->children, siblings) {
+		child->gone = 1;
 		if (child->dev_type == EDGE_DEV ||
 		    child->dev_type == FANOUT_DEV)
 			sas_unregister_ex_tree(child);
@@ -1744,6 +1748,7 @@
 			&ex_dev->children, siblings) {
 			if (SAS_ADDR(child->sas_addr) ==
 			    SAS_ADDR(phy->attached_sas_addr)) {
+				child->gone = 1;
 				if (child->dev_type == EDGE_DEV ||
 				    child->dev_type == FANOUT_DEV)
 					sas_unregister_ex_tree(child);
@@ -1752,6 +1757,7 @@
 				break;
 			}
 		}
+		parent->gone = 1;
 		sas_disable_routing(parent, phy->attached_sas_addr);
 	}
 	memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index f0cfba9..55f09e9 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -130,17 +130,6 @@
 	sc->scsi_done(sc);
 }
 
-static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd)
-{
-	enum task_attribute ta = TASK_ATTR_SIMPLE;
-	if (cmd->request && blk_rq_tagged(cmd->request)) {
-		if (cmd->device->ordered_tags &&
-		    (cmd->request->cmd_flags & REQ_HARDBARRIER))
-			ta = TASK_ATTR_ORDERED;
-	}
-	return ta;
-}
-
 static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
 					       struct domain_device *dev,
 					       gfp_t gfp_flags)
@@ -160,7 +149,7 @@
 	task->ssp_task.retry_count = 1;
 	int_to_scsilun(cmd->device->lun, &lun);
 	memcpy(task->ssp_task.LUN, &lun.scsi_lun, 8);
-	task->ssp_task.task_attr = sas_scsi_get_task_attr(cmd);
+	task->ssp_task.task_attr = TASK_ATTR_SIMPLE;
 	memcpy(task->ssp_task.cdb, cmd->cmnd, 16);
 
 	task->scatter = scsi_sglist(cmd);
@@ -228,6 +217,13 @@
 			goto out;
 		}
 
+		/* If the device fell off, no sense in issuing commands */
+		if (dev->gone) {
+			cmd->result = DID_BAD_TARGET << 16;
+			scsi_done(cmd);
+			goto out;
+		}
+
 		res = -ENOMEM;
 		task = sas_create_task(cmd, dev, GFP_ATOMIC);
 		if (!task)
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 23ce457..f681eea 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -586,6 +586,11 @@
 			       phba->cfg_link_speed);
 		mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq,
 						     phba->fc_ratov * 2);
+		if ((mbxstatus == MBX_SUCCESS) &&
+		    (pmboxq->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION))
+			lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+					"2859 SLI authentication is required "
+					"for INIT_LINK but has not done yet\n");
 	}
 
 	lpfc_set_loopback_flag(phba);
@@ -2159,6 +2164,11 @@
 	if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
 		vport->cfg_nodev_tmo = val;
 		vport->cfg_devloss_tmo = val;
+		/*
+		 * For compat: set the fc_host dev loss so new rports
+		 * will get the value.
+		 */
+		fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
 		lpfc_update_rport_devloss_tmo(vport);
 		return 0;
 	}
@@ -2208,6 +2218,7 @@
 		vport->cfg_nodev_tmo = val;
 		vport->cfg_devloss_tmo = val;
 		vport->dev_loss_tmo_changed = 1;
+		fc_host_dev_loss_tmo(lpfc_shost_from_vport(vport)) = val;
 		lpfc_update_rport_devloss_tmo(vport);
 		return 0;
 	}
@@ -3776,6 +3787,11 @@
 		case MBX_PORT_CAPABILITIES:
 		case MBX_PORT_IOV_CONTROL:
 			break;
+		case MBX_SECURITY_MGMT:
+		case MBX_AUTH_PORT:
+			if (phba->pci_dev_grp == LPFC_PCI_DEV_OC)
+				return -EPERM;
+			break;
 		case MBX_READ_SPARM64:
 		case MBX_READ_LA:
 		case MBX_READ_LA64:
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 49d0cf9..f5d60b5 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -259,6 +259,7 @@
 	struct bsg_job_data *dd_data;
 	uint32_t creg_val;
 	int rc = 0;
+	int iocb_stat;
 
 	/* in case no data is transferred */
 	job->reply->reply_payload_rcv_len = 0;
@@ -373,14 +374,13 @@
 		readl(phba->HCregaddr); /* flush */
 	}
 
-	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
-
-	if (rc == IOCB_SUCCESS)
+	iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
+	if (iocb_stat == IOCB_SUCCESS)
 		return 0; /* done for now */
-	else if (rc == IOCB_BUSY)
-		rc = EAGAIN;
+	else if (iocb_stat == IOCB_BUSY)
+		rc = -EAGAIN;
 	else
-		rc = EIO;
+		rc = -EIO;
 
 
 	/* iocb failed so cleanup */
@@ -631,9 +631,9 @@
 	if (rc == IOCB_SUCCESS)
 		return 0; /* done for now */
 	else if (rc == IOCB_BUSY)
-		rc = EAGAIN;
+		rc = -EAGAIN;
 	else
-		rc = EIO;
+		rc = -EIO;
 
 	pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
 		     job->request_payload.sg_cnt, DMA_TO_DEVICE);
@@ -1299,7 +1299,7 @@
 	/* Allocate buffer for  command iocb */
 	ctiocb = lpfc_sli_get_iocbq(phba);
 	if (!ctiocb) {
-		rc = ENOMEM;
+		rc = -ENOMEM;
 		goto no_ctiocb;
 	}
 
@@ -1518,7 +1518,7 @@
 	loopback_mode = (struct diag_mode_set *)
 		job->request->rqst_data.h_vendor.vendor_cmd;
 	link_flags = loopback_mode->type;
-	timeout = loopback_mode->timeout;
+	timeout = loopback_mode->timeout * 100;
 
 	if ((phba->link_state == LPFC_HBA_ERROR) ||
 	    (psli->sli_flag & LPFC_BLOCK_MGMT_IO) ||
@@ -1649,17 +1649,18 @@
 
 	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!mbox)
-		return ENOMEM;
+		return -ENOMEM;
 
 	status = lpfc_reg_rpi(phba, 0, phba->pport->fc_myDID,
 				(uint8_t *)&phba->pport->fc_sparam, mbox, 0);
 	if (status) {
 		mempool_free(mbox, phba->mbox_mem_pool);
-		return ENOMEM;
+		return -ENOMEM;
 	}
 
 	dmabuff = (struct lpfc_dmabuf *) mbox->context1;
 	mbox->context1 = NULL;
+	mbox->context2 = NULL;
 	status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
 
 	if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
@@ -1667,7 +1668,7 @@
 		kfree(dmabuff);
 		if (status != MBX_TIMEOUT)
 			mempool_free(mbox, phba->mbox_mem_pool);
-		return ENODEV;
+		return -ENODEV;
 	}
 
 	*rpi = mbox->u.mb.un.varWords[0];
@@ -1693,7 +1694,7 @@
 	/* Allocate mboxq structure */
 	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (mbox == NULL)
-		return ENOMEM;
+		return -ENOMEM;
 
 	lpfc_unreg_login(phba, 0, rpi, mbox);
 	status = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
@@ -1701,7 +1702,7 @@
 	if ((status != MBX_SUCCESS) || (mbox->u.mb.mbxStatus)) {
 		if (status != MBX_TIMEOUT)
 			mempool_free(mbox, phba->mbox_mem_pool);
-		return EIO;
+		return -EIO;
 	}
 
 	mempool_free(mbox, phba->mbox_mem_pool);
@@ -1730,6 +1731,8 @@
 	struct ulp_bde64 *bpl = NULL;
 	struct lpfc_sli_ct_request *ctreq = NULL;
 	int ret_val = 0;
+	int time_left;
+	int iocb_stat = 0;
 	unsigned long flags;
 
 	*txxri = 0;
@@ -1737,7 +1740,7 @@
 	evt = lpfc_bsg_event_new(FC_REG_CT_EVENT, current->pid,
 				SLI_CT_ELX_LOOPBACK);
 	if (!evt)
-		return ENOMEM;
+		return -ENOMEM;
 
 	spin_lock_irqsave(&phba->ct_ev_lock, flags);
 	list_add(&evt->node, &phba->ct_ev_waiters);
@@ -1770,7 +1773,7 @@
 	if (cmdiocbq == NULL || rspiocbq == NULL ||
 	    dmabuf == NULL || bpl == NULL || ctreq == NULL ||
 		dmabuf->virt == NULL) {
-		ret_val = ENOMEM;
+		ret_val = -ENOMEM;
 		goto err_get_xri_exit;
 	}
 
@@ -1806,24 +1809,24 @@
 	cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
 	cmdiocbq->vport = phba->pport;
 
-	ret_val = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
+	iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
 				rspiocbq,
 				(phba->fc_ratov * 2)
 				+ LPFC_DRVR_TIMEOUT);
-	if (ret_val)
+	if (iocb_stat) {
+		ret_val = -EIO;
 		goto err_get_xri_exit;
-
+	}
 	*txxri =  rsp->ulpContext;
 
 	evt->waiting = 1;
 	evt->wait_time_stamp = jiffies;
-	ret_val = wait_event_interruptible_timeout(
+	time_left = wait_event_interruptible_timeout(
 		evt->wq, !list_empty(&evt->events_to_see),
 		((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
 	if (list_empty(&evt->events_to_see))
-		ret_val = (ret_val) ? EINTR : ETIMEDOUT;
+		ret_val = (time_left) ? -EINTR : -ETIMEDOUT;
 	else {
-		ret_val = IOCB_SUCCESS;
 		spin_lock_irqsave(&phba->ct_ev_lock, flags);
 		list_move(evt->events_to_see.prev, &evt->events_to_get);
 		spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
@@ -1845,7 +1848,7 @@
 		kfree(dmabuf);
 	}
 
-	if (cmdiocbq && (ret_val != IOCB_TIMEDOUT))
+	if (cmdiocbq && (iocb_stat != IOCB_TIMEDOUT))
 		lpfc_sli_release_iocbq(phba, cmdiocbq);
 	if (rspiocbq)
 		lpfc_sli_release_iocbq(phba, rspiocbq);
@@ -1959,6 +1962,7 @@
 	uint32_t num_bde;
 	struct lpfc_dmabufext *rxbuffer = NULL;
 	int ret_val = 0;
+	int iocb_stat;
 	int i = 0;
 
 	cmdiocbq = lpfc_sli_get_iocbq(phba);
@@ -1973,7 +1977,7 @@
 	}
 
 	if (!cmdiocbq || !rxbmp || !rxbpl || !rxbuffer) {
-		ret_val = ENOMEM;
+		ret_val = -ENOMEM;
 		goto err_post_rxbufs_exit;
 	}
 
@@ -2022,16 +2026,16 @@
 		cmd->ulpClass = CLASS3;
 		cmd->ulpContext = rxxri;
 
-		ret_val = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
-
-		if (ret_val == IOCB_ERROR) {
+		iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq,
+						0);
+		if (iocb_stat == IOCB_ERROR) {
 			diag_cmd_data_free(phba,
 				(struct lpfc_dmabufext *)mp[0]);
 			if (mp[1])
 				diag_cmd_data_free(phba,
 					  (struct lpfc_dmabufext *)mp[1]);
 			dmp = list_entry(next, struct lpfc_dmabuf, list);
-			ret_val = EIO;
+			ret_val = -EIO;
 			goto err_post_rxbufs_exit;
 		}
 
@@ -2045,7 +2049,7 @@
 		cmdiocbq = lpfc_sli_get_iocbq(phba);
 		if (!cmdiocbq) {
 			dmp = list_entry(next, struct lpfc_dmabuf, list);
-			ret_val = EIO;
+			ret_val = -EIO;
 			goto err_post_rxbufs_exit;
 		}
 
@@ -2111,6 +2115,8 @@
 	uint32_t num_bde;
 	uint8_t *ptr = NULL, *rx_databuf = NULL;
 	int rc = 0;
+	int time_left;
+	int iocb_stat;
 	unsigned long flags;
 	void *dataout = NULL;
 	uint32_t total_mem;
@@ -2185,22 +2191,18 @@
 				ptr, size);
 
 	rc = lpfcdiag_loop_self_reg(phba, &rpi);
-	if (rc) {
-		rc = -ENOMEM;
+	if (rc)
 		goto loopback_test_exit;
-	}
 
 	rc = lpfcdiag_loop_get_xri(phba, rpi, &txxri, &rxxri);
 	if (rc) {
 		lpfcdiag_loop_self_unreg(phba, rpi);
-		rc = -ENOMEM;
 		goto loopback_test_exit;
 	}
 
 	rc = lpfcdiag_loop_post_rxbufs(phba, rxxri, full_size);
 	if (rc) {
 		lpfcdiag_loop_self_unreg(phba, rpi);
-		rc = -ENOMEM;
 		goto loopback_test_exit;
 	}
 
@@ -2290,21 +2292,22 @@
 	cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
 	cmdiocbq->vport = phba->pport;
 
-	rc = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, rspiocbq,
-				      (phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT);
+	iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
+					     rspiocbq, (phba->fc_ratov * 2) +
+					     LPFC_DRVR_TIMEOUT);
 
-	if ((rc != IOCB_SUCCESS) || (rsp->ulpStatus != IOCB_SUCCESS)) {
+	if ((iocb_stat != IOCB_SUCCESS) || (rsp->ulpStatus != IOCB_SUCCESS)) {
 		rc = -EIO;
 		goto err_loopback_test_exit;
 	}
 
 	evt->waiting = 1;
-	rc = wait_event_interruptible_timeout(
+	time_left = wait_event_interruptible_timeout(
 		evt->wq, !list_empty(&evt->events_to_see),
 		((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ);
 	evt->waiting = 0;
 	if (list_empty(&evt->events_to_see))
-		rc = (rc) ? -EINTR : -ETIMEDOUT;
+		rc = (time_left) ? -EINTR : -ETIMEDOUT;
 	else {
 		spin_lock_irqsave(&phba->ct_ev_lock, flags);
 		list_move(evt->events_to_see.prev, &evt->events_to_get);
@@ -2470,6 +2473,17 @@
 			to += sizeof(MAILBOX_t);
 			size = pmboxq->u.mb.un.varWords[5];
 			memcpy(to, from, size);
+		} else if ((phba->sli_rev == LPFC_SLI_REV4) &&
+			(pmboxq->u.mb.mbxCommand == MBX_SLI4_CONFIG)) {
+			struct lpfc_mbx_nembed_cmd *nembed_sge =
+				(struct lpfc_mbx_nembed_cmd *)
+				&pmboxq->u.mb.un.varWords[0];
+
+			from = (uint8_t *)dd_data->context_un.mbox.dmp->dma.
+						virt;
+			to += sizeof(MAILBOX_t);
+			size = nembed_sge->sge[0].length;
+			memcpy(to, from, size);
 		} else if (pmboxq->u.mb.mbxCommand == MBX_READ_EVENT_LOG) {
 			from = (uint8_t *)dd_data->context_un.
 						mbox.dmp->dma.virt;
@@ -2911,6 +2925,59 @@
 			from += sizeof(MAILBOX_t);
 			memcpy((uint8_t *)dmp->dma.virt, from,
 				bde->tus.f.bdeSize);
+		} else if (pmb->mbxCommand == MBX_SLI4_CONFIG) {
+			struct lpfc_mbx_nembed_cmd *nembed_sge;
+			struct mbox_header *header;
+			uint32_t receive_length;
+
+			/* rebuild the command for sli4 using our own buffers
+			* like we do for biu diags
+			*/
+			header = (struct mbox_header *)&pmb->un.varWords[0];
+			nembed_sge = (struct lpfc_mbx_nembed_cmd *)
+				&pmb->un.varWords[0];
+			receive_length = nembed_sge->sge[0].length;
+
+			/* receive length cannot be greater than mailbox
+			 * extension size
+			 */
+			if ((receive_length == 0) ||
+				(receive_length > MAILBOX_EXT_SIZE)) {
+				rc = -ERANGE;
+				goto job_done;
+			}
+
+			rxbmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+			if (!rxbmp) {
+				rc = -ENOMEM;
+				goto job_done;
+			}
+
+			rxbmp->virt = lpfc_mbuf_alloc(phba, 0, &rxbmp->phys);
+			if (!rxbmp->virt) {
+				rc = -ENOMEM;
+				goto job_done;
+			}
+
+			INIT_LIST_HEAD(&rxbmp->list);
+			rxbpl = (struct ulp_bde64 *) rxbmp->virt;
+			dmp = diag_cmd_data_alloc(phba, rxbpl, receive_length,
+						0);
+			if (!dmp) {
+				rc = -ENOMEM;
+				goto job_done;
+			}
+
+			INIT_LIST_HEAD(&dmp->dma.list);
+			nembed_sge->sge[0].pa_hi = putPaddrHigh(dmp->dma.phys);
+			nembed_sge->sge[0].pa_lo = putPaddrLow(dmp->dma.phys);
+			/* copy the transmit data found in the mailbox
+			 * extension area
+			 */
+			from = (uint8_t *)mb;
+			from += sizeof(MAILBOX_t);
+			memcpy((uint8_t *)dmp->dma.virt, from,
+				header->cfg_mhdr.payload_length);
 		}
 	}
 
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 8d09191..e6ca12f 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3250,6 +3250,8 @@
 		lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi);
 
 	pmb->context1 = NULL;
+	pmb->context2 = NULL;
+
 	lpfc_mbuf_free(phba, mp->virt, mp->phys);
 	kfree(mp);
 	mempool_free(pmb, phba->mbox_mem_pool);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 1f62ea8..c3d7174 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1015,7 +1015,6 @@
 lpfc_mbx_cmpl_reg_fcfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 {
 	struct lpfc_vport *vport = mboxq->vport;
-	unsigned long flags;
 
 	if (mboxq->u.mb.mbxStatus) {
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
@@ -1029,18 +1028,18 @@
 	/* Start FCoE discovery by sending a FLOGI. */
 	phba->fcf.fcfi = bf_get(lpfc_reg_fcfi_fcfi, &mboxq->u.mqe.un.reg_fcfi);
 	/* Set the FCFI registered flag */
-	spin_lock_irqsave(&phba->hbalock, flags);
+	spin_lock_irq(&phba->hbalock);
 	phba->fcf.fcf_flag |= FCF_REGISTERED;
-	spin_unlock_irqrestore(&phba->hbalock, flags);
+	spin_unlock_irq(&phba->hbalock);
 	/* If there is a pending FCoE event, restart FCF table scan. */
 	if (lpfc_check_pending_fcoe_event(phba, 1)) {
 		mempool_free(mboxq, phba->mbox_mem_pool);
 		return;
 	}
-	spin_lock_irqsave(&phba->hbalock, flags);
+	spin_lock_irq(&phba->hbalock);
 	phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE);
 	phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-	spin_unlock_irqrestore(&phba->hbalock, flags);
+	spin_unlock_irq(&phba->hbalock);
 	if (vport->port_state != LPFC_FLOGI)
 		lpfc_initial_flogi(vport);
 
@@ -1240,14 +1239,13 @@
 {
 	LPFC_MBOXQ_t *fcf_mbxq;
 	int rc;
-	unsigned long flags;
 
-	spin_lock_irqsave(&phba->hbalock, flags);
+	spin_lock_irq(&phba->hbalock);
 
 	/* If the FCF is not availabe do nothing. */
 	if (!(phba->fcf.fcf_flag & FCF_AVAILABLE)) {
 		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-		spin_unlock_irqrestore(&phba->hbalock, flags);
+		spin_unlock_irq(&phba->hbalock);
 		return;
 	}
 
@@ -1255,19 +1253,19 @@
 	if (phba->fcf.fcf_flag & FCF_REGISTERED) {
 		phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE);
 		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-		spin_unlock_irqrestore(&phba->hbalock, flags);
+		spin_unlock_irq(&phba->hbalock);
 		if (phba->pport->port_state != LPFC_FLOGI)
 			lpfc_initial_flogi(phba->pport);
 		return;
 	}
-	spin_unlock_irqrestore(&phba->hbalock, flags);
+	spin_unlock_irq(&phba->hbalock);
 
 	fcf_mbxq = mempool_alloc(phba->mbox_mem_pool,
 		GFP_KERNEL);
 	if (!fcf_mbxq) {
-		spin_lock_irqsave(&phba->hbalock, flags);
+		spin_lock_irq(&phba->hbalock);
 		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-		spin_unlock_irqrestore(&phba->hbalock, flags);
+		spin_unlock_irq(&phba->hbalock);
 		return;
 	}
 
@@ -1276,9 +1274,9 @@
 	fcf_mbxq->mbox_cmpl = lpfc_mbx_cmpl_reg_fcfi;
 	rc = lpfc_sli_issue_mbox(phba, fcf_mbxq, MBX_NOWAIT);
 	if (rc == MBX_NOT_FINISHED) {
-		spin_lock_irqsave(&phba->hbalock, flags);
+		spin_lock_irq(&phba->hbalock);
 		phba->hba_flag &= ~FCF_DISC_INPROGRESS;
-		spin_unlock_irqrestore(&phba->hbalock, flags);
+		spin_unlock_irq(&phba->hbalock);
 		mempool_free(fcf_mbxq, phba->mbox_mem_pool);
 	}
 
@@ -2851,6 +2849,7 @@
 	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 
 	pmb->context1 = NULL;
+	pmb->context2 = NULL;
 
 	if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
 		ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
@@ -3149,6 +3148,7 @@
 	ndlp = (struct lpfc_nodelist *) pmb->context2;
 	pmb->context1 = NULL;
 	pmb->context2 = NULL;
+
 	if (mb->mbxStatus) {
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
 				 "0258 Register Fabric login error: 0x%x\n",
@@ -3218,6 +3218,9 @@
 	struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
 	struct lpfc_vport *vport = pmb->vport;
 
+	pmb->context1 = NULL;
+	pmb->context2 = NULL;
+
 	if (mb->mbxStatus) {
 out:
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -3249,8 +3252,6 @@
 		return;
 	}
 
-	pmb->context1 = NULL;
-
 	ndlp->nlp_rpi = mb->un.varWords[0];
 	ndlp->nlp_flag |= NLP_RPI_VALID;
 	ndlp->nlp_type |= NLP_FABRIC;
@@ -4784,6 +4785,7 @@
 	struct lpfc_vport    *vport = pmb->vport;
 
 	pmb->context1 = NULL;
+	pmb->context2 = NULL;
 
 	ndlp->nlp_rpi = mb->un.varWords[0];
 	ndlp->nlp_flag |= NLP_RPI_VALID;
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 1676f61..a631647 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1380,6 +1380,9 @@
 #define MBX_INIT_VFI        0xA3
 #define MBX_INIT_VPI        0xA4
 
+#define MBX_AUTH_PORT       0xF8
+#define MBX_SECURITY_MGMT   0xF9
+
 /* IOCB Commands */
 
 #define CMD_RCV_SEQUENCE_CX     0x01
@@ -1502,7 +1505,8 @@
 #define MBXERR_DMA_ERROR            15
 #define MBXERR_ERROR                16
 #define MBXERR_LINK_DOWN            0x33
-#define MBX_NOT_FINISHED           255
+#define MBXERR_SEC_NO_PERMISSION    0xF02
+#define MBX_NOT_FINISHED            255
 
 #define MBX_BUSY                   0xffffff /* Attempted cmd to busy Mailbox */
 #define MBX_TIMEOUT                0xfffffe /* time-out expired waiting for */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index da9ba06..295c7dd 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1076,21 +1076,16 @@
 		} else {
 			/*
 			* If heart beat timeout called with hb_outstanding set
-			* we need to take the HBA offline.
+			* we need to give the hb mailbox cmd a chance to
+			* complete or TMO.
 			*/
-			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-					"0459 Adapter heartbeat failure, "
-					"taking this port offline.\n");
-
-			spin_lock_irq(&phba->hbalock);
-			psli->sli_flag &= ~LPFC_SLI_ACTIVE;
-			spin_unlock_irq(&phba->hbalock);
-
-			lpfc_offline_prep(phba);
-			lpfc_offline(phba);
-			lpfc_unblock_mgmt_io(phba);
-			phba->link_state = LPFC_HBA_ERROR;
-			lpfc_hba_down_post(phba);
+			lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+					"0459 Adapter heartbeat still out"
+					"standing:last compl time was %d ms.\n",
+					jiffies_to_msecs(jiffies
+						 - phba->last_completion_time));
+			mod_timer(&phba->hb_tmofunc,
+				  jiffies + HZ * LPFC_HB_MBOX_TIMEOUT);
 		}
 	}
 }
@@ -1277,13 +1272,21 @@
 	if (phba->hba_flag & DEFER_ERATT)
 		lpfc_handle_deferred_eratt(phba);
 
-	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]);
+	if ((phba->work_hs & HS_FFER6) || (phba->work_hs & HS_FFER8)) {
+		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]);
+		if (phba->work_hs & HS_FFER8)
+			/* Device Zeroization */
+			lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
+					"2861 Host Authentication device "
+					"zeroization Data:x%x x%x x%x\n",
+					phba->work_hs, phba->work_status[0],
+					phba->work_status[1]);
 
 		spin_lock_irq(&phba->hbalock);
 		psli->sli_flag &= ~LPFC_SLI_ACTIVE;
@@ -2817,6 +2820,8 @@
 		(((uint32_t) vport->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
 		(uint32_t) vport->fc_sparam.cmn.bbRcvSizeLsb;
 
+	fc_host_dev_loss_tmo(shost) = vport->cfg_devloss_tmo;
+
 	/* This value is also unchanging */
 	memset(fc_host_active_fc4s(shost), 0,
 	       sizeof(fc_host_active_fc4s(shost)));
@@ -2883,65 +2888,6 @@
 }
 
 /**
- * lpfc_sli4_remove_dflt_fcf - Remove the driver default fcf record from the port.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to remove the driver default fcf record from
- * the port.  This routine currently acts on FCF Index 0.
- *
- **/
-void
-lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba)
-{
-	int rc = 0;
-	LPFC_MBOXQ_t *mboxq;
-	struct lpfc_mbx_del_fcf_tbl_entry *del_fcf_record;
-	uint32_t mbox_tmo, req_len;
-	uint32_t shdr_status, shdr_add_status;
-
-	mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mboxq) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-			"2020 Failed to allocate mbox for ADD_FCF cmd\n");
-		return;
-	}
-
-	req_len = sizeof(struct lpfc_mbx_del_fcf_tbl_entry) -
-		  sizeof(struct lpfc_sli4_cfg_mhdr);
-	rc = lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
-			      LPFC_MBOX_OPCODE_FCOE_DELETE_FCF,
-			      req_len, LPFC_SLI4_MBX_EMBED);
-	/*
-	 * In phase 1, there is a single FCF index, 0.  In phase2, the driver
-	 * supports multiple FCF indices.
-	 */
-	del_fcf_record = &mboxq->u.mqe.un.del_fcf_entry;
-	bf_set(lpfc_mbx_del_fcf_tbl_count, del_fcf_record, 1);
-	bf_set(lpfc_mbx_del_fcf_tbl_index, del_fcf_record,
-	       phba->fcf.current_rec.fcf_indx);
-
-	if (!phba->sli4_hba.intr_enable)
-		rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-	else {
-		mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
-		rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
-	}
-	/* The IOCTL status is embedded in the mailbox subheader. */
-	shdr_status = bf_get(lpfc_mbox_hdr_status,
-			     &del_fcf_record->header.cfg_shdr.response);
-	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
-				 &del_fcf_record->header.cfg_shdr.response);
-	if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"2516 DEL FCF of default FCF Index failed "
-				"mbx status x%x, status x%x add_status x%x\n",
-				rc, shdr_status, shdr_add_status);
-	}
-	if (rc != MBX_TIMEOUT)
-		mempool_free(mboxq, phba->mbox_mem_pool);
-}
-
-/**
  * lpfc_fcf_redisc_wait_start_timer - Start fcf rediscover wait timer
  * @phba: Pointer to hba for which this call is being executed.
  *
@@ -4283,12 +4229,6 @@
 {
 	struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry;
 
-	/* unregister default FCFI from the HBA */
-	lpfc_sli4_fcfi_unreg(phba, phba->fcf.fcfi);
-
-	/* Free the default FCR table */
-	lpfc_sli_remove_dflt_fcf(phba);
-
 	/* Free memory allocated for msi-x interrupt vector entries */
 	kfree(phba->sli4_hba.msix_entries);
 
@@ -4316,9 +4256,6 @@
 	lpfc_sli4_cq_event_release_all(phba);
 	lpfc_sli4_cq_event_pool_destroy(phba);
 
-	/* Reset SLI4 HBA FCoE function */
-	lpfc_pci_function_reset(phba);
-
 	/* Free the bsmbx region. */
 	lpfc_destroy_bootstrap_mbox(phba);
 
@@ -4545,7 +4482,6 @@
 {
 	struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
 	LIST_HEAD(sglq_list);
-	int rc = 0;
 
 	spin_lock_irq(&phba->hbalock);
 	list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &sglq_list);
@@ -4558,11 +4494,6 @@
 		kfree(sglq_entry);
 		phba->sli4_hba.total_sglq_bufs--;
 	}
-	rc = lpfc_sli4_remove_all_sgl_pages(phba);
-	if (rc) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-			"2005 Unable to deregister pages from HBA: %x\n", rc);
-	}
 	kfree(phba->sli4_hba.lpfc_els_sgl_array);
 }
 
@@ -4725,8 +4656,8 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ * 	-ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 int
 lpfc_sli4_init_rpi_hdrs(struct lpfc_hba *phba)
@@ -5419,7 +5350,7 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - could not allocated memory.
+ * 	-ENOMEM - could not allocated memory.
  **/
 static int
 lpfc_create_bootstrap_mbox(struct lpfc_hba *phba)
@@ -5518,8 +5449,8 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ * 	-ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
 lpfc_sli4_read_config(struct lpfc_hba *phba)
@@ -5622,8 +5553,8 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ * 	-ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
 lpfc_setup_endian_order(struct lpfc_hba *phba)
@@ -5671,8 +5602,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
 lpfc_sli4_queue_create(struct lpfc_hba *phba)
@@ -5966,8 +5897,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 static void
 lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
@@ -6030,8 +5961,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 int
 lpfc_sli4_queue_setup(struct lpfc_hba *phba)
@@ -6275,8 +6206,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 void
 lpfc_sli4_queue_unset(struct lpfc_hba *phba)
@@ -6481,8 +6412,8 @@
  *
  * Return codes
  *      0 - successful
- *      ENOMEM - No availble memory
- *      EIO - The mailbox failed to complete successfully.
+ *      -ENOMEM - No availble memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 int
 lpfc_pci_function_reset(struct lpfc_hba *phba)
@@ -6592,50 +6523,6 @@
 }
 
 /**
- * lpfc_sli4_fcfi_unreg - Unregister fcfi to device
- * @phba: pointer to lpfc hba data structure.
- * @fcfi: fcf index.
- *
- * This routine is invoked to unregister a FCFI from device.
- **/
-void
-lpfc_sli4_fcfi_unreg(struct lpfc_hba *phba, uint16_t fcfi)
-{
-	LPFC_MBOXQ_t *mbox;
-	uint32_t mbox_tmo;
-	int rc;
-	unsigned long flags;
-
-	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-
-	if (!mbox)
-		return;
-
-	lpfc_unreg_fcfi(mbox, fcfi);
-
-	if (!phba->sli4_hba.intr_enable)
-		rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
-	else {
-		mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG);
-		rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
-	}
-	if (rc != MBX_TIMEOUT)
-		mempool_free(mbox, phba->mbox_mem_pool);
-	if (rc != MBX_SUCCESS)
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"2517 Unregister FCFI command failed "
-				"status %d, mbxStatus x%x\n", rc,
-				bf_get(lpfc_mqe_status, &mbox->u.mqe));
-	else {
-		spin_lock_irqsave(&phba->hbalock, flags);
-		/* Mark the FCFI is no longer registered */
-		phba->fcf.fcf_flag &=
-			~(FCF_AVAILABLE | FCF_REGISTERED | FCF_SCAN_DONE);
-		spin_unlock_irqrestore(&phba->hbalock, flags);
-	}
-}
-
-/**
  * lpfc_sli4_pci_mem_setup - Setup SLI4 HBA PCI memory space.
  * @phba: pointer to lpfc hba data structure.
  *
@@ -7372,10 +7259,14 @@
 
 	phba->pport->work_port_events = 0;
 
-	lpfc_sli4_hba_down(phba);
+	/* Stop the SLI4 device port */
+	lpfc_stop_port(phba);
 
 	lpfc_sli4_disable_intr(phba);
 
+	/* Reset SLI4 HBA FCoE function */
+	lpfc_pci_function_reset(phba);
+
 	return;
 }
 
@@ -7424,15 +7315,15 @@
 		spin_unlock_irq(&phba->hbalock);
 	}
 
-	/* Tear down the queues in the HBA */
-	lpfc_sli4_queue_unset(phba);
-
 	/* Disable PCI subsystem interrupt */
 	lpfc_sli4_disable_intr(phba);
 
 	/* Stop kthread signal shall trigger work_done one more time */
 	kthread_stop(phba->worker_thread);
 
+	/* Reset SLI4 HBA FCoE function */
+	lpfc_pci_function_reset(phba);
+
 	/* Stop the SLI4 device port */
 	phba->pport->work_port_events = 0;
 }
@@ -8368,7 +8259,7 @@
 	list_del_init(&vport->listentry);
 	spin_unlock_irq(&phba->hbalock);
 
-	/* Call scsi_free before lpfc_sli4_driver_resource_unset since scsi
+	/* Perform scsi free before driver resource_unset since scsi
 	 * buffers are released to their corresponding pools here.
 	 */
 	lpfc_scsi_free(phba);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 2e51aa6..3a65895 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -599,6 +599,7 @@
 		iocb->ulpClass = CLASS3;
 		psb->status = IOSTAT_SUCCESS;
 		/* Put it back into the SCSI buffer list */
+		psb->cur_iocbq.context1  = psb;
 		lpfc_release_scsi_buf_s3(phba, psb);
 
 	}
@@ -849,6 +850,7 @@
 		iocb->ulpBdeCount = 1;
 		iocb->ulpLe = 1;
 		iocb->ulpClass = CLASS3;
+		psb->cur_iocbq.context1  = psb;
 		if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
 			pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE;
 		else
@@ -2276,15 +2278,24 @@
 	 * Check SLI validation that all the transfer was actually done
 	 * (fcpi_parm should be zero). Apply check only to reads.
 	 */
-	} else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm &&
-			(cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
+	} else if (fcpi_parm && (cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
 		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR,
 				 "9029 FCP Read Check Error Data: "
-				 "x%x x%x x%x x%x\n",
+				 "x%x x%x x%x x%x x%x\n",
 				 be32_to_cpu(fcpcmd->fcpDl),
 				 be32_to_cpu(fcprsp->rspResId),
-				 fcpi_parm, cmnd->cmnd[0]);
-		host_status = DID_ERROR;
+				 fcpi_parm, cmnd->cmnd[0], scsi_status);
+		switch (scsi_status) {
+		case SAM_STAT_GOOD:
+		case SAM_STAT_CHECK_CONDITION:
+			/* Fabric dropped a data frame. Fail any successful
+			 * command in which we detected dropped frames.
+			 * A status of good or some check conditions could
+			 * be considered a successful command.
+			 */
+			host_status = DID_ERROR;
+			break;
+		}
 		scsi_set_resid(cmnd, scsi_bufflen(cmnd));
 	}
 
@@ -3072,7 +3083,14 @@
 	if (ret)
 		return ret;
 	lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
-	BUG_ON(!lpfc_cmd);
+	if (!lpfc_cmd) {
+		lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+			 "2873 SCSI Layer I/O Abort Request IO CMPL Status "
+			 "x%x ID %d "
+			 "LUN %d snum %#lx\n", ret, cmnd->device->id,
+			 cmnd->device->lun, cmnd->serial_number);
+		return SUCCESS;
+	}
 
 	/*
 	 * If pCmd field of the corresponding lpfc_scsi_buf structure
@@ -3656,7 +3674,6 @@
  *
  * This routine configures following items
  *   - Tag command queuing support for @sdev if supported.
- *   - Dev loss time out value of fc_rport.
  *   - Enable SLI polling for fcp ring if ENABLE_FCP_RING_POLLING flag is set.
  *
  * Return codes:
@@ -3667,21 +3684,12 @@
 {
 	struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
 	struct lpfc_hba   *phba = vport->phba;
-	struct fc_rport   *rport = starget_to_rport(sdev->sdev_target);
 
 	if (sdev->tagged_supported)
 		scsi_activate_tcq(sdev, vport->cfg_lun_queue_depth);
 	else
 		scsi_deactivate_tcq(sdev, vport->cfg_lun_queue_depth);
 
-	/*
-	 * Initialize the fc transport attributes for the target
-	 * containing this scsi device.  Also note that the driver's
-	 * target pointer is stored in the starget_data for the
-	 * driver's sysfs entry point functions.
-	 */
-	rport->dev_loss_tmo = vport->cfg_devloss_tmo;
-
 	if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
 		lpfc_sli_handle_fast_ring_event(phba,
 			&phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index fb8905f..0d1e187 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1677,6 +1677,8 @@
 	case MBX_RESUME_RPI:
 	case MBX_READ_EVENT_LOG_STATUS:
 	case MBX_READ_EVENT_LOG:
+	case MBX_SECURITY_MGMT:
+	case MBX_AUTH_PORT:
 		ret = mbxCommand;
 		break;
 	default:
@@ -1730,10 +1732,11 @@
 void
 lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 {
+	struct lpfc_vport  *vport = pmb->vport;
 	struct lpfc_dmabuf *mp;
+	struct lpfc_nodelist *ndlp;
 	uint16_t rpi, vpi;
 	int rc;
-	struct lpfc_vport  *vport = pmb->vport;
 
 	mp = (struct lpfc_dmabuf *) (pmb->context1);
 
@@ -1774,6 +1777,19 @@
 			return;
 	}
 
+	if (pmb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
+		ndlp = (struct lpfc_nodelist *)pmb->context2;
+		lpfc_nlp_put(ndlp);
+		pmb->context2 = NULL;
+	}
+
+	/* Check security permission status on INIT_LINK mailbox command */
+	if ((pmb->u.mb.mbxCommand == MBX_INIT_LINK) &&
+	    (pmb->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION))
+		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+				"2860 SLI authentication is required "
+				"for INIT_LINK but has not done yet\n");
+
 	if (bf_get(lpfc_mqe_command, &pmb->u.mqe) == MBX_SLI4_CONFIG)
 		lpfc_sli4_mbox_cmd_free(phba, pmb);
 	else
@@ -3651,11 +3667,15 @@
 	i = 0;
 	while ((status & (HS_FFRDY | HS_MBRDY)) != (HS_FFRDY | HS_MBRDY)) {
 
-		/* Check every 100ms for 5 retries, then every 500ms for 5, then
-		 * every 2.5 sec for 5, then reset board and every 2.5 sec for
-		 * 4.
+		/* Check every 10ms for 10 retries, then every 100ms for 90
+		 * retries, then every 1 sec for 50 retires for a total of
+		 * ~60 seconds before reset the board again and check every
+		 * 1 sec for 50 retries. The up to 60 seconds before the
+		 * board ready is required by the Falcon FIPS zeroization
+		 * complete, and any reset the board in between shall cause
+		 * restart of zeroization, further delay the board ready.
 		 */
-		if (i++ >= 20) {
+		if (i++ >= 200) {
 			/* Adapter failed to init, timeout, status reg
 			   <status> */
 			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -3683,16 +3703,15 @@
 			return -EIO;
 		}
 
-		if (i <= 5) {
+		if (i <= 10)
 			msleep(10);
-		} else if (i <= 10) {
-			msleep(500);
-		} else {
-			msleep(2500);
-		}
+		else if (i <= 100)
+			msleep(100);
+		else
+			msleep(1000);
 
-		if (i == 15) {
-				/* Do post */
+		if (i == 150) {
+			/* Do post */
 			phba->pport->port_state = LPFC_VPORT_UNKNOWN;
 			lpfc_sli_brdrestart(phba);
 		}
@@ -4186,7 +4205,7 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - could not allocated memory.
+ * 	-ENOMEM - could not allocated memory.
  **/
 static int
 lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
@@ -5943,6 +5962,8 @@
 	uint8_t command_type = ELS_COMMAND_NON_FIP;
 	uint8_t cmnd;
 	uint16_t xritag;
+	uint16_t abrt_iotag;
+	struct lpfc_iocbq *abrtiocbq;
 	struct ulp_bde64 *bpl = NULL;
 	uint32_t els_id = ELS_ID_DEFAULT;
 	int numBdes, i;
@@ -6155,9 +6176,17 @@
 	case CMD_ABORT_XRI_CX:
 		/* words 0-2 memcpy should be 0 rserved */
 		/* port will send abts */
-		if (iocbq->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
+		abrt_iotag = iocbq->iocb.un.acxri.abortContextTag;
+		if (abrt_iotag != 0 && abrt_iotag <= phba->sli.last_iotag) {
+			abrtiocbq = phba->sli.iocbq_lookup[abrt_iotag];
+			fip = abrtiocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK;
+		} else
+			fip = 0;
+
+		if ((iocbq->iocb.ulpCommand == CMD_CLOSE_XRI_CN) || fip)
 			/*
-			 * The link is down so the fw does not need to send abts
+			 * The link is down, or the command was ELS_FIP
+			 * so the fw does not need to send abts
 			 * on the wire.
 			 */
 			bf_set(abort_cmd_ia, &wqe->abort_cmd, 1);
@@ -6901,37 +6930,6 @@
 }
 
 /**
- * lpfc_sli4_hba_down - PCI function resource cleanup for the SLI4 HBA
- * @phba: Pointer to HBA context object.
- *
- * This function cleans up all queues, iocb, buffers, mailbox commands while
- * shutting down the SLI4 HBA FCoE function. This function is called with no
- * lock held and always returns 1.
- *
- * This function does the following to cleanup driver FCoE function resources:
- * - Free discovery resources for each virtual port
- * - Cleanup any pending fabric iocbs
- * - Iterate through the iocb txq and free each entry in the list.
- * - Free up any buffer posted to the HBA.
- * - Clean up all the queue entries: WQ, RQ, MQ, EQ, CQ, etc.
- * - Free mailbox commands in the mailbox queue.
- **/
-int
-lpfc_sli4_hba_down(struct lpfc_hba *phba)
-{
-	/* Stop the SLI4 device port */
-	lpfc_stop_port(phba);
-
-	/* Tear down the queues in the HBA */
-	lpfc_sli4_queue_unset(phba);
-
-	/* unregister default FCFI from the HBA */
-	lpfc_sli4_fcfi_unreg(phba, phba->fcf.fcfi);
-
-	return 1;
-}
-
-/**
  * lpfc_sli_pcimem_bcopy - SLI memory copy function
  * @srcp: Source memory pointer.
  * @destp: Destination memory pointer.
@@ -7888,7 +7886,7 @@
 		/* Check if there is a deferred error condition is active */
 		if ((HS_FFER1 & phba->work_hs) &&
 		    ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
-		     HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+		      HS_FFER6 | HS_FFER7 | HS_FFER8) & phba->work_hs)) {
 			phba->hba_flag |= DEFER_ERATT;
 			/* Clear all interrupt enable conditions */
 			writel(0, phba->HCregaddr);
@@ -8204,7 +8202,8 @@
 			 */
 			if ((HS_FFER1 & phba->work_hs) &&
 				((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
-				HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+				  HS_FFER6 | HS_FFER7 | HS_FFER8) &
+				  phba->work_hs)) {
 				phba->hba_flag |= DEFER_ERATT;
 				/* Clear all interrupt enable conditions */
 				writel(0, phba->HCregaddr);
@@ -8476,7 +8475,7 @@
 	 * If there is deferred error attention, do not check for any interrupt.
 	 */
 	if (unlikely(phba->hba_flag & DEFER_ERATT)) {
-		spin_unlock_irq(&phba->hbalock);
+		spin_unlock(&phba->hbalock);
 		return IRQ_NONE;
 	}
 
@@ -9724,8 +9723,8 @@
  * command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t imax)
@@ -9840,8 +9839,8 @@
  * command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
@@ -10011,8 +10010,8 @@
  * command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 int32_t
 lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
@@ -10146,8 +10145,8 @@
  * command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
@@ -10234,8 +10233,8 @@
  * mailbox command to finish before continuing.
  *
  * On success this function will return a zero. If unable to allocate enough
- * memory this function will return ENOMEM. If the queue create mailbox command
- * fails this function will return ENXIO.
+ * memory this function will return -ENOMEM. If the queue create mailbox command
+ * fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
@@ -10403,7 +10402,7 @@
  * The @eq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq)
@@ -10458,7 +10457,7 @@
  * The @cq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq)
@@ -10511,7 +10510,7 @@
  * The @mq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq)
@@ -10564,7 +10563,7 @@
  * The @wq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq)
@@ -10616,7 +10615,7 @@
  * The @rq struct is used to get the queue ID of the queue to destroy.
  *
  * On success this function will return a zero. If the queue destroy mailbox
- * command fails this function will return ENXIO.
+ * command fails this function will return -ENXIO.
  **/
 uint32_t
 lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq,
@@ -10758,51 +10757,6 @@
 	}
 	return 0;
 }
-/**
- * lpfc_sli4_remove_all_sgl_pages - Post scatter gather list for an XRI to HBA
- * @phba: The virtual port for which this call being executed.
- *
- * This routine will remove all of the sgl pages registered with the hba.
- *
- * Return codes:
- * 	0 - Success
- * 	-ENXIO, -ENOMEM - Failure
- **/
-int
-lpfc_sli4_remove_all_sgl_pages(struct lpfc_hba *phba)
-{
-	LPFC_MBOXQ_t *mbox;
-	int rc;
-	uint32_t shdr_status, shdr_add_status;
-	union lpfc_sli4_cfg_shdr *shdr;
-
-	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-	if (!mbox)
-		return -ENOMEM;
-
-	lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
-			LPFC_MBOX_OPCODE_FCOE_REMOVE_SGL_PAGES, 0,
-			LPFC_SLI4_MBX_EMBED);
-	if (!phba->sli4_hba.intr_enable)
-		rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
-	else
-		rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
-	/* The IOCTL status is embedded in the mailbox subheader. */
-	shdr = (union lpfc_sli4_cfg_shdr *)
-		&mbox->u.mqe.un.sli4_config.header.cfg_shdr;
-	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
-	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
-	if (rc != MBX_TIMEOUT)
-		mempool_free(mbox, phba->mbox_mem_pool);
-	if (shdr_status || shdr_add_status || rc) {
-		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-				"2512 REMOVE_ALL_SGL_PAGES mailbox failed with "
-				"status x%x add_status x%x, mbx status x%x\n",
-				shdr_status, shdr_add_status, rc);
-		rc = -ENXIO;
-	}
-	return rc;
-}
 
 /**
  * lpfc_sli4_next_xritag - Get an xritag for the io
@@ -11819,7 +11773,7 @@
  *
  * Return codes
  * 	0 - successful
- *      EIO - The mailbox failed to complete successfully.
+ *      -EIO - The mailbox failed to complete successfully.
  * 	When this error occurs, the driver is not guaranteed
  *	to have any rpi regions posted to the device and
  *	must either attempt to repost the regions or take a
@@ -11857,8 +11811,8 @@
  *
  * Return codes
  * 	0 - successful
- * 	ENOMEM - No available memory
- *      EIO - The mailbox failed to complete successfully.
+ * 	-ENOMEM - No available memory
+ *      -EIO - The mailbox failed to complete successfully.
  **/
 int
 lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
@@ -12805,8 +12759,11 @@
 	LPFC_MBOXQ_t *mb, *nextmb;
 	struct lpfc_dmabuf *mp;
 	struct lpfc_nodelist *ndlp;
+	struct lpfc_nodelist *act_mbx_ndlp = NULL;
 	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
+	LIST_HEAD(mbox_cmd_list);
 
+	/* Clean up internally queued mailbox commands with the vport */
 	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
 		if (mb->vport != vport)
@@ -12816,6 +12773,28 @@
 			(mb->u.mb.mbxCommand != MBX_REG_VPI))
 			continue;
 
+		list_del(&mb->list);
+		list_add_tail(&mb->list, &mbox_cmd_list);
+	}
+	/* Clean up active mailbox command with the vport */
+	mb = phba->sli.mbox_active;
+	if (mb && (mb->vport == vport)) {
+		if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) ||
+			(mb->u.mb.mbxCommand == MBX_REG_VPI))
+			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
+			act_mbx_ndlp = (struct lpfc_nodelist *)mb->context2;
+			/* Put reference count for delayed processing */
+			act_mbx_ndlp = lpfc_nlp_get(act_mbx_ndlp);
+			/* Unregister the RPI when mailbox complete */
+			mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
+		}
+	}
+	spin_unlock_irq(&phba->hbalock);
+
+	/* Release the cleaned-up mailbox commands */
+	while (!list_empty(&mbox_cmd_list)) {
+		list_remove_head(&mbox_cmd_list, mb, LPFC_MBOXQ_t, list);
 		if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
 			if (phba->sli_rev == LPFC_SLI_REV4)
 				__lpfc_sli4_free_rpi(phba,
@@ -12826,36 +12805,24 @@
 				kfree(mp);
 			}
 			ndlp = (struct lpfc_nodelist *) mb->context2;
+			mb->context2 = NULL;
 			if (ndlp) {
-				spin_lock_irq(shost->host_lock);
+				spin_lock(shost->host_lock);
 				ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
-				spin_unlock_irq(shost->host_lock);
+				spin_unlock(shost->host_lock);
 				lpfc_nlp_put(ndlp);
-				mb->context2 = NULL;
 			}
 		}
-		list_del(&mb->list);
 		mempool_free(mb, phba->mbox_mem_pool);
 	}
-	mb = phba->sli.mbox_active;
-	if (mb && (mb->vport == vport)) {
-		if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) ||
-			(mb->u.mb.mbxCommand == MBX_REG_VPI))
-			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-		if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
-			ndlp = (struct lpfc_nodelist *) mb->context2;
-			if (ndlp) {
-				spin_lock_irq(shost->host_lock);
-				ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
-				spin_unlock_irq(shost->host_lock);
-				lpfc_nlp_put(ndlp);
-				mb->context2 = NULL;
-			}
-			/* Unregister the RPI when mailbox complete */
-			mb->mbox_flag |= LPFC_MBX_IMED_UNREG;
-		}
+
+	/* Release the ndlp with the cleaned-up active mailbox command */
+	if (act_mbx_ndlp) {
+		spin_lock(shost->host_lock);
+		act_mbx_ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
+		spin_unlock(shost->host_lock);
+		lpfc_nlp_put(act_mbx_ndlp);
 	}
-	spin_unlock_irq(&phba->hbalock);
 }
 
 /**
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index a3b24d9..a0ca572 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -481,7 +481,6 @@
  */
 int lpfc_pci_function_reset(struct lpfc_hba *);
 int lpfc_sli4_hba_setup(struct lpfc_hba *);
-int lpfc_sli4_hba_down(struct lpfc_hba *);
 int lpfc_sli4_config(struct lpfc_hba *, struct lpfcMboxq *, uint8_t,
 		     uint8_t, uint32_t, bool);
 void lpfc_sli4_mbox_cmd_free(struct lpfc_hba *, struct lpfcMboxq *);
@@ -514,7 +513,6 @@
 void lpfc_sli4_queue_unset(struct lpfc_hba *);
 int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t);
 int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *);
-int lpfc_sli4_remove_all_sgl_pages(struct lpfc_hba *);
 uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *);
 int lpfc_sli4_post_async_mbox(struct lpfc_hba *);
 int lpfc_sli4_post_sgl_list(struct lpfc_hba *phba);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 61afb34..f93120e 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.3.16"
+#define LPFC_DRIVER_VERSION "8.3.17"
 #define LPFC_DRIVER_NAME		"lpfc"
 #define LPFC_SP_DRIVER_HANDLER_NAME	"lpfc:sp"
 #define LPFC_FP_DRIVER_HANDLER_NAME	"lpfc:fp"
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 1655507..a5281ce 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -580,7 +580,9 @@
 				 "static vport.\n");
 		return VPORT_ERROR;
 	}
-
+	spin_lock_irq(&phba->hbalock);
+	vport->load_flag |= FC_UNLOADING;
+	spin_unlock_irq(&phba->hbalock);
 	/*
 	 * If we are not unloading the driver then prevent the vport_delete
 	 * from happening until after this vport's discovery is finished.
@@ -618,10 +620,6 @@
 		scsi_host_put(shost);
 		return VPORT_INVAL;
 	}
-	spin_lock_irq(&phba->hbalock);
-	vport->load_flag |= FC_UNLOADING;
-	spin_unlock_irq(&phba->hbalock);
-
 	lpfc_free_sysfs_attr(vport);
 
 	lpfc_debugfs_terminate(vport);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 0b6e322..7ceb5cf 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -46,7 +46,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <scsi/scsicam.h>
 
@@ -62,6 +62,7 @@
 MODULE_LICENSE ("GPL");
 MODULE_VERSION(MEGARAID_MODULE_VERSION);
 
+static DEFINE_MUTEX(megadev_mutex);
 static unsigned int max_cmd_per_lun = DEF_CMD_PER_LUN;
 module_param(max_cmd_per_lun, uint, 0);
 MODULE_PARM_DESC(max_cmd_per_lun, "Maximum number of commands which can be issued to a single LUN (default=DEF_CMD_PER_LUN=63)");
@@ -101,6 +102,7 @@
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= megadev_unlocked_ioctl,
 	.open		= megadev_open,
+	.llseek		= noop_llseek,
 };
 
 /*
@@ -3282,7 +3284,6 @@
 static int
 megadev_open (struct inode *inode, struct file *filep)
 {
-	cycle_kernel_lock();
 	/*
 	 * Only allow superuser to access private ioctl interface
 	 */
@@ -3701,9 +3702,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&megadev_mutex);
 	ret = megadev_ioctl(filep, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&megadev_mutex);
 
 	return ret;
 }
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index 41f82f7..a7008c0 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -16,11 +16,12 @@
  */
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include "megaraid_mm.h"
 
 
 // Entry points for char node driver
+static DEFINE_MUTEX(mraid_mm_mutex);
 static int mraid_mm_open(struct inode *, struct file *);
 static long mraid_mm_unlocked_ioctl(struct file *, uint, unsigned long);
 
@@ -75,6 +76,7 @@
 	.compat_ioctl = mraid_mm_compat_ioctl,
 #endif
 	.owner	= THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice megaraid_mm_dev = {
@@ -98,7 +100,6 @@
 	 */
 	if (!capable(CAP_SYS_ADMIN)) return (-EACCES);
 
-	cycle_kernel_lock();
 	return 0;
 }
 
@@ -224,9 +225,9 @@
 	int err;
 
 	/* inconsistant: mraid_mm_compat_ioctl doesn't take the BKL */
-	lock_kernel();
+	mutex_lock(&mraid_mm_mutex);
 	err = mraid_mm_ioctl(filep, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&mraid_mm_mutex);
 
 	return err;
 }
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 99e4478..d3c9cde 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -33,7 +33,6 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
@@ -62,6 +61,11 @@
 MODULE_AUTHOR("megaraidlinux@lsi.com");
 MODULE_DESCRIPTION("LSI MegaRAID SAS Driver");
 
+static int megasas_transition_to_ready(struct megasas_instance *instance);
+static int megasas_get_pd_list(struct megasas_instance *instance);
+static int megasas_issue_init_mfi(struct megasas_instance *instance);
+static int megasas_register_aen(struct megasas_instance *instance,
+				u32 seq_num, u32 class_locale_word);
 /*
  * PCI ID table for all supported controllers
  */
@@ -164,7 +168,7 @@
 static inline void
 megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
 {
-	writel(1, &(regs)->outbound_intr_mask);
+	writel(0, &(regs)->outbound_intr_mask);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_mask);
@@ -200,24 +204,27 @@
 megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
 {
 	u32 status;
+	u32 mfiStatus = 0;
 	/*
 	 * Check if it is our interrupt
 	 */
 	status = readl(&regs->outbound_intr_status);
 
-	if (!(status & MFI_OB_INTR_STATUS_MASK)) {
-		return 1;
-	}
+	if (status & MFI_OB_INTR_STATUS_MASK)
+		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+	if (status & MFI_XSCALE_OMR0_CHANGE_INTERRUPT)
+		mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
 
 	/*
 	 * Clear the interrupt by writing back the same value
 	 */
-	writel(status, &regs->outbound_intr_status);
+	if (mfiStatus)
+		writel(status, &regs->outbound_intr_status);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_status);
 
-	return 0;
+	return mfiStatus;
 }
 
 /**
@@ -232,8 +239,69 @@
 		u32 frame_count,
 		struct megasas_register_set __iomem *regs)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel((frame_phys_addr >> 3)|(frame_count),
 	       &(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_xscale -  For controller reset
+ * @regs:                              MFI register set
+ */
+static int
+megasas_adp_reset_xscale(struct megasas_instance *instance,
+	struct megasas_register_set __iomem *regs)
+{
+	u32 i;
+	u32 pcidata;
+	writel(MFI_ADP_RESET, &regs->inbound_doorbell);
+
+	for (i = 0; i < 3; i++)
+		msleep(1000); /* sleep for 3 secs */
+	pcidata  = 0;
+	pci_read_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, &pcidata);
+	printk(KERN_NOTICE "pcidata = %x\n", pcidata);
+	if (pcidata & 0x2) {
+		printk(KERN_NOTICE "mfi 1068 offset read=%x\n", pcidata);
+		pcidata &= ~0x2;
+		pci_write_config_dword(instance->pdev,
+				MFI_1068_PCSR_OFFSET, pcidata);
+
+		for (i = 0; i < 2; i++)
+			msleep(1000); /* need to wait 2 secs again */
+
+		pcidata  = 0;
+		pci_read_config_dword(instance->pdev,
+				MFI_1068_FW_HANDSHAKE_OFFSET, &pcidata);
+		printk(KERN_NOTICE "1068 offset handshake read=%x\n", pcidata);
+		if ((pcidata & 0xffff0000) == MFI_1068_FW_READY) {
+			printk(KERN_NOTICE "1068 offset pcidt=%x\n", pcidata);
+			pcidata = 0;
+			pci_write_config_dword(instance->pdev,
+				MFI_1068_FW_HANDSHAKE_OFFSET, pcidata);
+		}
+	}
+	return 0;
+}
+
+/**
+ * megasas_check_reset_xscale -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_xscale(struct megasas_instance *instance,
+		struct megasas_register_set __iomem *regs)
+{
+	u32 consumer;
+	consumer = *instance->consumer;
+
+	if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) &&
+		(*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) {
+		return 1;
+	}
+	return 0;
 }
 
 static struct megasas_instance_template megasas_instance_template_xscale = {
@@ -243,6 +311,8 @@
 	.disable_intr = megasas_disable_intr_xscale,
 	.clear_intr = megasas_clear_intr_xscale,
 	.read_fw_status_reg = megasas_read_fw_status_reg_xscale,
+	.adp_reset = megasas_adp_reset_xscale,
+	.check_reset = megasas_check_reset_xscale,
 };
 
 /**
@@ -264,7 +334,7 @@
 {
 	writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
     
-	writel(~0x80000004, &(regs)->outbound_intr_mask);
+	writel(~0x80000000, &(regs)->outbound_intr_mask);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_mask);
@@ -307,7 +377,7 @@
 	status = readl(&regs->outbound_intr_status);
 
 	if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
-		return 1;
+		return 0;
 	}
 
 	/*
@@ -318,7 +388,7 @@
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_doorbell_clear);
 
-	return 0;
+	return 1;
 }
 /**
  * megasas_fire_cmd_ppc -	Sends command to the FW
@@ -332,10 +402,34 @@
 		u32 frame_count,
 		struct megasas_register_set __iomem *regs)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel((frame_phys_addr | (frame_count<<1))|1, 
 			&(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
 }
 
+/**
+ * megasas_adp_reset_ppc -	For controller reset
+ * @regs:				MFI register set
+ */
+static int
+megasas_adp_reset_ppc(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
+
+/**
+ * megasas_check_reset_ppc -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_ppc(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
 static struct megasas_instance_template megasas_instance_template_ppc = {
 	
 	.fire_cmd = megasas_fire_cmd_ppc,
@@ -343,6 +437,8 @@
 	.disable_intr = megasas_disable_intr_ppc,
 	.clear_intr = megasas_clear_intr_ppc,
 	.read_fw_status_reg = megasas_read_fw_status_reg_ppc,
+	.adp_reset = megasas_adp_reset_ppc,
+	.check_reset = megasas_check_reset_ppc,
 };
 
 /**
@@ -397,7 +493,7 @@
 	status = readl(&regs->outbound_intr_status);
 
 	if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
-		return 1;
+		return 0;
 	}
 
 	/*
@@ -410,7 +506,7 @@
 	*/
 	readl(&regs->outbound_intr_status);
 
-	return 0;
+	return 1;
 }
 
 /**
@@ -426,11 +522,33 @@
 			struct megasas_register_set __iomem *regs)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&instance->fire_lock, flags);
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel(0, &(regs)->inbound_high_queue_port);
 	writel((frame_phys_addr | (frame_count<<1))|1,
 		&(regs)->inbound_low_queue_port);
-	spin_unlock_irqrestore(&instance->fire_lock, flags);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_skinny -	For controller reset
+ * @regs:				MFI register set
+ */
+static int
+megasas_adp_reset_skinny(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *regs)
+{
+	return 0;
+}
+
+/**
+ * megasas_check_reset_skinny -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_skinny(struct megasas_instance *instance,
+				struct megasas_register_set __iomem *regs)
+{
+	return 0;
 }
 
 static struct megasas_instance_template megasas_instance_template_skinny = {
@@ -440,6 +558,8 @@
 	.disable_intr = megasas_disable_intr_skinny,
 	.clear_intr = megasas_clear_intr_skinny,
 	.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
+	.adp_reset = megasas_adp_reset_skinny,
+	.check_reset = megasas_check_reset_skinny,
 };
 
 
@@ -495,23 +615,29 @@
 megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
 {
 	u32 status;
+	u32 mfiStatus = 0;
 	/*
 	 * Check if it is our interrupt
 	 */
 	status = readl(&regs->outbound_intr_status);
 
-	if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK))
-		return 1;
+	if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK) {
+		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+	}
+	if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT) {
+		mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
+	}
 
 	/*
 	 * Clear the interrupt by writing back the same value
 	 */
-	writel(status, &regs->outbound_doorbell_clear);
+	if (mfiStatus)
+		writel(status, &regs->outbound_doorbell_clear);
 
 	/* Dummy readl to force pci flush */
 	readl(&regs->outbound_intr_status);
 
-	return 0;
+	return mfiStatus;
 }
 /**
  * megasas_fire_cmd_gen2 -     Sends command to the FW
@@ -525,8 +651,74 @@
 			u32 frame_count,
 			struct megasas_register_set __iomem *regs)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&instance->hba_lock, flags);
 	writel((frame_phys_addr | (frame_count<<1))|1,
 			&(regs)->inbound_queue_port);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+}
+
+/**
+ * megasas_adp_reset_gen2 -	For controller reset
+ * @regs:				MFI register set
+ */
+static int
+megasas_adp_reset_gen2(struct megasas_instance *instance,
+			struct megasas_register_set __iomem *reg_set)
+{
+	u32			retry = 0 ;
+	u32			HostDiag;
+
+	writel(0, &reg_set->seq_offset);
+	writel(4, &reg_set->seq_offset);
+	writel(0xb, &reg_set->seq_offset);
+	writel(2, &reg_set->seq_offset);
+	writel(7, &reg_set->seq_offset);
+	writel(0xd, &reg_set->seq_offset);
+	msleep(1000);
+
+	HostDiag = (u32)readl(&reg_set->host_diag);
+
+	while ( !( HostDiag & DIAG_WRITE_ENABLE) ) {
+		msleep(100);
+		HostDiag = (u32)readl(&reg_set->host_diag);
+		printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
+					retry, HostDiag);
+
+		if (retry++ >= 100)
+			return 1;
+
+	}
+
+	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
+
+	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
+
+	ssleep(10);
+
+	HostDiag = (u32)readl(&reg_set->host_diag);
+	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
+		msleep(100);
+		HostDiag = (u32)readl(&reg_set->host_diag);
+		printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n",
+				retry, HostDiag);
+
+		if (retry++ >= 1000)
+			return 1;
+
+	}
+	return 0;
+}
+
+/**
+ * megasas_check_reset_gen2 -	For controller reset check
+ * @regs:				MFI register set
+ */
+static int
+megasas_check_reset_gen2(struct megasas_instance *instance,
+		struct megasas_register_set __iomem *regs)
+{
+	return 0;
 }
 
 static struct megasas_instance_template megasas_instance_template_gen2 = {
@@ -536,11 +728,13 @@
 	.disable_intr = megasas_disable_intr_gen2,
 	.clear_intr = megasas_clear_intr_gen2,
 	.read_fw_status_reg = megasas_read_fw_status_reg_gen2,
+	.adp_reset = megasas_adp_reset_gen2,
+	.check_reset = megasas_check_reset_gen2,
 };
 
 /**
 *	This is the end of set of functions & definitions
-* 	specific to ppc (deviceid : 0x60) controllers
+*       specific to gen2 (deviceid : 0x78, 0x79) controllers
 */
 
 /**
@@ -599,8 +793,7 @@
 	instance->instancet->fire_cmd(instance,
 			cmd->frame_phys_addr, 0, instance->reg_set);
 
-	wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA),
-		MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
+	wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA);
 
 	return 0;
 }
@@ -648,8 +841,8 @@
 	/*
 	 * Wait for this cmd to complete
 	 */
-	wait_event_timeout(instance->abort_cmd_wait_q, (cmd->cmd_status != 0xFF),
-		MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ);
+	wait_event(instance->abort_cmd_wait_q, cmd->cmd_status != 0xFF);
+	cmd->sync_cmd = 0;
 
 	megasas_return_cmd(instance, cmd);
 	return 0;
@@ -1131,14 +1324,22 @@
 	u32 frame_count;
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance;
+	unsigned long flags;
 
 	instance = (struct megasas_instance *)
 	    scmd->device->host->hostdata;
 
-	/* Don't process if we have already declared adapter dead */
-	if (instance->hw_crit_error)
+	if (instance->issuepend_done == 0)
 		return SCSI_MLQUEUE_HOST_BUSY;
 
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
 	scmd->scsi_done = done;
 	scmd->result = 0;
 
@@ -1274,6 +1475,18 @@
 	return 0;
 }
 
+static void megaraid_sas_kill_hba(struct megasas_instance *instance)
+{
+	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
+		(instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
+		writel(MFI_STOP_ADP,
+			&instance->reg_set->reserved_0[0]);
+	} else {
+		writel(MFI_STOP_ADP,
+			&instance->reg_set->inbound_doorbell);
+	}
+}
+
 /**
  * megasas_complete_cmd_dpc	 -	Returns FW's controller structure
  * @instance_addr:			Address of adapter soft state
@@ -1291,7 +1504,7 @@
 	unsigned long flags;
 
 	/* If we have already declared adapter dead, donot complete cmds */
-	if (instance->hw_crit_error)
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR )
 		return;
 
 	spin_lock_irqsave(&instance->completion_lock, flags);
@@ -1301,6 +1514,11 @@
 
 	while (consumer != producer) {
 		context = instance->reply_queue[consumer];
+		if (context >= instance->max_fw_cmds) {
+			printk(KERN_ERR "Unexpected context value %x\n",
+				context);
+			BUG();
+		}
 
 		cmd = instance->cmd_list[context];
 
@@ -1350,7 +1568,76 @@
 static int megasas_wait_for_outstanding(struct megasas_instance *instance)
 {
 	int i;
+	u32 reset_index;
 	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
+	u8 adprecovery;
+	unsigned long flags;
+	struct list_head clist_local;
+	struct megasas_cmd *reset_cmd;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	adprecovery = instance->adprecovery;
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+
+		INIT_LIST_HEAD(&clist_local);
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		list_splice_init(&instance->internal_reset_pending_q,
+				&clist_local);
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		printk(KERN_NOTICE "megasas: HBA reset wait ...\n");
+		for (i = 0; i < wait_time; i++) {
+			msleep(1000);
+			spin_lock_irqsave(&instance->hba_lock, flags);
+			adprecovery = instance->adprecovery;
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			if (adprecovery == MEGASAS_HBA_OPERATIONAL)
+				break;
+		}
+
+		if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
+			printk(KERN_NOTICE "megasas: reset: Stopping HBA.\n");
+			spin_lock_irqsave(&instance->hba_lock, flags);
+			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			return FAILED;
+		}
+
+		reset_index	= 0;
+		while (!list_empty(&clist_local)) {
+			reset_cmd	= list_entry((&clist_local)->next,
+						struct megasas_cmd, list);
+			list_del_init(&reset_cmd->list);
+			if (reset_cmd->scmd) {
+				reset_cmd->scmd->result = DID_RESET << 16;
+				printk(KERN_NOTICE "%d:%p reset [%02x], %#lx\n",
+					reset_index, reset_cmd,
+					reset_cmd->scmd->cmnd[0],
+					reset_cmd->scmd->serial_number);
+
+				reset_cmd->scmd->scsi_done(reset_cmd->scmd);
+				megasas_return_cmd(instance, reset_cmd);
+			} else if (reset_cmd->sync_cmd) {
+				printk(KERN_NOTICE "megasas:%p synch cmds"
+						"reset queue\n",
+						reset_cmd);
+
+				reset_cmd->cmd_status = ENODATA;
+				instance->instancet->fire_cmd(instance,
+						reset_cmd->frame_phys_addr,
+						0, instance->reg_set);
+			} else {
+				printk(KERN_NOTICE "megasas: %p unexpected"
+					"cmds lst\n",
+					reset_cmd);
+			}
+			reset_index++;
+		}
+
+		return SUCCESS;
+	}
 
 	for (i = 0; i < wait_time; i++) {
 
@@ -1373,6 +1660,7 @@
 	}
 
 	if (atomic_read(&instance->fw_outstanding)) {
+		printk(KERN_NOTICE "megaraid_sas: pending cmds after reset\n");
 		/*
 		* Send signal to FW to stop processing any pending cmds.
 		* The controller will be taken offline by the OS now.
@@ -1388,10 +1676,14 @@
 				&instance->reg_set->inbound_doorbell);
 		}
 		megasas_dump_pending_frames(instance);
-		instance->hw_crit_error = 1;
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
 		return FAILED;
 	}
 
+	printk(KERN_NOTICE "megaraid_sas: no pending cmds after reset\n");
+
 	return SUCCESS;
 }
 
@@ -1413,7 +1705,7 @@
 	scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
 		 scmd->serial_number, scmd->cmnd[0], scmd->retries);
 
-	if (instance->hw_crit_error) {
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
 		printk(KERN_ERR "megasas: cannot recover from previous reset "
 		       "failures\n");
 		return FAILED;
@@ -1568,7 +1860,8 @@
 	instance->aen_cmd = NULL;
 	megasas_return_cmd(instance, cmd);
 
-	if (instance->unload == 0) {
+	if ((instance->unload == 0) &&
+		((instance->issuepend_done == 1))) {
 		struct megasas_aen_event *ev;
 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
 		if (!ev) {
@@ -1663,6 +1956,9 @@
 	struct megasas_header *hdr = &cmd->frame->hdr;
 	unsigned long flags;
 
+	/* flag for the retry reset */
+	cmd->retry_for_fw_reset = 0;
+
 	if (cmd->scmd)
 		cmd->scmd->SCp.ptr = NULL;
 
@@ -1783,39 +2079,301 @@
 }
 
 /**
+ * megasas_issue_pending_cmds_again -	issue all pending cmds
+ *                              	in FW again because of the fw reset
+ * @instance:				Adapter soft state
+ */
+static inline void
+megasas_issue_pending_cmds_again(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	struct list_head clist_local;
+	union megasas_evt_class_locale class_locale;
+	unsigned long flags;
+	u32 seq_num;
+
+	INIT_LIST_HEAD(&clist_local);
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	list_splice_init(&instance->internal_reset_pending_q, &clist_local);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	while (!list_empty(&clist_local)) {
+		cmd	= list_entry((&clist_local)->next,
+					struct megasas_cmd, list);
+		list_del_init(&cmd->list);
+
+		if (cmd->sync_cmd || cmd->scmd) {
+			printk(KERN_NOTICE "megaraid_sas: command %p, %p:%d"
+				"detected to be pending while HBA reset.\n",
+					cmd, cmd->scmd, cmd->sync_cmd);
+
+			cmd->retry_for_fw_reset++;
+
+			if (cmd->retry_for_fw_reset == 3) {
+				printk(KERN_NOTICE "megaraid_sas: cmd %p, %p:%d"
+					"was tried multiple times during reset."
+					"Shutting down the HBA\n",
+					cmd, cmd->scmd, cmd->sync_cmd);
+				megaraid_sas_kill_hba(instance);
+
+				instance->adprecovery =
+						MEGASAS_HW_CRITICAL_ERROR;
+				return;
+			}
+		}
+
+		if (cmd->sync_cmd == 1) {
+			if (cmd->scmd) {
+				printk(KERN_NOTICE "megaraid_sas: unexpected"
+					"cmd attached to internal command!\n");
+			}
+			printk(KERN_NOTICE "megasas: %p synchronous cmd"
+						"on the internal reset queue,"
+						"issue it again.\n", cmd);
+			cmd->cmd_status = ENODATA;
+			instance->instancet->fire_cmd(instance,
+							cmd->frame_phys_addr ,
+							0, instance->reg_set);
+		} else if (cmd->scmd) {
+			printk(KERN_NOTICE "megasas: %p scsi cmd [%02x],%#lx"
+			"detected on the internal queue, issue again.\n",
+			cmd, cmd->scmd->cmnd[0], cmd->scmd->serial_number);
+
+			atomic_inc(&instance->fw_outstanding);
+			instance->instancet->fire_cmd(instance,
+					cmd->frame_phys_addr,
+					cmd->frame_count-1, instance->reg_set);
+		} else {
+			printk(KERN_NOTICE "megasas: %p unexpected cmd on the"
+				"internal reset defer list while re-issue!!\n",
+				cmd);
+		}
+	}
+
+	if (instance->aen_cmd) {
+		printk(KERN_NOTICE "megaraid_sas: aen_cmd in def process\n");
+		megasas_return_cmd(instance, instance->aen_cmd);
+
+		instance->aen_cmd	= NULL;
+	}
+
+	/*
+	* Initiate AEN (Asynchronous Event Notification)
+	*/
+	seq_num = instance->last_seq_num;
+	class_locale.members.reserved = 0;
+	class_locale.members.locale = MR_EVT_LOCALE_ALL;
+	class_locale.members.class = MR_EVT_CLASS_DEBUG;
+
+	megasas_register_aen(instance, seq_num, class_locale.word);
+}
+
+/**
+ * Move the internal reset pending commands to a deferred queue.
+ *
+ * We move the commands pending at internal reset time to a
+ * pending queue. This queue would be flushed after successful
+ * completion of the internal reset sequence. if the internal reset
+ * did not complete in time, the kernel reset handler would flush
+ * these commands.
+ **/
+static void
+megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
+{
+	struct megasas_cmd *cmd;
+	int i;
+	u32 max_cmd = instance->max_fw_cmds;
+	u32 defer_index;
+	unsigned long flags;
+
+	defer_index     = 0;
+	spin_lock_irqsave(&instance->cmd_pool_lock, flags);
+	for (i = 0; i < max_cmd; i++) {
+		cmd = instance->cmd_list[i];
+		if (cmd->sync_cmd == 1 || cmd->scmd) {
+			printk(KERN_NOTICE "megasas: moving cmd[%d]:%p:%d:%p"
+					"on the defer queue as internal\n",
+				defer_index, cmd, cmd->sync_cmd, cmd->scmd);
+
+			if (!list_empty(&cmd->list)) {
+				printk(KERN_NOTICE "megaraid_sas: ERROR while"
+					" moving this cmd:%p, %d %p, it was"
+					"discovered on some list?\n",
+					cmd, cmd->sync_cmd, cmd->scmd);
+
+				list_del_init(&cmd->list);
+			}
+			defer_index++;
+			list_add_tail(&cmd->list,
+				&instance->internal_reset_pending_q);
+		}
+	}
+	spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
+}
+
+
+static void
+process_fw_state_change_wq(struct work_struct *work)
+{
+	struct megasas_instance *instance =
+		container_of(work, struct megasas_instance, work_init);
+	u32 wait;
+	unsigned long flags;
+
+	if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
+		printk(KERN_NOTICE "megaraid_sas: error, recovery st %x \n",
+				instance->adprecovery);
+		return ;
+	}
+
+	if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
+		printk(KERN_NOTICE "megaraid_sas: FW detected to be in fault"
+					"state, restarting it...\n");
+
+		instance->instancet->disable_intr(instance->reg_set);
+		atomic_set(&instance->fw_outstanding, 0);
+
+		atomic_set(&instance->fw_reset_no_pci_access, 1);
+		instance->instancet->adp_reset(instance, instance->reg_set);
+		atomic_set(&instance->fw_reset_no_pci_access, 0 );
+
+		printk(KERN_NOTICE "megaraid_sas: FW restarted successfully,"
+					"initiating next stage...\n");
+
+		printk(KERN_NOTICE "megaraid_sas: HBA recovery state machine,"
+					"state 2 starting...\n");
+
+		/*waitting for about 20 second before start the second init*/
+		for (wait = 0; wait < 30; wait++) {
+			msleep(1000);
+		}
+
+		if (megasas_transition_to_ready(instance)) {
+			printk(KERN_NOTICE "megaraid_sas:adapter not ready\n");
+
+			megaraid_sas_kill_hba(instance);
+			instance->adprecovery	= MEGASAS_HW_CRITICAL_ERROR;
+			return ;
+		}
+
+		if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
+			(instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
+			(instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR)
+			) {
+			*instance->consumer = *instance->producer;
+		} else {
+			*instance->consumer = 0;
+			*instance->producer = 0;
+		}
+
+		megasas_issue_init_mfi(instance);
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		instance->adprecovery	= MEGASAS_HBA_OPERATIONAL;
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		instance->instancet->enable_intr(instance->reg_set);
+
+		megasas_issue_pending_cmds_again(instance);
+		instance->issuepend_done = 1;
+	}
+	return ;
+}
+
+/**
  * megasas_deplete_reply_queue -	Processes all completed commands
  * @instance:				Adapter soft state
  * @alt_status:				Alternate status to be returned to
  * 					SCSI mid-layer instead of the status
  * 					returned by the FW
+ * Note: this must be called with hba lock held
  */
 static int
-megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
+megasas_deplete_reply_queue(struct megasas_instance *instance,
+					u8 alt_status)
 {
-	/*
-	 * Check if it is our interrupt
-	 * Clear the interrupt 
-	 */
-	if(instance->instancet->clear_intr(instance->reg_set))
-		return IRQ_NONE;
+	u32 mfiStatus;
+	u32 fw_state;
 
-	if (instance->hw_crit_error)
-		goto out_done;
-        /*
-	 * Schedule the tasklet for cmd completion
-	 */
+	if ((mfiStatus = instance->instancet->check_reset(instance,
+					instance->reg_set)) == 1) {
+		return IRQ_HANDLED;
+	}
+
+	if ((mfiStatus = instance->instancet->clear_intr(
+						instance->reg_set)
+						) == 0) {
+		return IRQ_NONE;
+	}
+
+	instance->mfiStatus = mfiStatus;
+
+	if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) {
+		fw_state = instance->instancet->read_fw_status_reg(
+				instance->reg_set) & MFI_STATE_MASK;
+
+		if (fw_state != MFI_STATE_FAULT) {
+			printk(KERN_NOTICE "megaraid_sas: fw state:%x\n",
+						fw_state);
+		}
+
+		if ((fw_state == MFI_STATE_FAULT) &&
+				(instance->disableOnlineCtrlReset == 0)) {
+			printk(KERN_NOTICE "megaraid_sas: wait adp restart\n");
+
+			if ((instance->pdev->device ==
+					PCI_DEVICE_ID_LSI_SAS1064R) ||
+				(instance->pdev->device ==
+					PCI_DEVICE_ID_DELL_PERC5) ||
+				(instance->pdev->device ==
+					PCI_DEVICE_ID_LSI_VERDE_ZCR)) {
+
+				*instance->consumer =
+					MEGASAS_ADPRESET_INPROG_SIGN;
+			}
+
+
+			instance->instancet->disable_intr(instance->reg_set);
+			instance->adprecovery	= MEGASAS_ADPRESET_SM_INFAULT;
+			instance->issuepend_done = 0;
+
+			atomic_set(&instance->fw_outstanding, 0);
+			megasas_internal_reset_defer_cmds(instance);
+
+			printk(KERN_NOTICE "megasas: fwState=%x, stage:%d\n",
+					fw_state, instance->adprecovery);
+
+			schedule_work(&instance->work_init);
+			return IRQ_HANDLED;
+
+		} else {
+			printk(KERN_NOTICE "megasas: fwstate:%x, dis_OCR=%x\n",
+				fw_state, instance->disableOnlineCtrlReset);
+		}
+	}
+
 	tasklet_schedule(&instance->isr_tasklet);
-out_done:
 	return IRQ_HANDLED;
 }
-
 /**
  * megasas_isr - isr entry point
  */
 static irqreturn_t megasas_isr(int irq, void *devp)
 {
-	return megasas_deplete_reply_queue((struct megasas_instance *)devp,
-					   DID_OK);
+	struct megasas_instance *instance;
+	unsigned long flags;
+	irqreturn_t	rc;
+
+	if (atomic_read(
+		&(((struct megasas_instance *)devp)->fw_reset_no_pci_access)))
+		return IRQ_HANDLED;
+
+	instance = (struct megasas_instance *)devp;
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	rc =  megasas_deplete_reply_queue(instance, DID_OK);
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+	return rc;
 }
 
 /**
@@ -1972,7 +2530,7 @@
 			       "in %d secs\n", fw_state, max_wait);
 			return -ENODEV;
 		}
-	};
+	}
  	printk(KERN_INFO "megasas: FW now in Ready state\n");
 
 	return 0;
@@ -2054,6 +2612,7 @@
 	 */
 	sgl_sz = sge_sz * instance->max_num_sge;
 	frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
+	frame_count = 15;
 
 	/*
 	 * We need one extra frame for the MFI command
@@ -2201,6 +2760,7 @@
 		cmd = instance->cmd_list[i];
 		memset(cmd, 0, sizeof(struct megasas_cmd));
 		cmd->index = i;
+		cmd->scmd = NULL;
 		cmd->instance = instance;
 
 		list_add_tail(&cmd->list, &instance->cmd_pool);
@@ -2368,7 +2928,7 @@
 
 	/* the following function will get the instance PD LIST */
 
-	if ((ret == 0) && (ci->ldCount < MAX_LOGICAL_DRIVES)) {
+	if ((ret == 0) && (ci->ldCount <= MAX_LOGICAL_DRIVES)) {
 		memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
 
 		for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
@@ -2682,6 +3242,21 @@
 	if (megasas_issue_init_mfi(instance))
 		goto fail_fw_init;
 
+	instance->fw_support_ieee = 0;
+	instance->fw_support_ieee =
+		(instance->instancet->read_fw_status_reg(reg_set) &
+		0x04000000);
+
+	printk(KERN_NOTICE "megasas_init_mfi: fw_support_ieee=%d",
+			instance->fw_support_ieee);
+
+	if (instance->fw_support_ieee)
+		instance->flag_ieee = 1;
+
+	/** for passthrough
+	* the following function will get the PD LIST.
+	*/
+
 	memset(instance->pd_list, 0 ,
 		(MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)));
 	megasas_get_pd_list(instance);
@@ -2708,6 +3283,8 @@
 		max_sectors_2 = ctrl_info->max_request_size;
 
 		tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
+		instance->disableOnlineCtrlReset =
+		ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
 	}
 
 	instance->max_sectors_per_req = instance->max_num_sge *
@@ -2929,6 +3506,7 @@
 	dcmd->flags = MFI_FRAME_DIR_READ;
 	dcmd->timeout = 0;
 	dcmd->pad_0 = 0;
+	instance->last_seq_num = seq_num;
 	dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
 	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
 	dcmd->mbox.w[0] = seq_num;
@@ -3097,6 +3675,7 @@
 
 	instance = (struct megasas_instance *)host->hostdata;
 	memset(instance, 0, sizeof(*instance));
+	atomic_set( &instance->fw_reset_no_pci_access, 0 );
 
 	instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
 						  &instance->producer_h);
@@ -3114,6 +3693,9 @@
 	megasas_poll_wait_aen = 0;
 	instance->flag_ieee = 0;
 	instance->ev = NULL;
+	instance->issuepend_done = 1;
+	instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+	megasas_poll_wait_aen = 0;
 
 	instance->evt_detail = pci_alloc_consistent(pdev,
 						    sizeof(struct
@@ -3130,6 +3712,7 @@
 	 * Initialize locks and queues
 	 */
 	INIT_LIST_HEAD(&instance->cmd_pool);
+	INIT_LIST_HEAD(&instance->internal_reset_pending_q);
 
 	atomic_set(&instance->fw_outstanding,0);
 
@@ -3137,7 +3720,7 @@
 	init_waitqueue_head(&instance->abort_cmd_wait_q);
 
 	spin_lock_init(&instance->cmd_pool_lock);
-	spin_lock_init(&instance->fire_lock);
+	spin_lock_init(&instance->hba_lock);
 	spin_lock_init(&instance->completion_lock);
 	spin_lock_init(&poll_aen_lock);
 
@@ -3162,6 +3745,9 @@
 	instance->flag = 0;
 	instance->unload = 1;
 	instance->last_time = 0;
+	instance->disableOnlineCtrlReset = 1;
+
+	INIT_WORK(&instance->work_init, process_fw_state_change_wq);
 
 	/*
 	 * Initialize MFI Firmware
@@ -3253,6 +3839,9 @@
 	struct megasas_cmd *cmd;
 	struct megasas_dcmd_frame *dcmd;
 
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+		return;
+
 	cmd = megasas_get_cmd(instance);
 
 	if (!cmd)
@@ -3290,6 +3879,9 @@
 	struct megasas_cmd *cmd;
 	struct megasas_dcmd_frame *dcmd;
 
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
+		return;
+
 	cmd = megasas_get_cmd(instance);
 
 	if (!cmd)
@@ -3557,7 +4149,6 @@
  */
 static int megasas_mgmt_open(struct inode *inode, struct file *filep)
 {
-	cycle_kernel_lock();
 	/*
 	 * Allow only those users with admin rights
 	 */
@@ -3781,6 +4372,9 @@
 	struct megasas_iocpacket *ioc;
 	struct megasas_instance *instance;
 	int error;
+	int i;
+	unsigned long flags;
+	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
 
 	ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
 	if (!ioc)
@@ -3797,8 +4391,8 @@
 		goto out_kfree_ioc;
 	}
 
-	if (instance->hw_crit_error == 1) {
-		printk(KERN_DEBUG "Controller in Crit ERROR\n");
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		printk(KERN_ERR "Controller in crit error\n");
 		error = -ENODEV;
 		goto out_kfree_ioc;
 	}
@@ -3815,6 +4409,35 @@
 		error = -ERESTARTSYS;
 		goto out_kfree_ioc;
 	}
+
+	for (i = 0; i < wait_time; i++) {
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+			spin_unlock_irqrestore(&instance->hba_lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: waiting"
+				"for controller reset to finish\n");
+		}
+
+		msleep(1000);
+	}
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		printk(KERN_ERR "megaraid_sas: timed out while"
+			"waiting for HBA to recover\n");
+		error = -ENODEV;
+		goto out_kfree_ioc;
+	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
 	error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
 	up(&instance->ioctl_sem);
 
@@ -3828,6 +4451,9 @@
 	struct megasas_instance *instance;
 	struct megasas_aen aen;
 	int error;
+	int i;
+	unsigned long flags;
+	u32 wait_time = MEGASAS_RESET_WAIT_TIME;
 
 	if (file->private_data != file) {
 		printk(KERN_DEBUG "megasas: fasync_helper was not "
@@ -3843,14 +4469,42 @@
 	if (!instance)
 		return -ENODEV;
 
-	if (instance->hw_crit_error == 1) {
-		error = -ENODEV;
+	if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
+		return -ENODEV;
 	}
 
 	if (instance->unload == 1) {
 		return -ENODEV;
 	}
 
+	for (i = 0; i < wait_time; i++) {
+
+		spin_lock_irqsave(&instance->hba_lock, flags);
+		if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
+			spin_unlock_irqrestore(&instance->hba_lock,
+						flags);
+			break;
+		}
+
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+
+		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
+			printk(KERN_NOTICE "megasas: waiting for"
+				"controller reset to finish\n");
+		}
+
+		msleep(1000);
+	}
+
+	spin_lock_irqsave(&instance->hba_lock, flags);
+	if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
+		spin_unlock_irqrestore(&instance->hba_lock, flags);
+		printk(KERN_ERR "megaraid_sas: timed out while waiting"
+				"for HBA to recover.\n");
+		return -ENODEV;
+	}
+	spin_unlock_irqrestore(&instance->hba_lock, flags);
+
 	mutex_lock(&instance->aen_mutex);
 	error = megasas_register_aen(instance, aen.seq_num,
 				     aen.class_locale_word);
@@ -3957,6 +4611,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = megasas_mgmt_compat_ioctl,
 #endif
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 9d8b6bf..16a4f68 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -60,6 +60,7 @@
 #define MFI_STATE_READY				0xB0000000
 #define MFI_STATE_OPERATIONAL			0xC0000000
 #define MFI_STATE_FAULT				0xF0000000
+#define  MFI_RESET_REQUIRED			0x00000001
 
 #define MEGAMFI_FRAME_SIZE			64
 
@@ -73,6 +74,12 @@
  * HOTPLUG	: Resume from Hotplug
  * MFI_STOP_ADP	: Send signal to FW to stop processing
  */
+#define WRITE_SEQUENCE_OFFSET		(0x0000000FC) /* I20 */
+#define HOST_DIAGNOSTIC_OFFSET		(0x000000F8)  /* I20 */
+#define DIAG_WRITE_ENABLE			(0x00000080)
+#define DIAG_RESET_ADAPTER			(0x00000004)
+
+#define MFI_ADP_RESET				0x00000040
 #define MFI_INIT_ABORT				0x00000001
 #define MFI_INIT_READY				0x00000002
 #define MFI_INIT_MFIMODE			0x00000004
@@ -402,8 +409,40 @@
 	u16 ecc_bucket_leak_rate;
 	u8 restore_hotspare_on_insertion;
 	u8 expose_encl_devices;
-	u8 reserved[38];
+	u8 maintainPdFailHistory;
+	u8 disallowHostRequestReordering;
+	u8 abortCCOnError;
+	u8 loadBalanceMode;
+	u8 disableAutoDetectBackplane;
 
+	u8 snapVDSpace;
+
+	/*
+	* Add properties that can be controlled by
+	* a bit in the following structure.
+	*/
+
+	struct {
+		u32     copyBackDisabled            : 1;
+		u32     SMARTerEnabled              : 1;
+		u32     prCorrectUnconfiguredAreas  : 1;
+		u32     useFdeOnly                  : 1;
+		u32     disableNCQ                  : 1;
+		u32     SSDSMARTerEnabled           : 1;
+		u32     SSDPatrolReadEnabled        : 1;
+		u32     enableSpinDownUnconfigured  : 1;
+		u32     autoEnhancedImport          : 1;
+		u32     enableSecretKeyControl      : 1;
+		u32     disableOnlineCtrlReset      : 1;
+		u32     allowBootWithPinnedCache    : 1;
+		u32     disableSpinDownHS           : 1;
+		u32     enableJBOD                  : 1;
+		u32     reserved                    :18;
+	} OnOffProperties;
+	u8 autoSnapVDSpace;
+	u8 viewSpace;
+	u16 spinDownTime;
+	u8  reserved[24];
 } __packed;
 
 /*
@@ -704,6 +743,12 @@
  */
 #define IS_DMA64				(sizeof(dma_addr_t) == 8)
 
+#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT		0x00000001
+
+#define MFI_INTR_FLAG_REPLY_MESSAGE			0x00000001
+#define MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE		0x00000002
+#define MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT	0x00000004
+
 #define MFI_OB_INTR_STATUS_MASK			0x00000002
 #define MFI_POLL_TIMEOUT_SECS			60
 #define MEGASAS_COMPLETION_TIMER_INTERVAL      (HZ/10)
@@ -714,6 +759,9 @@
 #define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT	0x40000000
 #define MFI_SKINNY_ENABLE_INTERRUPT_MASK	(0x00000001)
 
+#define MFI_1068_PCSR_OFFSET			0x84
+#define MFI_1068_FW_HANDSHAKE_OFFSET		0x64
+#define MFI_1068_FW_READY			0xDDDD0000
 /*
 * register set for both 1068 and 1078 controllers
 * structure extended for 1078 registers
@@ -755,8 +803,10 @@
 	u32 	inbound_high_queue_port ;	/*00C4h*/
 
 	u32 	reserved_5;			/*00C8h*/
-	u32 	index_registers[820];		/*00CCh*/
-
+	u32	res_6[11];			/*CCh*/
+	u32	host_diag;
+	u32	seq_offset;
+	u32 	index_registers[807];		/*00CCh*/
 } __attribute__ ((packed));
 
 struct megasas_sge32 {
@@ -1226,11 +1276,12 @@
 
 	struct megasas_cmd **cmd_list;
 	struct list_head cmd_pool;
+	/* used to sync fire the cmd to fw */
 	spinlock_t cmd_pool_lock;
+	/* used to sync fire the cmd to fw */
+	spinlock_t hba_lock;
 	/* used to synch producer, consumer ptrs in dpc */
 	spinlock_t completion_lock;
-	/* used to sync fire the cmd to fw */
-	spinlock_t fire_lock;
 	struct dma_pool *frame_dma_pool;
 	struct dma_pool *sense_dma_pool;
 
@@ -1247,19 +1298,36 @@
 
 	struct pci_dev *pdev;
 	u32 unique_id;
+	u32 fw_support_ieee;
 
 	atomic_t fw_outstanding;
-	u32 hw_crit_error;
+	atomic_t fw_reset_no_pci_access;
 
 	struct megasas_instance_template *instancet;
 	struct tasklet_struct isr_tasklet;
+	struct work_struct work_init;
 
 	u8 flag;
 	u8 unload;
 	u8 flag_ieee;
+	u8 issuepend_done;
+	u8 disableOnlineCtrlReset;
+	u8 adprecovery;
 	unsigned long last_time;
+	u32 mfiStatus;
+	u32 last_seq_num;
 
 	struct timer_list io_completion_timer;
+	struct list_head internal_reset_pending_q;
+};
+
+enum {
+	MEGASAS_HBA_OPERATIONAL			= 0,
+	MEGASAS_ADPRESET_SM_INFAULT		= 1,
+	MEGASAS_ADPRESET_SM_FW_RESET_SUCCESS	= 2,
+	MEGASAS_ADPRESET_SM_OPERATIONAL		= 3,
+	MEGASAS_HW_CRITICAL_ERROR		= 4,
+	MEGASAS_ADPRESET_INPROG_SIGN		= 0xDEADDEAD,
 };
 
 struct megasas_instance_template {
@@ -1272,6 +1340,10 @@
 	int (*clear_intr)(struct megasas_register_set __iomem *);
 
 	u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
+	int (*adp_reset)(struct megasas_instance *, \
+		struct megasas_register_set __iomem *);
+	int (*check_reset)(struct megasas_instance *, \
+		struct megasas_register_set __iomem *);
 };
 
 #define MEGASAS_IS_LOGICAL(scp)						\
@@ -1291,7 +1363,9 @@
 	u32 index;
 	u8 sync_cmd;
 	u8 cmd_status;
-	u16 abort_aen;
+	u8 abort_aen;
+	u8 retry_for_fw_reset;
+
 
 	struct list_head list;
 	struct scsi_cmnd *scmd;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 57bcd5c..12faf64 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -534,7 +534,7 @@
 		if (event_data->DiscoveryStatus)
 			printk("discovery_status(0x%08x)",
 			    le32_to_cpu(event_data->DiscoveryStatus));
-			printk("\n");
+		printk("\n");
 		return;
 	}
 	case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index b774973..40cb8ae 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -51,7 +51,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/compat.h>
 #include <linux/poll.h>
 
@@ -61,6 +61,7 @@
 #include "mpt2sas_base.h"
 #include "mpt2sas_ctl.h"
 
+static DEFINE_MUTEX(_ctl_mutex);
 static struct fasync_struct *async_queue;
 static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
 
@@ -2238,9 +2239,9 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&_ctl_mutex);
 	ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
-	unlock_kernel();
+	mutex_unlock(&_ctl_mutex);
 	return ret;
 }
 
@@ -2309,12 +2310,12 @@
 {
 	long ret;
 
-	lock_kernel();
+	mutex_lock(&_ctl_mutex);
 	if (cmd == MPT2COMMAND32)
 		ret = _ctl_compat_mpt_command(file, cmd, arg);
 	else
 		ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
-	unlock_kernel();
+	mutex_unlock(&_ctl_mutex);
 	return ret;
 }
 #endif
@@ -2952,6 +2953,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = _ctl_ioctl_compat,
 #endif
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice ctl_dev = {
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index ffdd9fd..b31a8e3 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -182,6 +182,7 @@
 	.open           = osd_uld_open,
 	.release        = osd_uld_release,
 	.unlocked_ioctl = osd_uld_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct osd_dev *osduld_path_lookup(const char *name)
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 278b352..54de1d1 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -51,7 +51,7 @@
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
 #include <asm/system.h>
@@ -80,6 +80,7 @@
 #include "osst_options.h"
 #include "osst_detect.h"
 
+static DEFINE_MUTEX(osst_int_mutex);
 static int max_dev = 0;
 static int write_threshold_kbs = 0;
 static int max_sg_segs = 0;
@@ -4807,9 +4808,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&osst_int_mutex);
 	ret = __os_scsi_tape_open(inode, filp);
-	unlock_kernel();
+	mutex_unlock(&osst_int_mutex);
 	return ret;
 }
 
@@ -4943,9 +4944,9 @@
 	char		    * name  = tape_name(STp);
 	void	    __user  * p     = (void __user *)arg;
 
-	lock_kernel();
+	mutex_lock(&osst_int_mutex);
 	if (mutex_lock_interruptible(&STp->lock)) {
-		unlock_kernel();
+		mutex_unlock(&osst_int_mutex);
 		return -ERESTARTSYS;
 	}
 
@@ -5260,14 +5261,14 @@
 	mutex_unlock(&STp->lock);
 
 	retval = scsi_ioctl(STp->device, cmd_in, p);
-	unlock_kernel();
+	mutex_unlock(&osst_int_mutex);
 	return retval;
 
 out:
 	if (SRpnt) osst_release_request(SRpnt);
 
 	mutex_unlock(&STp->lock);
-	unlock_kernel();
+	mutex_unlock(&osst_int_mutex);
 
 	return retval;
 }
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
index 53857c6..ecc855c 100644
--- a/drivers/scsi/pcmcia/Kconfig
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -11,7 +11,6 @@
 
 config PCMCIA_AHA152X
 	tristate "Adaptec AHA152X PCMCIA support"
-	depends on !64BIT
 	select SCSI_SPI_ATTRS
 	help
 	  Say Y here if you intend to attach this type of PCMCIA SCSI host
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 9793aa6..d8db013 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -4194,6 +4194,8 @@
 
 	nvmd_type = ioctl_payload->minor_function;
 	fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
+	if (!fw_control_context)
+		return -ENOMEM;
 	fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0];
 	fw_control_context->len = ioctl_payload->length;
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
@@ -4272,6 +4274,8 @@
 
 	nvmd_type = ioctl_payload->minor_function;
 	fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
+	if (!fw_control_context)
+		return -ENOMEM;
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
 		ioctl_payload->func_specific,
@@ -4381,6 +4385,8 @@
 	struct pm8001_ioctl_payload *ioctl_payload = payload;
 
 	fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
+	if (!fw_control_context)
+		return -ENOMEM;
 	fw_control = (struct fw_control_info *)&ioctl_payload->func_specific[0];
 	if (fw_control->len != 0) {
 		if (pm8001_mem_alloc(pm8001_ha->pdev,
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index ecc45c8..4b87657 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -4165,6 +4165,7 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = pmcraid_chr_ioctl,
 #endif
+	.llseek = noop_llseek,
 };
 
 
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 114bc5a..2ff4342 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1538,6 +1538,15 @@
 	if (!fcport)
 		return;
 
+	/*
+	 * Transport has effectively 'deleted' the rport, clear
+	 * all local references.
+	 */
+	spin_lock_irq(host->host_lock);
+	fcport->rport = fcport->drport = NULL;
+	*((fc_port_t **)rport->dd_data) = NULL;
+	spin_unlock_irq(host->host_lock);
+
 	if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
 		return;
 
@@ -1545,15 +1554,6 @@
 		qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
 		return;
 	}
-
-	/*
-	 * Transport has effectively 'deleted' the rport, clear
-	 * all local references.
-	 */
-	spin_lock_irq(host->host_lock);
-	fcport->rport = NULL;
-	*((fc_port_t **)rport->dd_data) = NULL;
-	spin_unlock_irq(host->host_lock);
 }
 
 static void
@@ -1676,14 +1676,14 @@
 qla2x00_get_host_fabric_name(struct Scsi_Host *shost)
 {
 	scsi_qla_host_t *vha = shost_priv(shost);
-	u64 node_name;
+	uint8_t node_name[WWN_SIZE] = { 0xFF, 0xFF, 0xFF, 0xFF, \
+		0xFF, 0xFF, 0xFF, 0xFF};
+	u64 fabric_name = wwn_to_u64(node_name);
 
 	if (vha->device_flags & SWITCH_FOUND)
-		node_name = wwn_to_u64(vha->fabric_node_name);
-	else
-		node_name = wwn_to_u64(vha->node_name);
+		fabric_name = wwn_to_u64(vha->fabric_node_name);
 
-	fc_host_fabric_name(shost) = node_name;
+	fc_host_fabric_name(shost) = fabric_name;
 }
 
 static void
@@ -1776,6 +1776,7 @@
 	}
 
 	/* initialize attributes */
+	fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
 	fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
 	fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
 	fc_host_supported_classes(vha->host) =
@@ -1984,6 +1985,7 @@
 	struct qla_hw_data *ha = vha->hw;
 	u32 speed = FC_PORTSPEED_UNKNOWN;
 
+	fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
 	fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
 	fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
 	fc_host_supported_classes(vha->host) = FC_COS_CLASS3;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 9067629..fdfbf83 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -1254,10 +1254,9 @@
 		return -EINVAL;
 	}
 
-	if (fcport->loop_id == FC_NO_LOOP_ID) {
-		DEBUG2(printk(KERN_ERR "%s(%ld): Invalid port loop id, "
-			"loop_id = 0x%x\n",
-			__func__, vha->host_no, fcport->loop_id));
+	if (atomic_read(&fcport->state) != FCS_ONLINE) {
+		DEBUG2(printk(KERN_ERR "%s(%ld): Port not online\n",
+			__func__, vha->host_no));
 		return -EINVAL;
 	}
 
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index d2a4e15..e1d3ad40 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -706,6 +706,11 @@
 #define MBC_SET_PORT_CONFIG		0x122	/* Set port configuration */
 #define MBC_GET_PORT_CONFIG		0x123	/* Get port configuration */
 
+/*
+ * ISP81xx mailbox commands
+ */
+#define MBC_WRITE_MPI_REGISTER		0x01    /* Write MPI Register. */
+
 /* Firmware return data sizes */
 #define FCAL_MAP_SIZE	128
 
@@ -2860,6 +2865,7 @@
 #define NPIV_CONFIG_NEEDED	16
 #define ISP_UNRECOVERABLE	17
 #define FCOE_CTX_RESET_NEEDED	18	/* Initiate FCoE context reset */
+#define MPI_RESET_NEEDED	19	/* Initiate MPI FW reset */
 
 	uint32_t	device_flags;
 #define SWITCH_FOUND		BIT_0
@@ -3003,6 +3009,8 @@
 
 #define CMD_SP(Cmnd)		((Cmnd)->SCp.ptr)
 
+#define QLA_SG_ALL	1024
+
 enum nexus_wait_type {
 	WAIT_HOST = 0,
 	WAIT_TARGET,
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 1a1b281..c33dec8 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -352,6 +352,8 @@
 extern int
 qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t);
 
+extern int
+qla81xx_write_mpi_register(scsi_qla_host_t *, uint16_t *);
 extern int qla2x00_get_data_rate(scsi_qla_host_t *);
 extern int qla24xx_set_fcp_prio(scsi_qla_host_t *, uint16_t, uint16_t,
 	uint16_t *);
@@ -501,7 +503,6 @@
 /* PCI related functions */
 extern int qla82xx_pci_config(struct scsi_qla_host *);
 extern int qla82xx_pci_mem_read_2M(struct qla_hw_data *, u64, void *, int);
-extern int qla82xx_pci_mem_write_2M(struct qla_hw_data *, u64, void *, int);
 extern char *qla82xx_pci_info_str(struct scsi_qla_host *, char *);
 extern int qla82xx_pci_region_offset(struct pci_dev *, int);
 extern int qla82xx_iospace_config(struct qla_hw_data *);
@@ -509,8 +510,8 @@
 /* Initialization related functions */
 extern void qla82xx_reset_chip(struct scsi_qla_host *);
 extern void qla82xx_config_rings(struct scsi_qla_host *);
-extern int qla82xx_pinit_from_rom(scsi_qla_host_t *);
 extern void qla82xx_watchdog(scsi_qla_host_t *);
+extern int qla82xx_start_firmware(scsi_qla_host_t *);
 
 /* Firmware and flash related functions */
 extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *);
@@ -533,25 +534,17 @@
 extern irqreturn_t qla82xx_msix_rsp_q(int, void *);
 extern void qla82xx_enable_intrs(struct qla_hw_data *);
 extern void qla82xx_disable_intrs(struct qla_hw_data *);
-extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t);
 extern void qla82xx_poll(int, void *);
 extern void qla82xx_init_flags(struct qla_hw_data *);
 
 /* ISP 8021 hardware related */
-extern int qla82xx_crb_win_lock(struct qla_hw_data *);
+extern void qla82xx_set_drv_active(scsi_qla_host_t *);
 extern void qla82xx_crb_win_unlock(struct qla_hw_data *);
-extern int qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *, ulong *);
 extern int qla82xx_wr_32(struct qla_hw_data *, ulong, u32);
 extern int qla82xx_rd_32(struct qla_hw_data *, ulong);
 extern int qla82xx_rdmem(struct qla_hw_data *, u64, void *, int);
 extern int qla82xx_wrmem(struct qla_hw_data *, u64, void *, int);
-extern int qla82xx_check_for_bad_spd(struct qla_hw_data *);
-extern int qla82xx_load_fw(scsi_qla_host_t *);
-extern int qla82xx_rom_lock(struct qla_hw_data *);
 extern void qla82xx_rom_unlock(struct qla_hw_data *);
-extern int qla82xx_rom_fast_read(struct qla_hw_data *, int , int *);
-extern int qla82xx_do_rom_fast_read(struct qla_hw_data *, int, int *);
-extern unsigned long qla82xx_decode_crb_addr(unsigned long);
 
 /* ISP 8021 IDC */
 extern void qla82xx_clear_drv_active(struct qla_hw_data *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 9c383ba..3cafbef 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -954,6 +954,19 @@
 }
 
 /**
+ * qla81xx_reset_mpi() - Reset's MPI FW via Write MPI Register MBC.
+ *
+ * Returns 0 on success.
+ */
+int
+qla81xx_reset_mpi(scsi_qla_host_t *vha)
+{
+	uint16_t mb[4] = {0x1010, 0, 1, 0};
+
+	return qla81xx_write_mpi_register(vha, mb);
+}
+
+/**
  * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC.
  * @ha: HA context
  *
@@ -967,6 +980,7 @@
 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 	uint32_t cnt, d2;
 	uint16_t wd;
+	static int abts_cnt; /* ISP abort retry counts */
 
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -1000,6 +1014,23 @@
 		barrier();
 	}
 
+	/* If required, do an MPI FW reset now */
+	if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) {
+		if (qla81xx_reset_mpi(vha) != QLA_SUCCESS) {
+			if (++abts_cnt < 5) {
+				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+				set_bit(MPI_RESET_NEEDED, &vha->dpc_flags);
+			} else {
+				/*
+				 * We exhausted the ISP abort retries. We have to
+				 * set the board offline.
+				 */
+				abts_cnt = 0;
+				vha->flags.online = 0;
+			}
+		}
+	}
+
 	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
 	RD_REG_DWORD(&reg->hccr);
 
@@ -2799,6 +2830,9 @@
 	if (!IS_IIDMA_CAPABLE(ha))
 		return;
 
+	if (atomic_read(&fcport->state) != FCS_ONLINE)
+		return;
+
 	if (fcport->fp_speed == PORT_SPEED_UNKNOWN ||
 	    fcport->fp_speed > ha->link_data_rate)
 		return;
@@ -3878,17 +3912,19 @@
 			    LOOP_DOWN_TIME);
 	}
 
-	/* Make sure for ISP 82XX IO DMA is complete */
-	if (IS_QLA82XX(ha)) {
-		if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
-			WAIT_HOST) == QLA_SUCCESS) {
-			DEBUG2(qla_printk(KERN_INFO, ha,
-			"Done wait for pending commands\n"));
+	if (!ha->flags.eeh_busy) {
+		/* Make sure for ISP 82XX IO DMA is complete */
+		if (IS_QLA82XX(ha)) {
+			if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
+				WAIT_HOST) == QLA_SUCCESS) {
+				DEBUG2(qla_printk(KERN_INFO, ha,
+				"Done wait for pending commands\n"));
+			}
 		}
-	}
 
-	/* Requeue all commands in outstanding command list. */
-	qla2x00_abort_all_cmds(vha, DID_RESET << 16);
+		/* Requeue all commands in outstanding command list. */
+		qla2x00_abort_all_cmds(vha, DID_RESET << 16);
+	}
 }
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 28f65be..e0e43d9 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -412,8 +412,14 @@
 				    "Unrecoverable Hardware Error: adapter "
 				    "marked OFFLINE!\n");
 				vha->flags.online = 0;
-			} else
+			} else {
+				/* Check to see if MPI timeout occured */
+				if ((mbx & MBX_3) && (ha->flags.port0))
+					set_bit(MPI_RESET_NEEDED,
+					    &vha->dpc_flags);
+
 				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+			}
 		} else if (mb[1] == 0) {
 			qla_printk(KERN_INFO, ha,
 			    "Unrecoverable Hardware Error: adapter marked "
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index a595ec8..effd8a1 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3828,8 +3828,6 @@
 
 	/* Copy mailbox information */
 	memcpy( mresp, mcp->mb, 64);
-	mresp[3] = mcp->mb[18];
-	mresp[4] = mcp->mb[19];
 	return rval;
 }
 
@@ -3890,9 +3888,10 @@
 	}
 
 	/* Copy mailbox information */
-	memcpy( mresp, mcp->mb, 32);
+	memcpy(mresp, mcp->mb, 64);
 	return rval;
 }
+
 int
 qla84xx_reset_chip(scsi_qla_host_t *ha, uint16_t enable_diagnostic)
 {
@@ -3953,6 +3952,67 @@
 }
 
 int
+qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
+{
+	int rval;
+	uint32_t stat, timer;
+	uint16_t mb0 = 0;
+	struct qla_hw_data *ha = vha->hw;
+	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+
+	rval = QLA_SUCCESS;
+
+	DEBUG11(qla_printk(KERN_INFO, ha,
+	    "%s(%ld): entered.\n", __func__, vha->host_no));
+
+	clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+
+	/* Write the MBC data to the registers */
+	WRT_REG_WORD(&reg->mailbox0, MBC_WRITE_MPI_REGISTER);
+	WRT_REG_WORD(&reg->mailbox1, mb[0]);
+	WRT_REG_WORD(&reg->mailbox2, mb[1]);
+	WRT_REG_WORD(&reg->mailbox3, mb[2]);
+	WRT_REG_WORD(&reg->mailbox4, mb[3]);
+
+	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
+
+	/* Poll for MBC interrupt */
+	for (timer = 6000000; timer; timer--) {
+		/* Check for pending interrupts. */
+		stat = RD_REG_DWORD(&reg->host_status);
+		if (stat & HSRX_RISC_INT) {
+			stat &= 0xff;
+
+			if (stat == 0x1 || stat == 0x2 ||
+			    stat == 0x10 || stat == 0x11) {
+				set_bit(MBX_INTERRUPT,
+				    &ha->mbx_cmd_flags);
+				mb0 = RD_REG_WORD(&reg->mailbox0);
+				WRT_REG_DWORD(&reg->hccr,
+				    HCCRX_CLR_RISC_INT);
+				RD_REG_DWORD(&reg->hccr);
+				break;
+			}
+		}
+		udelay(5);
+	}
+
+	if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags))
+		rval = mb0 & MBS_MASK;
+	else
+		rval = QLA_FUNCTION_FAILED;
+
+	if (rval != QLA_SUCCESS) {
+		DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n",
+		    __func__, vha->host_no, rval, mb[0]));
+	} else {
+		DEBUG11(printk(KERN_INFO
+		    "%s(%ld): done.\n", __func__, vha->host_no));
+	}
+
+	return rval;
+}
+int
 qla2x00_get_data_rate(scsi_qla_host_t *vha)
 {
 	int rval;
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 0a71cc7..8d9edfb 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -403,6 +403,54 @@
 	return off;
 }
 
+static int
+qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong *off)
+{
+	struct crb_128M_2M_sub_block_map *m;
+
+	if (*off >= QLA82XX_CRB_MAX)
+		return -1;
+
+	if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) {
+		*off = (*off - QLA82XX_PCI_CAMQM) +
+		    QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase;
+		return 0;
+	}
+
+	if (*off < QLA82XX_PCI_CRBSPACE)
+		return -1;
+
+	*off -= QLA82XX_PCI_CRBSPACE;
+
+	/* Try direct map */
+	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
+
+	if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {
+		*off = *off + m->start_2M - m->start_128M + ha->nx_pcibase;
+		return 0;
+	}
+	/* Not in direct map, use crb window */
+	return 1;
+}
+
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+static int qla82xx_crb_win_lock(struct qla_hw_data *ha)
+{
+	int done = 0, timeout = 0;
+
+	while (!done) {
+		/* acquire semaphore3 from PCI HW block */
+		done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK));
+		if (done == 1)
+			break;
+		if (timeout >= CRB_WIN_LOCK_TIMEOUT)
+			return -1;
+		timeout++;
+	}
+	qla82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->portnum);
+	return 0;
+}
+
 int
 qla82xx_wr_32(struct qla_hw_data *ha, ulong off, u32 data)
 {
@@ -453,24 +501,6 @@
 	return data;
 }
 
-#define CRB_WIN_LOCK_TIMEOUT 100000000
-int qla82xx_crb_win_lock(struct qla_hw_data *ha)
-{
-	int done = 0, timeout = 0;
-
-	while (!done) {
-		/* acquire semaphore3 from PCI HW block */
-		done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK));
-		if (done == 1)
-			break;
-		if (timeout >= CRB_WIN_LOCK_TIMEOUT)
-			return -1;
-		timeout++;
-	}
-	qla82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->portnum);
-	return 0;
-}
-
 #define IDC_LOCK_TIMEOUT 100000000
 int qla82xx_idc_lock(struct qla_hw_data *ha)
 {
@@ -504,36 +534,6 @@
 	qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_UNLOCK));
 }
 
-int
-qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong *off)
-{
-	struct crb_128M_2M_sub_block_map *m;
-
-	if (*off >= QLA82XX_CRB_MAX)
-		return -1;
-
-	if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) {
-		*off = (*off - QLA82XX_PCI_CAMQM) +
-		    QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase;
-		return 0;
-	}
-
-	if (*off < QLA82XX_PCI_CRBSPACE)
-		return -1;
-
-	*off -= QLA82XX_PCI_CRBSPACE;
-
-	/* Try direct map */
-	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
-
-	if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {
-		*off = *off + m->start_2M - m->start_128M + ha->nx_pcibase;
-		return 0;
-	}
-	/* Not in direct map, use crb window */
-	return 1;
-}
-
 /*  PCI Windowing for DDR regions.  */
 #define QLA82XX_ADDR_IN_RANGE(addr, low, high) \
 	(((addr) <= (high)) && ((addr) >= (low)))
@@ -557,7 +557,7 @@
 
 int qla82xx_pci_set_window_warning_count;
 
-unsigned long
+static unsigned long
 qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
 {
 	int window;
@@ -798,7 +798,8 @@
 }
 
 #define MTU_FUDGE_FACTOR 100
-unsigned long qla82xx_decode_crb_addr(unsigned long addr)
+static unsigned long
+qla82xx_decode_crb_addr(unsigned long addr)
 {
 	int i;
 	unsigned long base_addr, offset, pci_base;
@@ -824,7 +825,7 @@
 static long rom_max_timeout = 100;
 static long qla82xx_rom_lock_timeout = 100;
 
-int
+static int
 qla82xx_rom_lock(struct qla_hw_data *ha)
 {
 	int done = 0, timeout = 0;
@@ -842,7 +843,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_wait_rom_busy(struct qla_hw_data *ha)
 {
 	long timeout = 0;
@@ -862,7 +863,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_wait_rom_done(struct qla_hw_data *ha)
 {
 	long timeout = 0;
@@ -882,7 +883,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_do_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
 {
 	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ADDRESS, addr);
@@ -905,7 +906,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_rom_fast_read(struct qla_hw_data *ha, int addr, int *valp)
 {
 	int ret, loops = 0;
@@ -926,7 +927,7 @@
 	return ret;
 }
 
-int
+static int
 qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val)
 {
 	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR);
@@ -940,7 +941,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_flash_wait_write_finish(struct qla_hw_data *ha)
 {
 	long timeout = 0;
@@ -964,7 +965,7 @@
 	return ret;
 }
 
-int
+static int
 qla82xx_flash_set_write_enable(struct qla_hw_data *ha)
 {
 	uint32_t val;
@@ -981,7 +982,7 @@
 	return 0;
 }
 
-int
+static int
 qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val)
 {
 	if (qla82xx_flash_set_write_enable(ha))
@@ -996,7 +997,7 @@
 	return qla82xx_flash_wait_write_finish(ha);
 }
 
-int
+static int
 qla82xx_write_disable_flash(struct qla_hw_data *ha)
 {
 	qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI);
@@ -1008,7 +1009,7 @@
 	return 0;
 }
 
-int
+static int
 ql82xx_rom_lock_d(struct qla_hw_data *ha)
 {
 	int loops = 0;
@@ -1024,7 +1025,7 @@
 	return 0;;
 }
 
-int
+static int
 qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr,
 	uint32_t data)
 {
@@ -1061,7 +1062,8 @@
 /* This routine does CRB initialize sequence
  *  to put the ISP into operational state
  */
-int qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
+static int
+qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
 {
 	int addr, val;
 	int i ;
@@ -1207,7 +1209,8 @@
 	return 0;
 }
 
-int qla82xx_check_for_bad_spd(struct qla_hw_data *ha)
+static int
+qla82xx_check_for_bad_spd(struct qla_hw_data *ha)
 {
 	u32 val = 0;
 	val = qla82xx_rd_32(ha, BOOT_LOADER_DIMM_STATUS);
@@ -1225,7 +1228,116 @@
 	return 0;
 }
 
-int
+static int
+qla82xx_pci_mem_write_2M(struct qla_hw_data *ha,
+		u64 off, void *data, int size)
+{
+	int i, j, ret = 0, loop, sz[2], off0;
+	int scale, shift_amount, startword;
+	uint32_t temp;
+	uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
+
+	/*
+	 * If not MN, go check for MS or invalid.
+	 */
+	if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX)
+		mem_crb = QLA82XX_CRB_QDR_NET;
+	else {
+		mem_crb = QLA82XX_CRB_DDR_NET;
+		if (qla82xx_pci_mem_bound_check(ha, off, size) == 0)
+			return qla82xx_pci_mem_write_direct(ha,
+			    off, data, size);
+	}
+
+	off0 = off & 0x7;
+	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+	sz[1] = size - sz[0];
+
+	off8 = off & 0xfffffff0;
+	loop = (((off & 0xf) + size - 1) >> 4) + 1;
+	shift_amount = 4;
+	scale = 2;
+	startword = (off & 0xf)/8;
+
+	for (i = 0; i < loop; i++) {
+		if (qla82xx_pci_mem_read_2M(ha, off8 +
+		    (i << shift_amount), &word[i * scale], 8))
+			return -1;
+	}
+
+	switch (size) {
+	case 1:
+		tmpw = *((uint8_t *)data);
+		break;
+	case 2:
+		tmpw = *((uint16_t *)data);
+		break;
+	case 4:
+		tmpw = *((uint32_t *)data);
+		break;
+	case 8:
+	default:
+		tmpw = *((uint64_t *)data);
+		break;
+	}
+
+	if (sz[0] == 8) {
+		word[startword] = tmpw;
+	} else {
+		word[startword] &=
+			~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+		word[startword] |= tmpw << (off0 * 8);
+	}
+	if (sz[1] != 0) {
+		word[startword+1] &= ~(~0ULL << (sz[1] * 8));
+		word[startword+1] |= tmpw >> (sz[0] * 8);
+	}
+
+	/*
+	 * don't lock here - write_wx gets the lock if each time
+	 * write_lock_irqsave(&adapter->adapter_lock, flags);
+	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+	 */
+	for (i = 0; i < loop; i++) {
+		temp = off8 + (i << shift_amount);
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);
+		temp = 0;
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp);
+		temp = word[i * scale] & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp);
+		temp = (word[i * scale] >> 32) & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp);
+		temp = word[i*scale + 1] & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb +
+		    MIU_TEST_AGT_WRDATA_UPPER_LO, temp);
+		temp = (word[i*scale + 1] >> 32) & 0xffffffff;
+		qla82xx_wr_32(ha, mem_crb +
+		    MIU_TEST_AGT_WRDATA_UPPER_HI, temp);
+
+		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
+		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
+
+		for (j = 0; j < MAX_CTL_CHECK; j++) {
+			temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL);
+			if ((temp & MIU_TA_CTL_BUSY) == 0)
+				break;
+		}
+
+		if (j >= MAX_CTL_CHECK) {
+			if (printk_ratelimit())
+				dev_err(&ha->pdev->dev,
+				    "failed to write through agent\n");
+			ret = -1;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int
 qla82xx_fw_load_from_flash(struct qla_hw_data *ha)
 {
 	int  i;
@@ -1357,114 +1469,6 @@
 	return 0;
 }
 
-int
-qla82xx_pci_mem_write_2M(struct qla_hw_data *ha,
-		u64 off, void *data, int size)
-{
-	int i, j, ret = 0, loop, sz[2], off0;
-	int scale, shift_amount, startword;
-	uint32_t temp;
-	uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
-
-	/*
-	 * If not MN, go check for MS or invalid.
-	 */
-	if (off >= QLA82XX_ADDR_QDR_NET && off <= QLA82XX_P3_ADDR_QDR_NET_MAX)
-		mem_crb = QLA82XX_CRB_QDR_NET;
-	else {
-		mem_crb = QLA82XX_CRB_DDR_NET;
-		if (qla82xx_pci_mem_bound_check(ha, off, size) == 0)
-			return qla82xx_pci_mem_write_direct(ha,
-			    off, data, size);
-	}
-
-	off0 = off & 0x7;
-	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
-	sz[1] = size - sz[0];
-
-	off8 = off & 0xfffffff0;
-	loop = (((off & 0xf) + size - 1) >> 4) + 1;
-	shift_amount = 4;
-	scale = 2;
-	startword = (off & 0xf)/8;
-
-	for (i = 0; i < loop; i++) {
-		if (qla82xx_pci_mem_read_2M(ha, off8 +
-		    (i << shift_amount), &word[i * scale], 8))
-			return -1;
-	}
-
-	switch (size) {
-	case 1:
-		tmpw = *((uint8_t *)data);
-		break;
-	case 2:
-		tmpw = *((uint16_t *)data);
-		break;
-	case 4:
-		tmpw = *((uint32_t *)data);
-		break;
-	case 8:
-	default:
-		tmpw = *((uint64_t *)data);
-		break;
-	}
-
-	if (sz[0] == 8) {
-		word[startword] = tmpw;
-	} else {
-		word[startword] &=
-			~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
-		word[startword] |= tmpw << (off0 * 8);
-	}
-	if (sz[1] != 0) {
-		word[startword+1] &= ~(~0ULL << (sz[1] * 8));
-		word[startword+1] |= tmpw >> (sz[0] * 8);
-	}
-
-	/*
-	 * don't lock here - write_wx gets the lock if each time
-	 * write_lock_irqsave(&adapter->adapter_lock, flags);
-	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
-	 */
-	for (i = 0; i < loop; i++) {
-		temp = off8 + (i << shift_amount);
-		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);
-		temp = 0;
-		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_ADDR_HI, temp);
-		temp = word[i * scale] & 0xffffffff;
-		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp);
-		temp = (word[i * scale] >> 32) & 0xffffffff;
-		qla82xx_wr_32(ha, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp);
-		temp = word[i*scale + 1] & 0xffffffff;
-		qla82xx_wr_32(ha, mem_crb +
-		    MIU_TEST_AGT_WRDATA_UPPER_LO, temp);
-		temp = (word[i*scale + 1] >> 32) & 0xffffffff;
-		qla82xx_wr_32(ha, mem_crb +
-		    MIU_TEST_AGT_WRDATA_UPPER_HI, temp);
-
-		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
-		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
-		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
-		qla82xx_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
-
-		for (j = 0; j < MAX_CTL_CHECK; j++) {
-			temp = qla82xx_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL);
-			if ((temp & MIU_TA_CTL_BUSY) == 0)
-				break;
-		}
-
-		if (j >= MAX_CTL_CHECK) {
-			if (printk_ratelimit())
-				dev_err(&ha->pdev->dev,
-				    "failed to write through agent\n");
-			ret = -1;
-			break;
-		}
-	}
-
-	return ret;
-}
 
 static struct qla82xx_uri_table_desc *
 qla82xx_get_table_desc(const u8 *unirom, int section)
@@ -1725,7 +1729,8 @@
 	ha->isp_ops->disable_intrs(ha);
 }
 
-int qla82xx_fw_load_from_blob(struct qla_hw_data *ha)
+static int
+qla82xx_fw_load_from_blob(struct qla_hw_data *ha)
 {
 	u64 *ptr64;
 	u32 i, flashaddr, size;
@@ -1836,7 +1841,8 @@
 	return 0;
 }
 
-int qla82xx_check_cmdpeg_state(struct qla_hw_data *ha)
+static int
+qla82xx_check_cmdpeg_state(struct qla_hw_data *ha)
 {
 	u32 val = 0;
 	int retries = 60;
@@ -1874,7 +1880,8 @@
 	return QLA_FUNCTION_FAILED;
 }
 
-int qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
+static int
+qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
 {
 	u32 val = 0;
 	int retries = 60;
@@ -1933,7 +1940,7 @@
  * @ha: SCSI driver HA context
  * @mb0: Mailbox0 register
  */
-void
+static void
 qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
 {
 	uint16_t	cnt;
@@ -2257,7 +2264,7 @@
 	ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
 }
 
-static inline void
+inline void
 qla82xx_set_drv_active(scsi_qla_host_t *vha)
 {
 	uint32_t drv_active;
@@ -2267,10 +2274,11 @@
 
 	/* If reset value is all FF's, initialize DRV_ACTIVE */
 	if (drv_active == 0xffffffff) {
-		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, 0);
+		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE,
+			QLA82XX_DRV_NOT_ACTIVE);
 		drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
 	}
-	drv_active |= (1 << (ha->portnum * 4));
+	drv_active |= (QLA82XX_DRV_ACTIVE << (ha->portnum * 4));
 	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active);
 }
 
@@ -2280,7 +2288,7 @@
 	uint32_t drv_active;
 
 	drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
-	drv_active &= ~(1 << (ha->portnum * 4));
+	drv_active &= ~(QLA82XX_DRV_ACTIVE << (ha->portnum * 4));
 	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active);
 }
 
@@ -2291,7 +2299,7 @@
 	int rval;
 
 	drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
-	rval = drv_state & (1 << (ha->portnum * 4));
+	rval = drv_state & (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
 	return rval;
 }
 
@@ -2305,7 +2313,7 @@
 
 	/* If reset value is all FF's, initialize DRV_STATE */
 	if (drv_state == 0xffffffff) {
-		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
+		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, QLA82XX_DRVST_NOT_RDY);
 		drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
 	}
 	drv_state |= (QLA82XX_DRVST_RST_RDY << (ha->portnum * 4));
@@ -2335,7 +2343,8 @@
 	qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state);
 }
 
-int qla82xx_load_fw(scsi_qla_host_t *vha)
+static int
+qla82xx_load_fw(scsi_qla_host_t *vha)
 {
 	int rst;
 	struct fw_blob *blob;
@@ -2411,7 +2420,7 @@
 	return QLA_FUNCTION_FAILED;
 }
 
-static int
+int
 qla82xx_start_firmware(scsi_qla_host_t *vha)
 {
 	int           pcie_cap;
@@ -2419,7 +2428,7 @@
 	struct qla_hw_data *ha = vha->hw;
 
 	/* scrub dma mask expansion register */
-	qla82xx_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
+	qla82xx_wr_32(ha, CRB_DMA_SHIFT, QLA82XX_DMA_SHIFT_VALUE);
 
 	/* Put both the PEG CMD and RCV PEG to default state
 	 * of 0 before resetting the hardware
@@ -2882,7 +2891,7 @@
 	return QLA_FUNCTION_FAILED;
 }
 
-uint32_t *
+static uint32_t *
 qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
 	uint32_t length)
 {
@@ -2903,7 +2912,7 @@
 	return dwptr;
 }
 
-int
+static int
 qla82xx_unprotect_flash(struct qla_hw_data *ha)
 {
 	int ret;
@@ -2934,7 +2943,7 @@
 	return ret;
 }
 
-int
+static int
 qla82xx_protect_flash(struct qla_hw_data *ha)
 {
 	int ret;
@@ -2963,7 +2972,7 @@
 	return ret;
 }
 
-int
+static int
 qla82xx_erase_sector(struct qla_hw_data *ha, int addr)
 {
 	int ret = 0;
@@ -3156,6 +3165,20 @@
 	}
 }
 
+void qla82xx_rom_lock_recovery(struct qla_hw_data *ha)
+{
+	if (qla82xx_rom_lock(ha))
+		/* Someone else is holding the lock. */
+		qla_printk(KERN_INFO, ha, "Resetting rom_lock\n");
+
+	/*
+	 * Either we got the lock, or someone
+	 * else died while holding it.
+	 * In either case, unlock.
+	 */
+	qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
+}
+
 /*
  * qla82xx_device_bootstrap
  *    Initialize device, set DEV_READY, start fw
@@ -3170,12 +3193,13 @@
 static int
 qla82xx_device_bootstrap(scsi_qla_host_t *vha)
 {
-	int rval, i, timeout;
+	int rval = QLA_SUCCESS;
+	int i, timeout;
 	uint32_t old_count, count;
 	struct qla_hw_data *ha = vha->hw;
+	int need_reset = 0, peg_stuck = 1;
 
-	if (qla82xx_need_reset(ha))
-		goto dev_initialize;
+	need_reset = qla82xx_need_reset(ha);
 
 	old_count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
 
@@ -3189,9 +3213,27 @@
 
 		count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
 		if (count != old_count)
+			peg_stuck = 0;
+	}
+
+	if (need_reset) {
+		/* We are trying to perform a recovery here. */
+		if (peg_stuck)
+			qla82xx_rom_lock_recovery(ha);
+		goto dev_initialize;
+	} else  {
+		/* Start of day for this ha context. */
+		if (peg_stuck) {
+			/* Either we are the first or recovery in progress. */
+			qla82xx_rom_lock_recovery(ha);
+			goto dev_initialize;
+		} else
+			/* Firmware already running. */
 			goto dev_ready;
 	}
 
+	return rval;
+
 dev_initialize:
 	/* set to DEV_INITIALIZING */
 	qla_printk(KERN_INFO, ha, "HW State: INITIALIZING\n");
@@ -3304,6 +3346,9 @@
 	struct qla_hw_data *ha = vha->hw;
 
 	fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
+	/* all 0xff, assume AER/EEH in progress, ignore */
+	if (fw_heartbeat_counter == 0xffffffff)
+		return;
 	if (vha->fw_heartbeat_counter == fw_heartbeat_counter) {
 		vha->seconds_since_last_heartbeat++;
 		/* FW not alive after 2 seconds */
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 15559ca..51ec0c5 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -26,6 +26,7 @@
 #define CRB_RCVPEG_STATE		QLA82XX_REG(0x13c)
 #define BOOT_LOADER_DIMM_STATUS		QLA82XX_REG(0x54)
 #define CRB_DMA_SHIFT			QLA82XX_REG(0xcc)
+#define QLA82XX_DMA_SHIFT_VALUE		0x55555555
 
 #define QLA82XX_HW_H0_CH_HUB_ADR    0x05
 #define QLA82XX_HW_H1_CH_HUB_ADR    0x0E
@@ -583,6 +584,10 @@
 #define	QLA82XX_DRVST_RST_RDY		1
 #define QLA82XX_DRVST_QSNT_RDY		2
 
+/* Different drive active state */
+#define QLA82XX_DRV_NOT_ACTIVE		0
+#define QLA82XX_DRV_ACTIVE		1
+
 /*
  * The PCI VendorID and DeviceID for our board.
  */
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 1e4bff6..800ea92 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1295,17 +1295,12 @@
 qla2xxx_slave_configure(struct scsi_device *sdev)
 {
 	scsi_qla_host_t *vha = shost_priv(sdev->host);
-	struct qla_hw_data *ha = vha->hw;
-	struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
 	struct req_que *req = vha->req;
 
 	if (sdev->tagged_supported)
 		scsi_activate_tcq(sdev, req->max_q_depth);
 	else
 		scsi_deactivate_tcq(sdev, req->max_q_depth);
-
-	rport->dev_loss_tmo = ha->port_down_retry_count;
-
 	return 0;
 }
 
@@ -2141,8 +2136,16 @@
 	else
 		base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
 						base_vha->vp_idx;
-	if (IS_QLA2100(ha))
-		host->sg_tablesize = 32;
+
+	/* Set the SG table size based on ISP type */
+	if (!IS_FWI2_CAPABLE(ha)) {
+		if (IS_QLA2100(ha))
+			host->sg_tablesize = 32;
+	} else {
+		if (!IS_QLA82XX(ha))
+			host->sg_tablesize = QLA_SG_ALL;
+	}
+
 	host->max_id = max_id;
 	host->this_id = 255;
 	host->cmd_per_lun = 3;
@@ -3553,6 +3556,11 @@
 	struct qla_hw_data *ha = vha->hw;
 	struct req_que *req;
 
+	if (ha->flags.eeh_busy) {
+		qla2x00_restart_timer(vha, WATCH_INTERVAL);
+		return;
+	}
+
 	if (IS_QLA82XX(ha))
 		qla82xx_watchdog(vha);
 
@@ -3782,8 +3790,21 @@
 		return PCI_ERS_RESULT_CAN_RECOVER;
 	case pci_channel_io_frozen:
 		ha->flags.eeh_busy = 1;
+		/* For ISP82XX complete any pending mailbox cmd */
+		if (IS_QLA82XX(ha)) {
+			ha->flags.fw_hung = 1;
+			if (ha->flags.mbox_busy) {
+				ha->flags.mbox_int = 1;
+				DEBUG2(qla_printk(KERN_ERR, ha,
+					"Due to pci channel io frozen, doing premature "
+					"completion of mbx command\n"));
+				complete(&ha->mbx_intr_comp);
+			}
+		}
 		qla2x00_free_irqs(vha);
 		pci_disable_device(pdev);
+		/* Return back all IOs */
+		qla2x00_abort_all_cmds(vha, DID_RESET << 16);
 		return PCI_ERS_RESULT_NEED_RESET;
 	case pci_channel_io_perm_failure:
 		ha->flags.pci_channel_io_perm_failure = 1;
@@ -3804,6 +3825,9 @@
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 	struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
 
+	if (IS_QLA82XX(ha))
+		return PCI_ERS_RESULT_RECOVERED;
+
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	if (IS_QLA2100(ha) || IS_QLA2200(ha)){
 		stat = RD_REG_DWORD(&reg->hccr);
@@ -3830,6 +3854,109 @@
 		return PCI_ERS_RESULT_RECOVERED;
 }
 
+uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
+{
+	uint32_t rval = QLA_FUNCTION_FAILED;
+	uint32_t drv_active = 0;
+	struct qla_hw_data *ha = base_vha->hw;
+	int fn;
+	struct pci_dev *other_pdev = NULL;
+
+	DEBUG17(qla_printk(KERN_INFO, ha,
+	    "scsi(%ld): In qla82xx_error_recovery\n", base_vha->host_no));
+
+	set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
+
+	if (base_vha->flags.online) {
+		/* Abort all outstanding commands,
+		 * so as to be requeued later */
+		qla2x00_abort_isp_cleanup(base_vha);
+	}
+
+
+	fn = PCI_FUNC(ha->pdev->devfn);
+	while (fn > 0) {
+		fn--;
+		DEBUG17(qla_printk(KERN_INFO, ha,
+		    "Finding pci device at function = 0x%x\n", fn));
+		other_pdev =
+		    pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
+		    ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
+		    fn));
+
+		if (!other_pdev)
+			continue;
+		if (atomic_read(&other_pdev->enable_cnt)) {
+			DEBUG17(qla_printk(KERN_INFO, ha,
+			    "Found PCI func availabe and enabled at 0x%x\n",
+			    fn));
+			pci_dev_put(other_pdev);
+			break;
+		}
+		pci_dev_put(other_pdev);
+	}
+
+	if (!fn) {
+		/* Reset owner */
+		DEBUG17(qla_printk(KERN_INFO, ha,
+		    "This devfn is reset owner = 0x%x\n", ha->pdev->devfn));
+		qla82xx_idc_lock(ha);
+
+		qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+		    QLA82XX_DEV_INITIALIZING);
+
+		qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION,
+		    QLA82XX_IDC_VERSION);
+
+		drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
+		DEBUG17(qla_printk(KERN_INFO, ha,
+		    "drv_active = 0x%x\n", drv_active));
+
+		qla82xx_idc_unlock(ha);
+		/* Reset if device is not already reset
+		 * drv_active would be 0 if a reset has already been done
+		 */
+		if (drv_active)
+			rval = qla82xx_start_firmware(base_vha);
+		else
+			rval = QLA_SUCCESS;
+		qla82xx_idc_lock(ha);
+
+		if (rval != QLA_SUCCESS) {
+			qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
+			qla82xx_clear_drv_active(ha);
+			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+			    QLA82XX_DEV_FAILED);
+		} else {
+			qla_printk(KERN_INFO, ha, "HW State: READY\n");
+			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
+			    QLA82XX_DEV_READY);
+			qla82xx_idc_unlock(ha);
+			ha->flags.fw_hung = 0;
+			rval = qla82xx_restart_isp(base_vha);
+			qla82xx_idc_lock(ha);
+			/* Clear driver state register */
+			qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
+			qla82xx_set_drv_active(base_vha);
+		}
+		qla82xx_idc_unlock(ha);
+	} else {
+		DEBUG17(qla_printk(KERN_INFO, ha,
+		    "This devfn is not reset owner = 0x%x\n", ha->pdev->devfn));
+		if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
+		    QLA82XX_DEV_READY)) {
+			ha->flags.fw_hung = 0;
+			rval = qla82xx_restart_isp(base_vha);
+			qla82xx_idc_lock(ha);
+			qla82xx_set_drv_active(base_vha);
+			qla82xx_idc_unlock(ha);
+		}
+	}
+	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
+
+	return rval;
+}
+
 static pci_ers_result_t
 qla2xxx_pci_slot_reset(struct pci_dev *pdev)
 {
@@ -3862,15 +3989,23 @@
 	if (rc) {
 		qla_printk(KERN_WARNING, ha,
 		    "Can't re-enable PCI device after reset.\n");
-		return ret;
+		goto exit_slot_reset;
 	}
 
 	rsp = ha->rsp_q_map[0];
 	if (qla2x00_request_irqs(ha, rsp))
-		return ret;
+		goto exit_slot_reset;
 
 	if (ha->isp_ops->pci_config(base_vha))
-		return ret;
+		goto exit_slot_reset;
+
+	if (IS_QLA82XX(ha)) {
+		if (qla82xx_error_recovery(base_vha) == QLA_SUCCESS) {
+			ret = PCI_ERS_RESULT_RECOVERED;
+			goto exit_slot_reset;
+		} else
+			goto exit_slot_reset;
+	}
 
 	while (ha->flags.mbox_busy && retries--)
 		msleep(1000);
@@ -3881,6 +4016,7 @@
 	clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
 
 
+exit_slot_reset:
 	DEBUG17(qla_printk(KERN_WARNING, ha,
 	    "slot_reset-return:ret=%x\n", ret));
 
@@ -3948,6 +4084,7 @@
 
 static struct file_operations apidev_fops = {
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 /**
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 5d4a382..449256f 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -5,6 +5,7 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <linux/pci.h>
 #include "ql4_def.h"
 #include "ql4_glbl.h"
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index b02bdc6..2c36bae 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -109,10 +109,12 @@
 #define DEF_PHYSBLK_EXP 0
 #define DEF_LOWEST_ALIGNED 0
 #define DEF_OPT_BLKS 64
-#define DEF_UNMAP_MAX_BLOCKS 0
-#define DEF_UNMAP_MAX_DESC 0
-#define DEF_UNMAP_GRANULARITY 0
+#define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
+#define DEF_UNMAP_MAX_DESC 256
+#define DEF_UNMAP_GRANULARITY 1
 #define DEF_UNMAP_ALIGNMENT 0
+#define DEF_TPWS 0
+#define DEF_TPU 0
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -177,10 +179,12 @@
 static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
 static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
 static int scsi_debug_opt_blks = DEF_OPT_BLKS;
-static int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
-static int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
-static int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
-static int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
+static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
+static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
+static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
+static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
+static unsigned int scsi_debug_tpws = DEF_TPWS;
+static unsigned int scsi_debug_tpu = DEF_TPU;
 
 static int scsi_debug_cmnd_count = 0;
 
@@ -723,16 +727,9 @@
 	/* Optimal Transfer Length */
 	put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
 
-	if (scsi_debug_unmap_max_desc) {
-		unsigned int blocks;
-
-		if (scsi_debug_unmap_max_blocks)
-			blocks = scsi_debug_unmap_max_blocks;
-		else
-			blocks = 0xffffffff;
-
+	if (scsi_debug_tpu) {
 		/* Maximum Unmap LBA Count */
-		put_unaligned_be32(blocks, &arr[16]);
+		put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
 
 		/* Maximum Unmap Block Descriptor Count */
 		put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
@@ -745,10 +742,9 @@
 	}
 
 	/* Optimal Unmap Granularity */
-	if (scsi_debug_unmap_granularity) {
-		put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
-		return 0x3c; /* Mandatory page length for thin provisioning */
-	}
+	put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
+
+	return 0x3c; /* Mandatory page length for thin provisioning */
 
 	return sizeof(vpdb0_data);
 }
@@ -765,6 +761,21 @@
 	return 0x3c;
 }
 
+/* Thin provisioning VPD page (SBC-3) */
+static int inquiry_evpd_b2(unsigned char *arr)
+{
+	memset(arr, 0, 0x8);
+	arr[0] = 0;			/* threshold exponent */
+
+	if (scsi_debug_tpu)
+		arr[1] = 1 << 7;
+
+	if (scsi_debug_tpws)
+		arr[1] |= 1 << 6;
+
+	return 0x8;
+}
+
 #define SDEBUG_LONG_INQ_SZ 96
 #define SDEBUG_MAX_INQ_ARR_SZ 584
 
@@ -820,6 +831,7 @@
 			arr[n++] = 0x89;  /* ATA information */
 			arr[n++] = 0xb0;  /* Block limits (SBC) */
 			arr[n++] = 0xb1;  /* Block characteristics (SBC) */
+			arr[n++] = 0xb2;  /* Thin provisioning (SBC) */
 			arr[3] = n - 4;	  /* number of supported VPD pages */
 		} else if (0x80 == cmd[2]) { /* unit serial number */
 			arr[1] = cmd[2];	/*sanity */
@@ -867,6 +879,9 @@
 		} else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
 			arr[1] = cmd[2];        /*sanity */
 			arr[3] = inquiry_evpd_b1(&arr[4]);
+		} else if (0xb2 == cmd[2]) { /* Thin provisioning (SBC) */
+			arr[1] = cmd[2];        /*sanity */
+			arr[3] = inquiry_evpd_b2(&arr[4]);
 		} else {
 			/* Illegal request, invalid field in cdb */
 			mk_sense_buffer(devip, ILLEGAL_REQUEST,
@@ -1038,7 +1053,7 @@
 	arr[13] = scsi_debug_physblk_exp & 0xf;
 	arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
 
-	if (scsi_debug_unmap_granularity)
+	if (scsi_debug_tpu || scsi_debug_tpws)
 		arr[14] |= 0x80; /* TPE */
 
 	arr[15] = scsi_debug_lowest_aligned & 0xff;
@@ -2708,6 +2723,8 @@
 module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
 module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
 module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
+module_param_named(tpu, scsi_debug_tpu, int, S_IRUGO);
+module_param_named(tpws, scsi_debug_tpws, int, S_IRUGO);
 
 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
 MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2739,10 +2756,12 @@
 MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
 MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
 MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
-MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0)");
-MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=0)");
-MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=0)");
+MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
+MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
+MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
 MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
+MODULE_PARM_DESC(tpu, "enable TP, support UNMAP command (def=0)");
+MODULE_PARM_DESC(tpws, "enable TP, support WRITE SAME(16) with UNMAP bit (def=0)");
 
 static char sdebug_info[256];
 
@@ -3130,7 +3149,7 @@
 {
 	ssize_t count;
 
-	if (scsi_debug_unmap_granularity == 0)
+	if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0)
 		return scnprintf(buf, PAGE_SIZE, "0-%u\n",
 				 sdebug_store_sectors);
 
@@ -3207,16 +3226,7 @@
 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_add_host);
 }
 
-static void pseudo_0_release(struct device *dev)
-{
-	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-		printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
-}
-
-static struct device pseudo_primary = {
-	.init_name	= "pseudo_0",
-	.release	= pseudo_0_release,
-};
+struct device *pseudo_primary;
 
 static int __init scsi_debug_init(void)
 {
@@ -3322,10 +3332,21 @@
 		memset(dif_storep, 0xff, dif_size);
 	}
 
-	if (scsi_debug_unmap_granularity) {
+	/* Thin Provisioning */
+	if (scsi_debug_tpu || scsi_debug_tpws) {
 		unsigned int map_bytes;
 
-		if (scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
+		scsi_debug_unmap_max_blocks =
+			clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU);
+
+		scsi_debug_unmap_max_desc =
+			clamp(scsi_debug_unmap_max_desc, 0U, 256U);
+
+		scsi_debug_unmap_granularity =
+			clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU);
+
+		if (scsi_debug_unmap_alignment &&
+		    scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
 			printk(KERN_ERR
 			       "%s: ERR: unmap_granularity < unmap_alignment\n",
 			       __func__);
@@ -3352,10 +3373,10 @@
 			map_region(0, 2);
 	}
 
-	ret = device_register(&pseudo_primary);
-	if (ret < 0) {
-		printk(KERN_WARNING "scsi_debug: device_register error: %d\n",
-			ret);
+	pseudo_primary = root_device_register("pseudo_0");
+	if (IS_ERR(pseudo_primary)) {
+		printk(KERN_WARNING "scsi_debug: root_device_register() error\n");
+		ret = PTR_ERR(pseudo_primary);
 		goto free_vm;
 	}
 	ret = bus_register(&pseudo_lld_bus);
@@ -3402,7 +3423,7 @@
 bus_unreg:
 	bus_unregister(&pseudo_lld_bus);
 dev_unreg:
-	device_unregister(&pseudo_primary);
+	root_device_unregister(pseudo_primary);
 free_vm:
 	if (map_storep)
 		vfree(map_storep);
@@ -3423,7 +3444,7 @@
 	do_remove_driverfs_files();
 	driver_unregister(&sdebug_driverfs_driver);
 	bus_unregister(&pseudo_lld_bus);
-	device_unregister(&pseudo_primary);
+	root_device_unregister(pseudo_primary);
 
 	if (dif_storep)
 		vfree(dif_storep);
@@ -3474,7 +3495,7 @@
         spin_unlock(&sdebug_host_list_lock);
 
         sdbg_host->dev.bus = &pseudo_lld_bus;
-        sdbg_host->dev.parent = &pseudo_primary;
+        sdbg_host->dev.parent = pseudo_primary;
         sdbg_host->dev.release = &sdebug_release_adapter;
         dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
 
@@ -3642,7 +3663,7 @@
 			errsts = resp_readcap16(SCpnt, devip);
 		else if (cmd[1] == SAI_GET_LBA_STATUS) {
 
-			if (scsi_debug_unmap_max_desc == 0) {
+			if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0) {
 				mk_sense_buffer(devip, ILLEGAL_REQUEST,
 						INVALID_COMMAND_OPCODE, 0);
 				errsts = check_condition_result;
@@ -3753,8 +3774,16 @@
 		}
 		break;
 	case WRITE_SAME_16:
-		if (cmd[1] & 0x8)
-			unmap = 1;
+		if (cmd[1] & 0x8) {
+			if (scsi_debug_tpws == 0) {
+				mk_sense_buffer(devip, ILLEGAL_REQUEST,
+						INVALID_FIELD_IN_CDB, 0);
+				errsts = check_condition_result;
+			} else
+				unmap = 1;
+		}
+		if (errsts)
+			break;
 		/* fall through */
 	case WRITE_SAME:
 		errsts = check_readiness(SCpnt, 0, devip);
@@ -3768,7 +3797,7 @@
 		if (errsts)
 			break;
 
-		if (scsi_debug_unmap_max_desc == 0) {
+		if (scsi_debug_unmap_max_desc == 0 || scsi_debug_tpu == 0) {
 			mk_sense_buffer(devip, ILLEGAL_REQUEST,
 					INVALID_COMMAND_OPCODE, 0);
 			errsts = check_condition_result;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ee02d38..8041fe1 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -968,11 +968,13 @@
  */
 int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 {
-	int error = scsi_init_sgtable(cmd->request, &cmd->sdb, gfp_mask);
+	struct request *rq = cmd->request;
+
+	int error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask);
 	if (error)
 		goto err_exit;
 
-	if (blk_bidi_rq(cmd->request)) {
+	if (blk_bidi_rq(rq)) {
 		struct scsi_data_buffer *bidi_sdb = kmem_cache_zalloc(
 			scsi_sdb_cache, GFP_ATOMIC);
 		if (!bidi_sdb) {
@@ -980,28 +982,28 @@
 			goto err_exit;
 		}
 
-		cmd->request->next_rq->special = bidi_sdb;
-		error = scsi_init_sgtable(cmd->request->next_rq, bidi_sdb,
-								    GFP_ATOMIC);
+		rq->next_rq->special = bidi_sdb;
+		error = scsi_init_sgtable(rq->next_rq, bidi_sdb, GFP_ATOMIC);
 		if (error)
 			goto err_exit;
 	}
 
-	if (blk_integrity_rq(cmd->request)) {
+	if (blk_integrity_rq(rq)) {
 		struct scsi_data_buffer *prot_sdb = cmd->prot_sdb;
 		int ivecs, count;
 
 		BUG_ON(prot_sdb == NULL);
-		ivecs = blk_rq_count_integrity_sg(cmd->request);
+		ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio);
 
 		if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask)) {
 			error = BLKPREP_DEFER;
 			goto err_exit;
 		}
 
-		count = blk_rq_map_integrity_sg(cmd->request,
+		count = blk_rq_map_integrity_sg(rq->q, rq->bio,
 						prot_sdb->table.sgl);
 		BUG_ON(unlikely(count > ivecs));
+		BUG_ON(unlikely(count > queue_max_integrity_segments(rq->q)));
 
 		cmd->prot_sdb = prot_sdb;
 		cmd->prot_sdb->table.nents = count;
@@ -1625,6 +1627,14 @@
 	blk_queue_max_segments(q, min_t(unsigned short, shost->sg_tablesize,
 					SCSI_MAX_SG_CHAIN_SEGMENTS));
 
+	if (scsi_host_prot_dma(shost)) {
+		shost->sg_prot_tablesize =
+			min_not_zero(shost->sg_prot_tablesize,
+				     (unsigned short)SCSI_MAX_PROT_SG_SEGMENTS);
+		BUG_ON(shost->sg_prot_tablesize < shost->sg_tablesize);
+		blk_queue_max_integrity_segments(q, shost->sg_prot_tablesize);
+	}
+
 	blk_queue_max_hw_sectors(q, shost->max_sectors);
 	blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
 	blk_queue_segment_boundary(q, shost->dma_boundary);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 3d0a1e6..087821f 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -417,9 +417,7 @@
 	starget->reap_ref = 1;
 	dev->parent = get_device(parent);
 	dev_set_name(dev, "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;
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index c3f6737..20ad59d 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -251,6 +251,7 @@
 shost_rd_attr(cmd_per_lun, "%hd\n");
 shost_rd_attr(can_queue, "%hd\n");
 shost_rd_attr(sg_tablesize, "%hu\n");
+shost_rd_attr(sg_prot_tablesize, "%hu\n");
 shost_rd_attr(unchecked_isa_dma, "%d\n");
 shost_rd_attr(prot_capabilities, "%u\n");
 shost_rd_attr(prot_guard_type, "%hd\n");
@@ -262,6 +263,7 @@
 	&dev_attr_cmd_per_lun.attr,
 	&dev_attr_can_queue.attr,
 	&dev_attr_sg_tablesize.attr,
+	&dev_attr_sg_prot_tablesize.attr,
 	&dev_attr_unchecked_isa_dma.attr,
 	&dev_attr_proc_name.attr,
 	&dev_attr_scan.attr,
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index a87e21c..0172de1 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -22,7 +22,6 @@
 #include <linux/miscdevice.h>
 #include <linux/gfp.h>
 #include <linux/file.h>
-#include <linux/smp_lock.h>
 #include <net/tcp.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -323,7 +322,6 @@
 {
 	tx_ring.tr_idx = rx_ring.tr_idx = 0;
 
-	cycle_kernel_lock();
 	return 0;
 }
 
@@ -333,6 +331,7 @@
 	.poll		= tgt_poll,
 	.write		= tgt_write,
 	.mmap		= tgt_mmap,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice tgt_miscdev = {
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index d7e470a..998c01b 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -53,6 +53,25 @@
 static void fc_bsg_goose_queue(struct fc_rport *);
 
 /*
+ * Module Parameters
+ */
+
+/*
+ * dev_loss_tmo: the default number of seconds that the FC transport
+ *   should insulate the loss of a remote port.
+ *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
+ */
+static unsigned int fc_dev_loss_tmo = 60;		/* seconds */
+
+module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(dev_loss_tmo,
+		 "Maximum number of seconds that the FC transport should"
+		 " insulate the loss of a remote port. Once this value is"
+		 " exceeded, the scsi target is removed. Value should be"
+		 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if"
+		 " fast_io_fail_tmo is not set.");
+
+/*
  * Redefine so that we can have same named attributes in the
  * sdev/starget/host objects.
  */
@@ -408,6 +427,7 @@
 	if (!fc_host->work_q)
 		return -ENOMEM;
 
+	fc_host->dev_loss_tmo = fc_dev_loss_tmo;
 	snprintf(fc_host->devloss_work_q_name,
 		 sizeof(fc_host->devloss_work_q_name),
 		 "fc_dl_%d", shost->host_no);
@@ -462,25 +482,6 @@
 			       NULL);
 
 /*
- * Module Parameters
- */
-
-/*
- * dev_loss_tmo: the default number of seconds that the FC transport
- *   should insulate the loss of a remote port.
- *   The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
- */
-static unsigned int fc_dev_loss_tmo = 60;		/* seconds */
-
-module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(dev_loss_tmo,
-		 "Maximum number of seconds that the FC transport should"
-		 " insulate the loss of a remote port. Once this value is"
-		 " exceeded, the scsi target is removed. Value should be"
-		 " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT if"
-		 " fast_io_fail_tmo is not set.");
-
-/*
  * Netlink Infrastructure
  */
 
@@ -830,24 +831,32 @@
 /*
  * dev_loss_tmo attribute
  */
-fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
-static ssize_t
-store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
+static int fc_str_to_dev_loss(const char *buf, unsigned long *val)
 {
-	unsigned long val;
-	struct fc_rport *rport = transport_class_to_rport(dev);
+	char *cp;
+
+	*val = simple_strtoul(buf, &cp, 0);
+	if ((*cp && (*cp != '\n')) || (*val < 0))
+		return -EINVAL;
+	/*
+	 * Check for overflow; dev_loss_tmo is u32
+	 */
+	if (*val > UINT_MAX)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int fc_rport_set_dev_loss_tmo(struct fc_rport *rport,
+				     unsigned long val)
+{
 	struct Scsi_Host *shost = rport_to_shost(rport);
 	struct fc_internal *i = to_fc_internal(shost->transportt);
-	char *cp;
+
 	if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
 	    (rport->port_state == FC_PORTSTATE_DELETED) ||
 	    (rport->port_state == FC_PORTSTATE_NOTPRESENT))
 		return -EBUSY;
-	val = simple_strtoul(buf, &cp, 0);
-	if ((*cp && (*cp != '\n')) || (val < 0))
-		return -EINVAL;
-
 	/*
 	 * Check for overflow; dev_loss_tmo is u32
 	 */
@@ -863,6 +872,25 @@
 		return -EINVAL;
 
 	i->f->set_rport_dev_loss_tmo(rport, val);
+	return 0;
+}
+
+fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
+static ssize_t
+store_fc_rport_dev_loss_tmo(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct fc_rport *rport = transport_class_to_rport(dev);
+	unsigned long val;
+	int rc;
+
+	rc = fc_str_to_dev_loss(buf, &val);
+	if (rc)
+		return rc;
+
+	rc = fc_rport_set_dev_loss_tmo(rport, val);
+	if (rc)
+		return rc;
 	return count;
 }
 static FC_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
@@ -1608,8 +1636,35 @@
 static FC_DEVICE_ATTR(host, issue_lip, S_IWUSR, NULL,
 			store_fc_private_host_issue_lip);
 
-fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
+static ssize_t
+store_fc_private_host_dev_loss_tmo(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct Scsi_Host *shost = transport_class_to_shost(dev);
+	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
+	struct fc_rport *rport;
+	unsigned long val, flags;
+	int rc;
 
+	rc = fc_str_to_dev_loss(buf, &val);
+	if (rc)
+		return rc;
+
+	fc_host_dev_loss_tmo(shost) = val;
+	spin_lock_irqsave(shost->host_lock, flags);
+	list_for_each_entry(rport, &fc_host->rports, peers)
+		fc_rport_set_dev_loss_tmo(rport, val);
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	return count;
+}
+
+fc_private_host_show_function(dev_loss_tmo, "%d\n", 20, );
+static FC_DEVICE_ATTR(host, dev_loss_tmo, S_IRUGO | S_IWUSR,
+		      show_fc_host_dev_loss_tmo,
+		      store_fc_private_host_dev_loss_tmo);
+
+fc_private_host_rd_attr(npiv_vports_inuse, "%u\n", 20);
 
 /*
  * Host Statistics Management
@@ -2165,6 +2220,7 @@
 	SETUP_HOST_ATTRIBUTE_RW(system_hostname);
 
 	/* Transport-managed attributes */
+	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(dev_loss_tmo);
 	SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
 	if (ft->issue_fc_host_lip)
 		SETUP_PRIVATE_HOST_ATTRIBUTE_RW(issue_lip);
@@ -2525,7 +2581,7 @@
 
 	rport->maxframe_size = -1;
 	rport->supported_classes = FC_COS_UNSPECIFIED;
-	rport->dev_loss_tmo = fc_dev_loss_tmo;
+	rport->dev_loss_tmo = fc_host->dev_loss_tmo;
 	memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
 	memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
 	rport->port_id = ids->port_id;
@@ -4044,11 +4100,54 @@
 /**
  * fc_bsg_remove - Deletes the bsg hooks on fchosts/rports
  * @q:	the request_queue that is to be torn down.
+ *
+ * Notes:
+ *   Before unregistering the queue empty any requests that are blocked
+ *
+ *
  */
 static void
 fc_bsg_remove(struct request_queue *q)
 {
+	struct request *req; /* block request */
+	int counts; /* totals for request_list count and starved */
+
 	if (q) {
+		/* Stop taking in new requests */
+		spin_lock_irq(q->queue_lock);
+		blk_stop_queue(q);
+
+		/* drain all requests in the queue */
+		while (1) {
+			/* need the lock to fetch a request
+			 * this may fetch the same reqeust as the previous pass
+			 */
+			req = blk_fetch_request(q);
+			/* save requests in use and starved */
+			counts = q->rq.count[0] + q->rq.count[1] +
+				q->rq.starved[0] + q->rq.starved[1];
+			spin_unlock_irq(q->queue_lock);
+			/* any requests still outstanding? */
+			if (counts == 0)
+				break;
+
+			/* This may be the same req as the previous iteration,
+			 * always send the blk_end_request_all after a prefetch.
+			 * It is not okay to not end the request because the
+			 * prefetch started the request.
+			 */
+			if (req) {
+				/* return -ENXIO to indicate that this queue is
+				 * going away
+				 */
+				req->errors = -ENXIO;
+				blk_end_request_all(req, -ENXIO);
+			}
+
+			msleep(200); /* allow bsg to possibly finish */
+			spin_lock_irq(q->queue_lock);
+		}
+
 		bsg_unregister_queue(q);
 		blk_cleanup_queue(q);
 	}
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index e84026d..332387a 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -537,7 +537,7 @@
 
 /**
  * iscsi_block_scsi_eh - block scsi eh until session state has transistioned
- * cmd: scsi cmd passed to scsi eh handler
+ * @cmd: scsi cmd passed to scsi eh handler
  *
  * If the session is down this function will wait for the recovery
  * timer to fire or for the session to be logged back in. If the
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index ffa0689..57d1e3e 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -477,7 +477,7 @@
 
 static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 {
-	rq->timeout = SD_TIMEOUT;
+	rq->timeout = SD_FLUSH_TIMEOUT;
 	rq->retries = SD_MAX_RETRIES;
 	rq->cmd[0] = SYNCHRONIZE_CACHE;
 	rq->cmd_len = 10;
@@ -1072,7 +1072,7 @@
 		 * flush everything.
 		 */
 		res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
-				       SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+				       SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL);
 		if (res == 0)
 			break;
 	}
@@ -1498,6 +1498,9 @@
 	unsigned long long lba;
 	unsigned sector_size;
 
+	if (sdp->no_read_capacity_16)
+		return -EINVAL;
+
 	do {
 		memset(cmd, 0, 16);
 		cmd[0] = SERVICE_ACTION_IN;
@@ -1554,7 +1557,7 @@
 	}
 
 	/* Logical blocks per physical block exponent */
-	sdkp->hw_sector_size = (1 << (buffer[13] & 0xf)) * sector_size;
+	sdkp->physical_block_size = (1 << (buffer[13] & 0xf)) * sector_size;
 
 	/* Lowest aligned logical block */
 	alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size;
@@ -1567,7 +1570,7 @@
 		struct request_queue *q = sdp->request_queue;
 
 		sdkp->thin_provisioning = 1;
-		q->limits.discard_granularity = sdkp->hw_sector_size;
+		q->limits.discard_granularity = sdkp->physical_block_size;
 		q->limits.max_discard_sectors = 0xffffffff;
 
 		if (buffer[14] & 0x40) /* TPRZ */
@@ -1626,6 +1629,15 @@
 	sector_size = get_unaligned_be32(&buffer[4]);
 	lba = get_unaligned_be32(&buffer[0]);
 
+	if (sdp->no_read_capacity_16 && (lba == 0xffffffff)) {
+		/* Some buggy (usb cardreader) devices return an lba of
+		   0xffffffff when the want to report a size of 0 (with
+		   which they really mean no media is present) */
+		sdkp->capacity = 0;
+		sdkp->physical_block_size = sector_size;
+		return sector_size;
+	}
+
 	if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) {
 		sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
 			"kernel compiled with support for large block "
@@ -1635,7 +1647,7 @@
 	}
 
 	sdkp->capacity = lba + 1;
-	sdkp->hw_sector_size = sector_size;
+	sdkp->physical_block_size = sector_size;
 	return sector_size;
 }
 
@@ -1756,10 +1768,10 @@
 				  (unsigned long long)sdkp->capacity,
 				  sector_size, cap_str_10, cap_str_2);
 
-			if (sdkp->hw_sector_size != sector_size)
+			if (sdkp->physical_block_size != sector_size)
 				sd_printk(KERN_NOTICE, sdkp,
 					  "%u-byte physical blocks\n",
-					  sdkp->hw_sector_size);
+					  sdkp->physical_block_size);
 		}
 	}
 
@@ -1773,7 +1785,8 @@
 	else if (sector_size == 256)
 		sdkp->capacity >>= 1;
 
-	blk_queue_physical_block_size(sdp->request_queue, sdkp->hw_sector_size);
+	blk_queue_physical_block_size(sdp->request_queue,
+				      sdkp->physical_block_size);
 	sdkp->device->sector_size = sector_size;
 }
 
@@ -2039,14 +2052,24 @@
 		lba_count = get_unaligned_be32(&buffer[20]);
 		desc_count = get_unaligned_be32(&buffer[24]);
 
-		if (lba_count) {
-			q->limits.max_discard_sectors =
-				lba_count * sector_sz >> 9;
-
-			if (desc_count)
+		if (lba_count && desc_count) {
+			if (sdkp->tpvpd && !sdkp->tpu)
+				sdkp->unmap = 0;
+			else
 				sdkp->unmap = 1;
 		}
 
+		if (sdkp->tpvpd && !sdkp->tpu && !sdkp->tpws) {
+			sd_printk(KERN_ERR, sdkp, "Thin provisioning is " \
+				  "enabled but neither TPU, nor TPWS are " \
+				  "set. Disabling discard!\n");
+			goto out;
+		}
+
+		if (lba_count)
+			q->limits.max_discard_sectors =
+				lba_count * sector_sz >> 9;
+
 		granularity = get_unaligned_be32(&buffer[28]);
 
 		if (granularity)
@@ -2087,6 +2110,31 @@
 	kfree(buffer);
 }
 
+/**
+ * sd_read_thin_provisioning - Query thin provisioning VPD page
+ * @disk: disk to query
+ */
+static void sd_read_thin_provisioning(struct scsi_disk *sdkp)
+{
+	unsigned char *buffer;
+	const int vpd_len = 8;
+
+	if (sdkp->thin_provisioning == 0)
+		return;
+
+	buffer = kmalloc(vpd_len, GFP_KERNEL);
+
+	if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb2, buffer, vpd_len))
+		goto out;
+
+	sdkp->tpvpd = 1;
+	sdkp->tpu   = (buffer[5] >> 7) & 1;	/* UNMAP */
+	sdkp->tpws  = (buffer[5] >> 6) & 1;	/* WRITE SAME(16) with UNMAP */
+
+ out:
+	kfree(buffer);
+}
+
 static int sd_try_extended_inquiry(struct scsi_device *sdp)
 {
 	/*
@@ -2109,7 +2157,7 @@
 	struct scsi_disk *sdkp = scsi_disk(disk);
 	struct scsi_device *sdp = sdkp->device;
 	unsigned char *buffer;
-	unsigned ordered;
+	unsigned flush = 0;
 
 	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
 				      "sd_revalidate_disk\n"));
@@ -2138,6 +2186,7 @@
 		sd_read_capacity(sdkp, buffer);
 
 		if (sd_try_extended_inquiry(sdp)) {
+			sd_read_thin_provisioning(sdkp);
 			sd_read_block_limits(sdkp);
 			sd_read_block_characteristics(sdkp);
 		}
@@ -2151,17 +2200,15 @@
 
 	/*
 	 * We now have all cache related info, determine how we deal
-	 * with ordered requests.  Note that as the current SCSI
-	 * dispatch function can alter request order, we cannot use
-	 * QUEUE_ORDERED_TAG_* even when ordered tag is supported.
+	 * with flush requests.
 	 */
-	if (sdkp->WCE)
-		ordered = sdkp->DPOFUA
-			? QUEUE_ORDERED_DRAIN_FUA : QUEUE_ORDERED_DRAIN_FLUSH;
-	else
-		ordered = QUEUE_ORDERED_DRAIN;
+	if (sdkp->WCE) {
+		flush |= REQ_FLUSH;
+		if (sdkp->DPOFUA)
+			flush |= REQ_FUA;
+	}
 
-	blk_queue_ordered(sdkp->disk->queue, ordered);
+	blk_queue_flush(sdkp->disk->queue, flush);
 
 	set_capacity(disk, sdkp->capacity);
 	kfree(buffer);
@@ -2252,11 +2299,10 @@
 	index = sdkp->index;
 	dev = &sdp->sdev_gendev;
 
-	if (index < SD_MAX_DISKS) {
-		gd->major = sd_major((index & 0xf0) >> 4);
-		gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
-		gd->minors = SD_MINORS;
-	}
+	gd->major = sd_major((index & 0xf0) >> 4);
+	gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
+	gd->minors = SD_MINORS;
+
 	gd->fops = &sd_fops;
 	gd->private_data = &sdkp->driver;
 	gd->queue = sdkp->device->request_queue;
@@ -2346,6 +2392,12 @@
 	if (error)
 		goto out_put;
 
+	if (index >= SD_MAX_DISKS) {
+		error = -ENODEV;
+		sdev_printk(KERN_WARNING, sdp, "SCSI disk (sd) name space exhausted.\n");
+		goto out_free_index;
+	}
+
 	error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN);
 	if (error)
 		goto out_free_index;
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index f81a930..55488fa 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -19,6 +19,7 @@
  */
 #define SD_TIMEOUT		(30 * HZ)
 #define SD_MOD_TIMEOUT		(75 * HZ)
+#define SD_FLUSH_TIMEOUT	(60 * HZ)
 
 /*
  * Number of allowed retries
@@ -50,7 +51,7 @@
 	atomic_t	openers;
 	sector_t	capacity;	/* size in 512-byte sectors */
 	u32		index;
-	unsigned short	hw_sector_size;
+	unsigned int	physical_block_size;
 	u8		media_present;
 	u8		write_prot;
 	u8		protection_type;/* Data Integrity Field */
@@ -62,6 +63,9 @@
 	unsigned	first_scan : 1;
 	unsigned	thin_provisioning : 1;
 	unsigned	unmap : 1;
+	unsigned	tpws : 1;
+	unsigned	tpu : 1;
+	unsigned	tpvpd : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 84be621..0cb39ff 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -375,21 +375,20 @@
 	unsigned int i, j;
 	u32 phys, virt;
 
-	/* Already remapped? */
-	if (rq->cmd_flags & REQ_INTEGRITY)
-		return 0;
-
 	sdkp = rq->bio->bi_bdev->bd_disk->private_data;
 
 	if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION)
 		return 0;
 
-	rq->cmd_flags |= REQ_INTEGRITY;
 	phys = hw_sector & 0xffffffff;
 
 	__rq_for_each_bio(bio, rq) {
 		struct bio_vec *iv;
 
+		/* Already remapped? */
+		if (bio_flagged(bio, BIO_MAPPED_INTEGRITY))
+			break;
+
 		virt = bio->bi_integrity->bip_sector & 0xffffffff;
 
 		bip_for_each_vec(iv, bio->bi_integrity, i) {
@@ -408,6 +407,8 @@
 
 			kunmap_atomic(sdt, KM_USER0);
 		}
+
+		bio->bi_flags |= BIO_MAPPED_INTEGRITY;
 	}
 
 	return 0;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 78d6163..5428d53 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -49,7 +49,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/blktrace_api.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include "scsi.h"
 #include <scsi/scsi_dbg.h>
@@ -103,6 +103,8 @@
 static int sg_add(struct device *, struct class_interface *);
 static void sg_remove(struct device *, struct class_interface *);
 
+static DEFINE_MUTEX(sg_mutex);
+
 static DEFINE_IDR(sg_index_idr);
 static DEFINE_RWLOCK(sg_index_lock);	/* Also used to lock
 							   file descriptor list for device */
@@ -229,7 +231,7 @@
 	int res;
 	int retval;
 
-	lock_kernel();
+	mutex_lock(&sg_mutex);
 	nonseekable_open(inode, filp);
 	SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
 	sdp = sg_get_dev(dev);
@@ -314,7 +316,7 @@
 sg_put:
 	if (sdp)
 		sg_put_dev(sdp);
-	unlock_kernel();
+	mutex_unlock(&sg_mutex);
 	return retval;
 }
 
@@ -1092,9 +1094,9 @@
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&sg_mutex);
 	ret = sg_ioctl(filp, cmd_in, arg);
-	unlock_kernel();
+	mutex_unlock(&sg_mutex);
 
 	return ret;
 }
@@ -1351,6 +1353,7 @@
 	.mmap = sg_mmap,
 	.release = sg_release,
 	.fasync = sg_fasync,
+	.llseek = no_llseek,
 };
 
 static struct class *sg_sysfs_class;
@@ -1657,7 +1660,7 @@
 	if (sg_allow_dio && hp->flags & SG_FLAG_DIRECT_IO &&
 	    dxfer_dir != SG_DXFER_UNKNOWN && !iov_count &&
 	    !sfp->parentdp->device->host->unchecked_isa_dma &&
-	    blk_rq_aligned(q, hp->dxferp, dxfer_len))
+	    blk_rq_aligned(q, (unsigned long)hp->dxferp, dxfer_len))
 		md = NULL;
 	else
 		md = &map_data;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index ba9c3e0..d7b383c 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -44,7 +44,6 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 
@@ -76,6 +75,7 @@
 	 CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \
 	 CDC_MRW|CDC_MRW_W|CDC_RAM)
 
+static DEFINE_MUTEX(sr_mutex);
 static int sr_probe(struct device *);
 static int sr_remove(struct device *);
 static int sr_done(struct scsi_cmnd *);
@@ -470,24 +470,24 @@
 	struct scsi_cd *cd;
 	int ret = -ENXIO;
 
-	lock_kernel();
+	mutex_lock(&sr_mutex);
 	cd = scsi_cd_get(bdev->bd_disk);
 	if (cd) {
 		ret = cdrom_open(&cd->cdi, bdev, mode);
 		if (ret)
 			scsi_cd_put(cd);
 	}
-	unlock_kernel();
+	mutex_unlock(&sr_mutex);
 	return ret;
 }
 
 static int sr_block_release(struct gendisk *disk, fmode_t mode)
 {
 	struct scsi_cd *cd = scsi_cd(disk);
-	lock_kernel();
+	mutex_lock(&sr_mutex);
 	cdrom_release(&cd->cdi, mode);
 	scsi_cd_put(cd);
-	unlock_kernel();
+	mutex_unlock(&sr_mutex);
 	return 0;
 }
 
@@ -499,7 +499,7 @@
 	void __user *argp = (void __user *)arg;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&sr_mutex);
 
 	/*
 	 * Send SCSI addressing ioctls directly to mid level, send other
@@ -529,7 +529,7 @@
 	ret = scsi_ioctl(sdev, cmd, argp);
 
 out:
-	unlock_kernel();
+	mutex_unlock(&sr_mutex);
 	return ret;
 }
 
@@ -862,10 +862,16 @@
 static int sr_packet(struct cdrom_device_info *cdi,
 		struct packet_command *cgc)
 {
+	struct scsi_cd *cd = cdi->handle;
+	struct scsi_device *sdev = cd->device;
+
+	if (cgc->cmd[0] == GPCMD_READ_DISC_INFO && sdev->no_read_disc_info)
+		return -EDRIVE_CANT_DO_THIS;
+
 	if (cgc->timeout <= 0)
 		cgc->timeout = IOCTL_TIMEOUT;
 
-	sr_do_ioctl(cdi->handle, cgc);
+	sr_do_ioctl(cd, cgc);
 
 	return cgc->stat;
 }
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 24211d0..5b7388f 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -9,7 +9,7 @@
    Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
    Michael Schaefer, J"org Weule, and Eric Youngdale.
 
-   Copyright 1992 - 2008 Kai Makisara
+   Copyright 1992 - 2010 Kai Makisara
    email Kai.Makisara@kolumbus.fi
 
    Some small formal changes - aeb, 950809
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static const char *verstr = "20081215";
+static const char *verstr = "20100829";
 
 #include <linux/module.h>
 
@@ -39,7 +39,6 @@
 #include <linux/cdev.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/dma.h>
@@ -76,6 +75,7 @@
 #include "st_options.h"
 #include "st.h"
 
+static DEFINE_MUTEX(st_mutex);
 static int buffer_kbs;
 static int max_sg_segs;
 static int try_direct_io = TRY_DIRECT_IO;
@@ -1180,7 +1180,7 @@
 	int dev = TAPE_NR(inode);
 	char *name;
 
-	lock_kernel();
+	mutex_lock(&st_mutex);
 	/*
 	 * We really want to do nonseekable_open(inode, filp); here, but some
 	 * versions of tar incorrectly call lseek on tapes and bail out if that
@@ -1189,7 +1189,7 @@
 	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
 
 	if (!(STp = scsi_tape_get(dev))) {
-		unlock_kernel();
+		mutex_unlock(&st_mutex);
 		return -ENXIO;
 	}
 
@@ -1200,7 +1200,7 @@
 	if (STp->in_use) {
 		write_unlock(&st_dev_arr_lock);
 		scsi_tape_put(STp);
-		unlock_kernel();
+		mutex_unlock(&st_mutex);
 		DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
 		return (-EBUSY);
 	}
@@ -1249,14 +1249,14 @@
 			retval = (-EIO);
 		goto err_out;
 	}
-	unlock_kernel();
+	mutex_unlock(&st_mutex);
 	return 0;
 
  err_out:
 	normalize_buffer(STp->buffer);
 	STp->in_use = 0;
 	scsi_tape_put(STp);
-	unlock_kernel();
+	mutex_unlock(&st_mutex);
 	return retval;
 
 }
@@ -2696,18 +2696,21 @@
 		}
 		break;
 	case MTWEOF:
+	case MTWEOFI:
 	case MTWSM:
 		if (STp->write_prot)
 			return (-EACCES);
 		cmd[0] = WRITE_FILEMARKS;
 		if (cmd_in == MTWSM)
 			cmd[1] = 2;
+		if (cmd_in == MTWEOFI)
+			cmd[1] |= 1;
 		cmd[2] = (arg >> 16);
 		cmd[3] = (arg >> 8);
 		cmd[4] = arg;
 		timeout = STp->device->request_queue->rq_timeout;
                 DEBC(
-                     if (cmd_in == MTWEOF)
+		     if (cmd_in != MTWSM)
                                printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name,
 				 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
                      else
@@ -2883,8 +2886,8 @@
 		else if (chg_eof)
 			STps->eof = ST_NOEOF;
 
-		if (cmd_in == MTWEOF)
-			STps->rw = ST_IDLE;
+		if (cmd_in == MTWEOF || cmd_in == MTWEOFI)
+			STps->rw = ST_IDLE;  /* prevent automatic WEOF at close */
 	} else { /* SCSI command was not completely successful. Don't return
                     from this block without releasing the SCSI command block! */
 		struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
@@ -2901,7 +2904,7 @@
 		else
 			undone = 0;
 
-		if (cmd_in == MTWEOF &&
+		if ((cmd_in == MTWEOF || cmd_in == MTWEOFI) &&
 		    cmdstatp->have_sense &&
 		    (cmdstatp->flags & SENSE_EOM)) {
 			if (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 0dff3bb..88b1335 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -1381,6 +1381,30 @@
 }
 
 
+/*
+ * 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.
+ */
+static int rs_360_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	ser_info_t *info = (ser_info_t *)tty->driver_data;
+	struct async_icount cnow;
+
+	local_irq_disable();
+	cnow = info->state->icount;
+	local_irq_enable();
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+
+	return 0;
+}
+
 static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -1394,7 +1418,7 @@
 	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
 		return -ENODEV;
 
-	if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+	if (cmd != TIOCMIWAIT) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
@@ -1477,31 +1501,6 @@
 			return 0;
 #endif
 
-		/* 
-		 * 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:
-			local_irq_disable();
-			cnow = info->state->icount;
-			local_irq_enable();
-			p_cuser = (struct serial_icounter_struct *) arg;
-/* 			error = put_user(cnow.cts, &p_cuser->cts); */
-/* 			if (error) return error; */
-/* 			error = put_user(cnow.dsr, &p_cuser->dsr); */
-/* 			if (error) return error; */
-/* 			error = put_user(cnow.rng, &p_cuser->rng); */
-/* 			if (error) return error; */
-/* 			error = put_user(cnow.dcd, &p_cuser->dcd); */
-/* 			if (error) return error; */
-
-			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 0;
 
 		default:
 			return -ENOIOCTLCMD;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 24110f6..167c4a6 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/tty.h>
+#include <linux/ratelimit.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_reg.h>
 #include <linux/serial_core.h>
@@ -154,12 +155,6 @@
 	unsigned char		lsr_saved_flags;
 #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
 	unsigned char		msr_saved_flags;
-
-	/*
-	 * We provide a per-port pm hook.
-	 */
-	void			(*pm)(struct uart_port *port,
-				      unsigned int state, unsigned int old);
 };
 
 struct irq_info {
@@ -1606,8 +1601,8 @@
 
 		if (l == i->head && pass_counter++ > PASS_LIMIT) {
 			/* If we hit this, we're dead. */
-			printk(KERN_ERR "serial8250: too much work for "
-				"irq%d\n", irq);
+			printk_ratelimited(KERN_ERR
+				"serial8250: too much work for irq%d\n", irq);
 			break;
 		}
 	} while (l != end);
@@ -1722,12 +1717,6 @@
 	mutex_unlock(&hash_mutex);
 }
 
-/* Base timer interval for polling */
-static inline int poll_timeout(int timeout)
-{
-	return timeout > 6 ? (timeout / 2 - 2) : 1;
-}
-
 /*
  * This function is used to handle ports that do not have an
  * interrupt.  This doesn't work very well for 16450's, but gives
@@ -1742,7 +1731,7 @@
 	iir = serial_in(up, UART_IIR);
 	if (!(iir & UART_IIR_NO_INT))
 		serial8250_handle_port(up);
-	mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+	mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
 }
 
 static void serial8250_backup_timeout(unsigned long data)
@@ -1787,7 +1776,7 @@
 
 	/* Standard timer interval plus 0.2s to keep the port running */
 	mod_timer(&up->timer,
-		jiffies + poll_timeout(up->port.timeout) + HZ / 5);
+		jiffies + uart_poll_timeout(&up->port) + HZ / 5);
 }
 
 static unsigned int serial8250_tx_empty(struct uart_port *port)
@@ -1867,15 +1856,17 @@
 	unsigned int status, tmout = 10000;
 
 	/* Wait up to 10ms for the character(s) to be sent. */
-	do {
+	for (;;) {
 		status = serial_in(up, UART_LSR);
 
 		up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
 
+		if ((status & bits) == bits)
+			break;
 		if (--tmout == 0)
 			break;
 		udelay(1);
-	} while ((status & bits) != bits);
+	}
 
 	/* Wait up to 1s for flow control if necessary */
 	if (up->port.flags & UPF_CONS_FLOW) {
@@ -2069,7 +2060,7 @@
 		up->timer.function = serial8250_backup_timeout;
 		up->timer.data = (unsigned long)up;
 		mod_timer(&up->timer, jiffies +
-			  poll_timeout(up->port.timeout) + HZ / 5);
+			uart_poll_timeout(port) + HZ / 5);
 	}
 
 	/*
@@ -2079,7 +2070,7 @@
 	 */
 	if (!is_real_interrupt(up->port.irq)) {
 		up->timer.data = (unsigned long)up;
-		mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+		mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
 	} else {
 		retval = serial_link_irq_chain(up);
 		if (retval)
@@ -2440,16 +2431,24 @@
 		port->flags &= ~UPF_HARDPPS_CD;
 }
 
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
-	      unsigned int oldstate)
+
+void serial8250_do_pm(struct uart_port *port, unsigned int state,
+		      unsigned int oldstate)
 {
 	struct uart_8250_port *p = (struct uart_8250_port *)port;
 
 	serial8250_set_sleep(p, state != 0);
+}
+EXPORT_SYMBOL(serial8250_do_pm);
 
-	if (p->pm)
-		p->pm(port, state, oldstate);
+static void
+serial8250_pm(struct uart_port *port, unsigned int state,
+	      unsigned int oldstate)
+{
+	if (port->pm)
+		port->pm(port, state, oldstate);
+	else
+		serial8250_do_pm(port, state, oldstate);
 }
 
 static unsigned int serial8250_port_size(struct uart_8250_port *pt)
@@ -2674,6 +2673,16 @@
 
 static struct uart_8250_port serial8250_ports[UART_NR];
 
+static void (*serial8250_isa_config)(int port, struct uart_port *up,
+	unsigned short *capabilities);
+
+void serial8250_set_isa_configurator(
+	void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
+{
+	serial8250_isa_config = v;
+}
+EXPORT_SYMBOL(serial8250_set_isa_configurator);
+
 static void __init serial8250_isa_init_ports(void)
 {
 	struct uart_8250_port *up;
@@ -2719,6 +2728,9 @@
 		up->port.regshift = old_serial_port[i].iomem_reg_shift;
 		set_io_from_upio(&up->port);
 		up->port.irqflags |= irqflag;
+		if (serial8250_isa_config != NULL)
+			serial8250_isa_config(i, &up->port, &up->capabilities);
+
 	}
 }
 
@@ -3010,6 +3022,7 @@
 		port.serial_in		= p->serial_in;
 		port.serial_out		= p->serial_out;
 		port.set_termios	= p->set_termios;
+		port.pm			= p->pm;
 		port.dev		= &dev->dev;
 		port.irqflags		|= irqflag;
 		ret = serial8250_register_port(&port);
@@ -3176,6 +3189,12 @@
 		/*  Possibly override set_termios call */
 		if (port->set_termios)
 			uart->port.set_termios = port->set_termios;
+		if (port->pm)
+			uart->port.pm = port->pm;
+
+		if (serial8250_isa_config != NULL)
+			serial8250_isa_config(0, &uart->port,
+					&uart->capabilities);
 
 		ret = uart_add_one_port(&serial8250_reg, &uart->port);
 		if (ret == 0)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 3198c53..9278164 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -718,13 +718,6 @@
 	  the Intel Moorestown platform. On other systems use the max3100
 	  driver.
 
-config MRST_MAX3110_IRQ
-	boolean "Enable GPIO IRQ for Max3110 over Moorestown"
-	default n
-	depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL
-	help
-	  This has to be enabled after Moorestown GPIO driver is loaded
-
 config SERIAL_MFD_HSU
 	tristate "Medfield High Speed UART support"
 	depends on PCI
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
index f8d8a00..7212162 100644
--- a/drivers/serial/altera_uart.c
+++ b/drivers/serial/altera_uart.c
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/console.h>
@@ -27,6 +28,8 @@
 #include <linux/altera_uart.h>
 
 #define DRV_NAME "altera_uart"
+#define SERIAL_ALTERA_MAJOR 204
+#define SERIAL_ALTERA_MINOR 213
 
 /*
  * Altera UART register definitions according to the Nios UART datasheet:
@@ -76,13 +79,28 @@
  */
 struct altera_uart {
 	struct uart_port port;
+	struct timer_list tmr;
 	unsigned int sigs;	/* Local copy of line sigs */
 	unsigned short imr;	/* Local IMR mirror */
 };
 
+static u32 altera_uart_readl(struct uart_port *port, int reg)
+{
+	struct altera_uart_platform_uart *platp = port->private_data;
+
+	return readl(port->membase + (reg << platp->bus_shift));
+}
+
+static void altera_uart_writel(struct uart_port *port, u32 dat, int reg)
+{
+	struct altera_uart_platform_uart *platp = port->private_data;
+
+	writel(dat, port->membase + (reg << platp->bus_shift));
+}
+
 static unsigned int altera_uart_tx_empty(struct uart_port *port)
 {
-	return (readl(port->membase + ALTERA_UART_STATUS_REG) &
+	return (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 		ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0;
 }
 
@@ -91,8 +109,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 	unsigned int sigs;
 
-	sigs =
-	    (readl(port->membase + ALTERA_UART_STATUS_REG) &
+	sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 	     ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
 	sigs |= (pp->sigs & TIOCM_RTS);
 
@@ -108,7 +125,7 @@
 		pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
 	else
 		pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_start_tx(struct uart_port *port)
@@ -116,7 +133,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 
 	pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_stop_tx(struct uart_port *port)
@@ -124,7 +141,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 
 	pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_stop_rx(struct uart_port *port)
@@ -132,7 +149,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 
 	pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 }
 
 static void altera_uart_break_ctl(struct uart_port *port, int break_state)
@@ -145,7 +162,7 @@
 		pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
 	else
 		pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
-	writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -168,7 +185,8 @@
 	tty_termios_encode_baud_rate(termios, baud, baud);
 
 	spin_lock_irqsave(&port->lock, flags);
-	writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG);
+	uart_update_timeout(port, termios->c_cflag, baud);
+	altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG);
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
@@ -178,14 +196,15 @@
 	unsigned char ch, flag;
 	unsigned short status;
 
-	while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) &
+	while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) &
 	       ALTERA_UART_STATUS_RRDY_MSK) {
-		ch = readl(port->membase + ALTERA_UART_RXDATA_REG);
+		ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG);
 		flag = TTY_NORMAL;
 		port->icount.rx++;
 
 		if (status & ALTERA_UART_STATUS_E_MSK) {
-			writel(status, port->membase + ALTERA_UART_STATUS_REG);
+			altera_uart_writel(port, status,
+					   ALTERA_UART_STATUS_REG);
 
 			if (status & ALTERA_UART_STATUS_BRK_MSK) {
 				port->icount.brk++;
@@ -225,18 +244,18 @@
 
 	if (port->x_char) {
 		/* Send special char - probably flow control */
-		writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG);
+		altera_uart_writel(port, port->x_char, ALTERA_UART_TXDATA_REG);
 		port->x_char = 0;
 		port->icount.tx++;
 		return;
 	}
 
-	while (readl(port->membase + ALTERA_UART_STATUS_REG) &
+	while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 	       ALTERA_UART_STATUS_TRDY_MSK) {
 		if (xmit->head == xmit->tail)
 			break;
-		writel(xmit->buf[xmit->tail],
-		       port->membase + ALTERA_UART_TXDATA_REG);
+		altera_uart_writel(port, xmit->buf[xmit->tail],
+		       ALTERA_UART_TXDATA_REG);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
 	}
@@ -246,7 +265,7 @@
 
 	if (xmit->head == xmit->tail) {
 		pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
-		writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
+		altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
 	}
 }
 
@@ -256,7 +275,7 @@
 	struct altera_uart *pp = container_of(port, struct altera_uart, port);
 	unsigned int isr;
 
-	isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr;
+	isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr;
 
 	spin_lock(&port->lock);
 	if (isr & ALTERA_UART_STATUS_RRDY_MSK)
@@ -268,14 +287,23 @@
 	return IRQ_RETVAL(isr);
 }
 
+static void altera_uart_timer(unsigned long data)
+{
+	struct uart_port *port = (void *)data;
+	struct altera_uart *pp = container_of(port, struct altera_uart, port);
+
+	altera_uart_interrupt(0, port);
+	mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
+}
+
 static void altera_uart_config_port(struct uart_port *port, int flags)
 {
 	port->type = PORT_ALTERA_UART;
 
 	/* Clear mask, so no surprise interrupts. */
-	writel(0, port->membase + ALTERA_UART_CONTROL_REG);
+	altera_uart_writel(port, 0, ALTERA_UART_CONTROL_REG);
 	/* Clear status register */
-	writel(0, port->membase + ALTERA_UART_STATUS_REG);
+	altera_uart_writel(port, 0, ALTERA_UART_STATUS_REG);
 }
 
 static int altera_uart_startup(struct uart_port *port)
@@ -284,6 +312,12 @@
 	unsigned long flags;
 	int ret;
 
+	if (!port->irq) {
+		setup_timer(&pp->tmr, altera_uart_timer, (unsigned long)port);
+		mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
+		return 0;
+	}
+
 	ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED,
 			DRV_NAME, port);
 	if (ret) {
@@ -316,7 +350,10 @@
 
 	spin_unlock_irqrestore(&port->lock, flags);
 
-	free_irq(port->irq, port);
+	if (port->irq)
+		free_irq(port->irq, port);
+	else
+		del_timer_sync(&pp->tmr);
 }
 
 static const char *altera_uart_type(struct uart_port *port)
@@ -384,8 +421,9 @@
 		port->iotype = SERIAL_IO_MEM;
 		port->irq = platp[i].irq;
 		port->uartclk = platp[i].uartclk;
-		port->flags = ASYNC_BOOT_AUTOCONF;
+		port->flags = UPF_BOOT_AUTOCONF;
 		port->ops = &altera_uart_ops;
+		port->private_data = platp;
 	}
 
 	return 0;
@@ -393,7 +431,7 @@
 
 static void altera_uart_console_putc(struct uart_port *port, const char c)
 {
-	while (!(readl(port->membase + ALTERA_UART_STATUS_REG) &
+	while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
 		 ALTERA_UART_STATUS_TRDY_MSK))
 		cpu_relax();
 
@@ -423,7 +461,7 @@
 	if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
 		return -EINVAL;
 	port = &altera_uart_ports[co->index].port;
-	if (port->membase == 0)
+	if (!port->membase)
 		return -ENODEV;
 
 	if (options)
@@ -435,7 +473,7 @@
 static struct uart_driver altera_uart_driver;
 
 static struct console altera_uart_console = {
-	.name	= "ttyS",
+	.name	= "ttyAL",
 	.write	= altera_uart_console_write,
 	.device	= uart_console_device,
 	.setup	= altera_uart_console_setup,
@@ -466,9 +504,9 @@
 static struct uart_driver altera_uart_driver = {
 	.owner		= THIS_MODULE,
 	.driver_name	= DRV_NAME,
-	.dev_name	= "ttyS",
-	.major		= TTY_MAJOR,
-	.minor		= 64,
+	.dev_name	= "ttyAL",
+	.major		= SERIAL_ALTERA_MAJOR,
+	.minor		= SERIAL_ALTERA_MINOR,
 	.nr		= CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
 	.cons		= ALTERA_UART_CONSOLE,
 };
@@ -477,38 +515,55 @@
 {
 	struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
 	struct uart_port *port;
-	int i;
+	struct resource *res_mem;
+	struct resource *res_irq;
+	int i = pdev->id;
 
-	for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
-		port = &altera_uart_ports[i].port;
+	/* -1 emphasizes that the platform must have one port, no .N suffix */
+	if (i == -1)
+		i = 0;
 
-		port->line = i;
-		port->type = PORT_ALTERA_UART;
-		port->mapbase = platp[i].mapbase;
-		port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
-		port->iotype = SERIAL_IO_MEM;
-		port->irq = platp[i].irq;
-		port->uartclk = platp[i].uartclk;
-		port->ops = &altera_uart_ops;
-		port->flags = ASYNC_BOOT_AUTOCONF;
+	if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
+		return -EINVAL;
 
-		uart_add_one_port(&altera_uart_driver, port);
-	}
+	port = &altera_uart_ports[i].port;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res_mem)
+		port->mapbase = res_mem->start;
+	else if (platp->mapbase)
+		port->mapbase = platp->mapbase;
+	else
+		return -EINVAL;
+
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res_irq)
+		port->irq = res_irq->start;
+	else if (platp->irq)
+		port->irq = platp->irq;
+
+	port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
+	if (!port->membase)
+		return -ENOMEM;
+
+	port->line = i;
+	port->type = PORT_ALTERA_UART;
+	port->iotype = SERIAL_IO_MEM;
+	port->uartclk = platp->uartclk;
+	port->ops = &altera_uart_ops;
+	port->flags = UPF_BOOT_AUTOCONF;
+	port->private_data = platp;
+
+	uart_add_one_port(&altera_uart_driver, port);
 
 	return 0;
 }
 
 static int __devexit altera_uart_remove(struct platform_device *pdev)
 {
-	struct uart_port *port;
-	int i;
+	struct uart_port *port = &altera_uart_ports[pdev->id].port;
 
-	for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) {
-		port = &altera_uart_ports[i].port;
-		if (port)
-			uart_remove_one_port(&altera_uart_driver, port);
-	}
-
+	uart_remove_one_port(&altera_uart_driver, port);
 	return 0;
 }
 
@@ -550,3 +605,4 @@
 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_ALTERA_MAJOR);
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
index 5318dd3..6f1b51e2 100644
--- a/drivers/serial/bfin_sport_uart.c
+++ b/drivers/serial/bfin_sport_uart.c
@@ -131,7 +131,12 @@
 	pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
 
 	tclkdiv = sclk / (2 * baud_rate) - 1;
-	rclkdiv = sclk / (2 * baud_rate * 2) - 1;
+	/* The actual uart baud rate of devices vary between +/-2%. The sport
+	 * RX sample rate should be faster than the double of the worst case,
+	 * otherwise, wrong data are received. So, set sport RX clock to be
+	 * 3% faster.
+	 */
+	rclkdiv = sclk / (2 * baud_rate * 2 * 97 / 100) - 1;
 	SPORT_PUT_TCLKDIV(up, tclkdiv);
 	SPORT_PUT_RCLKDIV(up, rclkdiv);
 	SSYNC();
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 66ecc7a..dfcf4b1 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -327,14 +327,13 @@
 {
 	struct circ_buf *xmit = &sport->port.state->xmit;
 
-	while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
+	while (!uart_circ_empty(xmit) &&
+			!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
 		/* send xmit->buf[xmit->tail]
 		 * out the port here */
 		writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		sport->port.icount.tx++;
-		if (uart_circ_empty(xmit))
-			break;
 	}
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index eaf5450..18f5484 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -172,13 +172,15 @@
 		 	jsm_uart_port_init here! */
 		dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
 		rc = -ENOMEM;
-		goto out_free_irq;
+		goto out_free_uart;
 	}
 
 	pci_set_drvdata(pdev, brd);
 	pci_save_state(pdev);
 
 	return 0;
+ out_free_uart:
+	jsm_remove_uart_port(brd);
  out_free_irq:
 	jsm_remove_uart_port(brd);
 	free_irq(brd->irq, brd);
diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
index 39f9a1a..d4b711c 100644
--- a/drivers/serial/kgdboc.c
+++ b/drivers/serial/kgdboc.c
@@ -243,7 +243,7 @@
 
 #ifdef CONFIG_KGDB_SERIAL_CONSOLE
 /* This is only available if kgdboc is a built in for early debugging */
-int __init kgdboc_early_init(char *opt)
+static int __init kgdboc_early_init(char *opt)
 {
 	/* save the first character of the config string because the
 	 * init routine can destroy it.
diff --git a/drivers/serial/max3107.c b/drivers/serial/max3107.c
index 67283c1..910870e 100644
--- a/drivers/serial/max3107.c
+++ b/drivers/serial/max3107.c
@@ -986,12 +986,14 @@
 	s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL);
 	if (!s->rxbuf) {
 		pr_err("Allocating RX buffer failed\n");
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err_free4;
 	}
 	s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL);
 	if (!s->rxstr) {
 		pr_err("Allocating RX buffer failed\n");
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err_free3;
 	}
 	/* SPI Tx buffer
 	 * SPI transfer buffer
@@ -1002,7 +1004,8 @@
 	s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL);
 	if (!s->txbuf) {
 		pr_err("Allocating TX buffer failed\n");
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err_free2;
 	}
 	/* Initialize shared data lock */
 	spin_lock_init(&s->data_lock);
@@ -1021,13 +1024,15 @@
 	buf[0] = MAX3107_REVID_REG;
 	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
 		dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
-		return -EIO;
+		retval = -EIO;
+		goto err_free1;
 	}
 	if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
 		(buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
 		dev_err(&s->spi->dev, "REVID %x does not match\n",
 				(buf[0] & MAX3107_SPI_RX_DATA_MASK));
-		return -ENODEV;
+		retval = -ENODEV;
+		goto err_free1;
 	}
 
 	/* Disable all interrupts */
@@ -1047,7 +1052,8 @@
 	/* Perform SPI transfer */
 	if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
 		dev_err(&s->spi->dev, "SPI transfer for init failed\n");
-		return -EIO;
+		retval = -EIO;
+		goto err_free1;
 	}
 
 	/* Register UART driver */
@@ -1055,7 +1061,7 @@
 		retval = uart_register_driver(&max3107_uart_driver);
 		if (retval) {
 			dev_err(&s->spi->dev, "Registering UART driver failed\n");
-			return retval;
+			goto err_free1;
 		}
 		driver_registered = 1;
 	}
@@ -1074,13 +1080,13 @@
 	retval = uart_add_one_port(&max3107_uart_driver, &s->port);
 	if (retval < 0) {
 		dev_err(&s->spi->dev, "Adding UART port failed\n");
-		return retval;
+		goto err_free1;
 	}
 
 	if (pdata->configure) {
 		retval = pdata->configure(s);
 		if (retval < 0)
-			return retval;
+			goto err_free1;
 	}
 
 	/* Go to suspend mode */
@@ -1088,6 +1094,16 @@
 		pdata->hw_suspend(s, 1);
 
 	return 0;
+
+err_free1:
+	kfree(s->txbuf);
+err_free2:
+	kfree(s->rxstr);
+err_free3:
+	kfree(s->rxbuf);
+err_free4:
+	kfree(s);
+	return retval;
 }
 EXPORT_SYMBOL_GPL(max3107_probe);
 
diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c
index 5dff45c..5fc699e 100644
--- a/drivers/serial/mfd.c
+++ b/drivers/serial/mfd.c
@@ -172,6 +172,9 @@
 	len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
 			"DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
 
+	if (len > HSU_REGS_BUFSIZE)
+		len = HSU_REGS_BUFSIZE;
+
 	ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
 	kfree(buf);
 	return ret;
@@ -219,6 +222,9 @@
 	len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
 			"D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
 
+	if (len > HSU_REGS_BUFSIZE)
+		len = HSU_REGS_BUFSIZE;
+
 	ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
 	kfree(buf);
 	return ret;
@@ -228,12 +234,14 @@
 	.owner		= THIS_MODULE,
 	.open		= hsu_show_regs_open,
 	.read		= port_show_regs,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations dma_regs_ops = {
 	.owner		= THIS_MODULE,
 	.open		= hsu_show_regs_open,
 	.read		= dma_show_regs,
+	.llseek		= default_llseek,
 };
 
 static int hsu_debugfs_init(struct hsu_port *hsu)
@@ -923,39 +931,52 @@
 		cval |= UART_LCR_EPAR;
 
 	/*
+	 * The base clk is 50Mhz, and the baud rate come from:
+	 *	baud = 50M * MUL / (DIV * PS * DLAB)
+	 *
 	 * For those basic low baud rate we can get the direct
-	 * scalar from 2746800, like 115200 = 2746800/24, for those
-	 * higher baud rate, we have to handle them case by case,
-	 * but DIV reg is never touched as its default value 0x3d09
+	 * scalar from 2746800, like 115200 = 2746800/24. For those
+	 * higher baud rate, we handle them case by case, mainly by
+	 * adjusting the MUL/PS registers, and DIV register is kept
+	 * as default value 0x3d09 to make things simple
 	 */
 	baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
-	quot = uart_get_divisor(port, baud);
 
+	quot = 1;
 	switch (baud) {
 	case 3500000:
 		mul = 0x3345;
 		ps = 0xC;
-		quot = 1;
+		break;
+	case 3000000:
+		mul = 0x2EE0;
 		break;
 	case 2500000:
 		mul = 0x2710;
-		ps = 0x10;
-		quot = 1;
 		break;
-	case 18432000:
+	case 2000000:
+		mul = 0x1F40;
+		break;
+	case 1843200:
 		mul = 0x2400;
-		ps = 0x10;
-		quot = 1;
 		break;
 	case 1500000:
-		mul = 0x1D4C;
-		ps = 0xc;
-		quot = 1;
+		mul = 0x1770;
+		break;
+	case 1000000:
+		mul = 0xFA0;
+		break;
+	case 500000:
+		mul = 0x7D0;
 		break;
 	default:
-		;
+		/* Use uart_get_divisor to get quot for other baud rates */
+		quot = 0;
 	}
 
+	if (!quot)
+		quot = uart_get_divisor(port, baud);
+
 	if ((up->port.uartclk / quot) < (2400 * 16))
 		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
 	else if ((up->port.uartclk / quot) < (230400 * 16))
diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c
index 51c15f5..b62857b 100644
--- a/drivers/serial/mrst_max3110.c
+++ b/drivers/serial/mrst_max3110.c
@@ -1,7 +1,7 @@
 /*
- *  max3110.c - spi uart protocol driver for Maxim 3110 on Moorestown
+ *  mrst_max3110.c - spi uart protocol driver for Maxim 3110
  *
- *  Copyright (C) Intel 2008 Feng Tang <feng.tang@intel.com>
+ * Copyright (c) 2008-2010, 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,
@@ -32,18 +32,13 @@
 #include <linux/irq.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 <linux/serial_reg.h>
 
 #include <linux/kthread.h>
-#include <linux/delay.h>
-#include <asm/atomic.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/dw_spi.h>
 
 #include "mrst_max3110.h"
 
@@ -56,7 +51,7 @@
 struct uart_max3110 {
 	struct uart_port port;
 	struct spi_device *spi;
-	char *name;
+	char name[24];
 
 	wait_queue_head_t wq;
 	struct task_struct *main_thread;
@@ -67,35 +62,30 @@
 	u16 cur_conf;
 	u8 clock;
 	u8 parity, word_7bits;
+	u16 irq;
 
 	unsigned long uart_flags;
 
 	/* console related */
 	struct circ_buf con_xmit;
-
-	/* irq related */
-	u16 irq;
 };
 
 /* global data structure, may need be removed */
-struct uart_max3110 *pmax;
-static inline void receive_char(struct uart_max3110 *max, u8 ch);
+static struct uart_max3110 *pmax;
+
 static void receive_chars(struct uart_max3110 *max,
 				unsigned char *str, int len);
-static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf);
-static void max3110_console_receive(struct uart_max3110 *max);
+static int max3110_read_multi(struct uart_max3110 *max, u8 *buf);
+static void max3110_con_receive(struct uart_max3110 *max);
 
-int max3110_write_then_read(struct uart_max3110 *max,
-		const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast)
+static int max3110_write_then_read(struct uart_max3110 *max,
+		const void *txbuf, void *rxbuf, unsigned len, int always_fast)
 {
 	struct spi_device *spi = max->spi;
 	struct spi_message	message;
 	struct spi_transfer	x;
 	int ret;
 
-	if (!txbuf || !rxbuf)
-		return -EINVAL;
-
 	spi_message_init(&message);
 	memset(&x, 0, sizeof x);
 	x.len = len;
@@ -104,7 +94,7 @@
 	spi_message_add_tail(&x, &message);
 
 	if (always_fast)
-		x.speed_hz = 3125000;
+		x.speed_hz = spi->max_speed_hz;
 	else if (max->baud)
 		x.speed_hz = max->baud;
 
@@ -113,58 +103,80 @@
 	return ret;
 }
 
-/* Write a u16 to the device, and return one u16 read back */
-int max3110_out(struct uart_max3110 *max, const u16 out)
+/* Write a 16b word to the device */
+static int max3110_out(struct uart_max3110 *max, const u16 out)
 {
-	u16 tmp;
+	void *buf;
+	u16 *obuf, *ibuf;
+	u8  ch;
 	int ret;
 
-	ret = max3110_write_then_read(max, (u8 *)&out, (u8 *)&tmp, 2, 1);
-	if (ret)
-		return ret;
+	buf = kzalloc(8, GFP_KERNEL | GFP_DMA);
+	if (!buf)
+		return -ENOMEM;
+
+	obuf = buf;
+	ibuf = buf + 4;
+	*obuf = out;
+	ret = max3110_write_then_read(max, obuf, ibuf, 2, 1);
+	if (ret) {
+		pr_warning(PR_FMT "%s(): get err msg %d when sending 0x%x\n",
+				__func__, ret, out);
+		goto exit;
+	}
 
 	/* If some valid data is read back */
-	if (tmp & MAX3110_READ_DATA_AVAILABLE)
-		receive_char(max, (tmp & 0xff));
+	if (*ibuf & MAX3110_READ_DATA_AVAILABLE) {
+		ch = *ibuf & 0xff;
+		receive_chars(max, &ch, 1);
+	}
 
+exit:
+	kfree(buf);
 	return ret;
 }
 
-#define MAX_READ_LEN	20
 /*
  * This is usually used to read data from SPIC RX FIFO, which doesn't
- * need any delay like flushing character out. It returns how many
- * valide bytes are read back
+ * need any delay like flushing character out.
+ *
+ * Return how many valide bytes are read back
  */
-static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf)
+static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf)
 {
-	u16 out[MAX_READ_LEN], in[MAX_READ_LEN];
-	u8 *pbuf, valid_str[MAX_READ_LEN];
-	int i, j, bytelen;
+	void *buf;
+	u16 *obuf, *ibuf;
+	u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH];
+	int i, j, blen;
 
-	if (len > MAX_READ_LEN) {
-		pr_err(PR_FMT "read len %d is too large\n", len);
+	blen = M3110_RX_FIFO_DEPTH * sizeof(u16);
+	buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA);
+	if (!buf) {
+		pr_warning(PR_FMT "%s(): fail to alloc dma buffer\n", __func__);
 		return 0;
 	}
 
-	bytelen = len * 2;
-	memset(out, 0, bytelen);
-	memset(in, 0, bytelen);
+	/* tx/rx always have the same length */
+	obuf = buf;
+	ibuf = buf + blen;
 
-	if (max3110_write_then_read(max, (u8 *)out, (u8 *)in, bytelen, 1))
+	if (max3110_write_then_read(max, obuf, ibuf, blen, 1)) {
+		kfree(buf);
 		return 0;
+	}
 
-	/* If caller don't provide a buffer, then handle received char */
-	pbuf = buf ? buf : valid_str;
+	/* If caller doesn't provide a buffer, then handle received char */
+	pbuf = rxbuf ? rxbuf : valid_str;
 
-	for (i = 0, j = 0; i < len; i++) {
-		if (in[i] & MAX3110_READ_DATA_AVAILABLE)
-			pbuf[j++] = (u8)(in[i] & 0xff);
+	for (i = 0, j = 0; i < M3110_RX_FIFO_DEPTH; i++) {
+		if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
+			pbuf[j++] = ibuf[i] & 0xff;
 	}
 
 	if (j && (pbuf == valid_str))
 		receive_chars(max, valid_str, j);
 
+	kfree(buf);
 	return j;
 }
 
@@ -178,10 +190,6 @@
 		xmit->buf[xmit->head] = (char)ch;
 		xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1);
 	}
-
-
-	if (!test_and_set_bit(CON_TX_NEEDED, &max->uart_flags))
-		wake_up_process(max->main_thread);
 }
 
 /*
@@ -197,6 +205,9 @@
 		return;
 
 	uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar);
+
+	if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags))
+		wake_up_process(pmax->main_thread);
 }
 
 static int __init
@@ -210,6 +221,9 @@
 
 	pr_info(PR_FMT "setting up console\n");
 
+	if (co->index == -1)
+		co->index = 0;
+
 	if (!max) {
 		pr_err(PR_FMT "pmax is NULL, return");
 		return -ENODEV;
@@ -240,8 +254,6 @@
 	.data		= &serial_m3110_reg,
 };
 
-#define MRST_CONSOLE	(&serial_m3110_console)
-
 static unsigned int serial_m3110_tx_empty(struct uart_port *port)
 {
 	return 1;
@@ -259,32 +271,44 @@
 }
 
 #define WORDS_PER_XFER	128
-static inline void send_circ_buf(struct uart_max3110 *max,
+static void send_circ_buf(struct uart_max3110 *max,
 				struct circ_buf *xmit)
 {
-	int len, left = 0;
-	u16 obuf[WORDS_PER_XFER], ibuf[WORDS_PER_XFER];
+	void *buf;
+	u16 *obuf, *ibuf;
 	u8 valid_str[WORDS_PER_XFER];
-	int i, j;
+	int i, j, len, blen, dma_size, left, ret = 0;
+
+
+	dma_size = WORDS_PER_XFER * sizeof(u16) * 2;
+	buf = kzalloc(dma_size, GFP_KERNEL | GFP_DMA);
+	if (!buf)
+		return;
+	obuf = buf;
+	ibuf = buf + dma_size/2;
 
 	while (!uart_circ_empty(xmit)) {
 		left = uart_circ_chars_pending(xmit);
 		while (left) {
-			len = (left >= WORDS_PER_XFER) ? WORDS_PER_XFER : left;
+			len = min(left, WORDS_PER_XFER);
+			blen = len * sizeof(u16);
+			memset(ibuf, 0, blen);
 
-			memset(obuf, 0, len * 2);
-			memset(ibuf, 0, len * 2);
 			for (i = 0; i < len; i++) {
 				obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG;
 				xmit->tail = (xmit->tail + 1) &
 						(UART_XMIT_SIZE - 1);
 			}
-			max3110_write_then_read(max, (u8 *)obuf,
-						(u8 *)ibuf, len * 2, 0);
+
+			/* Fail to send msg to console is not very critical */
+			ret = max3110_write_then_read(max, obuf, ibuf, blen, 0);
+			if (ret)
+				pr_warning(PR_FMT "%s(): get err msg %d\n",
+						__func__, ret);
 
 			for (i = 0, j = 0; i < len; i++) {
 				if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
-					valid_str[j++] = (u8)(ibuf[i] & 0xff);
+					valid_str[j++] = ibuf[i] & 0xff;
 			}
 
 			if (j)
@@ -294,6 +318,8 @@
 			left -= len;
 		}
 	}
+
+	kfree(buf);
 }
 
 static void transmit_char(struct uart_max3110 *max)
@@ -313,8 +339,10 @@
 		serial_m3110_stop_tx(port);
 }
 
-/* This will be called by uart_write() and tty_write, can't
- * go to sleep */
+/*
+ * This will be called by uart_write() and tty_write, can't
+ * go to sleep
+ */
 static void serial_m3110_start_tx(struct uart_port *port)
 {
 	struct uart_max3110 *max =
@@ -336,7 +364,7 @@
 
 	tty = port->state->port.tty;
 	if (!tty)
-		return;	/* receive some char before the tty is opened */
+		return;
 
 	while (len) {
 		usable = tty_buffer_request_room(tty, len);
@@ -344,32 +372,37 @@
 			tty_insert_flip_string(tty, str, usable);
 			str += usable;
 			port->icount.rx += usable;
-			tty_flip_buffer_push(tty);
 		}
 		len -= usable;
 	}
+	tty_flip_buffer_push(tty);
 }
 
-static inline void receive_char(struct uart_max3110 *max, u8 ch)
-{
-	receive_chars(max, &ch, 1);
-}
-
-static void max3110_console_receive(struct uart_max3110 *max)
+/*
+ * This routine will be used in read_thread or RX IRQ handling,
+ * it will first do one round buffer read(8 words), if there is some
+ * valid RX data, will try to read 5 more rounds till all data
+ * is read out.
+ *
+ * Use stack space as data buffer to save some system load, and chose
+ * 504 Btyes as a threadhold to do a bulk push to upper tty layer when
+ * receiving bulk data, a much bigger buffer may cause stack overflow
+ */
+static void max3110_con_receive(struct uart_max3110 *max)
 {
 	int loop = 1, num, total = 0;
 	u8 recv_buf[512], *pbuf;
 
 	pbuf = recv_buf;
 	do {
-		num = max3110_read_multi(max, 8, pbuf);
+		num = max3110_read_multi(max, pbuf);
 
 		if (num) {
-			loop = 10;
+			loop = 5;
 			pbuf += num;
 			total += num;
 
-			if (total >= 500) {
+			if (total >= 504) {
 				receive_chars(max, recv_buf, total);
 				pbuf = recv_buf;
 				total = 0;
@@ -397,7 +430,7 @@
 		mutex_lock(&max->thread_mutex);
 
 		if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags))
-			max3110_console_receive(max);
+			max3110_con_receive(max);
 
 		/* first handle console output */
 		if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags))
@@ -414,7 +447,6 @@
 	return ret;
 }
 
-#ifdef CONFIG_MRST_MAX3110_IRQ
 static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
 {
 	struct uart_max3110 *max = dev_id;
@@ -426,7 +458,7 @@
 
 	return IRQ_HANDLED;
 }
-#else
+
 /* if don't use RX IRQ, then need a thread to polling read */
 static int max3110_read_thread(void *_max)
 {
@@ -434,9 +466,14 @@
 
 	pr_info(PR_FMT "start read thread\n");
 	do {
-		mutex_lock(&max->thread_mutex);
-		max3110_console_receive(max);
-		mutex_unlock(&max->thread_mutex);
+		/*
+		 * If can't acquire the mutex, it means the main thread
+		 * is running which will also perform the rx job
+		 */
+		if (mutex_trylock(&max->thread_mutex)) {
+			max3110_con_receive(max);
+			mutex_unlock(&max->thread_mutex);
+		}
 
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ / 20);
@@ -444,7 +481,6 @@
 
 	return 0;
 }
-#endif
 
 static int serial_m3110_startup(struct uart_port *port)
 {
@@ -453,33 +489,54 @@
 	u16 config = 0;
 	int ret = 0;
 
-	if (port->line != 0)
+	if (port->line != 0) {
 		pr_err(PR_FMT "uart port startup failed\n");
+		return -1;
+	}
 
-	/* firstly disable all IRQ and config it to 115200, 8n1 */
+	/* Disable all IRQ and config it to 115200, 8n1 */
 	config = WC_TAG | WC_FIFO_ENABLE
 			| WC_1_STOPBITS
 			| WC_8BIT_WORD
 			| WC_BAUD_DR2;
-	ret = max3110_out(max, config);
 
 	/* as we use thread to handle tx/rx, need set low latency */
 	port->state->port.tty->low_latency = 1;
 
-#ifdef CONFIG_MRST_MAX3110_IRQ
-	ret = request_irq(max->irq, serial_m3110_irq,
+	if (max->irq) {
+		max->read_thread = NULL;
+		ret = request_irq(max->irq, serial_m3110_irq,
 				IRQ_TYPE_EDGE_FALLING, "max3110", max);
-	if (ret)
-		return ret;
+		if (ret) {
+			max->irq = 0;
+			pr_err(PR_FMT "unable to allocate IRQ, polling\n");
+		}  else {
+			/* Enable RX IRQ only */
+			config |= WC_RXA_IRQ_ENABLE;
+		}
+	}
 
-	/* enable RX IRQ only */
-	config |= WC_RXA_IRQ_ENABLE;
-	max3110_out(max, config);
-#else
-	/* if IRQ is disabled, start a read thread for input data */
-	max->read_thread =
-		kthread_run(max3110_read_thread, max, "max3110_read");
-#endif
+	if (max->irq == 0) {
+		/* If IRQ is disabled, start a read thread for input data */
+		max->read_thread =
+			kthread_run(max3110_read_thread, max, "max3110_read");
+		if (IS_ERR(max->read_thread)) {
+			ret = PTR_ERR(max->read_thread);
+			max->read_thread = NULL;
+			pr_err(PR_FMT "Can't create read thread!\n");
+			return ret;
+		}
+	}
+
+	ret = max3110_out(max, config);
+	if (ret) {
+		if (max->irq)
+			free_irq(max->irq, max);
+		if (max->read_thread)
+			kthread_stop(max->read_thread);
+		max->read_thread = NULL;
+		return ret;
+	}
 
 	max->cur_conf = config;
 	return 0;
@@ -496,9 +553,8 @@
 		max->read_thread = NULL;
 	}
 
-#ifdef CONFIG_MRST_MAX3110_IRQ
-	free_irq(max->irq, max);
-#endif
+	if (max->irq)
+		free_irq(max->irq, max);
 
 	/* Disable interrupts from this port */
 	config = WC_TAG | WC_SW_SHDI;
@@ -516,8 +572,7 @@
 
 static void serial_m3110_config_port(struct uart_port *port, int flags)
 {
-	/* give it fake type */
-	port->type = PORT_PXA;
+	port->type = PORT_MAX3100;
 }
 
 static int
@@ -552,6 +607,9 @@
 		new_conf |= WC_7BIT_WORD;
 		break;
 	default:
+		/* We only support CS7 & CS8 */
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= CS8;
 	case CS8:
 		cval = UART_LCR_WLEN8;
 		new_conf |= WC_8BIT_WORD;
@@ -560,7 +618,7 @@
 
 	baud = uart_get_baud_rate(port, termios, old, 0, 230400);
 
-	/* first calc the div for 1.8MHZ clock case */
+	/* First calc the div for 1.8MHZ clock case */
 	switch (baud) {
 	case 300:
 		clk_div = WC_BAUD_DR384;
@@ -596,7 +654,7 @@
 		if (max->clock & MAX3110_HIGH_CLK)
 			break;
 	default:
-		/* pick the previous baud rate */
+		/* Pick the previous baud rate */
 		baud = max->baud;
 		clk_div = max->cur_conf & WC_BAUD_DIV_MASK;
 		tty_termios_encode_baud_rate(termios, baud, baud);
@@ -604,15 +662,21 @@
 
 	if (max->clock & MAX3110_HIGH_CLK) {
 		clk_div += 1;
-		/* high clk version max3110 doesn't support B300 */
-		if (baud == 300)
+		/* High clk version max3110 doesn't support B300 */
+		if (baud == 300) {
 			baud = 600;
+			clk_div = WC_BAUD_DR384;
+		}
 		if (baud == 230400)
 			clk_div = WC_BAUD_DR1;
 		tty_termios_encode_baud_rate(termios, baud, baud);
 	}
 
 	new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div;
+
+	if (unlikely(termios->c_cflag & CMSPAR))
+		termios->c_cflag &= ~CMSPAR;
+
 	if (termios->c_cflag & CSTOPB)
 		new_conf |= WC_2_STOPBITS;
 	else
@@ -632,13 +696,14 @@
 
 	new_conf |= WC_TAG;
 	if (new_conf != max->cur_conf) {
-		max3110_out(max, new_conf);
-		max->cur_conf = new_conf;
-		max->baud = baud;
+		if (!max3110_out(max, new_conf)) {
+			max->cur_conf = new_conf;
+			max->baud = baud;
+		}
 	}
 }
 
-/* don't handle hw handshaking */
+/* Don't handle hw handshaking */
 static unsigned int serial_m3110_get_mctrl(struct uart_port *port)
 {
 	return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR;
@@ -672,7 +737,7 @@
 	.break_ctl	= serial_m3110_break_ctl,
 	.startup	= serial_m3110_startup,
 	.shutdown	= serial_m3110_shutdown,
-	.set_termios	= serial_m3110_set_termios,	/* must have */
+	.set_termios	= serial_m3110_set_termios,
 	.pm		= serial_m3110_pm,
 	.type		= serial_m3110_type,
 	.release_port	= serial_m3110_release_port,
@@ -688,52 +753,60 @@
 	.major		= TTY_MAJOR,
 	.minor		= 64,
 	.nr		= 1,
-	.cons		= MRST_CONSOLE,
+	.cons		= &serial_m3110_console,
 };
 
+#ifdef CONFIG_PM
 static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
 {
+	struct uart_max3110 *max = spi_get_drvdata(spi);
+
+	disable_irq(max->irq);
+	uart_suspend_port(&serial_m3110_reg, &max->port);
+	max3110_out(max, max->cur_conf | WC_SW_SHDI);
 	return 0;
 }
 
 static int serial_m3110_resume(struct spi_device *spi)
 {
+	struct uart_max3110 *max = spi_get_drvdata(spi);
+
+	max3110_out(max, max->cur_conf);
+	uart_resume_port(&serial_m3110_reg, &max->port);
+	enable_irq(max->irq);
 	return 0;
 }
+#else
+#define serial_m3110_suspend	NULL
+#define serial_m3110_resume	NULL
+#endif
 
-static struct dw_spi_chip spi0_uart = {
-	.poll_mode = 1,
-	.enable_dma = 0,
-	.type = SPI_FRF_SPI,
-};
-
-static int serial_m3110_probe(struct spi_device *spi)
+static int __devinit serial_m3110_probe(struct spi_device *spi)
 {
 	struct uart_max3110 *max;
-	int ret;
-	unsigned char *buffer;
+	void *buffer;
 	u16 res;
+	int ret = 0;
+
 	max = kzalloc(sizeof(*max), GFP_KERNEL);
 	if (!max)
 		return -ENOMEM;
 
-	/* set spi info */
-	spi->mode = SPI_MODE_0;
+	/* Set spi info */
 	spi->bits_per_word = 16;
 	max->clock = MAX3110_HIGH_CLK;
-	spi->controller_data = &spi0_uart;
 
 	spi_setup(spi);
 
-	max->port.type = PORT_PXA;	/* need apply for a max3110 type */
-	max->port.fifosize = 2;		/* only have 16b buffer */
+	max->port.type = PORT_MAX3100;
+	max->port.fifosize = 2;		/* Only have 16b buffer */
 	max->port.ops = &serial_m3110_ops;
 	max->port.line = 0;
 	max->port.dev = &spi->dev;
 	max->port.uartclk = 115200;
 
 	max->spi = spi;
-	max->name = spi->modalias;	/* use spi name as the name */
+	strcpy(max->name, spi->modalias);
 	max->irq = (u16)spi->irq;
 
 	mutex_init(&max->thread_mutex);
@@ -755,13 +828,15 @@
 		ret = -ENODEV;
 		goto err_get_page;
 	}
-	buffer = (unsigned char *)__get_free_page(GFP_KERNEL);
+
+	buffer = (void *)__get_free_page(GFP_KERNEL);
 	if (!buffer) {
 		ret = -ENOMEM;
 		goto err_get_page;
 	}
-	max->con_xmit.buf = (unsigned char *)buffer;
-	max->con_xmit.head = max->con_xmit.tail = 0;
+	max->con_xmit.buf = buffer;
+	max->con_xmit.head = 0;
+	max->con_xmit.tail = 0;
 
 	max->main_thread = kthread_run(max3110_main_thread,
 					max, "max3110_main");
@@ -770,8 +845,10 @@
 		goto err_kthread;
 	}
 
+	spi_set_drvdata(spi, max);
 	pmax = max;
-	/* give membase a psudo value to pass serial_core's check */
+
+	/* Give membase a psudo value to pass serial_core's check */
 	max->port.membase = (void *)0xff110000;
 	uart_add_one_port(&serial_m3110_reg, &max->port);
 
@@ -780,19 +857,17 @@
 err_kthread:
 	free_page((unsigned long)buffer);
 err_get_page:
-	pmax = NULL;
 	kfree(max);
 	return ret;
 }
 
-static int max3110_remove(struct spi_device *dev)
+static int __devexit serial_m3110_remove(struct spi_device *dev)
 {
-	struct uart_max3110 *max = pmax;
+	struct uart_max3110 *max = spi_get_drvdata(dev);
 
-	if (!pmax)
+	if (!max)
 		return 0;
 
-	pmax = NULL;
 	uart_remove_one_port(&serial_m3110_reg, &max->port);
 
 	free_page((unsigned long)max->con_xmit.buf);
@@ -811,13 +886,12 @@
 			.owner	= THIS_MODULE,
 	},
 	.probe		= serial_m3110_probe,
-	.remove		= __devexit_p(max3110_remove),
+	.remove		= __devexit_p(serial_m3110_remove),
 	.suspend	= serial_m3110_suspend,
 	.resume		= serial_m3110_resume,
 };
 
-
-int __init serial_m3110_init(void)
+static int __init serial_m3110_init(void)
 {
 	int ret = 0;
 
@@ -832,7 +906,7 @@
 	return ret;
 }
 
-void __exit serial_m3110_exit(void)
+static void __exit serial_m3110_exit(void)
 {
 	spi_unregister_driver(&uart_max3110_driver);
 	uart_unregister_driver(&serial_m3110_reg);
@@ -841,5 +915,5 @@
 module_init(serial_m3110_init);
 module_exit(serial_m3110_exit);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("max3110-uart");
diff --git a/drivers/serial/mrst_max3110.h b/drivers/serial/mrst_max3110.h
index 363478a..d1ef43a 100644
--- a/drivers/serial/mrst_max3110.h
+++ b/drivers/serial/mrst_max3110.h
@@ -56,4 +56,5 @@
 #define WC_BAUD_DR192		(0xE)
 #define WC_BAUD_DR384		(0xF)
 
+#define M3110_RX_FIFO_DEPTH	8
 #endif
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index cd85112..c4ea146 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1074,10 +1074,10 @@
  * NB: both 1->0 and 0->1 transitions are counted except for
  *     RI where only 0->1 is counted.
  */
-static int uart_get_count(struct uart_state *state,
-			  struct serial_icounter_struct __user *icnt)
+static int uart_get_icount(struct tty_struct *tty,
+			  struct serial_icounter_struct *icount)
 {
-	struct serial_icounter_struct icount;
+	struct uart_state *state = tty->driver_data;
 	struct uart_icount cnow;
 	struct uart_port *uport = state->uart_port;
 
@@ -1085,19 +1085,19 @@
 	memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
 	spin_unlock_irq(&uport->lock);
 
-	icount.cts         = cnow.cts;
-	icount.dsr         = cnow.dsr;
-	icount.rng         = cnow.rng;
-	icount.dcd         = cnow.dcd;
-	icount.rx          = cnow.rx;
-	icount.tx          = cnow.tx;
-	icount.frame       = cnow.frame;
-	icount.overrun     = cnow.overrun;
-	icount.parity      = cnow.parity;
-	icount.brk         = cnow.brk;
-	icount.buf_overrun = cnow.buf_overrun;
+	icount->cts         = cnow.cts;
+	icount->dsr         = cnow.dsr;
+	icount->rng         = cnow.rng;
+	icount->dcd         = cnow.dcd;
+	icount->rx          = cnow.rx;
+	icount->tx          = cnow.tx;
+	icount->frame       = cnow.frame;
+	icount->overrun     = cnow.overrun;
+	icount->parity      = cnow.parity;
+	icount->brk         = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
 
-	return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+	return 0;
 }
 
 /*
@@ -1150,10 +1150,6 @@
 	case TIOCMIWAIT:
 		ret = uart_wait_modem_status(state, arg);
 		break;
-
-	case TIOCGICOUNT:
-		ret = uart_get_count(state, uarg);
-		break;
 	}
 
 	if (ret != -ENOIOCTLCMD)
@@ -2065,7 +2061,19 @@
 	/*
 	 * Re-enable the console device after suspending.
 	 */
-	if (uart_console(uport)) {
+	if (console_suspend_enabled && uart_console(uport)) {
+		/*
+		 * First try to use the console cflag setting.
+		 */
+		memset(&termios, 0, sizeof(struct ktermios));
+		termios.c_cflag = uport->cons->cflag;
+
+		/*
+		 * If that's unset, use the tty termios setting.
+		 */
+		if (port->tty && port->tty->termios && termios.c_cflag == 0)
+			termios = *(port->tty->termios);
+
 		uart_change_pm(state, 0);
 		uport->ops->set_termios(uport, &termios, NULL);
 		console_start(uport->cons);
@@ -2283,6 +2291,7 @@
 #endif
 	.tiocmget	= uart_tiocmget,
 	.tiocmset	= uart_tiocmset,
+	.get_icount	= uart_get_icount,
 #ifdef CONFIG_CONSOLE_POLL
 	.poll_init	= uart_poll_init,
 	.poll_get_char	= uart_poll_get_char,
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index 9b03d7b..c4bf54b 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -322,6 +322,26 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+static int ulite_get_poll_char(struct uart_port *port)
+{
+	if (!(ioread32be(port->membase + ULITE_STATUS)
+						& ULITE_STATUS_RXVALID))
+		return NO_POLL_CHAR;
+
+	return ioread32be(port->membase + ULITE_RX);
+}
+
+static void ulite_put_poll_char(struct uart_port *port, unsigned char ch)
+{
+	while (ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL)
+		cpu_relax();
+
+	/* write char to device */
+	iowrite32be(ch, port->membase + ULITE_TX);
+}
+#endif
+
 static struct uart_ops ulite_ops = {
 	.tx_empty	= ulite_tx_empty,
 	.set_mctrl	= ulite_set_mctrl,
@@ -338,7 +358,11 @@
 	.release_port	= ulite_release_port,
 	.request_port	= ulite_request_port,
 	.config_port	= ulite_config_port,
-	.verify_port	= ulite_verify_port
+	.verify_port	= ulite_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char	= ulite_get_poll_char,
+	.poll_put_char	= ulite_put_poll_char,
+#endif
 };
 
 /* ---------------------------------------------------------------------
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 5624785..9043931 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -131,6 +131,7 @@
 	.owner		= THIS_MODULE,
 	.open		= spi_show_regs_open,
 	.read		= spi_show_regs,
+	.llseek		= default_llseek,
 };
 
 static int mrst_spi_debugfs_init(struct dw_spi *dws)
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index ea1bec3..4e6245e 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -545,6 +545,7 @@
 	.unlocked_ioctl = spidev_ioctl,
 	.open =		spidev_open,
 	.release =	spidev_release,
+	.llseek =	no_llseek,
 };
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 1409131..fecb89e 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1922,6 +1922,7 @@
 	.mmap = comedi_mmap,
 	.poll = comedi_poll,
 	.fasync = comedi_fasync,
+	.llseek = noop_llseek,
 };
 
 struct class *comedi_class;
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index fc772a8..6b7372e 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -496,7 +496,6 @@
 
 static void dio700_config(struct pcmcia_device *link)
 {
-	win_req_t req;
 	int ret;
 
 	printk(KERN_INFO "ni_daq_700:  cs-config\n");
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
index fbb80f0..af25899 100644
--- a/drivers/staging/crystalhd/crystalhd_lnx.c
+++ b/drivers/staging/crystalhd/crystalhd_lnx.c
@@ -351,6 +351,7 @@
 	.unlocked_ioctl = chd_dec_ioctl,
 	.open    = chd_dec_open,
 	.release = chd_dec_close,
+	.llseek = noop_llseek,
 };
 
 static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig
index df7756a..813cb35 100644
--- a/drivers/staging/cx25821/Kconfig
+++ b/drivers/staging/cx25821/Kconfig
@@ -1,6 +1,7 @@
 config VIDEO_CX25821
 	tristate "Conexant cx25821 support"
 	depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
+	depends on BKL # please fix
 	select I2C_ALGOBIT
 	select VIDEO_BTCX
 	select VIDEO_TVEEPROM
diff --git a/drivers/staging/dream/camera/msm_camera.c b/drivers/staging/dream/camera/msm_camera.c
index 81bd71f..de4ab61 100644
--- a/drivers/staging/dream/camera/msm_camera.c
+++ b/drivers/staging/dream/camera/msm_camera.c
@@ -1941,6 +1941,7 @@
 	.open = msm_open,
 	.unlocked_ioctl = msm_ioctl_config,
 	.release = msm_release_config,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations msm_fops_control = {
@@ -1948,6 +1949,7 @@
 	.open = msm_open_control,
 	.unlocked_ioctl = msm_ioctl_control,
 	.release = msm_release_control,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations msm_fops_frame = {
@@ -1956,6 +1958,7 @@
 	.unlocked_ioctl = msm_ioctl_frame,
 	.release = msm_release_frame,
 	.poll = msm_poll_frame,
+	.llseek = no_llseek,
 };
 
 static int msm_setup_cdev(struct msm_device *msm,
diff --git a/drivers/staging/dream/pmem.c b/drivers/staging/dream/pmem.c
index 7d6bbad..3640d1f 100644
--- a/drivers/staging/dream/pmem.c
+++ b/drivers/staging/dream/pmem.c
@@ -180,6 +180,7 @@
 	.mmap = pmem_mmap,
 	.open = pmem_open,
 	.unlocked_ioctl = pmem_ioctl,
+	.llseek = noop_llseek,
 };
 
 static int get_id(struct file *file)
@@ -1204,6 +1205,7 @@
 static struct file_operations debug_fops = {
 	.read = debug_read,
 	.open = debug_open,
+	.llseek = default_llseek,
 };
 #endif
 
diff --git a/drivers/staging/dream/qdsp5/adsp_driver.c b/drivers/staging/dream/qdsp5/adsp_driver.c
index 8197765..28a6f8d 100644
--- a/drivers/staging/dream/qdsp5/adsp_driver.c
+++ b/drivers/staging/dream/qdsp5/adsp_driver.c
@@ -582,6 +582,7 @@
 	.open = adsp_open,
 	.unlocked_ioctl = adsp_ioctl,
 	.release = adsp_release,
+	.llseek = no_llseek,
 };
 
 static void adsp_create(struct adsp_device *adev, const char *name,
diff --git a/drivers/staging/dream/qdsp5/audio_aac.c b/drivers/staging/dream/qdsp5/audio_aac.c
index a373f35..45f4c78 100644
--- a/drivers/staging/dream/qdsp5/audio_aac.c
+++ b/drivers/staging/dream/qdsp5/audio_aac.c
@@ -1030,6 +1030,7 @@
 	.read = audio_read,
 	.write = audio_write,
 	.unlocked_ioctl = audio_ioctl,
+	.llseek = noop_llseek,
 };
 
 struct miscdevice audio_aac_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_amrnb.c b/drivers/staging/dream/qdsp5/audio_amrnb.c
index 07b79d5..402bbc1 100644
--- a/drivers/staging/dream/qdsp5/audio_amrnb.c
+++ b/drivers/staging/dream/qdsp5/audio_amrnb.c
@@ -841,6 +841,7 @@
 	.read = audamrnb_read,
 	.write = audamrnb_write,
 	.unlocked_ioctl = audamrnb_ioctl,
+	.llseek = noop_llseek,
 };
 
 struct miscdevice audio_amrnb_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_evrc.c b/drivers/staging/dream/qdsp5/audio_evrc.c
index ad989ee..24a8926 100644
--- a/drivers/staging/dream/qdsp5/audio_evrc.c
+++ b/drivers/staging/dream/qdsp5/audio_evrc.c
@@ -813,6 +813,7 @@
 	.read = audevrc_read,
 	.write = audevrc_write,
 	.unlocked_ioctl = audevrc_ioctl,
+	.llseek = noop_llseek,
 };
 
 struct miscdevice audio_evrc_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_in.c b/drivers/staging/dream/qdsp5/audio_in.c
index 6ae48e7..b51fa09 100644
--- a/drivers/staging/dream/qdsp5/audio_in.c
+++ b/drivers/staging/dream/qdsp5/audio_in.c
@@ -921,12 +921,14 @@
 	.read		= audio_in_read,
 	.write		= audio_in_write,
 	.unlocked_ioctl	= audio_in_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct file_operations audpre_fops = {
 	.owner          = THIS_MODULE,
 	.open           = audpre_open,
 	.unlocked_ioctl = audpre_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct miscdevice audio_in_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_mp3.c b/drivers/staging/dream/qdsp5/audio_mp3.c
index 530e1f3..409a19c 100644
--- a/drivers/staging/dream/qdsp5/audio_mp3.c
+++ b/drivers/staging/dream/qdsp5/audio_mp3.c
@@ -948,6 +948,7 @@
 	.read		= audio_read,
 	.write		= audio_write,
 	.unlocked_ioctl	= audio_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct miscdevice audio_mp3_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_out.c b/drivers/staging/dream/qdsp5/audio_out.c
index 76d7fa5..d20e895 100644
--- a/drivers/staging/dream/qdsp5/audio_out.c
+++ b/drivers/staging/dream/qdsp5/audio_out.c
@@ -807,12 +807,14 @@
 	.read		= audio_read,
 	.write		= audio_write,
 	.unlocked_ioctl	= audio_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct file_operations audpp_fops = {
 	.owner		= THIS_MODULE,
 	.open		= audpp_open,
 	.unlocked_ioctl	= audpp_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct miscdevice audio_misc = {
diff --git a/drivers/staging/dream/qdsp5/audio_qcelp.c b/drivers/staging/dream/qdsp5/audio_qcelp.c
index effa96f3..911bab4 100644
--- a/drivers/staging/dream/qdsp5/audio_qcelp.c
+++ b/drivers/staging/dream/qdsp5/audio_qcelp.c
@@ -824,6 +824,7 @@
 	.read = audqcelp_read,
 	.write = audqcelp_write,
 	.unlocked_ioctl = audqcelp_ioctl,
+	.llseek = noop_llseek,
 };
 
 struct miscdevice audio_qcelp_misc = {
diff --git a/drivers/staging/dream/qdsp5/evlog.h b/drivers/staging/dream/qdsp5/evlog.h
index 922ce67..e5ab86b 100644
--- a/drivers/staging/dream/qdsp5/evlog.h
+++ b/drivers/staging/dream/qdsp5/evlog.h
@@ -123,6 +123,7 @@
 static const struct file_operations ev_log_ops = {
 	.read = ev_log_read,
 	.open = ev_log_open,
+	.llseek = default_llseek,
 };
 
 static int ev_log_init(struct ev_log *log)
diff --git a/drivers/staging/dream/qdsp5/snd.c b/drivers/staging/dream/qdsp5/snd.c
index 037d7ff..e0f2f7b 100644
--- a/drivers/staging/dream/qdsp5/snd.c
+++ b/drivers/staging/dream/qdsp5/snd.c
@@ -247,6 +247,7 @@
 	.open		= snd_open,
 	.release	= snd_release,
 	.unlocked_ioctl	= snd_ioctl,
+	.llseek		= noop_llseek,
 };
 
 struct miscdevice snd_misc = {
diff --git a/drivers/staging/easycap/Kconfig b/drivers/staging/easycap/Kconfig
index bd96f39..9d5fe4d 100644
--- a/drivers/staging/easycap/Kconfig
+++ b/drivers/staging/easycap/Kconfig
@@ -1,6 +1,7 @@
 config EASYCAP
 	tristate "EasyCAP USB ID 05e1:0408 support"
 	depends on USB && VIDEO_DEV
+	depends on BKL # please fix
 
 	---help---
 	  This is an integrated audio/video driver for EasyCAP cards with
diff --git a/drivers/staging/frontier/alphatrack.c b/drivers/staging/frontier/alphatrack.c
index 4e52105..689099b 100644
--- a/drivers/staging/frontier/alphatrack.c
+++ b/drivers/staging/frontier/alphatrack.c
@@ -641,6 +641,7 @@
 	.open = usb_alphatrack_open,
 	.release = usb_alphatrack_release,
 	.poll = usb_alphatrack_poll,
+	.llseek = no_llseek,
 };
 
 /*
diff --git a/drivers/staging/frontier/tranzport.c b/drivers/staging/frontier/tranzport.c
index eed74f0..3d12c17 100644
--- a/drivers/staging/frontier/tranzport.c
+++ b/drivers/staging/frontier/tranzport.c
@@ -767,6 +767,7 @@
 	.open = usb_tranzport_open,
 	.release = usb_tranzport_release,
 	.poll = usb_tranzport_poll,
+	.llseek = no_llseek,
 };
 
 /*
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig
index e47f683..75fa468 100644
--- a/drivers/staging/go7007/Kconfig
+++ b/drivers/staging/go7007/Kconfig
@@ -1,6 +1,7 @@
 config VIDEO_GO7007
 	tristate "WIS GO7007 MPEG encoder support"
 	depends on VIDEO_DEV && PCI && I2C && INPUT
+	depends on BKL # please fix
 	depends on SND
 	select VIDEOBUF_DMA_SG
 	select VIDEO_IR
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index ff1d247..8284297 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -25,7 +25,7 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/hdreg.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -124,6 +124,7 @@
 };
 
 /* Static decl */
+static DEFINE_MUTEX(blkvsc_mutex);
 static int blkvsc_probe(struct device *dev);
 static int blkvsc_remove(struct device *device);
 static void blkvsc_shutdown(struct device *device);
@@ -1309,7 +1310,7 @@
 	DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
 		   blkdev->gd->disk_name);
 
-	lock_kernel();
+	mutex_lock(&blkvsc_mutex);
 	spin_lock(&blkdev->lock);
 
 	if (!blkdev->users && blkdev->device_type == DVD_TYPE) {
@@ -1321,7 +1322,7 @@
 	blkdev->users++;
 
 	spin_unlock(&blkdev->lock);
-	unlock_kernel();
+	mutex_unlock(&blkvsc_mutex);
 	return 0;
 }
 
@@ -1332,7 +1333,7 @@
 	DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
 		   blkdev->gd->disk_name);
 
-	lock_kernel();
+	mutex_lock(&blkvsc_mutex);
 	spin_lock(&blkdev->lock);
 	if (blkdev->users == 1) {
 		spin_unlock(&blkdev->lock);
@@ -1343,7 +1344,7 @@
 	blkdev->users--;
 
 	spin_unlock(&blkdev->lock);
-	unlock_kernel();
+	mutex_unlock(&blkvsc_mutex);
 	return 0;
 }
 
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index dd4d87a..92a212f 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -349,6 +349,7 @@
 	.release = iio_event_chrdev_release,
 	.open = iio_event_chrdev_open,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static void iio_event_dev_release(struct device *dev)
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c
index 6ab578e..1c5f672 100644
--- a/drivers/staging/iio/industrialio-ring.c
+++ b/drivers/staging/iio/industrialio-ring.c
@@ -133,6 +133,7 @@
 	.release = iio_ring_release,
 	.open = iio_ring_open,
 	.owner = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 /**
diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c
index 6649325..ed5c5fe 100644
--- a/drivers/staging/lirc/lirc_imon.c
+++ b/drivers/staging/lirc/lirc_imon.c
@@ -115,7 +115,8 @@
 	.owner		= THIS_MODULE,
 	.open		= &display_open,
 	.write		= &vfd_write,
-	.release	= &display_close
+	.release	= &display_close,
+	.llseek		= noop_llseek,
 };
 
 /*
diff --git a/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c
index ec11c0e..543c5c3b 100644
--- a/drivers/staging/lirc/lirc_it87.c
+++ b/drivers/staging/lirc/lirc_it87.c
@@ -342,6 +342,7 @@
 	.unlocked_ioctl	= lirc_ioctl,
 	.open		= lirc_open,
 	.release	= lirc_close,
+	.llseek		= noop_llseek,
 };
 
 static int set_use_inc(void *data)
diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c
index 73166c3..8f72a84 100644
--- a/drivers/staging/lirc/lirc_sasem.c
+++ b/drivers/staging/lirc/lirc_sasem.c
@@ -125,6 +125,7 @@
 	.write		= &vfd_write,
 	.unlocked_ioctl	= &vfd_ioctl,
 	.release	= &vfd_close,
+	.llseek		= noop_llseek,
 };
 
 /* USB Device ID for Sasem USB Control Board */
diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c
index 9456f8e..8da3824 100644
--- a/drivers/staging/lirc/lirc_serial.c
+++ b/drivers/staging/lirc/lirc_serial.c
@@ -1058,6 +1058,7 @@
 	.poll		= lirc_dev_fop_poll,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
+	.llseek		= no_llseek,
 };
 
 static struct lirc_driver driver = {
diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c
index eb08fa7..2478871 100644
--- a/drivers/staging/lirc/lirc_sir.c
+++ b/drivers/staging/lirc/lirc_sir.c
@@ -459,6 +459,7 @@
 	.unlocked_ioctl	= lirc_ioctl,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
+	.llseek		= no_llseek,
 };
 
 static int set_use_inc(void *data)
diff --git a/drivers/staging/memrar/memrar_handler.c b/drivers/staging/memrar/memrar_handler.c
index a98b3f1..cfcaa8e 100644
--- a/drivers/staging/memrar/memrar_handler.c
+++ b/drivers/staging/memrar/memrar_handler.c
@@ -890,6 +890,7 @@
 	.mmap           = memrar_mmap,
 	.open           = memrar_open,
 	.release        = memrar_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice memrar_miscdev = {
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 3221814..6885f9a 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -1631,6 +1631,7 @@
 	.read    = keypad_read,		/* read */
 	.open    = keypad_open,		/* open */
 	.release = keypad_release,	/* close */
+	.llseek  = default_llseek,
 };
 
 static struct miscdevice keypad_dev = {
diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c
index fa21a0f..c7932da 100644
--- a/drivers/staging/spectra/ffsport.c
+++ b/drivers/staging/spectra/ffsport.c
@@ -27,7 +27,6 @@
 #include <linux/kthread.h>
 #include <linux/log2.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 
 /**** Helper functions used for Div, Remainder operation on u64 ****/
@@ -590,14 +589,16 @@
 	return -ENOTTY;
 }
 
+static DEFINE_MUTEX(ffsport_mutex);
+
 int GLOB_SBD_unlocked_ioctl(struct block_device *bdev, fmode_t mode,
 		unsigned int cmd, unsigned long arg)
 {
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&ffsport_mutex);
 	ret = GLOB_SBD_ioctl(bdev, mode, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ffsport_mutex);
 
 	return ret;
 }
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
index 7ee8949..7b3a7d0 100644
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
@@ -144,6 +144,7 @@
 	.release = bridge_release,
 	.unlocked_ioctl = bridge_ioctl,
 	.mmap = bridge_mmap,
+	.llseek = noop_llseek,
 };
 
 #ifdef CONFIG_PM
diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
index 2c1d10a..b11ec37 100644
--- a/drivers/staging/usbip/Kconfig
+++ b/drivers/staging/usbip/Kconfig
@@ -1,6 +1,6 @@
 config USB_IP_COMMON
 	tristate "USB IP support (EXPERIMENTAL)"
-	depends on USB && NET && EXPERIMENTAL
+	depends on USB && NET && EXPERIMENTAL && BKL
 	default N
 	---help---
 	  This enables pushing USB packets over IP to allow remote
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index b53deee..0d236f4 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -257,7 +257,7 @@
 #include <linux/fs.h>		/* everything... */
 #include <linux/errno.h>	/* error codes */
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
@@ -277,6 +277,7 @@
 #define TYPE(inode) (iminor(inode) >> 4)
 #define NUM(inode) (iminor(inode) & 0xf)
 
+static DEFINE_MUTEX(ixj_mutex);
 static int ixjdebug;
 static int hertz = HZ;
 static int samplerate = 100;
@@ -6655,9 +6656,9 @@
 static long ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg)
 {
 	long ret;
-	lock_kernel();
+	mutex_lock(&ixj_mutex);
 	ret = do_ixj_ioctl(file_p, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&ixj_mutex);
 	return ret;
 }
 
@@ -6676,7 +6677,8 @@
         .poll           = ixj_poll,
         .unlocked_ioctl = ixj_ioctl,
         .release        = ixj_release,
-        .fasync         = ixj_fasync
+        .fasync         = ixj_fasync,
+        .llseek	 = default_llseek,
 };
 
 static int ixj_linetest(IXJ *j)
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
index f3873f6..1915af2 100644
--- a/drivers/telephony/phonedev.c
+++ b/drivers/telephony/phonedev.c
@@ -130,6 +130,7 @@
 {
 	.owner		= THIS_MODULE,
 	.open		= phone_open,
+	.llseek		= noop_llseek,
 };
 
 /*
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index bff1afb..a858d2b 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -23,9 +23,10 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/kobject.h>
+#include <linux/cdev.h>
 #include <linux/uio_driver.h>
 
-#define UIO_MAX_DEVICES 255
+#define UIO_MAX_DEVICES		(1U << MINORBITS)
 
 struct uio_device {
 	struct module		*owner;
@@ -41,15 +42,10 @@
 };
 
 static int uio_major;
+static struct cdev *uio_cdev;
 static DEFINE_IDR(uio_idr);
 static const struct file_operations uio_fops;
 
-/* UIO class infrastructure */
-static struct uio_class {
-	struct kref kref;
-	struct class *class;
-} *uio_class;
-
 /* Protect idr accesses */
 static DEFINE_MUTEX(minor_lock);
 
@@ -232,45 +228,34 @@
 			 struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
-	if (idev)
-		return sprintf(buf, "%s\n", idev->info->name);
-	else
-		return -ENODEV;
+	return sprintf(buf, "%s\n", idev->info->name);
 }
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 static ssize_t show_version(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
-	if (idev)
-		return sprintf(buf, "%s\n", idev->info->version);
-	else
-		return -ENODEV;
+	return sprintf(buf, "%s\n", idev->info->version);
 }
-static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
 
 static ssize_t show_event(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
 	struct uio_device *idev = dev_get_drvdata(dev);
-	if (idev)
-		return sprintf(buf, "%u\n",
-				(unsigned int)atomic_read(&idev->event));
-	else
-		return -ENODEV;
+	return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
 }
-static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
 
-static struct attribute *uio_attrs[] = {
-	&dev_attr_name.attr,
-	&dev_attr_version.attr,
-	&dev_attr_event.attr,
-	NULL,
+static struct device_attribute uio_class_attributes[] = {
+	__ATTR(name, S_IRUGO, show_name, NULL),
+	__ATTR(version, S_IRUGO, show_version, NULL),
+	__ATTR(event, S_IRUGO, show_event, NULL),
+	{}
 };
 
-static struct attribute_group uio_attr_grp = {
-	.attrs = uio_attrs,
+/* UIO class infrastructure */
+static struct class uio_class = {
+	.name = "uio",
+	.dev_attrs = uio_class_attributes,
 };
 
 /*
@@ -287,10 +272,6 @@
 	struct uio_port *port;
 	struct uio_portio *portio;
 
-	ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);
-	if (ret)
-		goto err_group;
-
 	for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
 		mem = &idev->info->mem[mi];
 		if (mem->size == 0)
@@ -358,8 +339,6 @@
 		kobject_put(&map->kobj);
 	}
 	kobject_put(idev->map_dir);
-	sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
-err_group:
 	dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
 	return ret;
 }
@@ -385,8 +364,6 @@
 		kobject_put(&port->portio->kobj);
 	}
 	kobject_put(idev->portio_dir);
-
-	sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
 }
 
 static int uio_get_minor(struct uio_device *idev)
@@ -525,7 +502,7 @@
 	struct uio_listener *listener = filep->private_data;
 	struct uio_device *idev = listener->dev;
 
-	if (idev->info->irq == UIO_IRQ_NONE)
+	if (!idev->info->irq)
 		return -EIO;
 
 	poll_wait(filep, &idev->wait, wait);
@@ -543,7 +520,7 @@
 	ssize_t retval;
 	s32 event_count;
 
-	if (idev->info->irq == UIO_IRQ_NONE)
+	if (!idev->info->irq)
 		return -EIO;
 
 	if (count != sizeof(s32))
@@ -591,7 +568,7 @@
 	ssize_t retval;
 	s32 irq_on;
 
-	if (idev->info->irq == UIO_IRQ_NONE)
+	if (!idev->info->irq)
 		return -EIO;
 
 	if (count != sizeof(s32))
@@ -740,72 +717,77 @@
 	.mmap		= uio_mmap,
 	.poll		= uio_poll,
 	.fasync		= uio_fasync,
+	.llseek		= noop_llseek,
 };
 
 static int uio_major_init(void)
 {
-	uio_major = register_chrdev(0, "uio", &uio_fops);
-	if (uio_major < 0)
-		return uio_major;
-	return 0;
+	static const char name[] = "uio";
+	struct cdev *cdev = NULL;
+	dev_t uio_dev = 0;
+	int result;
+
+	result = alloc_chrdev_region(&uio_dev, 0, UIO_MAX_DEVICES, name);
+	if (result)
+		goto out;
+
+	result = -ENOMEM;
+	cdev = cdev_alloc();
+	if (!cdev)
+		goto out_unregister;
+
+	cdev->owner = THIS_MODULE;
+	cdev->ops = &uio_fops;
+	kobject_set_name(&cdev->kobj, "%s", name);
+
+	result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES);
+	if (result)
+		goto out_put;
+
+	uio_major = MAJOR(uio_dev);
+	uio_cdev = cdev;
+	result = 0;
+out:
+	return result;
+out_put:
+	kobject_put(&cdev->kobj);
+out_unregister:
+	unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
+	goto out;
 }
 
 static void uio_major_cleanup(void)
 {
-	unregister_chrdev(uio_major, "uio");
+	unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES);
+	cdev_del(uio_cdev);
 }
 
 static int init_uio_class(void)
 {
-	int ret = 0;
-
-	if (uio_class != NULL) {
-		kref_get(&uio_class->kref);
-		goto exit;
-	}
+	int ret;
 
 	/* This is the first time in here, set everything up properly */
 	ret = uio_major_init();
 	if (ret)
 		goto exit;
 
-	uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL);
-	if (!uio_class) {
-		ret = -ENOMEM;
-		goto err_kzalloc;
-	}
-
-	kref_init(&uio_class->kref);
-	uio_class->class = class_create(THIS_MODULE, "uio");
-	if (IS_ERR(uio_class->class)) {
-		ret = IS_ERR(uio_class->class);
-		printk(KERN_ERR "class_create failed for uio\n");
-		goto err_class_create;
+	ret = class_register(&uio_class);
+	if (ret) {
+		printk(KERN_ERR "class_register failed for uio\n");
+		goto err_class_register;
 	}
 	return 0;
 
-err_class_create:
-	kfree(uio_class);
-	uio_class = NULL;
-err_kzalloc:
+err_class_register:
 	uio_major_cleanup();
 exit:
 	return ret;
 }
 
-static void release_uio_class(struct kref *kref)
+static void release_uio_class(void)
 {
-	/* Ok, we cheat as we know we only have one uio_class */
-	class_destroy(uio_class->class);
-	kfree(uio_class);
+	class_unregister(&uio_class);
 	uio_major_cleanup();
-	uio_class = NULL;
-}
-
-static void uio_class_destroy(void)
-{
-	if (uio_class)
-		kref_put(&uio_class->kref, release_uio_class);
 }
 
 /**
@@ -828,10 +810,6 @@
 
 	info->uio_dev = NULL;
 
-	ret = init_uio_class();
-	if (ret)
-		return ret;
-
 	idev = kzalloc(sizeof(*idev), GFP_KERNEL);
 	if (!idev) {
 		ret = -ENOMEM;
@@ -847,7 +825,7 @@
 	if (ret)
 		goto err_get_minor;
 
-	idev->dev = device_create(uio_class->class, parent,
+	idev->dev = device_create(&uio_class, parent,
 				  MKDEV(uio_major, idev->minor), idev,
 				  "uio%d", idev->minor);
 	if (IS_ERR(idev->dev)) {
@@ -862,9 +840,9 @@
 
 	info->uio_dev = idev;
 
-	if (idev->info->irq >= 0) {
-		ret = request_irq(idev->info->irq, uio_interrupt,
-				  idev->info->irq_flags, idev->info->name, idev);
+	if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
+		ret = request_irq(info->irq, uio_interrupt,
+				  info->irq_flags, info->name, idev);
 		if (ret)
 			goto err_request_irq;
 	}
@@ -874,13 +852,12 @@
 err_request_irq:
 	uio_dev_del_attributes(idev);
 err_uio_dev_add_attributes:
-	device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
+	device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
 err_device_create:
 	uio_free_minor(idev);
 err_get_minor:
 	kfree(idev);
 err_kzalloc:
-	uio_class_destroy();
 	return ret;
 }
 EXPORT_SYMBOL_GPL(__uio_register_device);
@@ -901,15 +878,13 @@
 
 	uio_free_minor(idev);
 
-	if (info->irq >= 0)
+	if (info->irq && (info->irq != UIO_IRQ_CUSTOM))
 		free_irq(info->irq, idev);
 
 	uio_dev_del_attributes(idev);
 
-	dev_set_drvdata(idev->dev, NULL);
-	device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
+	device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
 	kfree(idev);
-	uio_class_destroy();
 
 	return;
 }
@@ -917,11 +892,12 @@
 
 static int __init uio_init(void)
 {
-	return 0;
+	return init_uio_class();
 }
 
 static void __exit uio_exit(void)
 {
+	release_uio_class();
 }
 
 module_init(uio_init)
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index 85c9884..fc22e1e 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -128,12 +128,6 @@
 	struct uio_pci_generic_dev *gdev;
 	int err;
 
-	if (!pdev->irq) {
-		dev_warn(&pdev->dev, "No IRQ assigned to device: "
-			 "no support for interrupts?\n");
-		return -ENODEV;
-	}
-
 	err = pci_enable_device(pdev);
 	if (err) {
 		dev_err(&pdev->dev, "%s: pci_enable_device failed: %d\n",
@@ -141,6 +135,13 @@
 		return err;
 	}
 
+	if (!pdev->irq) {
+		dev_warn(&pdev->dev, "No IRQ assigned to device: "
+			 "no support for interrupts?\n");
+		pci_disable_device(pdev);
+		return -ENODEV;
+	}
+
 	err = verify_pci_2_3(pdev);
 	if (err)
 		goto err_verify;
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 4aa00e6..67eb377 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -59,6 +59,7 @@
 config USB_ARCH_HAS_EHCI
 	boolean
 	default y if PPC_83xx
+	default y if PPC_MPC512x
 	default y if SOC_AU1200
 	default y if ARCH_IXP4XX
 	default y if ARCH_W90X900
diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile
index 4c4a776..a5d792e 100644
--- a/drivers/usb/atm/Makefile
+++ b/drivers/usb/atm/Makefile
@@ -2,12 +2,10 @@
 # Makefile for USB ATM/xDSL drivers
 #
 
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
+
 obj-$(CONFIG_USB_CXACRU)	+= cxacru.o
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= speedtch.o
 obj-$(CONFIG_USB_UEAGLEATM)	+= ueagle-atm.o
 obj-$(CONFIG_USB_ATM)		+= usbatm.o
 obj-$(CONFIG_USB_XUSBATM)	+= xusbatm.o
-
-ifeq ($(CONFIG_USB_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/usb/c67x00/Makefile b/drivers/usb/c67x00/Makefile
index 868bc41..b121868 100644
--- a/drivers/usb/c67x00/Makefile
+++ b/drivers/usb/c67x00/Makefile
@@ -2,8 +2,8 @@
 # Makefile for Cypress C67X00 USB Controller
 #
 
-ccflags-$(CONFIG_USB_DEBUG)		+= -DDEBUG
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
-obj-$(CONFIG_USB_C67X00_HCD)		+= c67x00.o
+obj-$(CONFIG_USB_C67X00_HCD)	+= c67x00.o
 
-c67x00-objs := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o
+c67x00-y := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index bc62fae..d6ede98 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1614,7 +1614,7 @@
 	/* Support Lego NXT using pbLua firmware */
 	{ USB_DEVICE(0x0694, 0xff00),
 	.driver_info = NOT_A_MODEM,
-       	},
+	},
 
 	/* control interfaces without any protocol set */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 094c76b..6ee4451 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -584,7 +584,8 @@
 	.open =		wdm_open,
 	.flush =	wdm_flush,
 	.release =	wdm_release,
-	.poll =		wdm_poll
+	.poll =		wdm_poll,
+	.llseek =	noop_llseek,
 };
 
 static struct usb_class_driver wdm_class = {
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index e325162..9eca405 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -1043,6 +1043,7 @@
 	.compat_ioctl =		usblp_ioctl,
 	.open =		usblp_open,
 	.release =	usblp_release,
+	.llseek =	noop_llseek,
 };
 
 static char *usblp_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 3e7c1b8..6a54634 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -987,6 +987,7 @@
 	.open		= usbtmc_open,
 	.release	= usbtmc_release,
 	.unlocked_ioctl	= usbtmc_ioctl,
+	.llseek		= default_llseek,
 };
 
 static struct usb_class_driver usbtmc_class = {
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index ec16e60..507a4e1 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -2,20 +2,13 @@
 # Makefile for USB Core files and filesystem
 #
 
-usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o driver.o \
-			config.o file.o buffer.o sysfs.o endpoint.o \
-			devio.o notify.o generic.o quirks.o devices.o
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
-ifeq ($(CONFIG_PCI),y)
-	usbcore-objs	+= hcd-pci.o
-endif
+usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o
+usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o
+usbcore-y += devio.o notify.o generic.o quirks.o devices.o
 
-ifeq ($(CONFIG_USB_DEVICEFS),y)
-	usbcore-objs	+= inode.o
-endif
+usbcore-$(CONFIG_PCI)		+= hcd-pci.o
+usbcore-$(CONFIG_USB_DEVICEFS)	+= inode.o
 
-obj-$(CONFIG_USB)	+= usbcore.o
-
-ifeq ($(CONFIG_USB_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+obj-$(CONFIG_USB)		+= usbcore.o
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 3449742..ddb4dc9 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -66,8 +66,8 @@
 #define ALLOW_SERIAL_NUMBER
 
 static const char *format_topo =
-/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
-"\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
+/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */
+"\nT:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n";
 
 static const char *format_string_manufacturer =
 /* S:  Manufacturer=xxxx */
@@ -520,11 +520,14 @@
 		speed = "1.5"; break;
 	case USB_SPEED_UNKNOWN:		/* usb 1.1 root hub code */
 	case USB_SPEED_FULL:
-		speed = "12 "; break;
+		speed = "12"; break;
+	case USB_SPEED_WIRELESS:	/* Wireless has no real fixed speed */
 	case USB_SPEED_HIGH:
 		speed = "480"; break;
+	case USB_SPEED_SUPER:
+		speed = "5000"; break;
 	default:
-		speed = "?? ";
+		speed = "??";
 	}
 	data_end = pages_start + sprintf(pages_start, format_topo,
 			bus->busnum, level, parent_devnum,
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index d7a4401..c0e60fb 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1337,7 +1337,7 @@
 	/* Avoid PM error messages for devices disconnected while suspended
 	 * as we'll display regular disconnect messages just a bit later.
 	 */
-	if (status == -ENODEV)
+	if (status == -ENODEV || status == -ESHUTDOWN)
 		status = 0;
 	return status;
 }
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 3788e73..9da2505 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -202,7 +202,7 @@
 	return retval;
 
 error_register:
-	kfree(ep_dev);
+	put_device(&ep_dev->dev);
 exit:
 	return retval;
 }
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 1e6ccef..9fe34fb 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -59,6 +59,7 @@
 static const struct file_operations usb_fops = {
 	.owner =	THIS_MODULE,
 	.open =		usb_open,
+	.llseek =	noop_llseek,
 };
 
 static struct usb_class {
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index c3f9854..3799573 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -329,8 +329,10 @@
 		return;
 
 	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) &&
-			hcd->driver->shutdown)
+			hcd->driver->shutdown) {
 		hcd->driver->shutdown(hcd);
+		pci_disable_device(dev);
+	}
 }
 EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 5cca00a..61800f7 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1263,10 +1263,8 @@
 	*dma_handle = 0;
 }
 
-static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+void unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb)
 {
-	enum dma_data_direction dir;
-
 	if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
 		dma_unmap_single(hcd->self.controller,
 				urb->setup_dma,
@@ -1279,6 +1277,17 @@
 				sizeof(struct usb_ctrlrequest),
 				DMA_TO_DEVICE);
 
+	/* Make it safe to call this routine more than once */
+	urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL);
+}
+EXPORT_SYMBOL_GPL(unmap_urb_setup_for_dma);
+
+void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+	enum dma_data_direction dir;
+
+	unmap_urb_setup_for_dma(hcd, urb);
+
 	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 	if (urb->transfer_flags & URB_DMA_MAP_SG)
 		dma_unmap_sg(hcd->self.controller,
@@ -1303,10 +1312,10 @@
 				dir);
 
 	/* Make it safe to call this routine more than once */
-	urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL |
-			URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
+	urb->transfer_flags &= ~(URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
 			URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
 }
+EXPORT_SYMBOL_GPL(unmap_urb_for_dma);
 
 static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
 			   gfp_t mem_flags)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 84c18971..27115b4 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -758,6 +758,9 @@
 				clear_port_feature(hdev, port1,
 						   USB_PORT_FEAT_ENABLE);
 				portstatus &= ~USB_PORT_STAT_ENABLE;
+			} else {
+				/* Pretend that power was lost for USB3 devs */
+				portstatus &= ~USB_PORT_STAT_ENABLE;
 			}
 		}
 
@@ -2594,16 +2597,14 @@
 		return 0;
 	if (udev->state != USB_STATE_DEFAULT)
 		return -EINVAL;
-	if (hcd->driver->address_device) {
+	if (hcd->driver->address_device)
 		retval = hcd->driver->address_device(hcd, udev);
-	} else {
+	else
 		retval = usb_control_msg(udev, usb_sndaddr0pipe(),
 				USB_REQ_SET_ADDRESS, 0, devnum, 0,
 				NULL, 0, USB_CTRL_SET_TIMEOUT);
-		if (retval == 0)
-			update_address(udev, devnum);
-	}
 	if (retval == 0) {
+		update_address(udev, devnum);
 		/* Device now using proper address. */
 		usb_set_device_state(udev, USB_STATE_ADDRESS);
 		usb_ep0_reinit(udev);
@@ -2860,13 +2861,16 @@
 	else
 		i = udev->descriptor.bMaxPacketSize0;
 	if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
-		if (udev->speed != USB_SPEED_FULL ||
+		if (udev->speed == USB_SPEED_LOW ||
 				!(i == 8 || i == 16 || i == 32 || i == 64)) {
-			dev_err(&udev->dev, "ep0 maxpacket = %d\n", i);
+			dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
 			retval = -EMSGSIZE;
 			goto fail;
 		}
-		dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+		if (udev->speed == USB_SPEED_FULL)
+			dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+		else
+			dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
 		usb_ep0_reinit(udev);
 	}
@@ -3097,16 +3101,17 @@
 			udev->speed = USB_SPEED_UNKNOWN;
 
 		/*
-		 * xHCI needs to issue an address device command later
-		 * in the hub_port_init sequence for SS/HS/FS/LS devices.
+		 * Set the address.
+		 * Note xHCI needs to issue an address device command later
+		 * in the hub_port_init sequence for SS/HS/FS/LS devices,
+		 * and xHC will assign an address to the device. But use
+		 * kernel assigned address here, to avoid any address conflict
+		 * issue.
 		 */
-		if (!(hcd->driver->flags & HCD_USB3)) {
-			/* set the address */
-			choose_address(udev);
-			if (udev->devnum <= 0) {
-				status = -ENOTCONN;	/* Don't retry */
-				goto loop;
-			}
+		choose_address(udev);
+		if (udev->devnum <= 0) {
+			status = -ENOTCONN;	/* Don't retry */
+			goto loop;
 		}
 
 		/* reset (non-USB 3.0 devices) and get descriptor */
@@ -3629,7 +3634,7 @@
 	}
 
 	if (!parent_hdev) {
-		/* this requires hcd-specific logic; see OHCI hc_restart() */
+		/* this requires hcd-specific logic; see ohci_restart() */
 		dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
 		return -EISDIR;
 	}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 9f0ce7d..d6e3e41 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1140,13 +1140,6 @@
 {
 	int i;
 
-	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, true);
-		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
-	}
-
 	/* getting rid of interfaces will disconnect
 	 * any drivers bound to them (a key side effect)
 	 */
@@ -1176,6 +1169,13 @@
 		if (dev->state == USB_STATE_CONFIGURED)
 			usb_set_device_state(dev, USB_STATE_ADDRESS);
 	}
+
+	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, true);
+		usb_disable_endpoint(dev, i + USB_DIR_IN, true);
+	}
 }
 
 /**
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 419e6b3..c14fc08 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -401,8 +401,11 @@
 	};
 
 	/* Check that the pipe's type matches the endpoint's type */
-	if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+	if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) {
+		dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
+			usb_pipetype(urb->pipe), pipetypes[xfertype]);
 		return -EPIPE;		/* The most suitable error code :-) */
+	}
 
 	/* enforce simple/standard policy */
 	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
diff --git a/drivers/usb/early/Makefile b/drivers/usb/early/Makefile
index dfedee8..24bbe51 100644
--- a/drivers/usb/early/Makefile
+++ b/drivers/usb/early/Makefile
@@ -2,4 +2,4 @@
 # Makefile for early USB devices
 #
 
-obj-$(CONFIG_EARLY_PRINTK_DBGP)        += ehci-dbgp.o
+obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index cd27f9b..b739ca8 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -158,6 +158,7 @@
 	boolean "Freescale Highspeed USB DR Peripheral Controller"
 	depends on FSL_SOC || ARCH_MXC
 	select USB_GADGET_DUALSPEED
+	select USB_FSL_MPH_DR_OF
 	help
 	   Some of Freescale PowerPC processors have a High Speed
 	   Dual-Role(DR) USB controller, which supports device mode.
@@ -209,17 +210,6 @@
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
-config USB_OTG
-	boolean "OTG Support"
-	depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD
-	help
-	   The most notable feature of USB OTG is support for a
-	   "Dual-Role" device, which can act as either a device
-	   or a host.  The initial role choice can be changed
-	   later, when two dual-role devices talk to each other.
-
-	   Select this only if your OMAP board has a Mini-AB connector.
-
 config USB_GADGET_PXA25X
 	boolean "PXA 25x or IXP 4xx"
 	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
@@ -716,8 +706,8 @@
 	depends on EXPERIMENTAL
 	select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
 	help
-	  The Function Filesystem (FunctioFS) lets one create USB
-	  composite functions in user space in the same way as GadgetFS
+	  The Function Filesystem (FunctionFS) lets one create USB
+	  composite functions in user space in the same way GadgetFS
 	  lets one create USB gadgets in user space.  This allows creation
 	  of composite gadgets such that some of the functions are
 	  implemented in kernel space (for instance Ethernet, serial or
@@ -733,14 +723,14 @@
 	bool "Include configuration with CDC ECM (Ethernet)"
 	depends on USB_FUNCTIONFS && NET
 	help
-	  Include a configuration with CDC ECM funcion (Ethernet) and the
-	  Funcion Filesystem.
+	  Include a configuration with CDC ECM function (Ethernet) and the
+	  Function Filesystem.
 
 config USB_FUNCTIONFS_RNDIS
 	bool "Include configuration with RNDIS (Ethernet)"
 	depends on USB_FUNCTIONFS && NET
 	help
-	  Include a configuration with RNDIS funcion (Ethernet) and the Filesystem.
+	  Include a configuration with RNDIS function (Ethernet) and the Filesystem.
 
 config USB_FUNCTIONFS_GENERIC
 	bool "Include 'pure' configuration"
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 27283df..5780db4 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -1,9 +1,7 @@
 #
 # USB peripheral controller drivers
 #
-ifeq ($(CONFIG_USB_GADGET_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
@@ -18,10 +16,8 @@
 obj-$(CONFIG_USB_AT91)		+= at91_udc.o
 obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
 obj-$(CONFIG_USB_FSL_USB2)	+= fsl_usb2_udc.o
-fsl_usb2_udc-objs		:= fsl_udc_core.o
-ifeq ($(CONFIG_ARCH_MXC),y)
-fsl_usb2_udc-objs		+= fsl_mxc_udc.o
-endif
+fsl_usb2_udc-y			:= fsl_udc_core.o
+fsl_usb2_udc-$(CONFIG_ARCH_MXC)	+= fsl_mxc_udc.o
 obj-$(CONFIG_USB_M66592)	+= m66592-udc.o
 obj-$(CONFIG_USB_R8A66597)	+= r8a66597-udc.o
 obj-$(CONFIG_USB_FSL_QE)	+= fsl_qe_udc.o
@@ -32,21 +28,21 @@
 #
 # USB gadget drivers
 #
-g_zero-objs			:= zero.o
-g_audio-objs			:= audio.o
-g_ether-objs			:= ether.o
-g_serial-objs			:= serial.o
-g_midi-objs			:= gmidi.o
-gadgetfs-objs			:= inode.o
-g_file_storage-objs		:= file_storage.o
-g_mass_storage-objs		:= mass_storage.o
-g_printer-objs			:= printer.o
-g_cdc-objs			:= cdc2.o
-g_multi-objs			:= multi.o
-g_hid-objs			:= hid.o
-g_dbgp-objs			:= dbgp.o
-g_nokia-objs			:= nokia.o
-g_webcam-objs			:= webcam.o
+g_zero-y			:= zero.o
+g_audio-y			:= audio.o
+g_ether-y			:= ether.o
+g_serial-y			:= serial.o
+g_midi-y			:= gmidi.o
+gadgetfs-y			:= inode.o
+g_file_storage-y		:= file_storage.o
+g_mass_storage-y		:= mass_storage.o
+g_printer-y			:= printer.o
+g_cdc-y				:= cdc2.o
+g_multi-y			:= multi.o
+g_hid-y				:= hid.o
+g_dbgp-y			:= dbgp.o
+g_nokia-y			:= nokia.o
+g_webcam-y			:= webcam.o
 
 obj-$(CONFIG_USB_ZERO)		+= g_zero.o
 obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
@@ -64,4 +60,3 @@
 obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
 obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
 obj-$(CONFIG_USB_G_WEBCAM)	+= g_webcam.o
-
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 731150d4..9034e034 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -203,7 +203,7 @@
 		DBG(dev, "DMA mode       = PPBNDU (packet per buffer "
 			"WITHOUT desc. update)\n");
 		dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU");
-	} else if (use_dma && use_dma_ppb_du && use_dma_ppb_du) {
+	} else if (use_dma && use_dma_ppb && use_dma_ppb_du) {
 		DBG(dev, "DMA mode       = PPBDU (packet per buffer "
 			"WITH desc. update)\n");
 		dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU");
@@ -1954,13 +1954,14 @@
 }
 
 /* Called by gadget driver to register itself */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct udc		*dev = udc;
 	int			retval;
 	u32 tmp;
 
-	if (!driver || !driver->bind || !driver->setup
+	if (!driver || !bind || !driver->setup
 			|| driver->speed != USB_SPEED_HIGH)
 		return -EINVAL;
 	if (!dev)
@@ -1972,7 +1973,7 @@
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
 
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 
 	/* Some gadget drivers use both ep0 directions.
 	 * NOTE: to gadget driver, ep0 is just one endpoint...
@@ -2000,7 +2001,7 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /* shutdown requests and disconnect from gadget */
 static void
@@ -3382,8 +3383,10 @@
 	udc = dev;
 
 	retval = device_register(&dev->gadget.dev);
-	if (retval)
+	if (retval) {
+		put_device(&dev->gadget.dev);
 		goto finished;
+	}
 
 	/* timer init */
 	init_timer(&udc_timer);
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 93ead19..387e503 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1628,7 +1628,8 @@
 		schedule_work(&udc->vbus_timer_work);
 }
 
-int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct at91_udc	*udc = &controller;
 	int		retval;
@@ -1636,7 +1637,7 @@
 
 	if (!driver
 			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
+			|| !bind
 			|| !driver->setup) {
 		DBG("bad parameter.\n");
 		return -EINVAL;
@@ -1653,9 +1654,9 @@
 	udc->enabled = 1;
 	udc->selfpowered = 1;
 
-	retval = driver->bind(&udc->gadget);
+	retval = bind(&udc->gadget);
 	if (retval) {
-		DBG("driver->bind() returned %d\n", retval);
+		DBG("bind() returned %d\n", retval);
 		udc->driver = NULL;
 		udc->gadget.dev.driver = NULL;
 		dev_set_drvdata(&udc->gadget.dev, NULL);
@@ -1671,7 +1672,7 @@
 	DBG("bound to %s\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index d623c7b..b5e20e8 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1789,7 +1789,8 @@
 	return IRQ_HANDLED;
 }
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct usba_udc *udc = &the_udc;
 	unsigned long flags;
@@ -1812,7 +1813,7 @@
 	clk_enable(udc->pclk);
 	clk_enable(udc->hclk);
 
-	ret = driver->bind(&udc->gadget);
+	ret = bind(&udc->gadget);
 	if (ret) {
 		DBG(DBG_ERR, "Could not bind to driver %s: error %d\n",
 			driver->driver.name, ret);
@@ -1841,7 +1842,7 @@
 	udc->gadget.dev.driver = NULL;
 	return ret;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
@@ -2014,6 +2015,9 @@
 			} else {
 				disable_irq(gpio_to_irq(udc->vbus_pin));
 			}
+		} else {
+			/* gpio_request fail so use -EINVAL for gpio_is_valid */
+			ubc->vbus_pin = -EINVAL;
 		}
 	}
 
diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c
index b744ccd..93b999e 100644
--- a/drivers/usb/gadget/audio.c
+++ b/drivers/usb/gadget/audio.c
@@ -89,7 +89,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref audio_do_config(struct usb_configuration *c)
+static int __init audio_do_config(struct usb_configuration *c)
 {
 	/* FIXME alloc iConfiguration string, set it in c->strings */
 
@@ -105,7 +105,6 @@
 
 static struct usb_configuration audio_config_driver = {
 	.label			= DRIVER_DESC,
-	.bind			= audio_do_config,
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -113,7 +112,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref audio_bind(struct usb_composite_dev *cdev)
+static int __init audio_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	int			status;
@@ -145,7 +144,7 @@
 	strings_dev[STRING_PRODUCT_IDX].id = status;
 	device_desc.iProduct = status;
 
-	status = usb_add_config(cdev, &audio_config_driver);
+	status = usb_add_config(cdev, &audio_config_driver, audio_do_config);
 	if (status < 0)
 		goto fail;
 
@@ -166,13 +165,12 @@
 	.name		= "g_audio",
 	.dev		= &device_desc,
 	.strings	= audio_strings,
-	.bind		= audio_bind,
 	.unbind		= __exit_p(audio_unbind),
 };
 
 static int __init init(void)
 {
-	return usb_composite_register(&audio_driver);
+	return usb_composite_probe(&audio_driver, audio_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
index 1f5ba2f..2720ab0 100644
--- a/drivers/usb/gadget/cdc2.c
+++ b/drivers/usb/gadget/cdc2.c
@@ -129,7 +129,7 @@
 /*
  * We _always_ have both CDC ECM and CDC ACM functions.
  */
-static int __ref cdc_do_config(struct usb_configuration *c)
+static int __init cdc_do_config(struct usb_configuration *c)
 {
 	int	status;
 
@@ -151,7 +151,6 @@
 
 static struct usb_configuration cdc_config_driver = {
 	.label			= "CDC Composite (ECM + ACM)",
-	.bind			= cdc_do_config,
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -159,7 +158,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref cdc_bind(struct usb_composite_dev *cdev)
+static int __init cdc_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -218,7 +217,7 @@
 	device_desc.iProduct = status;
 
 	/* register our configuration */
-	status = usb_add_config(cdev, &cdc_config_driver);
+	status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
 	if (status < 0)
 		goto fail1;
 
@@ -245,7 +244,6 @@
 	.name		= "g_cdc",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= cdc_bind,
 	.unbind		= __exit_p(cdc_unbind),
 };
 
@@ -255,7 +253,7 @@
 
 static int __init init(void)
 {
-	return usb_composite_register(&cdc_driver);
+	return usb_composite_probe(&cdc_driver, cdc_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 6996951..98b36fc 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2340,12 +2340,15 @@
 static const struct usb_gadget_ops usb_gadget_ops;
 
 /**
- * usb_gadget_register_driver: register a gadget driver
+ * usb_gadget_probe_driver: register a gadget driver
+ * @driver: the driver being registered
+ * @bind: the driver's bind callback
  *
- * Check usb_gadget_register_driver() at "usb_gadget.h" for details
- * Interrupts are enabled here
+ * Check usb_gadget_probe_driver() at <linux/usb/gadget.h> for details.
+ * Interrupts are enabled here.
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct ci13xxx *udc = _udc;
 	unsigned long i, k, flags;
@@ -2354,7 +2357,7 @@
 	trace("%p", driver);
 
 	if (driver             == NULL ||
-	    driver->bind       == NULL ||
+	    bind               == NULL ||
 	    driver->unbind     == NULL ||
 	    driver->setup      == NULL ||
 	    driver->disconnect == NULL ||
@@ -2430,7 +2433,7 @@
 	udc->gadget.dev.driver = &driver->driver;
 
 	spin_unlock_irqrestore(udc->lock, flags);
-	retval = driver->bind(&udc->gadget);                /* MAY SLEEP */
+	retval = bind(&udc->gadget);                /* MAY SLEEP */
 	spin_lock_irqsave(udc->lock, flags);
 
 	if (retval) {
@@ -2447,7 +2450,7 @@
 		usb_gadget_unregister_driver(driver);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /**
  * usb_gadget_unregister_driver: unregister a gadget driver
@@ -2462,7 +2465,6 @@
 	trace("%p", driver);
 
 	if (driver             == NULL ||
-	    driver->bind       == NULL ||
 	    driver->unbind     == NULL ||
 	    driver->setup      == NULL ||
 	    driver->disconnect == NULL ||
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 1160c55..7b5cc16 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/device.h>
+#include <linux/utsname.h>
 
 #include <linux/usb/composite.h>
 
@@ -39,6 +40,7 @@
 #define USB_BUFSIZ	1024
 
 static struct usb_composite_driver *composite;
+static int (*composite_gadget_bind)(struct usb_composite_dev *cdev);
 
 /* Some systems will need runtime overrides for the  product identifers
  * published in the device descriptor, either numbers or strings or both.
@@ -69,6 +71,8 @@
 module_param(iSerialNumber, charp, 0);
 MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
 
+static char composite_manufacturer[50];
+
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -470,18 +474,20 @@
  * usb_add_config() - add a configuration to a device.
  * @cdev: wraps the USB gadget
  * @config: the configuration, with bConfigurationValue assigned
+ * @bind: the configuration's bind function
  * Context: single threaded during gadget setup
  *
- * One of the main tasks of a composite driver's bind() routine is to
+ * One of the main tasks of a composite @bind() routine is to
  * add each of the configurations it supports, using this routine.
  *
- * This function returns the value of the configuration's bind(), which
+ * This function returns the value of the configuration's @bind(), which
  * is zero for success else a negative errno value.  Binding configurations
  * assigns global resources including string IDs, and per-configuration
  * resources such as interface IDs and endpoints.
  */
 int usb_add_config(struct usb_composite_dev *cdev,
-		struct usb_configuration *config)
+		struct usb_configuration *config,
+		int (*bind)(struct usb_configuration *))
 {
 	int				status = -EINVAL;
 	struct usb_configuration	*c;
@@ -490,7 +496,7 @@
 			config->bConfigurationValue,
 			config->label, config);
 
-	if (!config->bConfigurationValue || !config->bind)
+	if (!config->bConfigurationValue || !bind)
 		goto done;
 
 	/* Prevent duplicate configuration identifiers */
@@ -507,7 +513,7 @@
 	INIT_LIST_HEAD(&config->functions);
 	config->next_interface_id = 0;
 
-	status = config->bind(config);
+	status = bind(config);
 	if (status < 0) {
 		list_del(&config->list);
 		config->cdev = NULL;
@@ -533,7 +539,7 @@
 		}
 	}
 
-	/* set_alt(), or next config->bind(), sets up
+	/* set_alt(), or next bind(), sets up
 	 * ep->driver_data as needed.
 	 */
 	usb_ep_autoconfig_reset(cdev->gadget);
@@ -599,6 +605,7 @@
 	struct usb_configuration	*c;
 	struct usb_function		*f;
 	int				len;
+	const char			*str;
 
 	/* Yes, not only is USB's I18N support probably more than most
 	 * folk will ever care about ... also, it's all supported here.
@@ -638,9 +645,29 @@
 		return s->bLength;
 	}
 
-	/* Otherwise, look up and return a specified string.  String IDs
-	 * are device-scoped, so we look up each string table we're told
-	 * about.  These lookups are infrequent; simpler-is-better here.
+	/* Otherwise, look up and return a specified string.  First
+	 * check if the string has not been overridden.
+	 */
+	if (cdev->manufacturer_override == id)
+		str = iManufacturer ?: composite->iManufacturer ?:
+			composite_manufacturer;
+	else if (cdev->product_override == id)
+		str = iProduct ?: composite->iProduct;
+	else if (cdev->serial_override == id)
+		str = iSerialNumber;
+	else
+		str = NULL;
+	if (str) {
+		struct usb_gadget_strings strings = {
+			.language = language,
+			.strings  = &(struct usb_string) { 0xff, str }
+		};
+		return usb_gadget_get_string(&strings, 0xff, buf);
+	}
+
+	/* String IDs are device-scoped, so we look up each string
+	 * table we're told about.  These lookups are infrequent;
+	 * simpler-is-better here.
 	 */
 	if (composite->strings) {
 		len = lookup_string(composite->strings, buf, language, id);
@@ -901,7 +928,8 @@
 		 */
 		switch (ctrl->bRequestType & USB_RECIP_MASK) {
 		case USB_RECIP_INTERFACE:
-			f = cdev->config->interface[intf];
+			if (cdev->config)
+				f = cdev->config->interface[intf];
 			break;
 
 		case USB_RECIP_ENDPOINT:
@@ -1025,26 +1053,17 @@
 	composite = NULL;
 }
 
-static void
-string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
+static u8 override_id(struct usb_composite_dev *cdev, u8 *desc)
 {
-	struct usb_string		*str = tab->strings;
-
-	for (str = tab->strings; str->s; str++) {
-		if (str->id == id) {
-			str->s = s;
-			return;
-		}
+	if (!*desc) {
+		int ret = usb_string_id(cdev);
+		if (unlikely(ret < 0))
+			WARNING(cdev, "failed to override string ID\n");
+		else
+			*desc = ret;
 	}
-}
 
-static void
-string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
-{
-	while (*tab) {
-		string_override_one(*tab, id, s);
-		tab++;
-	}
+	return *desc;
 }
 
 static int composite_bind(struct usb_gadget *gadget)
@@ -1074,7 +1093,13 @@
 	cdev->bufsiz = USB_BUFSIZ;
 	cdev->driver = composite;
 
-	usb_gadget_set_selfpowered(gadget);
+	/*
+	 * As per USB compliance update, a device that is actively drawing
+	 * more than 100mA from USB must report itself as bus-powered in
+	 * the GetStatus(DEVICE) call.
+	 */
+	if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW)
+		usb_gadget_set_selfpowered(gadget);
 
 	/* interface and string IDs start at zero via kzalloc.
 	 * we force endpoints to start unassigned; few controller
@@ -1094,26 +1119,41 @@
 	 * serial number), register function drivers, potentially update
 	 * power state and consumption, etc
 	 */
-	status = composite->bind(cdev);
+	status = composite_gadget_bind(cdev);
 	if (status < 0)
 		goto fail;
 
 	cdev->desc = *composite->dev;
 	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
-	/* strings can't be assigned before bind() allocates the
-	 * releavnt identifiers
-	 */
-	if (cdev->desc.iManufacturer && iManufacturer)
-		string_override(composite->strings,
-			cdev->desc.iManufacturer, iManufacturer);
-	if (cdev->desc.iProduct && iProduct)
-		string_override(composite->strings,
-			cdev->desc.iProduct, iProduct);
-	if (cdev->desc.iSerialNumber && iSerialNumber)
-		string_override(composite->strings,
-			cdev->desc.iSerialNumber, iSerialNumber);
+	/* stirng overrides */
+	if (iManufacturer || !cdev->desc.iManufacturer) {
+		if (!iManufacturer && !composite->iManufacturer &&
+		    !*composite_manufacturer)
+			snprintf(composite_manufacturer,
+				 sizeof composite_manufacturer,
+				 "%s %s with %s",
+				 init_utsname()->sysname,
+				 init_utsname()->release,
+				 gadget->name);
 
+		cdev->manufacturer_override =
+			override_id(cdev, &cdev->desc.iManufacturer);
+	}
+
+	if (iProduct || (!cdev->desc.iProduct && composite->iProduct))
+		cdev->product_override =
+			override_id(cdev, &cdev->desc.iProduct);
+
+	if (iSerialNumber)
+		cdev->serial_override =
+			override_id(cdev, &cdev->desc.iSerialNumber);
+
+	/* has userspace failed to provide a serial number? */
+	if (composite->needs_serial && !cdev->desc.iSerialNumber)
+		WARNING(cdev, "userspace failed to provide iSerialNumber\n");
+
+	/* finish up */
 	status = device_create_file(&gadget->dev, &dev_attr_suspended);
 	if (status)
 		goto fail;
@@ -1177,7 +1217,6 @@
 static struct usb_gadget_driver composite_driver = {
 	.speed		= USB_SPEED_HIGH,
 
-	.bind		= composite_bind,
 	.unbind		= composite_unbind,
 
 	.setup		= composite_setup,
@@ -1192,8 +1231,12 @@
 };
 
 /**
- * usb_composite_register() - register a composite driver
+ * usb_composite_probe() - register a composite driver
  * @driver: the driver to register
+ * @bind: the callback used to allocate resources that are shared across the
+ *	whole device, such as string IDs, and add its configurations using
+ *	@usb_add_config().  This may fail by returning a negative errno
+ *	value; it should return zero on successful initialization.
  * Context: single threaded during gadget setup
  *
  * This function is used to register drivers using the composite driver
@@ -1206,18 +1249,22 @@
  * while it was binding.  That would usually be done in order to wait for
  * some userspace participation.
  */
-int usb_composite_register(struct usb_composite_driver *driver)
+extern int usb_composite_probe(struct usb_composite_driver *driver,
+			       int (*bind)(struct usb_composite_dev *cdev))
 {
-	if (!driver || !driver->dev || !driver->bind || composite)
+	if (!driver || !driver->dev || !bind || composite)
 		return -EINVAL;
 
+	if (!driver->iProduct)
+		driver->iProduct = driver->name;
 	if (!driver->name)
 		driver->name = "composite";
 	composite_driver.function =  (char *) driver->name;
 	composite_driver.driver.name = driver->name;
 	composite = driver;
+	composite_gadget_bind = bind;
 
-	return usb_gadget_register_driver(&composite_driver);
+	return usb_gadget_probe_driver(&composite_driver, composite_bind);
 }
 
 /**
diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c
index 0ed50a2..e5ac8a3 100644
--- a/drivers/usb/gadget/dbgp.c
+++ b/drivers/usb/gadget/dbgp.c
@@ -386,15 +386,13 @@
 	} else
 		goto fail;
 
-	if (len >= 0) {
-		req->length = min(length, len);
-		req->zero = len < req->length;
-		if (data && req->length)
-			memcpy(req->buf, data, req->length);
+	req->length = min(length, len);
+	req->zero = len < req->length;
+	if (data && req->length)
+		memcpy(req->buf, data, req->length);
 
-		req->complete = dbgp_setup_complete;
-		return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
-	}
+	req->complete = dbgp_setup_complete;
+	return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
 
 fail:
 	dev_dbg(&dbgp.gadget->dev,
@@ -405,7 +403,6 @@
 static struct usb_gadget_driver dbgp_driver = {
 	.function = "dbgp",
 	.speed = USB_SPEED_HIGH,
-	.bind = dbgp_bind,
 	.unbind = dbgp_unbind,
 	.setup = dbgp_setup,
 	.disconnect = dbgp_disconnect,
@@ -417,7 +414,7 @@
 
 static int __init dbgp_init(void)
 {
-	return usb_gadget_register_driver(&dbgp_driver);
+	return usb_gadget_probe_driver(&dbgp_driver, dbgp_bind);
 }
 
 static void __exit dbgp_exit(void)
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index dc65462..1d2a2ab 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -748,7 +748,8 @@
  */
 
 int
-usb_gadget_register_driver (struct usb_gadget_driver *driver)
+usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct dummy	*dum = the_controller;
 	int		retval, i;
@@ -757,8 +758,7 @@
 		return -EINVAL;
 	if (dum->driver)
 		return -EBUSY;
-	if (!driver->bind || !driver->setup
-			|| driver->speed == USB_SPEED_UNKNOWN)
+	if (!bind || !driver->setup || driver->speed == USB_SPEED_UNKNOWN)
 		return -EINVAL;
 
 	/*
@@ -796,7 +796,7 @@
 	dum->gadget.dev.driver = &driver->driver;
 	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
-	retval = driver->bind(&dum->gadget);
+	retval = bind(&dum->gadget);
 	if (retval) {
 		dum->driver = NULL;
 		dum->gadget.dev.driver = NULL;
@@ -812,7 +812,7 @@
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
 }
-EXPORT_SYMBOL (usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int
 usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
@@ -874,6 +874,8 @@
 	struct dummy	*dum = the_controller;
 	int		rc;
 
+	usb_get_hcd(dummy_to_hcd(dum));
+
 	dum->gadget.name = gadget_name;
 	dum->gadget.ops = &dummy_ops;
 	dum->gadget.is_dualspeed = 1;
@@ -885,10 +887,10 @@
 	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.release = dummy_gadget_release;
 	rc = device_register (&dum->gadget.dev);
-	if (rc < 0)
+	if (rc < 0) {
+		put_device(&dum->gadget.dev);
 		return rc;
-
-	usb_get_hcd (dummy_to_hcd (dum));
+	}
 
 	platform_set_drvdata (pdev, dum);
 	rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 114fa02..1690c9d 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -237,7 +237,7 @@
  * the first one present.  That's to make Microsoft's drivers happy,
  * and to follow DOCSIS 1.0 (cable modem standard).
  */
-static int __ref rndis_do_config(struct usb_configuration *c)
+static int __init rndis_do_config(struct usb_configuration *c)
 {
 	/* FIXME alloc iConfiguration string, set it in c->strings */
 
@@ -251,7 +251,6 @@
 
 static struct usb_configuration rndis_config_driver = {
 	.label			= "RNDIS",
-	.bind			= rndis_do_config,
 	.bConfigurationValue	= 2,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -270,7 +269,7 @@
 /*
  * We _always_ have an ECM, CDC Subset, or EEM configuration.
  */
-static int __ref eth_do_config(struct usb_configuration *c)
+static int __init eth_do_config(struct usb_configuration *c)
 {
 	/* FIXME alloc iConfiguration string, set it in c->strings */
 
@@ -289,7 +288,6 @@
 
 static struct usb_configuration eth_config_driver = {
 	/* .label = f(hardware) */
-	.bind			= eth_do_config,
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -297,7 +295,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref eth_bind(struct usb_composite_dev *cdev)
+static int __init eth_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -373,12 +371,13 @@
 
 	/* register our configuration(s); RNDIS first, if it's used */
 	if (has_rndis()) {
-		status = usb_add_config(cdev, &rndis_config_driver);
+		status = usb_add_config(cdev, &rndis_config_driver,
+				rndis_do_config);
 		if (status < 0)
 			goto fail;
 	}
 
-	status = usb_add_config(cdev, &eth_config_driver);
+	status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
 	if (status < 0)
 		goto fail;
 
@@ -402,7 +401,6 @@
 	.name		= "g_ether",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= eth_bind,
 	.unbind		= __exit_p(eth_unbind),
 };
 
@@ -412,7 +410,7 @@
 
 static int __init init(void)
 {
-	return usb_composite_register(&eth_driver);
+	return usb_composite_probe(&eth_driver, eth_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index d47a123..bd6226c 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -111,7 +111,7 @@
 	.bInterfaceCount = 	2,	// control + data
 	.bFunctionClass =	USB_CLASS_COMM,
 	.bFunctionSubClass =	USB_CDC_SUBCLASS_ACM,
-	.bFunctionProtocol =	USB_CDC_PROTO_NONE,
+	.bFunctionProtocol =	USB_CDC_ACM_PROTO_AT_V25TER,
 	/* .iFunction =		DYNAMIC */
 };
 
diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c
index 53e1202..2b98bd2 100644
--- a/drivers/usb/gadget/f_hid.c
+++ b/drivers/usb/gadget/f_hid.c
@@ -451,6 +451,7 @@
 	.write		= f_hidg_write,
 	.read		= f_hidg_read,
 	.poll		= f_hidg_poll,
+	.llseek		= noop_llseek,
 };
 
 static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 4322587..b37960f 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -324,7 +324,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref loopback_bind_config(struct usb_configuration *c)
+static int __init loopback_bind_config(struct usb_configuration *c)
 {
 	struct f_loopback	*loop;
 	int			status;
@@ -346,10 +346,9 @@
 	return status;
 }
 
-static  struct usb_configuration loopback_driver = {
+static struct usb_configuration loopback_driver = {
 	.label		= "loopback",
 	.strings	= loopback_strings,
-	.bind		= loopback_bind_config,
 	.bConfigurationValue = 2,
 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
 	/* .iConfiguration = DYNAMIC */
@@ -382,5 +381,5 @@
 		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	return usb_add_config(cdev, &loopback_driver);
+	return usb_add_config(cdev, &loopback_driver, loopback_bind_config);
 }
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 32cce02..838286b 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -73,6 +73,8 @@
  *				being removable.
  *	->cdrom		Flag specifying that LUN shall be reported as
  *				being a CD-ROM.
+ *	->nofua		Flag specifying that FUA flag in SCSI WRITE(10,12)
+ *				commands for this LUN shall be ignored.
  *
  *	lun_name_format	A printf-like format for names of the LUN
  *				devices.  This determines how the
@@ -127,6 +129,8 @@
  *			Default true, boolean for removable media.
  *	cdrom=b[,b...]	Default false, boolean for whether to emulate
  *				a CD-ROM drive.
+ *	nofua=b[,b...]	Default false, booleans for ignore FUA flag
+ *				in SCSI WRITE(10,12) commands
  *	luns=N		Default N = number of filenames, number of
  *				LUNs to support.
  *	stall		Default determined according to the type of
@@ -409,6 +413,7 @@
 		char ro;
 		char removable;
 		char cdrom;
+		char nofua;
 	} luns[FSG_MAX_LUNS];
 
 	const char		*lun_name_format;
@@ -736,7 +741,7 @@
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
-	if (common->cmnd[0] == SC_READ_6)
+	if (common->cmnd[0] == READ_6)
 		lba = get_unaligned_be24(&common->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&common->cmnd[2]);
@@ -874,7 +879,7 @@
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
-	if (common->cmnd[0] == SC_WRITE_6)
+	if (common->cmnd[0] == WRITE_6)
 		lba = get_unaligned_be24(&common->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&common->cmnd[2]);
@@ -887,7 +892,7 @@
 			curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			return -EINVAL;
 		}
-		if (common->cmnd[1] & 0x08) {	/* FUA */
+		if (!curlun->nofua && (common->cmnd[1] & 0x08)) { /* FUA */
 			spin_lock(&curlun->filp->f_lock);
 			curlun->filp->f_flags |= O_SYNC;
 			spin_unlock(&curlun->filp->f_lock);
@@ -1181,7 +1186,7 @@
 		return 36;
 	}
 
-	buf[0] = curlun->cdrom ? TYPE_CDROM : TYPE_DISK;
+	buf[0] = curlun->cdrom ? TYPE_ROM : TYPE_DISK;
 	buf[1] = curlun->removable ? 0x80 : 0;
 	buf[2] = 2;		/* ANSI SCSI level 2 */
 	buf[3] = 2;		/* SCSI-2 INQUIRY data format */
@@ -1348,11 +1353,11 @@
 	 * The only variable value is the WriteProtect bit.  We will fill in
 	 * the mode data length later. */
 	memset(buf, 0, 8);
-	if (mscmnd == SC_MODE_SENSE_6) {
+	if (mscmnd == MODE_SENSE) {
 		buf[2] = (curlun->ro ? 0x80 : 0x00);		/* WP, DPOFUA */
 		buf += 4;
 		limit = 255;
-	} else {			/* SC_MODE_SENSE_10 */
+	} else {			/* MODE_SENSE_10 */
 		buf[3] = (curlun->ro ? 0x80 : 0x00);		/* WP, DPOFUA */
 		buf += 8;
 		limit = 65535;		/* Should really be FSG_BUFLEN */
@@ -1392,7 +1397,7 @@
 	}
 
 	/*  Store the mode data length */
-	if (mscmnd == SC_MODE_SENSE_6)
+	if (mscmnd == MODE_SENSE)
 		buf0[0] = len - 1;
 	else
 		put_unaligned_be16(len - 2, buf0);
@@ -1881,7 +1886,7 @@
 	if (common->lun >= 0 && common->lun < common->nluns) {
 		curlun = &common->luns[common->lun];
 		common->curlun = curlun;
-		if (common->cmnd[0] != SC_REQUEST_SENSE) {
+		if (common->cmnd[0] != REQUEST_SENSE) {
 			curlun->sense_data = SS_NO_SENSE;
 			curlun->sense_data_info = 0;
 			curlun->info_valid = 0;
@@ -1893,8 +1898,8 @@
 
 		/* INQUIRY and REQUEST SENSE commands are explicitly allowed
 		 * to use unsupported LUNs; all others may not. */
-		if (common->cmnd[0] != SC_INQUIRY &&
-		    common->cmnd[0] != SC_REQUEST_SENSE) {
+		if (common->cmnd[0] != INQUIRY &&
+		    common->cmnd[0] != REQUEST_SENSE) {
 			DBG(common, "unsupported LUN %d\n", common->lun);
 			return -EINVAL;
 		}
@@ -1903,8 +1908,8 @@
 	/* If a unit attention condition exists, only INQUIRY and
 	 * REQUEST SENSE commands are allowed; anything else must fail. */
 	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
-			common->cmnd[0] != SC_INQUIRY &&
-			common->cmnd[0] != SC_REQUEST_SENSE) {
+			common->cmnd[0] != INQUIRY &&
+			common->cmnd[0] != REQUEST_SENSE) {
 		curlun->sense_data = curlun->unit_attention_data;
 		curlun->unit_attention_data = SS_NO_SENSE;
 		return -EINVAL;
@@ -1955,7 +1960,7 @@
 	down_read(&common->filesem);	/* We're using the backing file */
 	switch (common->cmnd[0]) {
 
-	case SC_INQUIRY:
+	case INQUIRY:
 		common->data_size_from_cmnd = common->cmnd[4];
 		reply = check_command(common, 6, DATA_DIR_TO_HOST,
 				      (1<<4), 0,
@@ -1964,7 +1969,7 @@
 			reply = do_inquiry(common, bh);
 		break;
 
-	case SC_MODE_SELECT_6:
+	case MODE_SELECT:
 		common->data_size_from_cmnd = common->cmnd[4];
 		reply = check_command(common, 6, DATA_DIR_FROM_HOST,
 				      (1<<1) | (1<<4), 0,
@@ -1973,7 +1978,7 @@
 			reply = do_mode_select(common, bh);
 		break;
 
-	case SC_MODE_SELECT_10:
+	case MODE_SELECT_10:
 		common->data_size_from_cmnd =
 			get_unaligned_be16(&common->cmnd[7]);
 		reply = check_command(common, 10, DATA_DIR_FROM_HOST,
@@ -1983,7 +1988,7 @@
 			reply = do_mode_select(common, bh);
 		break;
 
-	case SC_MODE_SENSE_6:
+	case MODE_SENSE:
 		common->data_size_from_cmnd = common->cmnd[4];
 		reply = check_command(common, 6, DATA_DIR_TO_HOST,
 				      (1<<1) | (1<<2) | (1<<4), 0,
@@ -1992,7 +1997,7 @@
 			reply = do_mode_sense(common, bh);
 		break;
 
-	case SC_MODE_SENSE_10:
+	case MODE_SENSE_10:
 		common->data_size_from_cmnd =
 			get_unaligned_be16(&common->cmnd[7]);
 		reply = check_command(common, 10, DATA_DIR_TO_HOST,
@@ -2002,7 +2007,7 @@
 			reply = do_mode_sense(common, bh);
 		break;
 
-	case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
+	case ALLOW_MEDIUM_REMOVAL:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 6, DATA_DIR_NONE,
 				      (1<<4), 0,
@@ -2011,7 +2016,7 @@
 			reply = do_prevent_allow(common);
 		break;
 
-	case SC_READ_6:
+	case READ_6:
 		i = common->cmnd[4];
 		common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
 		reply = check_command(common, 6, DATA_DIR_TO_HOST,
@@ -2021,7 +2026,7 @@
 			reply = do_read(common);
 		break;
 
-	case SC_READ_10:
+	case READ_10:
 		common->data_size_from_cmnd =
 				get_unaligned_be16(&common->cmnd[7]) << 9;
 		reply = check_command(common, 10, DATA_DIR_TO_HOST,
@@ -2031,7 +2036,7 @@
 			reply = do_read(common);
 		break;
 
-	case SC_READ_12:
+	case READ_12:
 		common->data_size_from_cmnd =
 				get_unaligned_be32(&common->cmnd[6]) << 9;
 		reply = check_command(common, 12, DATA_DIR_TO_HOST,
@@ -2041,7 +2046,7 @@
 			reply = do_read(common);
 		break;
 
-	case SC_READ_CAPACITY:
+	case READ_CAPACITY:
 		common->data_size_from_cmnd = 8;
 		reply = check_command(common, 10, DATA_DIR_TO_HOST,
 				      (0xf<<2) | (1<<8), 1,
@@ -2050,7 +2055,7 @@
 			reply = do_read_capacity(common, bh);
 		break;
 
-	case SC_READ_HEADER:
+	case READ_HEADER:
 		if (!common->curlun || !common->curlun->cdrom)
 			goto unknown_cmnd;
 		common->data_size_from_cmnd =
@@ -2062,7 +2067,7 @@
 			reply = do_read_header(common, bh);
 		break;
 
-	case SC_READ_TOC:
+	case READ_TOC:
 		if (!common->curlun || !common->curlun->cdrom)
 			goto unknown_cmnd;
 		common->data_size_from_cmnd =
@@ -2074,7 +2079,7 @@
 			reply = do_read_toc(common, bh);
 		break;
 
-	case SC_READ_FORMAT_CAPACITIES:
+	case READ_FORMAT_CAPACITIES:
 		common->data_size_from_cmnd =
 			get_unaligned_be16(&common->cmnd[7]);
 		reply = check_command(common, 10, DATA_DIR_TO_HOST,
@@ -2084,7 +2089,7 @@
 			reply = do_read_format_capacities(common, bh);
 		break;
 
-	case SC_REQUEST_SENSE:
+	case REQUEST_SENSE:
 		common->data_size_from_cmnd = common->cmnd[4];
 		reply = check_command(common, 6, DATA_DIR_TO_HOST,
 				      (1<<4), 0,
@@ -2093,7 +2098,7 @@
 			reply = do_request_sense(common, bh);
 		break;
 
-	case SC_START_STOP_UNIT:
+	case START_STOP:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 6, DATA_DIR_NONE,
 				      (1<<1) | (1<<4), 0,
@@ -2102,7 +2107,7 @@
 			reply = do_start_stop(common);
 		break;
 
-	case SC_SYNCHRONIZE_CACHE:
+	case SYNCHRONIZE_CACHE:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 10, DATA_DIR_NONE,
 				      (0xf<<2) | (3<<7), 1,
@@ -2111,7 +2116,7 @@
 			reply = do_synchronize_cache(common);
 		break;
 
-	case SC_TEST_UNIT_READY:
+	case TEST_UNIT_READY:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 6, DATA_DIR_NONE,
 				0, 1,
@@ -2120,7 +2125,7 @@
 
 	/* Although optional, this command is used by MS-Windows.  We
 	 * support a minimal version: BytChk must be 0. */
-	case SC_VERIFY:
+	case VERIFY:
 		common->data_size_from_cmnd = 0;
 		reply = check_command(common, 10, DATA_DIR_NONE,
 				      (1<<1) | (0xf<<2) | (3<<7), 1,
@@ -2129,7 +2134,7 @@
 			reply = do_verify(common);
 		break;
 
-	case SC_WRITE_6:
+	case WRITE_6:
 		i = common->cmnd[4];
 		common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
 		reply = check_command(common, 6, DATA_DIR_FROM_HOST,
@@ -2139,7 +2144,7 @@
 			reply = do_write(common);
 		break;
 
-	case SC_WRITE_10:
+	case WRITE_10:
 		common->data_size_from_cmnd =
 				get_unaligned_be16(&common->cmnd[7]) << 9;
 		reply = check_command(common, 10, DATA_DIR_FROM_HOST,
@@ -2149,7 +2154,7 @@
 			reply = do_write(common);
 		break;
 
-	case SC_WRITE_12:
+	case WRITE_12:
 		common->data_size_from_cmnd =
 				get_unaligned_be32(&common->cmnd[6]) << 9;
 		reply = check_command(common, 12, DATA_DIR_FROM_HOST,
@@ -2163,10 +2168,10 @@
 	 * They don't mean much in this setting.  It's left as an exercise
 	 * for anyone interested to implement RESERVE and RELEASE in terms
 	 * of Posix locks. */
-	case SC_FORMAT_UNIT:
-	case SC_RELEASE:
-	case SC_RESERVE:
-	case SC_SEND_DIAGNOSTIC:
+	case FORMAT_UNIT:
+	case RELEASE:
+	case RESERVE:
+	case SEND_DIAGNOSTIC:
 		/* Fall through */
 
 	default:
@@ -2662,6 +2667,7 @@
 
 /* Write permission is checked per LUN in store_*() functions. */
 static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro);
+static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua);
 static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file);
 
 
@@ -2768,6 +2774,9 @@
 		rc = device_create_file(&curlun->dev, &dev_attr_file);
 		if (rc)
 			goto error_luns;
+		rc = device_create_file(&curlun->dev, &dev_attr_nofua);
+		if (rc)
+			goto error_luns;
 
 		if (lcfg->filename) {
 			rc = fsg_lun_open(curlun, lcfg->filename);
@@ -2911,6 +2920,7 @@
 
 		/* In error recovery common->nluns may be zero. */
 		for (; i; --i, ++lun) {
+			device_remove_file(&lun->dev, &dev_attr_nofua);
 			device_remove_file(&lun->dev, &dev_attr_ro);
 			device_remove_file(&lun->dev, &dev_attr_file);
 			fsg_lun_close(lun);
@@ -3069,8 +3079,10 @@
 	int		ro[FSG_MAX_LUNS];
 	int		removable[FSG_MAX_LUNS];
 	int		cdrom[FSG_MAX_LUNS];
+	int		nofua[FSG_MAX_LUNS];
 
 	unsigned int	file_count, ro_count, removable_count, cdrom_count;
+	unsigned int	nofua_count;
 	unsigned int	luns;	/* nluns */
 	int		stall;	/* can_stall */
 };
@@ -3096,6 +3108,8 @@
 				"true to simulate removable media");	\
 	_FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool,		\
 				"true to simulate CD-ROM instead of disk"); \
+	_FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool,		\
+				"true to ignore SCSI WRITE(10,12) FUA bit"); \
 	_FSG_MODULE_PARAM(prefix, params, luns, uint,			\
 			  "number of LUNs");				\
 	_FSG_MODULE_PARAM(prefix, params, stall, bool,			\
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
index 685d768..e403a53 100644
--- a/drivers/usb/gadget/f_sourcesink.c
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -404,7 +404,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref sourcesink_bind_config(struct usb_configuration *c)
+static int __init sourcesink_bind_config(struct usb_configuration *c)
 {
 	struct f_sourcesink	*ss;
 	int			status;
@@ -498,7 +498,6 @@
 static struct usb_configuration sourcesink_driver = {
 	.label		= "source/sink",
 	.strings	= sourcesink_strings,
-	.bind		= sourcesink_bind_config,
 	.setup		= sourcesink_setup,
 	.bConfigurationValue = 3,
 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
@@ -532,5 +531,5 @@
 		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	return usb_add_config(cdev, &sourcesink_driver);
+	return usb_add_config(cdev, &sourcesink_driver, sourcesink_bind_config);
 }
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index a857b7a..d4fdf65 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -89,6 +89,7 @@
  *				Required if "removable" is not set, names of
  *					the files or block devices used for
  *					backing storage
+ *	serial=HHHH...		Required serial number (string of hex chars)
  *	ro=b[,b...]		Default false, booleans for read-only access
  *	removable		Default false, boolean for removable media
  *	luns=N			Default N = number of filenames, number of
@@ -108,12 +109,11 @@
  *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
  *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
  *	release=0xRRRR		Override the USB release number (bcdDevice)
- *	serial=HHHH...		Override serial number (string of hex chars)
  *	buflen=N		Default N=16384, buffer size used (will be
  *					rounded down to a multiple of
  *					PAGE_CACHE_SIZE)
  *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
+ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
  * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
  * default values are used for everything else.
  *
@@ -273,13 +273,10 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-/* DRIVER_VERSION must be at least 6 characters long, as it is used
- * to generate a fallback serial number. */
-#define DRIVER_VERSION		"20 November 2008"
+#define DRIVER_VERSION		"1 September 2010"
 
 static       char fsg_string_manufacturer[64];
 static const char fsg_string_product[] = DRIVER_DESC;
-static       char fsg_string_serial[13];
 static const char fsg_string_config[] = "Self-powered";
 static const char fsg_string_interface[] = "Mass Storage";
 
@@ -305,6 +302,7 @@
 
 static struct {
 	char		*file[FSG_MAX_LUNS];
+	char		*serial;
 	int		ro[FSG_MAX_LUNS];
 	int		nofua[FSG_MAX_LUNS];
 	unsigned int	num_filenames;
@@ -321,7 +319,6 @@
 	unsigned short	vendor;
 	unsigned short	product;
 	unsigned short	release;
-	char		*serial;
 	unsigned int	buflen;
 
 	int		transport_type;
@@ -346,6 +343,9 @@
 		S_IRUGO);
 MODULE_PARM_DESC(file, "names of backing files or devices");
 
+module_param_named(serial, mod_data.serial, charp, S_IRUGO);
+MODULE_PARM_DESC(serial, "USB serial number");
+
 module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
 MODULE_PARM_DESC(ro, "true to force read-only");
 
@@ -365,9 +365,6 @@
 module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
 MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
 
-module_param_named(serial, mod_data.serial, charp, S_IRUGO);
-MODULE_PARM_DESC(serial, "USB serial number");
-
 /* In the non-TEST version, only the module parameters listed above
  * are available. */
 #ifdef CONFIG_USB_FILE_STORAGE_TEST
@@ -786,7 +783,7 @@
 {
 	struct usb_request	*req = fsg->ep0req;
 	static u8		cbi_reset_cmnd[6] = {
-			SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
+			SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
 
 	/* Error in command transfer? */
 	if (req->status || req->length != req->actual ||
@@ -1138,7 +1135,7 @@
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
-	if (fsg->cmnd[0] == SC_READ_6)
+	if (fsg->cmnd[0] == READ_6)
 		lba = get_unaligned_be24(&fsg->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&fsg->cmnd[2]);
@@ -1273,7 +1270,7 @@
 
 	/* Get the starting Logical Block Address and check that it's
 	 * not too big */
-	if (fsg->cmnd[0] == SC_WRITE_6)
+	if (fsg->cmnd[0] == WRITE_6)
 		lba = get_unaligned_be24(&fsg->cmnd[1]);
 	else {
 		lba = get_unaligned_be32(&fsg->cmnd[2]);
@@ -1581,7 +1578,7 @@
 	}
 
 	memset(buf, 0, 8);
-	buf[0] = (mod_data.cdrom ? TYPE_CDROM : TYPE_DISK);
+	buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
 	if (mod_data.removable)
 		buf[1] = 0x80;
 	buf[2] = 2;		// ANSI SCSI level 2
@@ -1750,11 +1747,11 @@
 	 * The only variable value is the WriteProtect bit.  We will fill in
 	 * the mode data length later. */
 	memset(buf, 0, 8);
-	if (mscmnd == SC_MODE_SENSE_6) {
+	if (mscmnd == MODE_SENSE) {
 		buf[2] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA
 		buf += 4;
 		limit = 255;
-	} else {			// SC_MODE_SENSE_10
+	} else {			// MODE_SENSE_10
 		buf[3] = (curlun->ro ? 0x80 : 0x00);		// WP, DPOFUA
 		buf += 8;
 		limit = 65535;		// Should really be mod_data.buflen
@@ -1794,7 +1791,7 @@
 	}
 
 	/*  Store the mode data length */
-	if (mscmnd == SC_MODE_SENSE_6)
+	if (mscmnd == MODE_SENSE)
 		buf0[0] = len - 1;
 	else
 		put_unaligned_be16(len - 2, buf0);
@@ -2319,7 +2316,7 @@
 	/* Check the LUN */
 	if (fsg->lun >= 0 && fsg->lun < fsg->nluns) {
 		fsg->curlun = curlun = &fsg->luns[fsg->lun];
-		if (fsg->cmnd[0] != SC_REQUEST_SENSE) {
+		if (fsg->cmnd[0] != REQUEST_SENSE) {
 			curlun->sense_data = SS_NO_SENSE;
 			curlun->sense_data_info = 0;
 			curlun->info_valid = 0;
@@ -2330,8 +2327,8 @@
 
 		/* INQUIRY and REQUEST SENSE commands are explicitly allowed
 		 * to use unsupported LUNs; all others may not. */
-		if (fsg->cmnd[0] != SC_INQUIRY &&
-				fsg->cmnd[0] != SC_REQUEST_SENSE) {
+		if (fsg->cmnd[0] != INQUIRY &&
+				fsg->cmnd[0] != REQUEST_SENSE) {
 			DBG(fsg, "unsupported LUN %d\n", fsg->lun);
 			return -EINVAL;
 		}
@@ -2340,8 +2337,8 @@
 	/* If a unit attention condition exists, only INQUIRY and
 	 * REQUEST SENSE commands are allowed; anything else must fail. */
 	if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
-			fsg->cmnd[0] != SC_INQUIRY &&
-			fsg->cmnd[0] != SC_REQUEST_SENSE) {
+			fsg->cmnd[0] != INQUIRY &&
+			fsg->cmnd[0] != REQUEST_SENSE) {
 		curlun->sense_data = curlun->unit_attention_data;
 		curlun->unit_attention_data = SS_NO_SENSE;
 		return -EINVAL;
@@ -2391,7 +2388,7 @@
 	down_read(&fsg->filesem);	// We're using the backing file
 	switch (fsg->cmnd[0]) {
 
-	case SC_INQUIRY:
+	case INQUIRY:
 		fsg->data_size_from_cmnd = fsg->cmnd[4];
 		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
 				(1<<4), 0,
@@ -2399,7 +2396,7 @@
 			reply = do_inquiry(fsg, bh);
 		break;
 
-	case SC_MODE_SELECT_6:
+	case MODE_SELECT:
 		fsg->data_size_from_cmnd = fsg->cmnd[4];
 		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
 				(1<<1) | (1<<4), 0,
@@ -2407,7 +2404,7 @@
 			reply = do_mode_select(fsg, bh);
 		break;
 
-	case SC_MODE_SELECT_10:
+	case MODE_SELECT_10:
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
 		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
 				(1<<1) | (3<<7), 0,
@@ -2415,7 +2412,7 @@
 			reply = do_mode_select(fsg, bh);
 		break;
 
-	case SC_MODE_SENSE_6:
+	case MODE_SENSE:
 		fsg->data_size_from_cmnd = fsg->cmnd[4];
 		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
 				(1<<1) | (1<<2) | (1<<4), 0,
@@ -2423,7 +2420,7 @@
 			reply = do_mode_sense(fsg, bh);
 		break;
 
-	case SC_MODE_SENSE_10:
+	case MODE_SENSE_10:
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
 				(1<<1) | (1<<2) | (3<<7), 0,
@@ -2431,7 +2428,7 @@
 			reply = do_mode_sense(fsg, bh);
 		break;
 
-	case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
+	case ALLOW_MEDIUM_REMOVAL:
 		fsg->data_size_from_cmnd = 0;
 		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
 				(1<<4), 0,
@@ -2439,7 +2436,7 @@
 			reply = do_prevent_allow(fsg);
 		break;
 
-	case SC_READ_6:
+	case READ_6:
 		i = fsg->cmnd[4];
 		fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
 		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
@@ -2448,7 +2445,7 @@
 			reply = do_read(fsg);
 		break;
 
-	case SC_READ_10:
+	case READ_10:
 		fsg->data_size_from_cmnd =
 				get_unaligned_be16(&fsg->cmnd[7]) << 9;
 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
@@ -2457,7 +2454,7 @@
 			reply = do_read(fsg);
 		break;
 
-	case SC_READ_12:
+	case READ_12:
 		fsg->data_size_from_cmnd =
 				get_unaligned_be32(&fsg->cmnd[6]) << 9;
 		if ((reply = check_command(fsg, 12, DATA_DIR_TO_HOST,
@@ -2466,7 +2463,7 @@
 			reply = do_read(fsg);
 		break;
 
-	case SC_READ_CAPACITY:
+	case READ_CAPACITY:
 		fsg->data_size_from_cmnd = 8;
 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
 				(0xf<<2) | (1<<8), 1,
@@ -2474,7 +2471,7 @@
 			reply = do_read_capacity(fsg, bh);
 		break;
 
-	case SC_READ_HEADER:
+	case READ_HEADER:
 		if (!mod_data.cdrom)
 			goto unknown_cmnd;
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
@@ -2484,7 +2481,7 @@
 			reply = do_read_header(fsg, bh);
 		break;
 
-	case SC_READ_TOC:
+	case READ_TOC:
 		if (!mod_data.cdrom)
 			goto unknown_cmnd;
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
@@ -2494,7 +2491,7 @@
 			reply = do_read_toc(fsg, bh);
 		break;
 
-	case SC_READ_FORMAT_CAPACITIES:
+	case READ_FORMAT_CAPACITIES:
 		fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
 		if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
 				(3<<7), 1,
@@ -2502,7 +2499,7 @@
 			reply = do_read_format_capacities(fsg, bh);
 		break;
 
-	case SC_REQUEST_SENSE:
+	case REQUEST_SENSE:
 		fsg->data_size_from_cmnd = fsg->cmnd[4];
 		if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
 				(1<<4), 0,
@@ -2510,7 +2507,7 @@
 			reply = do_request_sense(fsg, bh);
 		break;
 
-	case SC_START_STOP_UNIT:
+	case START_STOP:
 		fsg->data_size_from_cmnd = 0;
 		if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
 				(1<<1) | (1<<4), 0,
@@ -2518,7 +2515,7 @@
 			reply = do_start_stop(fsg);
 		break;
 
-	case SC_SYNCHRONIZE_CACHE:
+	case SYNCHRONIZE_CACHE:
 		fsg->data_size_from_cmnd = 0;
 		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
 				(0xf<<2) | (3<<7), 1,
@@ -2526,7 +2523,7 @@
 			reply = do_synchronize_cache(fsg);
 		break;
 
-	case SC_TEST_UNIT_READY:
+	case TEST_UNIT_READY:
 		fsg->data_size_from_cmnd = 0;
 		reply = check_command(fsg, 6, DATA_DIR_NONE,
 				0, 1,
@@ -2535,7 +2532,7 @@
 
 	/* Although optional, this command is used by MS-Windows.  We
 	 * support a minimal version: BytChk must be 0. */
-	case SC_VERIFY:
+	case VERIFY:
 		fsg->data_size_from_cmnd = 0;
 		if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
 				(1<<1) | (0xf<<2) | (3<<7), 1,
@@ -2543,7 +2540,7 @@
 			reply = do_verify(fsg);
 		break;
 
-	case SC_WRITE_6:
+	case WRITE_6:
 		i = fsg->cmnd[4];
 		fsg->data_size_from_cmnd = (i == 0 ? 256 : i) << 9;
 		if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
@@ -2552,7 +2549,7 @@
 			reply = do_write(fsg);
 		break;
 
-	case SC_WRITE_10:
+	case WRITE_10:
 		fsg->data_size_from_cmnd =
 				get_unaligned_be16(&fsg->cmnd[7]) << 9;
 		if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
@@ -2561,7 +2558,7 @@
 			reply = do_write(fsg);
 		break;
 
-	case SC_WRITE_12:
+	case WRITE_12:
 		fsg->data_size_from_cmnd =
 				get_unaligned_be32(&fsg->cmnd[6]) << 9;
 		if ((reply = check_command(fsg, 12, DATA_DIR_FROM_HOST,
@@ -2574,10 +2571,10 @@
 	 * They don't mean much in this setting.  It's left as an exercise
 	 * for anyone interested to implement RESERVE and RELEASE in terms
 	 * of Posix locks. */
-	case SC_FORMAT_UNIT:
-	case SC_RELEASE:
-	case SC_RESERVE:
-	case SC_SEND_DIAGNOSTIC:
+	case FORMAT_UNIT:
+	case RELEASE:
+	case RESERVE:
+	case SEND_DIAGNOSTIC:
 		// Fall through
 
 	default:
@@ -3178,6 +3175,7 @@
 	for (i = 0; i < fsg->nluns; ++i) {
 		curlun = &fsg->luns[i];
 		if (curlun->registered) {
+			device_remove_file(&curlun->dev, &dev_attr_nofua);
 			device_remove_file(&curlun->dev, &dev_attr_ro);
 			device_remove_file(&curlun->dev, &dev_attr_file);
 			fsg_lun_close(curlun);
@@ -3213,7 +3211,6 @@
 {
 	int	prot;
 	int	gcnum;
-	int	i;
 
 	/* Store the default values */
 	mod_data.transport_type = USB_PR_BULK;
@@ -3309,45 +3306,29 @@
 			if ((*ch < '0' || *ch > '9') &&
 			    (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
 				WARNING(fsg,
-					"Invalid serial string character: %c; "
-					"Failing back to default\n",
+					"Invalid serial string character: %c\n",
 					*ch);
-				goto fill_serial;
+				goto no_serial;
 			}
 		}
 		if (len > 126 ||
 		    (mod_data.transport_type == USB_PR_BULK && len < 12) ||
 		    (mod_data.transport_type != USB_PR_BULK && len > 12)) {
-			WARNING(fsg,
-				"Invalid serial string length; "
-				"Failing back to default\n");
-			goto fill_serial;
+			WARNING(fsg, "Invalid serial string length!\n");
+			goto no_serial;
 		}
 		fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
 	} else {
-		WARNING(fsg,
-			"Userspace failed to provide serial number; "
-			"Failing back to default\n");
-fill_serial:
-		/* Serial number not specified or invalid, make our own.
-		 * We just encode it from the driver version string,
-		 * 12 characters to comply with both CB[I] and BBB spec.
-		 * Warning : Two devices running the same kernel will have
-		 * the same fallback serial number. */
-		for (i = 0; i < 12; i += 2) {
-			unsigned char	c = DRIVER_VERSION[i / 2];
-
-			if (!c)
-				break;
-			sprintf(&fsg_string_serial[i], "%02X", c);
-		}
+		WARNING(fsg, "No serial-number string provided!\n");
+ no_serial:
+		device_desc.iSerialNumber = 0;
 	}
 
 	return 0;
 }
 
 
-static int __ref fsg_bind(struct usb_gadget *gadget)
+static int __init fsg_bind(struct usb_gadget *gadget)
 {
 	struct fsg_dev		*fsg = the_fsg;
 	int			rc;
@@ -3607,7 +3588,6 @@
 	.speed		= USB_SPEED_FULL,
 #endif
 	.function	= (char *) fsg_string_product,
-	.bind		= fsg_bind,
 	.unbind		= fsg_unbind,
 	.disconnect	= fsg_disconnect,
 	.setup		= fsg_setup,
@@ -3649,7 +3629,7 @@
 	if ((rc = fsg_alloc()) != 0)
 		return rc;
 	fsg = the_fsg;
-	if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
+	if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
 		kref_put(&fsg->ref, fsg_release);
 	return rc;
 }
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c
index eafa6d2..5bdbfe6 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/fsl_mxc_udc.c
@@ -22,6 +22,10 @@
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_usb_clk;
 
+/* workaround ENGcm09152 for i.MX35 */
+#define USBPHYCTRL_OTGBASE_OFFSET	0x608
+#define USBPHYCTRL_EVDO			(1 << 23)
+
 int fsl_udc_clk_init(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
@@ -84,6 +88,17 @@
 void fsl_udc_clk_finalize(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+#if defined(CONFIG_ARCH_MX35)
+	unsigned int v;
+
+	/* workaround ENGcm09152 for i.MX35 */
+	if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
+		v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+				USBPHYCTRL_OTGBASE_OFFSET));
+		writel(v | USBPHYCTRL_EVDO, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+				USBPHYCTRL_OTGBASE_OFFSET));
+	}
+#endif
 
 	/* ULPI transceivers don't need usbpll */
 	if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index a5ea2c1..792d5ef 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2302,9 +2302,10 @@
 }
 
 /*-------------------------------------------------------------------------
-	Gadget driver register and unregister.
+	Gadget driver probe and unregister.
  --------------------------------------------------------------------------*/
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	int retval;
 	unsigned long flags = 0;
@@ -2315,8 +2316,7 @@
 
 	if (!driver || (driver->speed != USB_SPEED_FULL
 			&& driver->speed != USB_SPEED_HIGH)
-			|| !driver->bind || !driver->disconnect
-			|| !driver->setup)
+			|| !bind || !driver->disconnect || !driver->setup)
 		return -EINVAL;
 
 	if (udc_controller->driver)
@@ -2332,7 +2332,7 @@
 	udc_controller->gadget.speed = (enum usb_device_speed)(driver->speed);
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
-	retval = driver->bind(&udc_controller->gadget);
+	retval = bind(&udc_controller->gadget);
 	if (retval) {
 		dev_err(udc_controller->dev, "bind to %s --> %d",
 				driver->driver.name, retval);
@@ -2353,7 +2353,7 @@
 		udc_controller->gadget.name, driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 08a9a62..c16b402 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -1765,7 +1765,8 @@
  * Hook to gadget drivers
  * Called by initialization code of gadget drivers
 *----------------------------------------------------------------*/
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	int retval = -ENODEV;
 	unsigned long flags = 0;
@@ -1775,8 +1776,7 @@
 
 	if (!driver || (driver->speed != USB_SPEED_FULL
 				&& driver->speed != USB_SPEED_HIGH)
-			|| !driver->bind || !driver->disconnect
-			|| !driver->setup)
+			|| !bind || !driver->disconnect || !driver->setup)
 		return -EINVAL;
 
 	if (udc_controller->driver)
@@ -1792,7 +1792,7 @@
 	spin_unlock_irqrestore(&udc_controller->lock, flags);
 
 	/* bind udc driver to gadget driver */
-	retval = driver->bind(&udc_controller->gadget);
+	retval = bind(&udc_controller->gadget);
 	if (retval) {
 		VDBG("bind to %s --> %d", driver->driver.name, retval);
 		udc_controller->gadget.dev.driver = NULL;
@@ -1814,7 +1814,7 @@
 		       retval);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /* Disconnect from gadget driver */
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index a9474f8..af75e36 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -52,9 +52,8 @@
 MODULE_AUTHOR("Michal Nazarewicz");
 MODULE_LICENSE("GPL");
 
-
-static unsigned short gfs_vendor_id    = 0x0525;	/* XXX NetChip */
-static unsigned short gfs_product_id   = 0xa4ac;	/* XXX */
+#define GFS_VENDOR_ID	0x1d6b	/* Linux Foundation */
+#define GFS_PRODUCT_ID	0x0105	/* FunctionFS Gadget */
 
 static struct usb_device_descriptor gfs_dev_desc = {
 	.bLength		= sizeof gfs_dev_desc,
@@ -63,29 +62,16 @@
 	.bcdUSB			= cpu_to_le16(0x0200),
 	.bDeviceClass		= USB_CLASS_PER_INTERFACE,
 
-	/* Vendor and product id can be overridden by module parameters.  */
-	/* .idVendor		= cpu_to_le16(gfs_vendor_id), */
-	/* .idProduct		= cpu_to_le16(gfs_product_id), */
-	/* .bcdDevice		= f(hardware) */
-	/* .iManufacturer	= DYNAMIC */
-	/* .iProduct		= DYNAMIC */
-	/* NO SERIAL NUMBER */
-	.bNumConfigurations	= 1,
+	.idVendor		= cpu_to_le16(GFS_VENDOR_ID),
+	.idProduct		= cpu_to_le16(GFS_PRODUCT_ID),
 };
 
-#define GFS_MODULE_PARAM_DESC(name, field) \
-	MODULE_PARM_DESC(name, "Value of the " #field " field of the device descriptor sent to the host.  Takes effect only prior to the user-space driver registering to the FunctionFS.")
-
-module_param_named(usb_class,    gfs_dev_desc.bDeviceClass,    byte,   0644);
-GFS_MODULE_PARAM_DESC(usb_class, bDeviceClass);
-module_param_named(usb_subclass, gfs_dev_desc.bDeviceSubClass, byte,   0644);
-GFS_MODULE_PARAM_DESC(usb_subclass, bDeviceSubClass);
-module_param_named(usb_protocol, gfs_dev_desc.bDeviceProtocol, byte,   0644);
-GFS_MODULE_PARAM_DESC(usb_protocol, bDeviceProtocol);
-module_param_named(usb_vendor,   gfs_vendor_id,                ushort, 0644);
-GFS_MODULE_PARAM_DESC(usb_vendor, idVendor);
-module_param_named(usb_product,  gfs_product_id,               ushort, 0644);
-GFS_MODULE_PARAM_DESC(usb_product, idProduct);
+module_param_named(bDeviceClass,    gfs_dev_desc.bDeviceClass,    byte,   0644);
+MODULE_PARM_DESC(bDeviceClass, "USB Device class");
+module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte,   0644);
+MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
+module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte,   0644);
+MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
 
 
 
@@ -95,8 +81,10 @@
 		.bLength		= sizeof(struct usb_otg_descriptor),
 		.bDescriptorType	= USB_DT_OTG,
 
-		/* REVISIT SRP-only hardware is possible, although
-		 * it would not be called "OTG" ... */
+		/*
+		 * REVISIT SRP-only hardware is possible, although
+		 * it would not be called "OTG" ...
+		 */
 		.bmAttributes		= USB_OTG_SRP | USB_OTG_HNP,
 	},
 
@@ -105,19 +93,7 @@
 
 /* string IDs are assigned dynamically */
 
-enum {
-	GFS_STRING_MANUFACTURER_IDX,
-	GFS_STRING_PRODUCT_IDX,
-	GFS_STRING_FIRST_CONFIG_IDX,
-};
-
-static       char gfs_manufacturer[50];
-static const char gfs_driver_desc[] = DRIVER_DESC;
-static const char gfs_short_name[]  = DRIVER_NAME;
-
 static struct usb_string gfs_strings[] = {
-	[GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer,
-	[GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc,
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
 	{ .s = "FunctionFS + RNDIS" },
 #endif
@@ -168,11 +144,11 @@
 static int gfs_do_config(struct usb_configuration *c);
 
 static struct usb_composite_driver gfs_driver = {
-	.name		= gfs_short_name,
+	.name		= DRIVER_NAME,
 	.dev		= &gfs_dev_desc,
 	.strings	= gfs_dev_strings,
-	.bind		= gfs_bind,
 	.unbind		= gfs_unbind,
+	.iProduct	= DRIVER_DESC,
 };
 
 
@@ -210,7 +186,7 @@
 		return -EBUSY;
 
 	gfs_ffs_data = ffs;
-	ret = usb_composite_register(&gfs_driver);
+	ret = usb_composite_probe(&gfs_driver, gfs_bind);
 	if (unlikely(ret < 0))
 		clear_bit(0, &gfs_registered);
 	return ret;
@@ -245,20 +221,10 @@
 	if (unlikely(ret < 0))
 		goto error_quick;
 
-	gfs_dev_desc.idVendor  = cpu_to_le16(gfs_vendor_id);
-	gfs_dev_desc.idProduct = cpu_to_le16(gfs_product_id);
-
-	snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s",
-		 init_utsname()->sysname, init_utsname()->release,
-		 cdev->gadget->name);
-
 	ret = usb_string_ids_tab(cdev, gfs_strings);
 	if (unlikely(ret < 0))
 		goto error;
 
-	gfs_dev_desc.iManufacturer = gfs_strings[GFS_STRING_MANUFACTURER_IDX].id;
-	gfs_dev_desc.iProduct      = gfs_strings[GFS_STRING_PRODUCT_IDX].id;
-
 	ret = functionfs_bind(gfs_ffs_data, cdev);
 	if (unlikely(ret < 0))
 		goto error;
@@ -266,14 +232,12 @@
 	for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
 		struct gfs_configuration *c = gfs_configurations + i;
 
-		ret = GFS_STRING_FIRST_CONFIG_IDX + i;
-		c->c.label			= gfs_strings[ret].s;
-		c->c.iConfiguration		= gfs_strings[ret].id;
-		c->c.bind			= gfs_do_config;
+		c->c.label			= gfs_strings[i].s;
+		c->c.iConfiguration		= gfs_strings[i].id;
 		c->c.bConfigurationValue	= 1 + i;
 		c->c.bmAttributes		= USB_CONFIG_ATT_SELFPOWER;
 
-		ret = usb_add_config(cdev, &c->c);
+		ret = usb_add_config(cdev, &c->c, gfs_do_config);
 		if (unlikely(ret < 0))
 			goto error_unbind;
 	}
@@ -293,13 +257,14 @@
 {
 	ENTER();
 
-	/* We may have been called in an error recovery frem
+	/*
+	 * We may have been called in an error recovery from
 	 * composite_bind() after gfs_unbind() failure so we need to
 	 * check if gfs_ffs_data is not NULL since gfs_bind() handles
 	 * all error recovery itself.  I'd rather we werent called
 	 * from composite on orror recovery, but what you're gonna
-	 * do...? */
-
+	 * do...?
+	 */
 	if (gfs_ffs_data) {
 		gether_cleanup();
 		functionfs_unbind(gfs_ffs_data);
@@ -334,14 +299,16 @@
 	if (unlikely(ret < 0))
 		return ret;
 
-	/* After previous do_configs there may be some invalid
+	/*
+	 * After previous do_configs there may be some invalid
 	 * pointers in c->interface array.  This happens every time
 	 * a user space function with fewer interfaces than a user
 	 * space function that was run before the new one is run.  The
 	 * compasit's set_config() assumes that if there is no more
 	 * then MAX_CONFIG_INTERFACES interfaces in a configuration
 	 * then there is a NULL pointer after the last interface in
-	 * c->interface array.  We need to make sure this is true. */
+	 * c->interface array.  We need to make sure this is true.
+	 */
 	if (c->next_interface_id < ARRAY_SIZE(c->interface))
 		c->interface[c->next_interface_id] = NULL;
 
@@ -350,10 +317,12 @@
 
 
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
+
 static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 {
 	return can_support_ecm(c->cdev->gadget)
 		? ecm_bind_config(c, ethaddr)
 		: geth_bind_config(c, ethaddr);
 }
+
 #endif
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 1b413a5c..0ab7e14 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -1157,7 +1157,7 @@
 /*
  * Creates an output endpoint, and initializes output ports.
  */
-static int __ref 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;
@@ -1292,7 +1292,6 @@
 static struct usb_gadget_driver gmidi_driver = {
 	.speed		= USB_SPEED_FULL,
 	.function	= (char *)longname,
-	.bind		= gmidi_bind,
 	.unbind		= gmidi_unbind,
 
 	.setup		= gmidi_setup,
@@ -1309,7 +1308,7 @@
 
 static int __init gmidi_init(void)
 {
-	return usb_gadget_register_driver(&gmidi_driver);
+	return usb_gadget_probe_driver(&gmidi_driver, gmidi_bind);
 }
 module_init(gmidi_init);
 
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 1088d08..48a76022 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1343,14 +1343,15 @@
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct goku_udc	*dev = the_controller;
 	int			retval;
 
 	if (!driver
 			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
+			|| !bind
 			|| !driver->disconnect
 			|| !driver->setup)
 		return -EINVAL;
@@ -1363,7 +1364,7 @@
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
 		DBG(dev, "bind to driver %s --> error %d\n",
 				driver->driver.name, retval);
@@ -1380,7 +1381,7 @@
 	DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
 	return 0;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void
 stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
@@ -1744,7 +1745,8 @@
 				pci_resource_len (pdev, 0));
 	if (dev->enabled)
 		pci_disable_device(pdev);
-	device_unregister(&dev->gadget.dev);
+	if (dev->registered)
+		device_unregister(&dev->gadget.dev);
 
 	pci_set_drvdata(pdev, NULL);
 	dev->regs = NULL;
@@ -1774,7 +1776,7 @@
 	if (!pdev->irq) {
 		printk(KERN_ERR "Check PCI %s IRQ setup!\n", pci_name(pdev));
 		retval = -ENODEV;
-		goto done;
+		goto err;
 	}
 
 	/* alloc, and start init */
@@ -1782,7 +1784,7 @@
 	if (dev == NULL){
 		pr_debug("enomem %s\n", pci_name(pdev));
 		retval = -ENOMEM;
-		goto done;
+		goto err;
 	}
 
 	spin_lock_init(&dev->lock);
@@ -1800,7 +1802,7 @@
 	retval = pci_enable_device(pdev);
 	if (retval < 0) {
 		DBG(dev, "can't enable, %d\n", retval);
-		goto done;
+		goto err;
 	}
 	dev->enabled = 1;
 
@@ -1809,7 +1811,7 @@
 	if (!request_mem_region(resource, len, driver_name)) {
 		DBG(dev, "controller already in use\n");
 		retval = -EBUSY;
-		goto done;
+		goto err;
 	}
 	dev->got_region = 1;
 
@@ -1817,7 +1819,7 @@
 	if (base == NULL) {
 		DBG(dev, "can't map memory\n");
 		retval = -EFAULT;
-		goto done;
+		goto err;
 	}
 	dev->regs = (struct goku_udc_regs __iomem *) base;
 
@@ -1833,7 +1835,7 @@
 			driver_name, dev) != 0) {
 		DBG(dev, "request interrupt %d failed\n", pdev->irq);
 		retval = -EBUSY;
-		goto done;
+		goto err;
 	}
 	dev->got_irq = 1;
 	if (use_dma)
@@ -1844,13 +1846,16 @@
 	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 #endif
 
-	/* done */
 	the_controller = dev;
 	retval = device_register(&dev->gadget.dev);
-	if (retval == 0)
-		return 0;
+	if (retval) {
+		put_device(&dev->gadget.dev);
+		goto err;
+	}
+	dev->registered = 1;
+	return 0;
 
-done:
+err:
 	if (dev)
 		goku_remove (pdev);
 	return retval;
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index 735495b..2523e54 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -127,7 +127,7 @@
 
 /****************************** Configurations ******************************/
 
-static int __ref do_config(struct usb_configuration *c)
+static int __init do_config(struct usb_configuration *c)
 {
 	struct hidg_func_node *e;
 	int func = 0, status = 0;
@@ -148,7 +148,6 @@
 
 static struct usb_configuration config_driver = {
 	.label			= "HID Gadget",
-	.bind			= do_config,
 	.bConfigurationValue	= 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -156,7 +155,7 @@
 
 /****************************** Gadget Bind ******************************/
 
-static int __ref hid_bind(struct usb_composite_dev *cdev)
+static int __init hid_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
 	struct list_head *tmp;
@@ -201,7 +200,7 @@
 	device_desc.iProduct = status;
 
 	/* register our configuration */
-	status = usb_add_config(cdev, &config_driver);
+	status = usb_add_config(cdev, &config_driver, do_config);
 	if (status < 0)
 		return status;
 
@@ -256,7 +255,6 @@
 	.name		= "g_hid",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= hid_bind,
 	.unbind		= __exit_p(hid_unbind),
 };
 
@@ -282,7 +280,7 @@
 	if (status < 0)
 		return status;
 
-	status = usb_composite_register(&hidg_driver);
+	status = usb_composite_probe(&hidg_driver, hid_bind);
 	if (status < 0)
 		platform_driver_unregister(&hidg_plat_driver);
 
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index e743122..ed02664 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1319,14 +1319,15 @@
  * USB gadged driver functions
  *******************************************************************************
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct imx_udc_struct *imx_usb = &controller;
 	int retval;
 
 	if (!driver
 		|| driver->speed < USB_SPEED_FULL
-		|| !driver->bind
+		|| !bind
 		|| !driver->disconnect
 		|| !driver->setup)
 			return -EINVAL;
@@ -1342,7 +1343,7 @@
 	retval = device_add(&imx_usb->gadget.dev);
 	if (retval)
 		goto fail;
-	retval = driver->bind(&imx_usb->gadget);
+	retval = bind(&imx_usb->gadget);
 	if (retval) {
 		D_ERR(imx_usb->dev, "<%s> bind to driver %s --> error %d\n",
 			__func__, driver->driver.name, retval);
@@ -1362,7 +1363,7 @@
 	imx_usb->gadget.dev.driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index fc35406..d1d72d9 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -33,7 +33,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -1775,7 +1774,6 @@
 	.speed		= USB_SPEED_FULL,
 #endif
 	.function	= (char *) driver_desc,
-	.bind		= gadgetfs_bind,
 	.unbind		= gadgetfs_unbind,
 	.setup		= gadgetfs_setup,
 	.disconnect	= gadgetfs_disconnect,
@@ -1798,7 +1796,6 @@
 
 static struct usb_gadget_driver probe_driver = {
 	.speed		= USB_SPEED_HIGH,
-	.bind		= gadgetfs_probe,
 	.unbind		= gadgetfs_nop,
 	.setup		= (void *)gadgetfs_nop,
 	.disconnect	= gadgetfs_nop,
@@ -1908,7 +1905,7 @@
 
 	/* triggers gadgetfs_bind(); then we can enumerate. */
 	spin_unlock_irq (&dev->lock);
-	value = usb_gadget_register_driver (&gadgetfs_driver);
+	value = usb_gadget_probe_driver(&gadgetfs_driver, gadgetfs_bind);
 	if (value != 0) {
 		kfree (dev->buf);
 		dev->buf = NULL;
@@ -2047,7 +2044,7 @@
 		return -ESRCH;
 
 	/* fake probe to determine $CHIP */
-	(void) usb_gadget_register_driver (&probe_driver);
+	(void) usb_gadget_probe_driver(&probe_driver, gadgetfs_probe);
 	if (!CHIP)
 		return -ENODEV;
 
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index c2d2a20..b8ec954 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -19,7 +19,7 @@
 
 
 /* #undef	DEBUG */
-/* #undef	VERBOSE */
+/* #undef	VERBOSE_DEBUG */
 
 #if defined(CONFIG_USB_LANGWELL_OTG)
 #define	OTG_TRANSCEIVER
@@ -77,141 +77,110 @@
 /*-------------------------------------------------------------------------*/
 /* debugging */
 
-#ifdef	DEBUG
-#define	DBG(dev, fmt, args...) \
-	pr_debug("%s %s: " fmt , driver_name, \
-			pci_name(dev->pdev), ## args)
-#else
-#define	DBG(dev, fmt, args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-
-#ifdef	VERBOSE
-#define	VDBG DBG
-#else
-#define	VDBG(dev, fmt, args...) \
-	do { } while (0)
-#endif	/* VERBOSE */
-
-
-#define	ERROR(dev, fmt, args...) \
-	pr_err("%s %s: " fmt , driver_name, \
-			pci_name(dev->pdev), ## args)
-
-#define	WARNING(dev, fmt, args...) \
-	pr_warning("%s %s: " fmt , driver_name, \
-			pci_name(dev->pdev), ## args)
-
-#define	INFO(dev, fmt, args...) \
-	pr_info("%s %s: " fmt , driver_name, \
-			pci_name(dev->pdev), ## args)
-
-
-#ifdef	VERBOSE
+#ifdef	VERBOSE_DEBUG
 static inline void print_all_registers(struct langwell_udc *dev)
 {
 	int	i;
 
 	/* Capability Registers */
-	printk(KERN_DEBUG "Capability Registers (offset: "
-			"0x%04x, length: 0x%08x)\n",
-			CAP_REG_OFFSET,
-			(u32)sizeof(struct langwell_cap_regs));
-	printk(KERN_DEBUG "caplength=0x%02x\n",
+	dev_dbg(&dev->pdev->dev,
+		"Capability Registers (offset: 0x%04x, length: 0x%08x)\n",
+		CAP_REG_OFFSET, (u32)sizeof(struct langwell_cap_regs));
+	dev_dbg(&dev->pdev->dev, "caplength=0x%02x\n",
 			readb(&dev->cap_regs->caplength));
-	printk(KERN_DEBUG "hciversion=0x%04x\n",
+	dev_dbg(&dev->pdev->dev, "hciversion=0x%04x\n",
 			readw(&dev->cap_regs->hciversion));
-	printk(KERN_DEBUG "hcsparams=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "hcsparams=0x%08x\n",
 			readl(&dev->cap_regs->hcsparams));
-	printk(KERN_DEBUG "hccparams=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "hccparams=0x%08x\n",
 			readl(&dev->cap_regs->hccparams));
-	printk(KERN_DEBUG "dciversion=0x%04x\n",
+	dev_dbg(&dev->pdev->dev, "dciversion=0x%04x\n",
 			readw(&dev->cap_regs->dciversion));
-	printk(KERN_DEBUG "dccparams=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "dccparams=0x%08x\n",
 			readl(&dev->cap_regs->dccparams));
 
 	/* Operational Registers */
-	printk(KERN_DEBUG "Operational Registers (offset: "
-			"0x%04x, length: 0x%08x)\n",
-			OP_REG_OFFSET,
-			(u32)sizeof(struct langwell_op_regs));
-	printk(KERN_DEBUG "extsts=0x%08x\n",
+	dev_dbg(&dev->pdev->dev,
+		"Operational Registers (offset: 0x%04x, length: 0x%08x)\n",
+		OP_REG_OFFSET, (u32)sizeof(struct langwell_op_regs));
+	dev_dbg(&dev->pdev->dev, "extsts=0x%08x\n",
 			readl(&dev->op_regs->extsts));
-	printk(KERN_DEBUG "extintr=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "extintr=0x%08x\n",
 			readl(&dev->op_regs->extintr));
-	printk(KERN_DEBUG "usbcmd=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "usbcmd=0x%08x\n",
 			readl(&dev->op_regs->usbcmd));
-	printk(KERN_DEBUG "usbsts=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "usbsts=0x%08x\n",
 			readl(&dev->op_regs->usbsts));
-	printk(KERN_DEBUG "usbintr=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "usbintr=0x%08x\n",
 			readl(&dev->op_regs->usbintr));
-	printk(KERN_DEBUG "frindex=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "frindex=0x%08x\n",
 			readl(&dev->op_regs->frindex));
-	printk(KERN_DEBUG "ctrldssegment=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "ctrldssegment=0x%08x\n",
 			readl(&dev->op_regs->ctrldssegment));
-	printk(KERN_DEBUG "deviceaddr=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "deviceaddr=0x%08x\n",
 			readl(&dev->op_regs->deviceaddr));
-	printk(KERN_DEBUG "endpointlistaddr=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endpointlistaddr=0x%08x\n",
 			readl(&dev->op_regs->endpointlistaddr));
-	printk(KERN_DEBUG "ttctrl=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "ttctrl=0x%08x\n",
 			readl(&dev->op_regs->ttctrl));
-	printk(KERN_DEBUG "burstsize=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "burstsize=0x%08x\n",
 			readl(&dev->op_regs->burstsize));
-	printk(KERN_DEBUG "txfilltuning=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "txfilltuning=0x%08x\n",
 			readl(&dev->op_regs->txfilltuning));
-	printk(KERN_DEBUG "txttfilltuning=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "txttfilltuning=0x%08x\n",
 			readl(&dev->op_regs->txttfilltuning));
-	printk(KERN_DEBUG "ic_usb=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "ic_usb=0x%08x\n",
 			readl(&dev->op_regs->ic_usb));
-	printk(KERN_DEBUG "ulpi_viewport=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "ulpi_viewport=0x%08x\n",
 			readl(&dev->op_regs->ulpi_viewport));
-	printk(KERN_DEBUG "configflag=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "configflag=0x%08x\n",
 			readl(&dev->op_regs->configflag));
-	printk(KERN_DEBUG "portsc1=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "portsc1=0x%08x\n",
 			readl(&dev->op_regs->portsc1));
-	printk(KERN_DEBUG "devlc=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "devlc=0x%08x\n",
 			readl(&dev->op_regs->devlc));
-	printk(KERN_DEBUG "otgsc=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "otgsc=0x%08x\n",
 			readl(&dev->op_regs->otgsc));
-	printk(KERN_DEBUG "usbmode=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "usbmode=0x%08x\n",
 			readl(&dev->op_regs->usbmode));
-	printk(KERN_DEBUG "endptnak=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptnak=0x%08x\n",
 			readl(&dev->op_regs->endptnak));
-	printk(KERN_DEBUG "endptnaken=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptnaken=0x%08x\n",
 			readl(&dev->op_regs->endptnaken));
-	printk(KERN_DEBUG "endptsetupstat=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptsetupstat=0x%08x\n",
 			readl(&dev->op_regs->endptsetupstat));
-	printk(KERN_DEBUG "endptprime=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptprime=0x%08x\n",
 			readl(&dev->op_regs->endptprime));
-	printk(KERN_DEBUG "endptflush=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptflush=0x%08x\n",
 			readl(&dev->op_regs->endptflush));
-	printk(KERN_DEBUG "endptstat=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptstat=0x%08x\n",
 			readl(&dev->op_regs->endptstat));
-	printk(KERN_DEBUG "endptcomplete=0x%08x\n",
+	dev_dbg(&dev->pdev->dev, "endptcomplete=0x%08x\n",
 			readl(&dev->op_regs->endptcomplete));
 
 	for (i = 0; i < dev->ep_max / 2; i++) {
-		printk(KERN_DEBUG "endptctrl[%d]=0x%08x\n",
+		dev_dbg(&dev->pdev->dev, "endptctrl[%d]=0x%08x\n",
 				i, readl(&dev->op_regs->endptctrl[i]));
 	}
 }
-#endif /* VERBOSE */
+#else
+
+#define	print_all_registers(dev)	do { } while (0)
+
+#endif /* VERBOSE_DEBUG */
 
 
 /*-------------------------------------------------------------------------*/
 
-#define	DIR_STRING(bAddress)	(((bAddress) & USB_DIR_IN) ? "in" : "out")
+#define	is_in(ep)	(((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir ==	\
+			USB_DIR_IN) : (usb_endpoint_dir_in((ep)->desc)))
 
-#define is_in(ep)	(((ep)->ep_num == 0) ? ((ep)->dev->ep0_dir == \
-			USB_DIR_IN) : ((ep)->desc->bEndpointAddress \
-			& USB_DIR_IN) == USB_DIR_IN)
+#define	DIR_STRING(ep)	(is_in(ep) ? "in" : "out")
 
 
-#ifdef	DEBUG
-static char *type_string(u8 bmAttributes)
+static char *type_string(const struct usb_endpoint_descriptor *desc)
 {
-	switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
+	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_BULK:
 		return "bulk";
 	case USB_ENDPOINT_XFER_ISOC:
@@ -222,7 +191,6 @@
 
 	return "control";
 }
-#endif
 
 
 /* configure endpoint control registers */
@@ -233,7 +201,7 @@
 	u32			endptctrl;
 
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
 	if (is_in) {	/* TX */
@@ -250,7 +218,7 @@
 
 	writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -260,7 +228,7 @@
 	struct langwell_ep	*ep;
 	int			i;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* ep0 in and out */
 	for (i = 0; i < 2; i++) {
@@ -274,17 +242,18 @@
 		ep->dqh->dqh_ios = 1;
 		ep->dqh->dqh_mpl = EP0_MAX_PKT_SIZE;
 
-		/* FIXME: enable ep0-in HW zero length termination select */
+		/* enable ep0-in HW zero length termination select */
 		if (is_in(ep))
 			ep->dqh->dqh_zlt = 0;
 		ep->dqh->dqh_mult = 0;
 
+		ep->dqh->dtd_next = DTD_TERM;
+
 		/* configure ep0 control registers */
 		ep_reset(&dev->ep[0], 0, i, USB_ENDPOINT_XFER_CONTROL);
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -300,12 +269,12 @@
 	struct langwell_ep	*ep;
 	u16			max = 0;
 	unsigned long		flags;
-	int			retval = 0;
+	int			i, retval = 0;
 	unsigned char		zlt, ios = 0, mult = 0;
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !desc || ep->desc
 			|| desc->bDescriptorType != USB_DT_ENDPOINT)
@@ -326,7 +295,7 @@
 	 * sanity check type, direction, address, and then
 	 * initialize the endpoint capabilities fields in dQH
 	 */
-	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	switch (usb_endpoint_type(desc)) {
 	case USB_ENDPOINT_XFER_CONTROL:
 		ios = 1;
 		break;
@@ -386,33 +355,36 @@
 
 	spin_lock_irqsave(&dev->lock, flags);
 
-	/* configure endpoint capabilities in dQH */
-	ep->dqh->dqh_ios = ios;
-	ep->dqh->dqh_mpl = cpu_to_le16(max);
-	ep->dqh->dqh_zlt = zlt;
-	ep->dqh->dqh_mult = mult;
-
 	ep->ep.maxpacket = max;
 	ep->desc = desc;
 	ep->stopped = 0;
-	ep->ep_num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	ep->ep_num = usb_endpoint_num(desc);
 
 	/* ep_type */
-	ep->ep_type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+	ep->ep_type = usb_endpoint_type(desc);
 
 	/* configure endpoint control registers */
 	ep_reset(ep, ep->ep_num, is_in(ep), ep->ep_type);
 
-	DBG(dev, "enabled %s (ep%d%s-%s), max %04x\n",
+	/* configure endpoint capabilities in dQH */
+	i = ep->ep_num * 2 + is_in(ep);
+	ep->dqh = &dev->ep_dqh[i];
+	ep->dqh->dqh_ios = ios;
+	ep->dqh->dqh_mpl = cpu_to_le16(max);
+	ep->dqh->dqh_zlt = zlt;
+	ep->dqh->dqh_mult = mult;
+	ep->dqh->dtd_next = DTD_TERM;
+
+	dev_dbg(&dev->pdev->dev, "enabled %s (ep%d%s-%s), max %04x\n",
 			_ep->name,
 			ep->ep_num,
-			DIR_STRING(desc->bEndpointAddress),
-			type_string(desc->bmAttributes),
+			DIR_STRING(ep),
+			type_string(desc),
 			max);
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 done:
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
@@ -428,7 +400,7 @@
 	struct langwell_dtd	*curr_dtd, *next_dtd;
 	int			i;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* remove the req from ep->queue */
 	list_del_init(&req->queue);
@@ -448,7 +420,8 @@
 	}
 
 	if (req->mapped) {
-		dma_unmap_single(&dev->pdev->dev, req->req.dma, req->req.length,
+		dma_unmap_single(&dev->pdev->dev,
+			req->req.dma, req->req.length,
 			is_in(ep) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
 		req->req.dma = DMA_ADDR_INVALID;
 		req->mapped = 0;
@@ -458,9 +431,10 @@
 				is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
 	if (status != -ESHUTDOWN)
-		DBG(dev, "complete %s, req %p, stat %d, len %u/%u\n",
-			ep->ep.name, &req->req, status,
-			req->req.actual, req->req.length);
+		dev_dbg(&dev->pdev->dev,
+				"complete %s, req %p, stat %d, len %u/%u\n",
+				ep->ep.name, &req->req, status,
+				req->req.actual, req->req.length);
 
 	/* don't modify queue heads during completion callback */
 	ep->stopped = 1;
@@ -473,7 +447,7 @@
 	spin_lock(&dev->lock);
 	ep->stopped = stopped;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -511,7 +485,7 @@
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc)
 		return -EINVAL;
@@ -535,8 +509,8 @@
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	DBG(dev, "disabled %s\n", _ep->name);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "disabled %s\n", _ep->name);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 
 	return 0;
 }
@@ -555,7 +529,7 @@
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	req = kzalloc(sizeof(*req), gfp_flags);
 	if (!req)
@@ -564,8 +538,8 @@
 	req->req.dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD(&req->queue);
 
-	VDBG(dev, "alloc request for %s\n", _ep->name);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "alloc request for %s\n", _ep->name);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return &req->req;
 }
 
@@ -580,7 +554,7 @@
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !_req)
 		return;
@@ -591,8 +565,8 @@
 	if (_req)
 		kfree(req);
 
-	VDBG(dev, "free request for %s\n", _ep->name);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "free request for %s\n", _ep->name);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -608,23 +582,24 @@
 	struct langwell_udc	*dev;
 
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	i = ep->ep_num * 2 + is_in(ep);
 	dqh = &dev->ep_dqh[i];
 
 	if (ep->ep_num)
-		VDBG(dev, "%s\n", ep->name);
+		dev_vdbg(&dev->pdev->dev, "%s\n", ep->name);
 	else
 		/* ep0 */
-		VDBG(dev, "%s-%s\n", ep->name, is_in(ep) ? "in" : "out");
+		dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep));
 
-	VDBG(dev, "ep_dqh[%d] addr: 0x%08x\n", i, (u32)&(dev->ep_dqh[i]));
+	dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%08x\n",
+			i, (u32)&(dev->ep_dqh[i]));
 
 	bit_mask = is_in(ep) ?
 		(1 << (ep->ep_num + 16)) : (1 << (ep->ep_num));
 
-	VDBG(dev, "bit_mask = 0x%08x\n", bit_mask);
+	dev_vdbg(&dev->pdev->dev, "bit_mask = 0x%08x\n", bit_mask);
 
 	/* check if the pipe is empty */
 	if (!(list_empty(&ep->queue))) {
@@ -665,14 +640,17 @@
 	/* clear active and halt bit */
 	dtd_status = (u8) ~(DTD_STS_ACTIVE | DTD_STS_HALTED);
 	dqh->dtd_status &= dtd_status;
-	VDBG(dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status);
+	dev_vdbg(&dev->pdev->dev, "dqh->dtd_status = 0x%x\n", dqh->dtd_status);
+
+	/* ensure that updates to the dQH will occure before priming */
+	wmb();
 
 	/* write 1 to endptprime register to PRIME endpoint */
 	bit_mask = is_in(ep) ? (1 << (ep->ep_num + 16)) : (1 << ep->ep_num);
-	VDBG(dev, "endprime bit_mask = 0x%08x\n", bit_mask);
+	dev_vdbg(&dev->pdev->dev, "endprime bit_mask = 0x%08x\n", bit_mask);
 	writel(bit_mask, &dev->op_regs->endptprime);
 out:
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -687,7 +665,7 @@
 	int			i;
 
 	dev = req->ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* the maximum transfer length, up to 16k bytes */
 	*length = min(req->req.length - req->req.actual,
@@ -708,7 +686,7 @@
 
 	/* fill in total bytes with transfer size */
 	dtd->dtd_total = cpu_to_le16(*length);
-	VDBG(dev, "dtd->dtd_total = %d\n", dtd->dtd_total);
+	dev_vdbg(&dev->pdev->dev, "dtd->dtd_total = %d\n", dtd->dtd_total);
 
 	/* set is_last flag if req->req.zero is set or not */
 	if (req->req.zero) {
@@ -722,7 +700,7 @@
 		*is_last = 0;
 
 	if (*is_last == 0)
-		VDBG(dev, "multi-dtd request!\n");
+		dev_vdbg(&dev->pdev->dev, "multi-dtd request!\n");
 
 	/* set interrupt on complete bit for the last dTD */
 	if (*is_last && !req->req.no_interrupt)
@@ -733,10 +711,12 @@
 
 	/* set the active bit of status field to 1 */
 	dtd->dtd_status = DTD_STS_ACTIVE;
-	VDBG(dev, "dtd->dtd_status = 0x%02x\n", dtd->dtd_status);
+	dev_vdbg(&dev->pdev->dev, "dtd->dtd_status = 0x%02x\n",
+			dtd->dtd_status);
 
-	VDBG(dev, "length = %d, dma addr= 0x%08x\n", *length, (int)*dma);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "length = %d, dma addr= 0x%08x\n",
+			*length, (int)*dma);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return dtd;
 }
 
@@ -751,7 +731,7 @@
 	dma_addr_t		dma;
 
 	dev = req->ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 	do {
 		dtd = build_dtd(req, &count, &dma, &is_last);
 		if (dtd == NULL)
@@ -773,7 +753,7 @@
 
 	req->tail = dtd;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -803,9 +783,9 @@
 
 	dev = ep->dev;
 	req->ep = ep;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+	if (usb_endpoint_xfer_isoc(ep->desc)) {
 		if (req->req.length > ep->ep.maxpacket)
 			return -EMSGSIZE;
 		is_iso = 1;
@@ -818,7 +798,7 @@
 	if (_req->dma == DMA_ADDR_INVALID) {
 		/* WORKAROUND: WARN_ON(size == 0) */
 		if (_req->length == 0) {
-			VDBG(dev, "req->length: 0->1\n");
+			dev_vdbg(&dev->pdev->dev, "req->length: 0->1\n");
 			zlflag = 1;
 			_req->length++;
 		}
@@ -827,24 +807,25 @@
 				_req->buf, _req->length,
 				is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 		if (zlflag && (_req->length == 1)) {
-			VDBG(dev, "req->length: 1->0\n");
+			dev_vdbg(&dev->pdev->dev, "req->length: 1->0\n");
 			zlflag = 0;
 			_req->length = 0;
 		}
 
 		req->mapped = 1;
-		VDBG(dev, "req->mapped = 1\n");
+		dev_vdbg(&dev->pdev->dev, "req->mapped = 1\n");
 	} else {
 		dma_sync_single_for_device(&dev->pdev->dev,
 				_req->dma, _req->length,
 				is_in(ep) ?  DMA_TO_DEVICE : DMA_FROM_DEVICE);
 		req->mapped = 0;
-		VDBG(dev, "req->mapped = 0\n");
+		dev_vdbg(&dev->pdev->dev, "req->mapped = 0\n");
 	}
 
-	DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08llx\n",
-	    _ep->name,
-	    _req, _req->length, _req->buf, (unsigned long long)_req->dma);
+	dev_dbg(&dev->pdev->dev,
+			"%s queue req %p, len %u, buf %p, dma 0x%08x\n",
+			_ep->name,
+			_req, _req->length, _req->buf, (int)_req->dma);
 
 	_req->status = -EINPROGRESS;
 	_req->actual = 0;
@@ -866,12 +847,12 @@
 
 	if (likely(req != NULL)) {
 		list_add_tail(&req->queue, &ep->queue);
-		VDBG(dev, "list_add_tail() \n");
+		dev_vdbg(&dev->pdev->dev, "list_add_tail()\n");
 	}
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -888,7 +869,7 @@
 
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc || !_req)
 		return -EINVAL;
@@ -924,7 +905,7 @@
 
 	/* queue head may be partially complete. */
 	if (ep->queue.next == &req->queue) {
-		DBG(dev, "unlink (%s) dma\n", _ep->name);
+		dev_dbg(&dev->pdev->dev, "unlink (%s) dma\n", _ep->name);
 		_req->status = -ECONNRESET;
 		langwell_ep_fifo_flush(&ep->ep);
 
@@ -963,7 +944,7 @@
 	ep->stopped = stopped;
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
@@ -976,7 +957,7 @@
 	u32			endptctrl = 0;
 	int			ep_num;
 	struct langwell_udc	*dev = ep->dev;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	ep_num = ep->ep_num;
 	endptctrl = readl(&dev->op_regs->endptctrl[ep_num]);
@@ -1001,7 +982,7 @@
 
 	writel(endptctrl, &dev->op_regs->endptctrl[ep_num]);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1016,7 +997,7 @@
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc)
 		return -EINVAL;
@@ -1024,8 +1005,7 @@
 	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
 		return -ESHUTDOWN;
 
-	if (ep->desc && (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			== USB_ENDPOINT_XFER_ISOC)
+	if (usb_endpoint_xfer_isoc(ep->desc))
 		return  -EOPNOTSUPP;
 
 	spin_lock_irqsave(&dev->lock, flags);
@@ -1036,7 +1016,7 @@
 	 */
 	if (!list_empty(&ep->queue) && is_in(ep) && value) {
 		/* IN endpoint FIFO holds bytes */
-		DBG(dev, "%s FIFO holds bytes\n", _ep->name);
+		dev_dbg(&dev->pdev->dev, "%s FIFO holds bytes\n", _ep->name);
 		retval = -EAGAIN;
 		goto done;
 	}
@@ -1050,8 +1030,9 @@
 	}
 done:
 	spin_unlock_irqrestore(&dev->lock, flags);
-	DBG(dev, "%s %s halt\n", _ep->name, value ? "set" : "clear");
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "%s %s halt\n",
+			_ep->name, value ? "set" : "clear");
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
@@ -1065,12 +1046,12 @@
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc)
 		return -EINVAL;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return usb_ep_set_halt(_ep);
 }
 
@@ -1086,15 +1067,16 @@
 	ep = container_of(_ep, struct langwell_ep, ep);
 	dev = ep->dev;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (!_ep || !ep->desc) {
-		VDBG(dev, "ep or ep->desc is NULL\n");
-		VDBG(dev, "<--- %s()\n", __func__);
+		dev_vdbg(&dev->pdev->dev, "ep or ep->desc is NULL\n");
+		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		return;
 	}
 
-	VDBG(dev, "%s-%s fifo flush\n", _ep->name, is_in(ep) ? "in" : "out");
+	dev_vdbg(&dev->pdev->dev, "%s-%s fifo flush\n",
+			_ep->name, DIR_STRING(ep));
 
 	/* flush endpoint buffer */
 	if (ep->ep_num == 0)
@@ -1110,14 +1092,14 @@
 		writel(flush_bit, &dev->op_regs->endptflush);
 		while (readl(&dev->op_regs->endptflush)) {
 			if (time_after(jiffies, timeout)) {
-				ERROR(dev, "ep flush timeout\n");
+				dev_err(&dev->pdev->dev, "ep flush timeout\n");
 				goto done;
 			}
 			cpu_relax();
 		}
 	} while (readl(&dev->op_regs->endptstat) & flush_bit);
 done:
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1167,31 +1149,59 @@
 		return -ENODEV;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	retval = readl(&dev->op_regs->frindex) & FRINDEX_MASK;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
 
+/* enter or exit PHY low power state */
+static void langwell_phy_low_power(struct langwell_udc *dev, bool flag)
+{
+	u32		devlc;
+	u8		devlc_byte2;
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
+
+	devlc = readl(&dev->op_regs->devlc);
+	dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
+
+	if (flag)
+		devlc |= LPM_PHCD;
+	else
+		devlc &= ~LPM_PHCD;
+
+	/* FIXME: workaround for Langwell A1/A2/A3 sighting */
+	devlc_byte2 = (devlc >> 16) & 0xff;
+	writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
+
+	devlc = readl(&dev->op_regs->devlc);
+	dev_vdbg(&dev->pdev->dev,
+			"%s PHY low power suspend, devlc = 0x%08x\n",
+			flag ? "enter" : "exit", devlc);
+}
+
+
 /* tries to wake up the host connected to this gadget */
 static int langwell_wakeup(struct usb_gadget *_gadget)
 {
 	struct langwell_udc	*dev;
-	u32 			portsc1, devlc;
-	unsigned long   	flags;
+	u32			portsc1;
+	unsigned long		flags;
 
 	if (!_gadget)
 		return 0;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	/* Remote Wakeup feature not enabled by host */
-	if (!dev->remote_wakeup)
+	/* remote wakeup feature not enabled by host */
+	if (!dev->remote_wakeup) {
+		dev_info(&dev->pdev->dev, "remote wakeup is disabled\n");
 		return -ENOTSUPP;
+	}
 
 	spin_lock_irqsave(&dev->lock, flags);
 
@@ -1201,27 +1211,23 @@
 		return 0;
 	}
 
-	/* LPM L1 to L0, remote wakeup */
-	if (dev->lpm && dev->lpm_state == LPM_L1) {
-		portsc1 |= PORTS_SLP;
-		writel(portsc1, &dev->op_regs->portsc1);
-	}
-
-	/* force port resume */
-	if (dev->usb_state == USB_STATE_SUSPENDED) {
-		portsc1 |= PORTS_FPR;
-		writel(portsc1, &dev->op_regs->portsc1);
-	}
+	/* LPM L1 to L0 or legacy remote wakeup */
+	if (dev->lpm && dev->lpm_state == LPM_L1)
+		dev_info(&dev->pdev->dev, "LPM L1 to L0 remote wakeup\n");
+	else
+		dev_info(&dev->pdev->dev, "device remote wakeup\n");
 
 	/* exit PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc &= ~LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
+
+	/* force port resume */
+	portsc1 |= PORTS_FPR;
+	writel(portsc1, &dev->op_regs->portsc1);
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1231,16 +1237,17 @@
 {
 	struct langwell_udc	*dev;
 	unsigned long		flags;
-	u32             	usbcmd;
+	u32			usbcmd;
 
 	if (!_gadget)
 		return -ENODEV;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	spin_lock_irqsave(&dev->lock, flags);
-	VDBG(dev, "VBUS status: %s\n", is_active ? "on" : "off");
+	dev_vdbg(&dev->pdev->dev, "VBUS status: %s\n",
+			is_active ? "on" : "off");
 
 	dev->vbus_active = (is_active != 0);
 	if (dev->driver && dev->softconnected && dev->vbus_active) {
@@ -1255,7 +1262,7 @@
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1269,15 +1276,15 @@
 		return -ENODEV;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->transceiver) {
-		VDBG(dev, "otg_set_power\n");
-		VDBG(dev, "<--- %s()\n", __func__);
+		dev_vdbg(&dev->pdev->dev, "otg_set_power\n");
+		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		return otg_set_power(dev->transceiver, mA);
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return -ENOTSUPP;
 }
 
@@ -1286,15 +1293,15 @@
 static int langwell_pullup(struct usb_gadget *_gadget, int is_on)
 {
 	struct langwell_udc	*dev;
-	u32             	usbcmd;
-	unsigned long   	flags;
+	u32			usbcmd;
+	unsigned long		flags;
 
 	if (!_gadget)
 		return -ENODEV;
 
 	dev = container_of(_gadget, struct langwell_udc, gadget);
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	spin_lock_irqsave(&dev->lock, flags);
 	dev->softconnected = (is_on != 0);
@@ -1310,7 +1317,7 @@
 	}
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1346,12 +1353,13 @@
 static int langwell_udc_reset(struct langwell_udc *dev)
 {
 	u32		usbcmd, usbmode, devlc, endpointlistaddr;
+	u8		devlc_byte0, devlc_byte2;
 	unsigned long	timeout;
 
 	if (!dev)
 		return -EINVAL;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* set controller to stop state */
 	usbcmd = readl(&dev->op_regs->usbcmd);
@@ -1367,7 +1375,7 @@
 	timeout = jiffies + RESET_TIMEOUT;
 	while (readl(&dev->op_regs->usbcmd) & CMD_RST) {
 		if (time_after(jiffies, timeout)) {
-			ERROR(dev, "device reset timeout\n");
+			dev_err(&dev->pdev->dev, "device reset timeout\n");
 			return -ETIMEDOUT;
 		}
 		cpu_relax();
@@ -1382,7 +1390,7 @@
 
 	writel(usbmode, &dev->op_regs->usbmode);
 	usbmode = readl(&dev->op_regs->usbmode);
-	VDBG(dev, "usbmode=0x%08x\n", usbmode);
+	dev_vdbg(&dev->pdev->dev, "usbmode=0x%08x\n", usbmode);
 
 	/* Write-Clear setup status */
 	writel(0, &dev->op_regs->usbsts);
@@ -1390,9 +1398,17 @@
 	/* if support USB LPM, ACK all LPM token */
 	if (dev->lpm) {
 		devlc = readl(&dev->op_regs->devlc);
+		dev_vdbg(&dev->pdev->dev, "devlc = 0x%08x\n", devlc);
+		/* FIXME: workaround for Langwell A1/A2/A3 sighting */
 		devlc &= ~LPM_STL;	/* don't STALL LPM token */
 		devlc &= ~LPM_NYT_ACK;	/* ACK LPM token */
-		writel(devlc, &dev->op_regs->devlc);
+		devlc_byte0 = devlc & 0xff;
+		devlc_byte2 = (devlc >> 16) & 0xff;
+		writeb(devlc_byte0, (u8 *)&dev->op_regs->devlc);
+		writeb(devlc_byte2, (u8 *)&dev->op_regs->devlc + 2);
+		devlc = readl(&dev->op_regs->devlc);
+		dev_vdbg(&dev->pdev->dev,
+				"ACK LPM token, devlc = 0x%08x\n", devlc);
 	}
 
 	/* fill endpointlistaddr register */
@@ -1400,10 +1416,11 @@
 	endpointlistaddr &= ENDPOINTLISTADDR_MASK;
 	writel(endpointlistaddr, &dev->op_regs->endpointlistaddr);
 
-	VDBG(dev, "dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n",
-			dev->ep_dqh, endpointlistaddr,
-			readl(&dev->op_regs->endpointlistaddr));
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev,
+		"dQH base (vir: %p, phy: 0x%08x), endpointlistaddr=0x%08x\n",
+		dev->ep_dqh, endpointlistaddr,
+		readl(&dev->op_regs->endpointlistaddr));
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1415,7 +1432,7 @@
 	char			name[14];
 	int			i;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* initialize ep0 */
 	ep = &dev->ep[0];
@@ -1449,11 +1466,9 @@
 
 		INIT_LIST_HEAD(&ep->queue);
 		list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
-
-		ep->dqh = &dev->ep_dqh[i];
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -1462,7 +1477,7 @@
 static void langwell_udc_start(struct langwell_udc *dev)
 {
 	u32	usbintr, usbcmd;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* enable interrupts */
 	usbintr = INTR_ULPIE	/* ULPI */
@@ -1485,8 +1500,7 @@
 	usbcmd |= CMD_RUNSTOP;
 	writel(usbcmd, &dev->op_regs->usbcmd);
 
-	DBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1495,7 +1509,7 @@
 {
 	u32	usbcmd;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* disable all interrupts */
 	writel(0, &dev->op_regs->usbintr);
@@ -1508,8 +1522,7 @@
 	usbcmd &= ~CMD_RUNSTOP;
 	writel(usbcmd, &dev->op_regs->usbcmd);
 
-	DBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1518,7 +1531,7 @@
 		struct usb_gadget_driver *driver)
 {
 	struct langwell_ep	*ep;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	nuke(&dev->ep[0], -ESHUTDOWN);
 
@@ -1533,7 +1546,7 @@
 		spin_lock(&dev->lock);
 	}
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1659,13 +1672,15 @@
 		"Over-current Change: %s\n"
 		"Port Enable/Disable Change: %s\n"
 		"Port Enabled/Disabled: %s\n"
-		"Current Connect Status: %s\n\n",
+		"Current Connect Status: %s\n"
+		"LPM Suspend Status: %s\n\n",
 		(tmp_reg & PORTS_PR) ? "Reset" : "Not Reset",
 		(tmp_reg & PORTS_SUSP) ? "Suspend " : "Not Suspend",
 		(tmp_reg & PORTS_OCC) ? "Detected" : "No",
 		(tmp_reg & PORTS_PEC) ? "Changed" : "Not Changed",
 		(tmp_reg & PORTS_PE) ? "Enable" : "Not Correct",
-		(tmp_reg & PORTS_CCS) ?  "Attached" : "Not Attached");
+		(tmp_reg & PORTS_CCS) ?  "Attached" : "Not Attached",
+		(tmp_reg & PORTS_SLP) ? "LPM L1" : "LPM L0");
 	size -= t;
 	next += t;
 
@@ -1676,7 +1691,7 @@
 		"Serial Transceiver : %d\n"
 		"Port Speed: %s\n"
 		"Port Force Full Speed Connenct: %s\n"
-		"PHY Low Power Suspend Clock Disable: %s\n"
+		"PHY Low Power Suspend Clock: %s\n"
 		"BmAttributes: %d\n\n",
 		LPM_PTS(tmp_reg),
 		(tmp_reg & LPM_STS) ? 1 : 0,
@@ -1797,6 +1812,36 @@
 static DEVICE_ATTR(langwell_udc, S_IRUGO, show_langwell_udc, NULL);
 
 
+/* device "remote_wakeup" sysfs attribute file */
+static ssize_t store_remote_wakeup(struct device *_dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct langwell_udc	*dev = the_controller;
+	unsigned long		flags;
+	ssize_t			rc = count;
+
+	if (count > 2)
+		return -EINVAL;
+
+	if (count > 0 && buf[count-1] == '\n')
+		((char *) buf)[count-1] = 0;
+
+	if (buf[0] != '1')
+		return -EINVAL;
+
+	/* force remote wakeup enabled in case gadget driver doesn't support */
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->remote_wakeup = 1;
+	dev->dev_status |= (1 << USB_DEVICE_REMOTE_WAKEUP);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	langwell_wakeup(&dev->gadget);
+
+	return rc;
+}
+static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup);
+
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -1807,7 +1852,8 @@
  * the driver might get unbound.
  */
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct langwell_udc	*dev = the_controller;
 	unsigned long		flags;
@@ -1816,7 +1862,7 @@
 	if (!dev)
 		return -ENODEV;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->driver)
 		return -EBUSY;
@@ -1830,9 +1876,9 @@
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
-		DBG(dev, "bind to driver %s --> %d\n",
+		dev_dbg(&dev->pdev->dev, "bind to driver %s --> %d\n",
 				driver->driver.name, retval);
 		dev->driver = NULL;
 		dev->gadget.dev.driver = NULL;
@@ -1851,13 +1897,13 @@
 	if (dev->got_irq)
 		langwell_udc_start(dev);
 
-	VDBG(dev, "After langwell_udc_start(), print all registers:\n");
-#ifdef	VERBOSE
+	dev_vdbg(&dev->pdev->dev,
+			"After langwell_udc_start(), print all registers:\n");
 	print_all_registers(dev);
-#endif
 
-	INFO(dev, "register driver: %s\n", driver->driver.name);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_info(&dev->pdev->dev, "register driver: %s\n",
+			driver->driver.name);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 
 err_unbind:
@@ -1865,10 +1911,10 @@
 	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 
 /* unregister gadget driver */
@@ -1880,11 +1926,15 @@
 	if (!dev)
 		return -ENODEV;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-	if (unlikely(!driver || !driver->bind || !driver->unbind))
+	if (unlikely(!driver || !driver->unbind))
 		return -EINVAL;
 
+	/* exit PHY low power suspend */
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
+
 	/* unbind OTG transceiver */
 	if (dev->transceiver)
 		(void)otg_set_peripheral(dev->transceiver, 0);
@@ -1910,8 +1960,9 @@
 
 	device_remove_file(&dev->pdev->dev, &dev_attr_function);
 
-	INFO(dev, "unregistered driver '%s'\n", driver->driver.name);
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_info(&dev->pdev->dev, "unregistered driver '%s'\n",
+			driver->driver.name);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 EXPORT_SYMBOL(usb_gadget_unregister_driver);
@@ -1930,7 +1981,7 @@
 	unsigned long		timeout;
 	struct langwell_dqh	*dqh;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* ep0 OUT dQH */
 	dqh = &dev->ep_dqh[EP_DIR_OUT];
@@ -1943,7 +1994,7 @@
 	timeout = jiffies + SETUPSTAT_TIMEOUT;
 	while (readl(&dev->op_regs->endptsetupstat)) {
 		if (time_after(jiffies, timeout)) {
-			ERROR(dev, "setup_tripwire timeout\n");
+			dev_err(&dev->pdev->dev, "setup_tripwire timeout\n");
 			break;
 		}
 		cpu_relax();
@@ -1963,7 +2014,7 @@
 	usbcmd = readl(&dev->op_regs->usbcmd);
 	writel(usbcmd & ~CMD_SUTW, &dev->op_regs->usbcmd);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1972,7 +2023,7 @@
 {
 	u32	endptctrl;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* set TX and RX to stall */
 	endptctrl = readl(&dev->op_regs->endptctrl[0]);
@@ -1983,7 +2034,7 @@
 	dev->ep0_state = WAIT_FOR_SETUP;
 	dev->ep0_dir = USB_DIR_OUT;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -1994,7 +2045,7 @@
 	struct langwell_ep	*ep;
 	int			status = 0;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dir == EP_DIR_IN)
 		dev->ep0_dir = USB_DIR_IN;
@@ -2019,11 +2070,11 @@
 		return -ENOMEM;
 
 	if (status)
-		ERROR(dev, "can't queue ep0 status request\n");
+		dev_err(&dev->pdev->dev, "can't queue ep0 status request\n");
 
 	list_add_tail(&req->queue, &ep->queue);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return status;
 }
 
@@ -2032,11 +2083,11 @@
 static void set_address(struct langwell_udc *dev, u16 value,
 		u16 index, u16 length)
 {
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* save the new address to device struct */
 	dev->dev_addr = (u8) value;
-	VDBG(dev, "dev->dev_addr = %d\n", dev->dev_addr);
+	dev_vdbg(&dev->pdev->dev, "dev->dev_addr = %d\n", dev->dev_addr);
 
 	/* update usb state */
 	dev->usb_state = USB_STATE_ADDRESS;
@@ -2045,7 +2096,7 @@
 	if (prime_status_phase(dev, EP_DIR_IN))
 		ep0_stall(dev);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2054,7 +2105,7 @@
 		u16 wIndex)
 {
 	struct langwell_ep		*ep;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if ((wIndex & USB_ENDPOINT_NUMBER_MASK) == 0)
 		return &dev->ep[0];
@@ -2073,7 +2124,7 @@
 			return ep;
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return NULL;
 }
 
@@ -2085,7 +2136,7 @@
 	u32			endptctrl;
 	int			retval;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	endptctrl = readl(&dev->op_regs->endptctrl[ep->ep_num]);
 	if (is_in(ep))
@@ -2093,7 +2144,7 @@
 	else
 		retval = endptctrl & EPCTRL_RXS ? 1 : 0;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return retval;
 }
 
@@ -2107,14 +2158,13 @@
 	u16	status_data = 0;	/* 16 bits cpu view status data */
 	int	status = 0;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	ep = &dev->ep[0];
 
 	if ((request_type & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
 		/* get device status */
-		status_data = 1 << USB_DEVICE_SELF_POWERED;
-		status_data |= dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+		status_data = dev->dev_status;
 	} else if ((request_type & USB_RECIP_MASK) == USB_RECIP_INTERFACE) {
 		/* get interface status */
 		status_data = 0;
@@ -2129,6 +2179,8 @@
 		status_data = ep_is_stall(epn) << USB_ENDPOINT_HALT;
 	}
 
+	dev_dbg(&dev->pdev->dev, "get status data: 0x%04x\n", status_data);
+
 	dev->ep0_dir = USB_DIR_IN;
 
 	/* borrow the per device status_req */
@@ -2150,18 +2202,19 @@
 		goto stall;
 
 	if (status) {
-		ERROR(dev, "response error on GET_STATUS request\n");
+		dev_err(&dev->pdev->dev,
+				"response error on GET_STATUS request\n");
 		goto stall;
 	}
 
 	list_add_tail(&req->queue, &ep->queue);
 	dev->ep0_state = DATA_STATE_XMIT;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return;
 stall:
 	ep0_stall(dev);
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2173,12 +2226,12 @@
 	u16	wIndex = le16_to_cpu(setup->wIndex);
 	u16	wLength = le16_to_cpu(setup->wLength);
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* ep0 fifo flush */
 	nuke(&dev->ep[0], -ESHUTDOWN);
 
-	DBG(dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+	dev_dbg(&dev->pdev->dev, "SETUP %02x.%02x v%04x i%04x l%04x\n",
 			setup->bRequestType, setup->bRequest,
 			wValue, wIndex, wLength);
 
@@ -2197,7 +2250,7 @@
 	/* We process some stardard setup requests here */
 	switch (setup->bRequest) {
 	case USB_REQ_GET_STATUS:
-		DBG(dev, "SETUP: USB_REQ_GET_STATUS\n");
+		dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_GET_STATUS\n");
 		/* get status, DATA and STATUS phase */
 		if ((setup->bRequestType & (USB_DIR_IN | USB_TYPE_MASK))
 					!= (USB_DIR_IN | USB_TYPE_STANDARD))
@@ -2206,7 +2259,7 @@
 		goto end;
 
 	case USB_REQ_SET_ADDRESS:
-		DBG(dev, "SETUP: USB_REQ_SET_ADDRESS\n");
+		dev_dbg(&dev->pdev->dev, "SETUP: USB_REQ_SET_ADDRESS\n");
 		/* STATUS phase */
 		if (setup->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD
 						| USB_RECIP_DEVICE))
@@ -2220,9 +2273,11 @@
 	{
 		int rc = -EOPNOTSUPP;
 		if (setup->bRequest == USB_REQ_SET_FEATURE)
-			DBG(dev, "SETUP: USB_REQ_SET_FEATURE\n");
+			dev_dbg(&dev->pdev->dev,
+					"SETUP: USB_REQ_SET_FEATURE\n");
 		else if (setup->bRequest == USB_REQ_CLEAR_FEATURE)
-			DBG(dev, "SETUP: USB_REQ_CLEAR_FEATURE\n");
+			dev_dbg(&dev->pdev->dev,
+					"SETUP: USB_REQ_CLEAR_FEATURE\n");
 
 		if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
 				== (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
@@ -2240,13 +2295,29 @@
 
 			spin_unlock(&dev->lock);
 			rc = langwell_ep_set_halt(&epn->ep,
-					(setup->bRequest == USB_REQ_SET_FEATURE)
-						? 1 : 0);
+				(setup->bRequest == USB_REQ_SET_FEATURE)
+				? 1 : 0);
 			spin_lock(&dev->lock);
 
 		} else if ((setup->bRequestType & (USB_RECIP_MASK
 				| USB_TYPE_MASK)) == (USB_RECIP_DEVICE
 				| USB_TYPE_STANDARD)) {
+			rc = 0;
+			switch (wValue) {
+			case USB_DEVICE_REMOTE_WAKEUP:
+				if (setup->bRequest == USB_REQ_SET_FEATURE) {
+					dev->remote_wakeup = 1;
+					dev->dev_status |= (1 << wValue);
+				} else {
+					dev->remote_wakeup = 0;
+					dev->dev_status &= ~(1 << wValue);
+				}
+				break;
+			default:
+				rc = -EOPNOTSUPP;
+				break;
+			}
+
 			if (!gadget_is_otg(&dev->gadget))
 				break;
 			else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) {
@@ -2262,7 +2333,6 @@
 				dev->gadget.a_alt_hnp_support = 1;
 			else
 				break;
-			rc = 0;
 		} else
 			break;
 
@@ -2274,31 +2344,38 @@
 	}
 
 	case USB_REQ_GET_DESCRIPTOR:
-		DBG(dev, "SETUP: USB_REQ_GET_DESCRIPTOR\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_GET_DESCRIPTOR\n");
 		goto delegate;
 
 	case USB_REQ_SET_DESCRIPTOR:
-		DBG(dev, "SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_SET_DESCRIPTOR unsupported\n");
 		goto delegate;
 
 	case USB_REQ_GET_CONFIGURATION:
-		DBG(dev, "SETUP: USB_REQ_GET_CONFIGURATION\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_GET_CONFIGURATION\n");
 		goto delegate;
 
 	case USB_REQ_SET_CONFIGURATION:
-		DBG(dev, "SETUP: USB_REQ_SET_CONFIGURATION\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_SET_CONFIGURATION\n");
 		goto delegate;
 
 	case USB_REQ_GET_INTERFACE:
-		DBG(dev, "SETUP: USB_REQ_GET_INTERFACE\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_GET_INTERFACE\n");
 		goto delegate;
 
 	case USB_REQ_SET_INTERFACE:
-		DBG(dev, "SETUP: USB_REQ_SET_INTERFACE\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_SET_INTERFACE\n");
 		goto delegate;
 
 	case USB_REQ_SYNCH_FRAME:
-		DBG(dev, "SETUP: USB_REQ_SYNCH_FRAME unsupported\n");
+		dev_dbg(&dev->pdev->dev,
+				"SETUP: USB_REQ_SYNCH_FRAME unsupported\n");
 		goto delegate;
 
 	default:
@@ -2310,7 +2387,8 @@
 			/* DATA phase from gadget, STATUS phase from udc */
 			dev->ep0_dir = (setup->bRequestType & USB_DIR_IN)
 					?  USB_DIR_IN : USB_DIR_OUT;
-			VDBG(dev, "dev->ep0_dir = 0x%x, wLength = %d\n",
+			dev_vdbg(&dev->pdev->dev,
+					"dev->ep0_dir = 0x%x, wLength = %d\n",
 					dev->ep0_dir, wLength);
 			spin_unlock(&dev->lock);
 			if (dev->driver->setup(&dev->gadget,
@@ -2322,7 +2400,8 @@
 		} else {
 			/* no DATA phase, IN STATUS phase from gadget */
 			dev->ep0_dir = USB_DIR_IN;
-			VDBG(dev, "dev->ep0_dir = 0x%x, wLength = %d\n",
+			dev_vdbg(&dev->pdev->dev,
+					"dev->ep0_dir = 0x%x, wLength = %d\n",
 					dev->ep0_dir, wLength);
 			spin_unlock(&dev->lock);
 			if (dev->driver->setup(&dev->gadget,
@@ -2334,8 +2413,7 @@
 		break;
 	}
 end:
-	VDBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2359,23 +2437,27 @@
 	td_complete = 0;
 	actual = curr_req->req.length;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	for (i = 0; i < curr_req->dtd_count; i++) {
-		remaining_length = le16_to_cpu(curr_dtd->dtd_total);
-		actual -= remaining_length;
 
 		/* command execution states by dTD */
 		dtd_status = curr_dtd->dtd_status;
 
+		barrier();
+		remaining_length = le16_to_cpu(curr_dtd->dtd_total);
+		actual -= remaining_length;
+
 		if (!dtd_status) {
 			/* transfers completed successfully */
 			if (!remaining_length) {
 				td_complete++;
-				VDBG(dev, "dTD transmitted successfully\n");
+				dev_vdbg(&dev->pdev->dev,
+					"dTD transmitted successfully\n");
 			} else {
 				if (dir) {
-					VDBG(dev, "TX dTD remains data\n");
+					dev_vdbg(&dev->pdev->dev,
+						"TX dTD remains data\n");
 					retval = -EPROTO;
 					break;
 
@@ -2387,27 +2469,32 @@
 		} else {
 			/* transfers completed with errors */
 			if (dtd_status & DTD_STS_ACTIVE) {
-				DBG(dev, "request not completed\n");
+				dev_dbg(&dev->pdev->dev,
+					"dTD status ACTIVE dQH[%d]\n", index);
 				retval = 1;
 				return retval;
 			} else if (dtd_status & DTD_STS_HALTED) {
-				ERROR(dev, "dTD error %08x dQH[%d]\n",
-						dtd_status, index);
+				dev_err(&dev->pdev->dev,
+					"dTD error %08x dQH[%d]\n",
+					dtd_status, index);
 				/* clear the errors and halt condition */
 				curr_dqh->dtd_status = 0;
 				retval = -EPIPE;
 				break;
 			} else if (dtd_status & DTD_STS_DBE) {
-				DBG(dev, "data buffer (overflow) error\n");
+				dev_dbg(&dev->pdev->dev,
+					"data buffer (overflow) error\n");
 				retval = -EPROTO;
 				break;
 			} else if (dtd_status & DTD_STS_TRE) {
-				DBG(dev, "transaction(ISO) error\n");
+				dev_dbg(&dev->pdev->dev,
+					"transaction(ISO) error\n");
 				retval = -EILSEQ;
 				break;
 			} else
-				ERROR(dev, "unknown error (0x%x)!\n",
-						dtd_status);
+				dev_err(&dev->pdev->dev,
+					"unknown error (0x%x)!\n",
+					dtd_status);
 		}
 
 		if (i != curr_req->dtd_count - 1)
@@ -2420,7 +2507,7 @@
 
 	curr_req->req.actual = actual;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -2430,7 +2517,7 @@
 		struct langwell_ep *ep0, struct langwell_request *req)
 {
 	u32	new_addr;
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->usb_state == USB_STATE_ADDRESS) {
 		/* set the new address */
@@ -2438,7 +2525,7 @@
 		writel(new_addr << USBADR_SHIFT, &dev->op_regs->deviceaddr);
 
 		new_addr = USBADR(readl(&dev->op_regs->deviceaddr));
-		VDBG(dev, "new_addr = %d\n", new_addr);
+		dev_vdbg(&dev->pdev->dev, "new_addr = %d\n", new_addr);
 	}
 
 	done(ep0, req, 0);
@@ -2458,14 +2545,14 @@
 		dev->ep0_state = WAIT_FOR_SETUP;
 		break;
 	case WAIT_FOR_SETUP:
-		ERROR(dev, "unexpect ep0 packets\n");
+		dev_err(&dev->pdev->dev, "unexpect ep0 packets\n");
 		break;
 	default:
 		ep0_stall(dev);
 		break;
 	}
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2477,16 +2564,17 @@
 	struct langwell_ep	*epn;
 	struct langwell_request	*curr_req, *temp_req;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	complete_bits = readl(&dev->op_regs->endptcomplete);
-	VDBG(dev, "endptcomplete register: 0x%08x\n", complete_bits);
+	dev_vdbg(&dev->pdev->dev, "endptcomplete register: 0x%08x\n",
+			complete_bits);
 
 	/* Write-Clear the bits in endptcomplete register */
 	writel(complete_bits, &dev->op_regs->endptcomplete);
 
 	if (!complete_bits) {
-		DBG(dev, "complete_bits = 0\n");
+		dev_dbg(&dev->pdev->dev, "complete_bits = 0\n");
 		goto done;
 	}
 
@@ -2506,23 +2594,25 @@
 			epn = &dev->ep[i];
 
 		if (epn->name == NULL) {
-			WARNING(dev, "invalid endpoint\n");
+			dev_warn(&dev->pdev->dev, "invalid endpoint\n");
 			continue;
 		}
 
 		if (i < 2)
 			/* ep0 in and out */
-			DBG(dev, "%s-%s transfer completed\n",
+			dev_dbg(&dev->pdev->dev, "%s-%s transfer completed\n",
 					epn->name,
 					is_in(epn) ? "in" : "out");
 		else
-			DBG(dev, "%s transfer completed\n", epn->name);
+			dev_dbg(&dev->pdev->dev, "%s transfer completed\n",
+					epn->name);
 
 		/* process the req queue until an uncomplete request */
 		list_for_each_entry_safe(curr_req, temp_req,
 				&epn->queue, queue) {
 			status = process_ep_req(dev, i, curr_req);
-			VDBG(dev, "%s req status: %d\n", epn->name, status);
+			dev_vdbg(&dev->pdev->dev, "%s req status: %d\n",
+					epn->name, status);
 
 			if (status)
 				break;
@@ -2540,8 +2630,7 @@
 		}
 	}
 done:
-	VDBG(dev, "<--- %s()\n", __func__);
-	return;
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2551,14 +2640,14 @@
 	u32	portsc1, devlc;
 	u32	speed;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->bus_reset)
 		dev->bus_reset = 0;
 
 	portsc1 = readl(&dev->op_regs->portsc1);
 	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "portsc1 = 0x%08x, devlc = 0x%08x\n",
+	dev_vdbg(&dev->pdev->dev, "portsc1 = 0x%08x, devlc = 0x%08x\n",
 			portsc1, devlc);
 
 	/* bus reset is finished */
@@ -2579,25 +2668,22 @@
 			dev->gadget.speed = USB_SPEED_UNKNOWN;
 			break;
 		}
-		VDBG(dev, "speed = %d, dev->gadget.speed = %d\n",
+		dev_vdbg(&dev->pdev->dev,
+				"speed = %d, dev->gadget.speed = %d\n",
 				speed, dev->gadget.speed);
 	}
 
 	/* LPM L0 to L1 */
 	if (dev->lpm && dev->lpm_state == LPM_L0)
 		if (portsc1 & PORTS_SUSP && portsc1 & PORTS_SLP) {
-				INFO(dev, "LPM L0 to L1\n");
-				dev->lpm_state = LPM_L1;
+			dev_info(&dev->pdev->dev, "LPM L0 to L1\n");
+			dev->lpm_state = LPM_L1;
 		}
 
 	/* LPM L1 to L0, force resume or remote wakeup finished */
 	if (dev->lpm && dev->lpm_state == LPM_L1)
 		if (!(portsc1 & PORTS_SUSP)) {
-			if (portsc1 & PORTS_SLP)
-				INFO(dev, "LPM L1 to L0, force resume\n");
-			else
-				INFO(dev, "LPM L1 to L0, remote wakeup\n");
-
+			dev_info(&dev->pdev->dev, "LPM L1 to L0\n");
 			dev->lpm_state = LPM_L0;
 		}
 
@@ -2605,7 +2691,7 @@
 	if (!dev->resume_state)
 		dev->usb_state = USB_STATE_DEFAULT;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2617,7 +2703,7 @@
 			endptcomplete;
 	unsigned long	timeout;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* Write-Clear the device address */
 	deviceaddr = readl(&dev->op_regs->deviceaddr);
@@ -2634,7 +2720,10 @@
 
 	dev->ep0_dir = USB_DIR_OUT;
 	dev->ep0_state = WAIT_FOR_SETUP;
-	dev->remote_wakeup = 0;		/* default to 0 on reset */
+
+	/* remote wakeup reset to 0 when the device is reset */
+	dev->remote_wakeup = 0;
+	dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
 	dev->gadget.b_hnp_enable = 0;
 	dev->gadget.a_hnp_support = 0;
 	dev->gadget.a_alt_hnp_support = 0;
@@ -2651,7 +2740,7 @@
 	timeout = jiffies + PRIME_TIMEOUT;
 	while (readl(&dev->op_regs->endptprime)) {
 		if (time_after(jiffies, timeout)) {
-			ERROR(dev, "USB reset timeout\n");
+			dev_err(&dev->pdev->dev, "USB reset timeout\n");
 			break;
 		}
 		cpu_relax();
@@ -2661,7 +2750,7 @@
 	writel((u32) ~0, &dev->op_regs->endptflush);
 
 	if (readl(&dev->op_regs->portsc1) & PORTS_PR) {
-		VDBG(dev, "USB bus reset\n");
+		dev_vdbg(&dev->pdev->dev, "USB bus reset\n");
 		/* bus is reseting */
 		dev->bus_reset = 1;
 
@@ -2669,7 +2758,7 @@
 		stop_activity(dev, dev->driver);
 		dev->usb_state = USB_STATE_DEFAULT;
 	} else {
-		VDBG(dev, "device controller reset\n");
+		dev_vdbg(&dev->pdev->dev, "device controller reset\n");
 		/* controller reset */
 		langwell_udc_reset(dev);
 
@@ -2691,15 +2780,14 @@
 		dev->lotg->hsm.b_hnp_enable = 0;
 #endif
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
 /* USB bus suspend/resume interrupt */
 static void handle_bus_suspend(struct langwell_udc *dev)
 {
-	u32		devlc;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	dev->resume_state = dev->usb_state;
 	dev->usb_state = USB_STATE_SUSPENDED;
@@ -2733,33 +2821,29 @@
 			spin_unlock(&dev->lock);
 			dev->driver->suspend(&dev->gadget);
 			spin_lock(&dev->lock);
-			DBG(dev, "suspend %s\n", dev->driver->driver.name);
+			dev_dbg(&dev->pdev->dev, "suspend %s\n",
+					dev->driver->driver.name);
 		}
 	}
 
 	/* enter PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc |= LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
 static void handle_bus_resume(struct langwell_udc *dev)
 {
-	u32		devlc;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	dev->usb_state = dev->resume_state;
 	dev->resume_state = 0;
 
 	/* exit PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc &= ~LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
 
 #ifdef	OTG_TRANSCEIVER
 	if (dev->lotg->otg.default_a == 0)
@@ -2772,11 +2856,12 @@
 			spin_unlock(&dev->lock);
 			dev->driver->resume(&dev->gadget);
 			spin_lock(&dev->lock);
-			DBG(dev, "resume %s\n", dev->driver->driver.name);
+			dev_dbg(&dev->pdev->dev, "resume %s\n",
+					dev->driver->driver.name);
 		}
 	}
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 
@@ -2789,11 +2874,11 @@
 				irq_sts,
 				portsc1;
 
-	VDBG(dev, "---> %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	if (dev->stopped) {
-		VDBG(dev, "handle IRQ_NONE\n");
-		VDBG(dev, "<--- %s()\n", __func__);
+		dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n");
+		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		return IRQ_NONE;
 	}
 
@@ -2806,12 +2891,13 @@
 	usbintr = readl(&dev->op_regs->usbintr);
 
 	irq_sts = usbsts & usbintr;
-	VDBG(dev, "usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n",
+	dev_vdbg(&dev->pdev->dev,
+			"usbsts = 0x%08x, usbintr = 0x%08x, irq_sts = 0x%08x\n",
 			usbsts, usbintr, irq_sts);
 
 	if (!irq_sts) {
-		VDBG(dev, "handle IRQ_NONE\n");
-		VDBG(dev, "<--- %s()\n", __func__);
+		dev_vdbg(&dev->pdev->dev, "handle IRQ_NONE\n");
+		dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		spin_unlock(&dev->lock);
 		return IRQ_NONE;
 	}
@@ -2827,12 +2913,13 @@
 
 	/* USB interrupt */
 	if (irq_sts & STS_UI) {
-		VDBG(dev, "USB interrupt\n");
+		dev_vdbg(&dev->pdev->dev, "USB interrupt\n");
 
 		/* setup packet received from ep0 */
 		if (readl(&dev->op_regs->endptsetupstat)
 				& EP0SETUPSTAT_MASK) {
-			VDBG(dev, "USB SETUP packet received interrupt\n");
+			dev_vdbg(&dev->pdev->dev,
+				"USB SETUP packet received interrupt\n");
 			/* setup tripwire semaphone */
 			setup_tripwire(dev);
 			handle_setup_packet(dev, &dev->local_setup_buff);
@@ -2840,7 +2927,8 @@
 
 		/* USB transfer completion */
 		if (readl(&dev->op_regs->endptcomplete)) {
-			VDBG(dev, "USB transfer completion interrupt\n");
+			dev_vdbg(&dev->pdev->dev,
+				"USB transfer completion interrupt\n");
 			handle_trans_complete(dev);
 		}
 	}
@@ -2848,36 +2936,36 @@
 	/* SOF received interrupt (for ISO transfer) */
 	if (irq_sts & STS_SRI) {
 		/* FIXME */
-		/* VDBG(dev, "SOF received interrupt\n"); */
+		/* dev_vdbg(&dev->pdev->dev, "SOF received interrupt\n"); */
 	}
 
 	/* port change detect interrupt */
 	if (irq_sts & STS_PCI) {
-		VDBG(dev, "port change detect interrupt\n");
+		dev_vdbg(&dev->pdev->dev, "port change detect interrupt\n");
 		handle_port_change(dev);
 	}
 
 	/* suspend interrrupt */
 	if (irq_sts & STS_SLI) {
-		VDBG(dev, "suspend interrupt\n");
+		dev_vdbg(&dev->pdev->dev, "suspend interrupt\n");
 		handle_bus_suspend(dev);
 	}
 
 	/* USB reset interrupt */
 	if (irq_sts & STS_URI) {
-		VDBG(dev, "USB reset interrupt\n");
+		dev_vdbg(&dev->pdev->dev, "USB reset interrupt\n");
 		handle_usb_reset(dev);
 	}
 
 	/* USB error or system error interrupt */
 	if (irq_sts & (STS_UEI | STS_SEI)) {
 		/* FIXME */
-		WARNING(dev, "error IRQ, irq_sts: %x\n", irq_sts);
+		dev_warn(&dev->pdev->dev, "error IRQ, irq_sts: %x\n", irq_sts);
 	}
 
 	spin_unlock(&dev->lock);
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return IRQ_HANDLED;
 }
 
@@ -2889,15 +2977,59 @@
 {
 	struct langwell_udc	*dev = the_controller;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	complete(dev->done);
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	kfree(dev);
 }
 
 
+/* enable SRAM caching if SRAM detected */
+static void sram_init(struct langwell_udc *dev)
+{
+	struct pci_dev		*pdev = dev->pdev;
+
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
+
+	dev->sram_addr = pci_resource_start(pdev, 1);
+	dev->sram_size = pci_resource_len(pdev, 1);
+	dev_info(&dev->pdev->dev, "Found private SRAM at %x size:%x\n",
+			dev->sram_addr, dev->sram_size);
+	dev->got_sram = 1;
+
+	if (pci_request_region(pdev, 1, kobject_name(&pdev->dev.kobj))) {
+		dev_warn(&dev->pdev->dev, "SRAM request failed\n");
+		dev->got_sram = 0;
+	} else if (!dma_declare_coherent_memory(&pdev->dev, dev->sram_addr,
+			dev->sram_addr, dev->sram_size, DMA_MEMORY_MAP)) {
+		dev_warn(&dev->pdev->dev, "SRAM DMA declare failed\n");
+		pci_release_region(pdev, 1);
+		dev->got_sram = 0;
+	}
+
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
+}
+
+
+/* release SRAM caching */
+static void sram_deinit(struct langwell_udc *dev)
+{
+	struct pci_dev *pdev = dev->pdev;
+
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
+
+	dma_release_declared_memory(&pdev->dev);
+	pci_release_region(pdev, 1);
+
+	dev->got_sram = 0;
+
+	dev_info(&dev->pdev->dev, "release SRAM caching\n");
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
+}
+
+
 /* tear down the binding between this driver and the pci device */
 static void langwell_udc_remove(struct pci_dev *pdev)
 {
@@ -2906,23 +3038,29 @@
 	DECLARE_COMPLETION(done);
 
 	BUG_ON(dev->driver);
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	dev->done = &done;
 
-	/* free memory allocated in probe */
+#ifndef	OTG_TRANSCEIVER
+	/* free dTD dma_pool and dQH */
 	if (dev->dtd_pool)
 		dma_pool_destroy(dev->dtd_pool);
 
+	if (dev->ep_dqh)
+		dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
+			dev->ep_dqh, dev->ep_dqh_dma);
+
+	/* release SRAM caching */
+	if (dev->has_sram && dev->got_sram)
+		sram_deinit(dev);
+#endif
+
 	if (dev->status_req) {
 		kfree(dev->status_req->req.buf);
 		kfree(dev->status_req);
 	}
 
-	if (dev->ep_dqh)
-		dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
-			dev->ep_dqh, dev->ep_dqh_dma);
-
 	kfree(dev->ep);
 
 	/* diable IRQ handler */
@@ -2949,11 +3087,12 @@
 
 	dev->cap_regs = NULL;
 
-	INFO(dev, "unbind\n");
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_info(&dev->pdev->dev, "unbind\n");
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 
 	device_unregister(&dev->gadget.dev);
 	device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
+	device_remove_file(&pdev->dev, &dev_attr_remote_wakeup);
 
 #ifndef	OTG_TRANSCEIVER
 	pci_set_drvdata(pdev, NULL);
@@ -2997,7 +3136,7 @@
 	spin_lock_init(&dev->lock);
 
 	dev->pdev = pdev;
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 #ifdef	OTG_TRANSCEIVER
 	/* PCI device is already enabled by otg_transceiver driver */
@@ -3022,7 +3161,7 @@
 	resource = pci_resource_start(pdev, 0);
 	len = pci_resource_len(pdev, 0);
 	if (!request_mem_region(resource, len, driver_name)) {
-		ERROR(dev, "controller already in use\n");
+		dev_err(&dev->pdev->dev, "controller already in use\n");
 		retval = -EBUSY;
 		goto error;
 	}
@@ -3031,33 +3170,43 @@
 	base = ioremap_nocache(resource, len);
 #endif
 	if (base == NULL) {
-		ERROR(dev, "can't map memory\n");
+		dev_err(&dev->pdev->dev, "can't map memory\n");
 		retval = -EFAULT;
 		goto error;
 	}
 
 	dev->cap_regs = (struct langwell_cap_regs __iomem *) base;
-	VDBG(dev, "dev->cap_regs: %p\n", dev->cap_regs);
+	dev_vdbg(&dev->pdev->dev, "dev->cap_regs: %p\n", dev->cap_regs);
 	dev->op_regs = (struct langwell_op_regs __iomem *)
 		(base + OP_REG_OFFSET);
-	VDBG(dev, "dev->op_regs: %p\n", dev->op_regs);
+	dev_vdbg(&dev->pdev->dev, "dev->op_regs: %p\n", dev->op_regs);
 
 	/* irq setup after old hardware is cleaned up */
 	if (!pdev->irq) {
-		ERROR(dev, "No IRQ. Check PCI setup!\n");
+		dev_err(&dev->pdev->dev, "No IRQ. Check PCI setup!\n");
 		retval = -ENODEV;
 		goto error;
 	}
 
+	dev->has_sram = 1;
+	dev->got_sram = 0;
+	dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram);
+
 #ifndef	OTG_TRANSCEIVER
-	INFO(dev, "irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n",
+	/* enable SRAM caching if detected */
+	if (dev->has_sram && !dev->got_sram)
+		sram_init(dev);
+
+	dev_info(&dev->pdev->dev,
+			"irq %d, io mem: 0x%08lx, len: 0x%08lx, pci mem 0x%p\n",
 			pdev->irq, resource, len, base);
 	/* enables bus-mastering for device dev */
 	pci_set_master(pdev);
 
 	if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED,
 				driver_name, dev) != 0) {
-		ERROR(dev, "request interrupt %d failed\n", pdev->irq);
+		dev_err(&dev->pdev->dev,
+				"request interrupt %d failed\n", pdev->irq);
 		retval = -EBUSY;
 		goto error;
 	}
@@ -3071,32 +3220,34 @@
 	dev->lpm = (readl(&dev->cap_regs->hccparams) & HCC_LEN) ? 1 : 0;
 	dev->dciversion = readw(&dev->cap_regs->dciversion);
 	dev->devcap = (readl(&dev->cap_regs->dccparams) & DEVCAP) ? 1 : 0;
-	VDBG(dev, "dev->lpm: %d\n", dev->lpm);
-	VDBG(dev, "dev->dciversion: 0x%04x\n", dev->dciversion);
-	VDBG(dev, "dccparams: 0x%08x\n", readl(&dev->cap_regs->dccparams));
-	VDBG(dev, "dev->devcap: %d\n", dev->devcap);
+	dev_vdbg(&dev->pdev->dev, "dev->lpm: %d\n", dev->lpm);
+	dev_vdbg(&dev->pdev->dev, "dev->dciversion: 0x%04x\n",
+			dev->dciversion);
+	dev_vdbg(&dev->pdev->dev, "dccparams: 0x%08x\n",
+			readl(&dev->cap_regs->dccparams));
+	dev_vdbg(&dev->pdev->dev, "dev->devcap: %d\n", dev->devcap);
 	if (!dev->devcap) {
-		ERROR(dev, "can't support device mode\n");
+		dev_err(&dev->pdev->dev, "can't support device mode\n");
 		retval = -ENODEV;
 		goto error;
 	}
 
 	/* a pair of endpoints (out/in) for each address */
 	dev->ep_max = DEN(readl(&dev->cap_regs->dccparams)) * 2;
-	VDBG(dev, "dev->ep_max: %d\n", dev->ep_max);
+	dev_vdbg(&dev->pdev->dev, "dev->ep_max: %d\n", dev->ep_max);
 
 	/* allocate endpoints memory */
 	dev->ep = kzalloc(sizeof(struct langwell_ep) * dev->ep_max,
 			GFP_KERNEL);
 	if (!dev->ep) {
-		ERROR(dev, "allocate endpoints memory failed\n");
+		dev_err(&dev->pdev->dev, "allocate endpoints memory failed\n");
 		retval = -ENOMEM;
 		goto error;
 	}
 
 	/* allocate device dQH memory */
 	size = dev->ep_max * sizeof(struct langwell_dqh);
-	VDBG(dev, "orig size = %d\n", size);
+	dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size);
 	if (size < DQH_ALIGNMENT)
 		size = DQH_ALIGNMENT;
 	else if ((size % DQH_ALIGNMENT) != 0) {
@@ -3106,17 +3257,18 @@
 	dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
 					&dev->ep_dqh_dma, GFP_KERNEL);
 	if (!dev->ep_dqh) {
-		ERROR(dev, "allocate dQH memory failed\n");
+		dev_err(&dev->pdev->dev, "allocate dQH memory failed\n");
 		retval = -ENOMEM;
 		goto error;
 	}
 	dev->ep_dqh_size = size;
-	VDBG(dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
+	dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
 
 	/* initialize ep0 status request structure */
 	dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL);
 	if (!dev->status_req) {
-		ERROR(dev, "allocate status_req memory failed\n");
+		dev_err(&dev->pdev->dev,
+				"allocate status_req memory failed\n");
 		retval = -ENOMEM;
 		goto error;
 	}
@@ -3129,7 +3281,10 @@
 	dev->resume_state = USB_STATE_NOTATTACHED;
 	dev->usb_state = USB_STATE_POWERED;
 	dev->ep0_dir = USB_DIR_OUT;
-	dev->remote_wakeup = 0;	/* default to 0 on reset */
+
+	/* remote wakeup reset to 0 when the device is reset */
+	dev->remote_wakeup = 0;
+	dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
 
 #ifndef	OTG_TRANSCEIVER
 	/* reset device controller */
@@ -3174,18 +3329,20 @@
 	}
 
 	/* done */
-	INFO(dev, "%s\n", driver_desc);
-	INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base);
-	INFO(dev, "Driver version: " DRIVER_VERSION "\n");
-	INFO(dev, "Support (max) %d endpoints\n", dev->ep_max);
-	INFO(dev, "Device interface version: 0x%04x\n", dev->dciversion);
-	INFO(dev, "Controller mode: %s\n", dev->devcap ? "Device" : "Host");
-	INFO(dev, "Support USB LPM: %s\n", dev->lpm ? "Yes" : "No");
+	dev_info(&dev->pdev->dev, "%s\n", driver_desc);
+	dev_info(&dev->pdev->dev, "irq %d, pci mem %p\n", pdev->irq, base);
+	dev_info(&dev->pdev->dev, "Driver version: " DRIVER_VERSION "\n");
+	dev_info(&dev->pdev->dev, "Support (max) %d endpoints\n", dev->ep_max);
+	dev_info(&dev->pdev->dev, "Device interface version: 0x%04x\n",
+			dev->dciversion);
+	dev_info(&dev->pdev->dev, "Controller mode: %s\n",
+			dev->devcap ? "Device" : "Host");
+	dev_info(&dev->pdev->dev, "Support USB LPM: %s\n",
+			dev->lpm ? "Yes" : "No");
 
-	VDBG(dev, "After langwell_udc_probe(), print all registers:\n");
-#ifdef	VERBOSE
+	dev_vdbg(&dev->pdev->dev,
+			"After langwell_udc_probe(), print all registers:\n");
 	print_all_registers(dev);
-#endif
 
 	the_controller = dev;
 
@@ -3197,12 +3354,18 @@
 	if (retval)
 		goto error;
 
-	VDBG(dev, "<--- %s()\n", __func__);
+	retval = device_create_file(&pdev->dev, &dev_attr_remote_wakeup);
+	if (retval)
+		goto error_attr1;
+
+	dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 
+error_attr1:
+	device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
 error:
 	if (dev) {
-		DBG(dev, "<--- %s()\n", __func__);
+		dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 		langwell_udc_remove(pdev);
 	}
 
@@ -3214,9 +3377,8 @@
 static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct langwell_udc	*dev = the_controller;
-	u32			devlc;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* disable interrupt and set controller to stop state */
 	langwell_udc_stop(dev);
@@ -3226,20 +3388,34 @@
 		free_irq(pdev->irq, dev);
 	dev->got_irq = 0;
 
-
 	/* save PCI state */
 	pci_save_state(pdev);
 
+	spin_lock_irq(&dev->lock);
+	/* stop all usb activities */
+	stop_activity(dev, dev->driver);
+	spin_unlock_irq(&dev->lock);
+
+	/* free dTD dma_pool and dQH */
+	if (dev->dtd_pool)
+		dma_pool_destroy(dev->dtd_pool);
+
+	if (dev->ep_dqh)
+		dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
+			dev->ep_dqh, dev->ep_dqh_dma);
+
+	/* release SRAM caching */
+	if (dev->has_sram && dev->got_sram)
+		sram_deinit(dev);
+
 	/* set device power state */
 	pci_set_power_state(pdev, PCI_D3hot);
 
 	/* enter PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc |= LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 1);
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -3248,27 +3424,58 @@
 static int langwell_udc_resume(struct pci_dev *pdev)
 {
 	struct langwell_udc	*dev = the_controller;
-	u32			devlc;
+	size_t			size;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* exit PHY low power suspend */
-	devlc = readl(&dev->op_regs->devlc);
-	VDBG(dev, "devlc = 0x%08x\n", devlc);
-	devlc &= ~LPM_PHCD;
-	writel(devlc, &dev->op_regs->devlc);
+	if (dev->pdev->device != 0x0829)
+		langwell_phy_low_power(dev, 0);
 
 	/* set device D0 power state */
 	pci_set_power_state(pdev, PCI_D0);
 
+	/* enable SRAM caching if detected */
+	if (dev->has_sram && !dev->got_sram)
+		sram_init(dev);
+
+	/* allocate device dQH memory */
+	size = dev->ep_max * sizeof(struct langwell_dqh);
+	dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size);
+	if (size < DQH_ALIGNMENT)
+		size = DQH_ALIGNMENT;
+	else if ((size % DQH_ALIGNMENT) != 0) {
+		size += DQH_ALIGNMENT + 1;
+		size &= ~(DQH_ALIGNMENT - 1);
+	}
+	dev->ep_dqh = dma_alloc_coherent(&pdev->dev, size,
+					&dev->ep_dqh_dma, GFP_KERNEL);
+	if (!dev->ep_dqh) {
+		dev_err(&dev->pdev->dev, "allocate dQH memory failed\n");
+		return -ENOMEM;
+	}
+	dev->ep_dqh_size = size;
+	dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
+
+	/* create dTD dma_pool resource */
+	dev->dtd_pool = dma_pool_create("langwell_dtd",
+			&dev->pdev->dev,
+			sizeof(struct langwell_dtd),
+			DTD_ALIGNMENT,
+			DMA_BOUNDARY);
+
+	if (!dev->dtd_pool)
+		return -ENOMEM;
+
 	/* restore PCI state */
 	pci_restore_state(pdev);
 
 	/* enable IRQ handler */
-	if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED, driver_name, dev)
-			!= 0) {
-		ERROR(dev, "request interrupt %d failed\n", pdev->irq);
-		return -1;
+	if (request_irq(pdev->irq, langwell_irq, IRQF_SHARED,
+				driver_name, dev) != 0) {
+		dev_err(&dev->pdev->dev, "request interrupt %d failed\n",
+				pdev->irq);
+		return -EBUSY;
 	}
 	dev->got_irq = 1;
 
@@ -3290,7 +3497,7 @@
 	dev->ep0_state = WAIT_FOR_SETUP;
 	dev->ep0_dir = USB_DIR_OUT;
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 	return 0;
 }
 
@@ -3301,15 +3508,15 @@
 	struct langwell_udc	*dev = the_controller;
 	u32			usbmode;
 
-	DBG(dev, "---> %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
 	/* reset controller mode to IDLE */
 	usbmode = readl(&dev->op_regs->usbmode);
-	DBG(dev, "usbmode = 0x%08x\n", usbmode);
+	dev_dbg(&dev->pdev->dev, "usbmode = 0x%08x\n", usbmode);
 	usbmode &= (~3 | MODE_IDLE);
 	writel(usbmode, &dev->op_regs->usbmode);
 
-	DBG(dev, "<--- %s()\n", __func__);
+	dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -3324,7 +3531,6 @@
 }, { /* end: all zeroes */ }
 };
 
-
 MODULE_DEVICE_TABLE(pci, pci_ids);
 
 
@@ -3343,12 +3549,6 @@
 };
 
 
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-
 static int __init init(void)
 {
 #ifdef	OTG_TRANSCEIVER
@@ -3370,3 +3570,9 @@
 }
 module_exit(cleanup);
 
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Xiaochen Shen <xiaochen.shen@intel.com>");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h
index 9719934..f1d9c1b 100644
--- a/drivers/usb/gadget/langwell_udc.h
+++ b/drivers/usb/gadget/langwell_udc.h
@@ -18,11 +18,7 @@
  */
 
 #include <linux/usb/langwell_udc.h>
-
-#if defined(CONFIG_USB_LANGWELL_OTG)
 #include <linux/usb/langwell_otg.h>
-#endif
-
 
 /*-------------------------------------------------------------------------*/
 
@@ -199,7 +195,9 @@
 				vbus_active:1,
 				suspended:1,
 				stopped:1,
-				lpm:1;	/* LPM capability */
+				lpm:1,		/* LPM capability */
+				has_sram:1,	/* SRAM caching */
+				got_sram:1;
 
 	/* pci state used to access those endpoints */
 	struct pci_dev		*pdev;
@@ -224,5 +222,12 @@
 
 	/* make sure release() is done */
 	struct completion	*done;
+
+	/* for private SRAM caching */
+	unsigned int		sram_addr;
+	unsigned int		sram_size;
+
+	/* device status data for get_status request */
+	u16			dev_status;
 };
 
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index fded3fc..6b58bd8 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -408,7 +408,8 @@
 /*
   Register entry point for the peripheral controller driver.
 */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct lh7a40x_udc *dev = the_controller;
 	int retval;
@@ -417,7 +418,7 @@
 
 	if (!driver
 			|| driver->speed != USB_SPEED_FULL
-			|| !driver->bind
+			|| !bind
 			|| !driver->disconnect
 			|| !driver->setup)
 		return -EINVAL;
@@ -431,7 +432,7 @@
 	dev->gadget.dev.driver = &driver->driver;
 
 	device_add(&dev->gadget.dev);
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
 		printk(KERN_WARNING "%s: bind to driver %s --> error %d\n",
 		       dev->gadget.name, driver->driver.name, retval);
@@ -453,8 +454,7 @@
 
 	return 0;
 }
-
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /*
   Unregister entry point for the peripheral controller driver.
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index e03058f..51b19f3 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1454,14 +1454,15 @@
 /*-------------------------------------------------------------------------*/
 static struct m66592 *the_controller;
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct m66592 *m66592 = the_controller;
 	int retval;
 
 	if (!driver
 			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
+			|| !bind
 			|| !driver->setup)
 		return -EINVAL;
 	if (!m66592)
@@ -1480,7 +1481,7 @@
 		goto error;
 	}
 
-	retval = driver->bind (&m66592->gadget);
+	retval = bind(&m66592->gadget);
 	if (retval) {
 		pr_err("bind to driver error (%d)\n", retval);
 		device_del(&m66592->gadget.dev);
@@ -1505,7 +1506,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 585f255..0769179 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -75,10 +75,6 @@
 	/* Vendor and product id can be overridden by module parameters.  */
 	.idVendor =		cpu_to_le16(FSG_VENDOR_ID),
 	.idProduct =		cpu_to_le16(FSG_PRODUCT_ID),
-	/* .bcdDevice = f(hardware) */
-	/* .iManufacturer = DYNAMIC */
-	/* .iProduct = DYNAMIC */
-	/* NO SERIAL NUMBER */
 	.bNumConfigurations =	1,
 };
 
@@ -86,7 +82,8 @@
 	.bLength =		sizeof otg_descriptor,
 	.bDescriptorType =	USB_DT_OTG,
 
-	/* REVISIT SRP-only hardware is possible, although
+	/*
+	 * REVISIT SRP-only hardware is possible, although
 	 * it would not be called "OTG" ...
 	 */
 	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
@@ -98,33 +95,6 @@
 };
 
 
-/* string IDs are assigned dynamically */
-
-#define STRING_MANUFACTURER_IDX		0
-#define STRING_PRODUCT_IDX		1
-#define STRING_CONFIGURATION_IDX	2
-
-static char manufacturer[50];
-
-static struct usb_string strings_dev[] = {
-	[STRING_MANUFACTURER_IDX].s = manufacturer,
-	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
-	[STRING_CONFIGURATION_IDX].s = "Self Powered",
-	{  } /* end of list */
-};
-
-static struct usb_gadget_strings stringtab_dev = {
-	.language	= 0x0409,	/* en-us */
-	.strings	= strings_dev,
-};
-
-static struct usb_gadget_strings *dev_strings[] = {
-	&stringtab_dev,
-	NULL,
-};
-
-
-
 /****************************** Configurations ******************************/
 
 static struct fsg_module_parameters mod_data = {
@@ -141,7 +111,7 @@
 	return 0;
 }
 
-static int __ref msg_do_config(struct usb_configuration *c)
+static int __init msg_do_config(struct usb_configuration *c)
 {
 	static const struct fsg_operations ops = {
 		.thread_exits = msg_thread_exits,
@@ -171,54 +141,23 @@
 
 static struct usb_configuration msg_config_driver = {
 	.label			= "Linux File-Backed Storage",
-	.bind			= msg_do_config,
 	.bConfigurationValue	= 1,
-	/* .iConfiguration = DYNAMIC */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
 };
 
 
-
 /****************************** Gadget Bind ******************************/
 
-
-static int __ref msg_bind(struct usb_composite_dev *cdev)
+static int __init msg_bind(struct usb_composite_dev *cdev)
 {
-	struct usb_gadget *gadget = cdev->gadget;
 	int status;
 
-	/* Allocate string descriptor numbers ... note that string
-	 * contents can be overridden by the composite_dev glue.
-	 */
-
-	/* device descriptor strings: manufacturer, product */
-	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
-	         init_utsname()->sysname, init_utsname()->release,
-	         gadget->name);
-	status = usb_string_id(cdev);
-	if (status < 0)
-		return status;
-	strings_dev[STRING_MANUFACTURER_IDX].id = status;
-	msg_device_desc.iManufacturer = status;
-
-	status = usb_string_id(cdev);
-	if (status < 0)
-		return status;
-	strings_dev[STRING_PRODUCT_IDX].id = status;
-	msg_device_desc.iProduct = status;
-
-	status = usb_string_id(cdev);
-	if (status < 0)
-		return status;
-	strings_dev[STRING_CONFIGURATION_IDX].id = status;
-	msg_config_driver.iConfiguration = status;
-
-	/* register our second configuration */
-	status = usb_add_config(cdev, &msg_config_driver);
+	status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
 	if (status < 0)
 		return status;
 
-	dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
+	dev_info(&cdev->gadget->dev,
+		 DRIVER_DESC ", version: " DRIVER_VERSION "\n");
 	set_bit(0, &msg_registered);
 	return 0;
 }
@@ -226,12 +165,11 @@
 
 /****************************** Some noise ******************************/
 
-
 static struct usb_composite_driver msg_driver = {
 	.name		= "g_mass_storage",
 	.dev		= &msg_device_desc,
-	.strings	= dev_strings,
-	.bind		= msg_bind,
+	.iProduct	= DRIVER_DESC,
+	.needs_serial	= 1,
 };
 
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -240,7 +178,7 @@
 
 static int __init msg_init(void)
 {
-	return usb_composite_register(&msg_driver);
+	return usb_composite_probe(&msg_driver, msg_bind);
 }
 module_init(msg_init);
 
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 795d762..d9feced 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -74,8 +74,8 @@
 
 /***************************** Device Descriptor ****************************/
 
-#define MULTI_VENDOR_NUM	0x0525	/* XXX NetChip */
-#define MULTI_PRODUCT_NUM	0xa4ab	/* XXX */
+#define MULTI_VENDOR_NUM	0x1d6b	/* Linux Foundation */
+#define MULTI_PRODUCT_NUM	0x0104	/* Multifunction Composite Gadget */
 
 
 enum {
@@ -121,8 +121,6 @@
 
 
 enum {
-	MULTI_STRING_MANUFACTURER_IDX,
-	MULTI_STRING_PRODUCT_IDX,
 #ifdef CONFIG_USB_G_MULTI_RNDIS
 	MULTI_STRING_RNDIS_CONFIG_IDX,
 #endif
@@ -131,11 +129,7 @@
 #endif
 };
 
-static char manufacturer[50];
-
 static struct usb_string strings_dev[] = {
-	[MULTI_STRING_MANUFACTURER_IDX].s = manufacturer,
-	[MULTI_STRING_PRODUCT_IDX].s      = DRIVER_DESC,
 #ifdef CONFIG_USB_G_MULTI_RNDIS
 	[MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS",
 #endif
@@ -170,7 +164,7 @@
 
 #ifdef USB_ETH_RNDIS
 
-static __ref int rndis_do_config(struct usb_configuration *c)
+static __init int rndis_do_config(struct usb_configuration *c)
 {
 	int ret;
 
@@ -197,7 +191,6 @@
 static int rndis_config_register(struct usb_composite_dev *cdev)
 {
 	static struct usb_configuration config = {
-		.bind			= rndis_do_config,
 		.bConfigurationValue	= MULTI_RNDIS_CONFIG_NUM,
 		.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
 	};
@@ -205,7 +198,7 @@
 	config.label          = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s;
 	config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id;
 
-	return usb_add_config(cdev, &config);
+	return usb_add_config(cdev, &config, rndis_do_config);
 }
 
 #else
@@ -222,7 +215,7 @@
 
 #ifdef CONFIG_USB_G_MULTI_CDC
 
-static __ref int cdc_do_config(struct usb_configuration *c)
+static __init int cdc_do_config(struct usb_configuration *c)
 {
 	int ret;
 
@@ -249,7 +242,6 @@
 static int cdc_config_register(struct usb_composite_dev *cdev)
 {
 	static struct usb_configuration config = {
-		.bind			= cdc_do_config,
 		.bConfigurationValue	= MULTI_CDC_CONFIG_NUM,
 		.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
 	};
@@ -257,7 +249,7 @@
 	config.label          = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s;
 	config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id;
 
-	return usb_add_config(cdev, &config);
+	return usb_add_config(cdev, &config, cdc_do_config);
 }
 
 #else
@@ -314,20 +306,11 @@
 		device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
 	}
 
-	/* allocate string descriptor numbers */
-	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
-	         init_utsname()->sysname, init_utsname()->release,
-	         gadget->name);
-
+	/* allocate string IDs */
 	status = usb_string_ids_tab(cdev, strings_dev);
 	if (unlikely(status < 0))
 		goto fail2;
 
-	device_desc.iManufacturer =
-		strings_dev[MULTI_STRING_MANUFACTURER_IDX].id;
-	device_desc.iProduct      =
-		strings_dev[MULTI_STRING_PRODUCT_IDX].id;
-
 	/* register configurations */
 	status = rndis_config_register(cdev);
 	if (unlikely(status < 0))
@@ -368,14 +351,15 @@
 	.name		= "g_multi",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= multi_bind,
 	.unbind		= __exit_p(multi_unbind),
+	.iProduct	= DRIVER_DESC,
+	.needs_serial	= 1,
 };
 
 
 static int __init multi_init(void)
 {
-	return usb_composite_register(&multi_driver);
+	return usb_composite_probe(&multi_driver, multi_bind);
 }
 module_init(multi_init);
 
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 9498be8..d09155b 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1929,7 +1929,8 @@
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct net2280		*dev = the_controller;
 	int			retval;
@@ -1941,8 +1942,7 @@
 	 */
 	if (!driver
 			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
-			|| !driver->setup)
+			|| !bind || !driver->setup)
 		return -EINVAL;
 	if (!dev)
 		return -ENODEV;
@@ -1957,7 +1957,7 @@
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
-	retval = driver->bind (&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
 		DEBUG (dev, "bind to driver %s --> %d\n",
 				driver->driver.name, retval);
@@ -1993,7 +1993,7 @@
 	dev->driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL (usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void
 stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c
index 7d6b66a..b5364f9d 100644
--- a/drivers/usb/gadget/nokia.c
+++ b/drivers/usb/gadget/nokia.c
@@ -135,7 +135,6 @@
 
 static struct usb_configuration nokia_config_500ma_driver = {
 	.label		= "Bus Powered",
-	.bind		= nokia_bind_config,
 	.bConfigurationValue = 1,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_ONE,
@@ -144,7 +143,6 @@
 
 static struct usb_configuration nokia_config_100ma_driver = {
 	.label		= "Self Powered",
-	.bind		= nokia_bind_config,
 	.bConfigurationValue = 2,
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
@@ -206,11 +204,13 @@
 	}
 
 	/* finaly register the configuration */
-	status = usb_add_config(cdev, &nokia_config_500ma_driver);
+	status = usb_add_config(cdev, &nokia_config_500ma_driver,
+			nokia_bind_config);
 	if (status < 0)
 		goto err_usb;
 
-	status = usb_add_config(cdev, &nokia_config_100ma_driver);
+	status = usb_add_config(cdev, &nokia_config_100ma_driver,
+			nokia_bind_config);
 	if (status < 0)
 		goto err_usb;
 
@@ -241,13 +241,12 @@
 	.name		= "g_nokia",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= nokia_bind,
 	.unbind		= __exit_p(nokia_unbind),
 };
 
 static int __init nokia_init(void)
 {
-	return usb_composite_register(&nokia_driver);
+	return usb_composite_probe(&nokia_driver, nokia_bind);
 }
 module_init(nokia_init);
 
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index f81e4f0..61d3ca6 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2102,7 +2102,8 @@
 		);
 }
 
-int usb_gadget_register_driver (struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	int		status = -ENODEV;
 	struct omap_ep	*ep;
@@ -2114,8 +2115,7 @@
 	if (!driver
 			// FIXME if otg, check:  driver->is_otg
 			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
-			|| !driver->setup)
+			|| !bind || !driver->setup)
 		return -EINVAL;
 
 	spin_lock_irqsave(&udc->lock, flags);
@@ -2145,7 +2145,7 @@
 	if (udc->dc_clk != NULL)
 		omap_udc_enable_clock(1);
 
-	status = driver->bind (&udc->gadget);
+	status = bind(&udc->gadget);
 	if (status) {
 		DBG("bind to %s --> %d\n", driver->driver.name, status);
 		udc->gadget.dev.driver = NULL;
@@ -2186,7 +2186,7 @@
 		omap_udc_enable_clock(0);
 	return status;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index cf241c3..2fc8636 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -884,7 +884,8 @@
 	.fsync =	printer_fsync,
 	.poll =		printer_poll,
 	.unlocked_ioctl = printer_ioctl,
-	.release =	printer_close
+	.release =	printer_close,
+	.llseek =	noop_llseek,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1347,7 +1348,7 @@
 	set_gadget_data(gadget, NULL);
 }
 
-static int __ref
+static int __init
 printer_bind(struct usb_gadget *gadget)
 {
 	struct printer_dev	*dev;
@@ -1543,7 +1544,6 @@
 	.speed		= DEVSPEED,
 
 	.function	= (char *) driver_desc,
-	.bind		= printer_bind,
 	.unbind		= printer_unbind,
 
 	.setup		= printer_setup,
@@ -1579,11 +1579,11 @@
 		return status;
 	}
 
-	status = usb_gadget_register_driver(&printer_driver);
+	status = usb_gadget_probe_driver(&printer_driver, printer_bind);
 	if (status) {
 		class_destroy(usb_gadget_class);
 		unregister_chrdev_region(g_printer_devno, 1);
-		DBG(dev, "usb_gadget_register_driver %x\n", status);
+		DBG(dev, "usb_gadget_probe_driver %x\n", status);
 	}
 
 	return status;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index be5fb34..b37f92c 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -1280,14 +1280,15 @@
  * disconnect is reported.  then a host may connect again, or
  * the driver might get unbound.
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct pxa25x_udc	*dev = the_controller;
 	int			retval;
 
 	if (!driver
 			|| driver->speed < USB_SPEED_FULL
-			|| !driver->bind
+			|| !bind
 			|| !driver->disconnect
 			|| !driver->setup)
 		return -EINVAL;
@@ -1308,7 +1309,7 @@
 		dev->gadget.dev.driver = NULL;
 		return retval;
 	}
-	retval = driver->bind(&dev->gadget);
+	retval = bind(&dev->gadget);
 	if (retval) {
 		DMSG("bind to driver %s --> error %d\n",
 				driver->driver.name, retval);
@@ -1338,7 +1339,7 @@
 bind_fail:
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void
 stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 9807624..027d66f 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -1792,8 +1792,9 @@
 }
 
 /**
- * usb_gadget_register_driver - Register gadget driver
+ * usb_gadget_probe_driver - Register gadget driver
  * @driver: gadget driver
+ * @bind: bind function
  *
  * When a driver is successfully registered, it will receive control requests
  * including set_configuration(), which enables non-control requests.  Then
@@ -1805,12 +1806,13 @@
  *
  * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct pxa_udc *udc = the_controller;
 	int retval;
 
-	if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind
+	if (!driver || driver->speed < USB_SPEED_FULL || !bind
 			|| !driver->disconnect || !driver->setup)
 		return -EINVAL;
 	if (!udc)
@@ -1828,7 +1830,7 @@
 		dev_err(udc->dev, "device_add error %d\n", retval);
 		goto add_fail;
 	}
-	retval = driver->bind(&udc->gadget);
+	retval = bind(&udc->gadget);
 	if (retval) {
 		dev_err(udc->dev, "bind to driver %s --> error %d\n",
 			driver->driver.name, retval);
@@ -1859,7 +1861,7 @@
 	udc->gadget.dev.driver = NULL;
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 
 /**
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index 2456ccd..20d43da 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -42,6 +42,7 @@
 	"ep8", "ep9",
 };
 
+static void init_controller(struct r8a66597 *r8a66597);
 static void disable_controller(struct r8a66597 *r8a66597);
 static void irq_ep0_write(struct r8a66597_ep *ep, struct r8a66597_request *req);
 static void irq_packet_write(struct r8a66597_ep *ep,
@@ -104,6 +105,8 @@
 	spin_lock(&r8a66597->lock);
 
 	disable_controller(r8a66597);
+	init_controller(r8a66597);
+	r8a66597_bset(r8a66597, VBSE, INTENB0);
 	INIT_LIST_HEAD(&r8a66597->ep[0].queue);
 }
 
@@ -274,7 +277,7 @@
 	}
 
 	if (buf_bsize && ((bufnum + 16) >= R8A66597_MAX_BUFNUM)) {
-		pr_err(KERN_ERR "r8a66597 pipe memory is insufficient\n");
+		pr_err("r8a66597 pipe memory is insufficient\n");
 		return -ENOMEM;
 	}
 
@@ -1405,14 +1408,15 @@
 /*-------------------------------------------------------------------------*/
 static struct r8a66597 *the_controller;
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct r8a66597 *r8a66597 = the_controller;
 	int retval;
 
 	if (!driver
 			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
+			|| !bind
 			|| !driver->setup)
 		return -EINVAL;
 	if (!r8a66597)
@@ -1431,7 +1435,7 @@
 		goto error;
 	}
 
-	retval = driver->bind(&r8a66597->gadget);
+	retval = bind(&r8a66597->gadget);
 	if (retval) {
 		printk(KERN_ERR "bind to driver error (%d)\n", retval);
 		device_del(&r8a66597->gadget.dev);
@@ -1456,7 +1460,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h
index f763b51..5fc22e0 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/r8a66597-udc.h
@@ -136,7 +136,7 @@
 				      int len)
 {
 	void __iomem *fifoaddr = r8a66597->reg + offset;
-	unsigned int data;
+	unsigned int data = 0;
 	int i;
 
 	if (r8a66597->pdata->on_chip) {
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 972d5dd..5b31404 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -61,17 +61,17 @@
 #define RNDIS_MAX_CONFIGS	1
 
 
-static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
+static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
 
 /* Driver Version */
-static const __le32 rndis_driver_version = cpu_to_le32 (1);
+static const __le32 rndis_driver_version = cpu_to_le32(1);
 
 /* Function Prototypes */
-static rndis_resp_t *rndis_add_response (int configNr, u32 length);
+static rndis_resp_t *rndis_add_response(int configNr, u32 length);
 
 
 /* supported OIDs */
-static const u32 oid_supported_list [] =
+static const u32 oid_supported_list[] =
 {
 	/* the general stuff */
 	OID_GEN_SUPPORTED_LIST,
@@ -161,21 +161,20 @@
 
 
 /* NDIS Functions */
-static int
-gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
-		rndis_resp_t *r)
+static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
+			       unsigned buf_len, rndis_resp_t *r)
 {
-	int			retval = -ENOTSUPP;
-	u32			length = 4;	/* usually */
-	__le32			*outbuf;
-	int			i, count;
-	rndis_query_cmplt_type	*resp;
-	struct net_device	*net;
+	int retval = -ENOTSUPP;
+	u32 length = 4;	/* usually */
+	__le32 *outbuf;
+	int i, count;
+	rndis_query_cmplt_type *resp;
+	struct net_device *net;
 	struct rtnl_link_stats64 temp;
 	const struct rtnl_link_stats64 *stats;
 
 	if (!r) return -ENOMEM;
-	resp = (rndis_query_cmplt_type *) r->buf;
+	resp = (rndis_query_cmplt_type *)r->buf;
 
 	if (!resp) return -ENOMEM;
 
@@ -191,8 +190,8 @@
 	}
 
 	/* response goes here, right after the header */
-	outbuf = (__le32 *) &resp[1];
-	resp->InformationBufferOffset = cpu_to_le32 (16);
+	outbuf = (__le32 *)&resp[1];
+	resp->InformationBufferOffset = cpu_to_le32(16);
 
 	net = rndis_per_dev_params[configNr].dev;
 	stats = dev_get_stats(net, &temp);
@@ -204,10 +203,10 @@
 	/* mandatory */
 	case OID_GEN_SUPPORTED_LIST:
 		pr_debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
-		length = sizeof (oid_supported_list);
-		count  = length / sizeof (u32);
+		length = sizeof(oid_supported_list);
+		count  = length / sizeof(u32);
 		for (i = 0; i < count; i++)
-			outbuf[i] = cpu_to_le32 (oid_supported_list[i]);
+			outbuf[i] = cpu_to_le32(oid_supported_list[i]);
 		retval = 0;
 		break;
 
@@ -220,14 +219,14 @@
 		 * reddite ergo quae sunt Caesaris Caesari
 		 * et quae sunt Dei Deo!
 		 */
-		*outbuf = cpu_to_le32 (0);
+		*outbuf = cpu_to_le32(0);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MEDIA_SUPPORTED:
 		pr_debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
-		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
+		*outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
 		retval = 0;
 		break;
 
@@ -235,16 +234,16 @@
 	case OID_GEN_MEDIA_IN_USE:
 		pr_debug("%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);
+		*outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_MAXIMUM_FRAME_SIZE:
 		pr_debug("%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);
+		if (rndis_per_dev_params[configNr].dev) {
+			*outbuf = cpu_to_le32(
+				rndis_per_dev_params[configNr].dev->mtu);
 			retval = 0;
 		}
 		break;
@@ -253,21 +252,21 @@
 	case OID_GEN_LINK_SPEED:
 		if (rndis_debug > 1)
 			pr_debug("%s: OID_GEN_LINK_SPEED\n", __func__);
-		if (rndis_per_dev_params [configNr].media_state
+		if (rndis_per_dev_params[configNr].media_state
 				== NDIS_MEDIA_STATE_DISCONNECTED)
-			*outbuf = cpu_to_le32 (0);
+			*outbuf = cpu_to_le32(0);
 		else
-			*outbuf = cpu_to_le32 (
-				rndis_per_dev_params [configNr].speed);
+			*outbuf = cpu_to_le32(
+				rndis_per_dev_params[configNr].speed);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_TRANSMIT_BLOCK_SIZE:
 		pr_debug("%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);
+		if (rndis_per_dev_params[configNr].dev) {
+			*outbuf = cpu_to_le32(
+				rndis_per_dev_params[configNr].dev->mtu);
 			retval = 0;
 		}
 		break;
@@ -275,9 +274,9 @@
 	/* mandatory */
 	case OID_GEN_RECEIVE_BLOCK_SIZE:
 		pr_debug("%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);
+		if (rndis_per_dev_params[configNr].dev) {
+			*outbuf = cpu_to_le32(
+				rndis_per_dev_params[configNr].dev->mtu);
 			retval = 0;
 		}
 		break;
@@ -285,18 +284,20 @@
 	/* mandatory */
 	case OID_GEN_VENDOR_ID:
 		pr_debug("%s: OID_GEN_VENDOR_ID\n", __func__);
-		*outbuf = cpu_to_le32 (
-			rndis_per_dev_params [configNr].vendorID);
+		*outbuf = cpu_to_le32(
+			rndis_per_dev_params[configNr].vendorID);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_GEN_VENDOR_DESCRIPTION:
 		pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
-		if ( rndis_per_dev_params [configNr].vendorDescr ) {
-			length = strlen (rndis_per_dev_params [configNr].vendorDescr);
-			memcpy (outbuf,
-				rndis_per_dev_params [configNr].vendorDescr, length);
+		if (rndis_per_dev_params[configNr].vendorDescr) {
+			length = strlen(rndis_per_dev_params[configNr].
+					vendorDescr);
+			memcpy(outbuf,
+				rndis_per_dev_params[configNr].vendorDescr,
+				length);
 		} else {
 			outbuf[0] = 0;
 		}
@@ -313,7 +314,7 @@
 	/* mandatory */
 	case OID_GEN_CURRENT_PACKET_FILTER:
 		pr_debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
-		*outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
+		*outbuf = cpu_to_le32(*rndis_per_dev_params[configNr].filter);
 		retval = 0;
 		break;
 
@@ -328,14 +329,14 @@
 	case OID_GEN_MEDIA_CONNECT_STATUS:
 		if (rndis_debug > 1)
 			pr_debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
-		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
+		*outbuf = cpu_to_le32(rndis_per_dev_params[configNr]
 						.media_state);
 		retval = 0;
 		break;
 
 	case OID_GEN_PHYSICAL_MEDIUM:
 		pr_debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
-		*outbuf = cpu_to_le32 (0);
+		*outbuf = cpu_to_le32(0);
 		retval = 0;
 		break;
 
@@ -409,10 +410,10 @@
 	/* mandatory */
 	case OID_802_3_PERMANENT_ADDRESS:
 		pr_debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
-		if (rndis_per_dev_params [configNr].dev) {
+		if (rndis_per_dev_params[configNr].dev) {
 			length = ETH_ALEN;
-			memcpy (outbuf,
-				rndis_per_dev_params [configNr].host_mac,
+			memcpy(outbuf,
+				rndis_per_dev_params[configNr].host_mac,
 				length);
 			retval = 0;
 		}
@@ -421,9 +422,9 @@
 	/* mandatory */
 	case OID_802_3_CURRENT_ADDRESS:
 		pr_debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
-		if (rndis_per_dev_params [configNr].dev) {
+		if (rndis_per_dev_params[configNr].dev) {
 			length = ETH_ALEN;
-			memcpy (outbuf,
+			memcpy(outbuf,
 				rndis_per_dev_params [configNr].host_mac,
 				length);
 			retval = 0;
@@ -434,7 +435,7 @@
 	case OID_802_3_MULTICAST_LIST:
 		pr_debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
 		/* Multicast base address only */
-		*outbuf = cpu_to_le32 (0xE0000000);
+		*outbuf = cpu_to_le32(0xE0000000);
 		retval = 0;
 		break;
 
@@ -442,7 +443,7 @@
 	case OID_802_3_MAXIMUM_LIST_SIZE:
 		pr_debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
 		/* Multicast base address only */
-		*outbuf = cpu_to_le32 (1);
+		*outbuf = cpu_to_le32(1);
 		retval = 0;
 		break;
 
@@ -466,14 +467,14 @@
 	/* mandatory */
 	case OID_802_3_XMIT_ONE_COLLISION:
 		pr_debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
-		*outbuf = cpu_to_le32 (0);
+		*outbuf = cpu_to_le32(0);
 		retval = 0;
 		break;
 
 	/* mandatory */
 	case OID_802_3_XMIT_MORE_COLLISIONS:
 		pr_debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
-		*outbuf = cpu_to_le32 (0);
+		*outbuf = cpu_to_le32(0);
 		retval = 0;
 		break;
 
@@ -484,22 +485,22 @@
 	if (retval < 0)
 		length = 0;
 
-	resp->InformationBufferLength = cpu_to_le32 (length);
-	r->length = length + sizeof *resp;
-	resp->MessageLength = cpu_to_le32 (r->length);
+	resp->InformationBufferLength = cpu_to_le32(length);
+	r->length = length + sizeof(*resp);
+	resp->MessageLength = cpu_to_le32(r->length);
 	return retval;
 }
 
-static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
-			rndis_resp_t *r)
+static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
+			     rndis_resp_t *r)
 {
-	rndis_set_cmplt_type		*resp;
-	int				i, retval = -ENOTSUPP;
-	struct rndis_params		*params;
+	rndis_set_cmplt_type *resp;
+	int i, retval = -ENOTSUPP;
+	struct rndis_params *params;
 
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_set_cmplt_type *) r->buf;
+	resp = (rndis_set_cmplt_type *)r->buf;
 	if (!resp)
 		return -ENOMEM;
 
@@ -514,7 +515,7 @@
 		}
 	}
 
-	params = &rndis_per_dev_params [configNr];
+	params = &rndis_per_dev_params[configNr];
 	switch (OID) {
 	case OID_GEN_CURRENT_PACKET_FILTER:
 
@@ -537,11 +538,11 @@
 			params->state = RNDIS_DATA_INITIALIZED;
 			netif_carrier_on(params->dev);
 			if (netif_running(params->dev))
-				netif_wake_queue (params->dev);
+				netif_wake_queue(params->dev);
 		} else {
 			params->state = RNDIS_INITIALIZED;
-			netif_carrier_off (params->dev);
-			netif_stop_queue (params->dev);
+			netif_carrier_off(params->dev);
+			netif_stop_queue(params->dev);
 		}
 		break;
 
@@ -563,48 +564,47 @@
  * Response Functions
  */
 
-static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
+static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
 {
-	rndis_init_cmplt_type	*resp;
-	rndis_resp_t            *r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_init_cmplt_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
 	if (!params->dev)
 		return -ENOTSUPP;
 
-	r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
+	r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_init_cmplt_type *) r->buf;
+	resp = (rndis_init_cmplt_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (
-			REMOTE_NDIS_INITIALIZE_CMPLT);
-	resp->MessageLength = cpu_to_le32 (52);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_INITIALIZE_CMPLT);
+	resp->MessageLength = cpu_to_le32(52);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
-	resp->MajorVersion = cpu_to_le32 (RNDIS_MAJOR_VERSION);
-	resp->MinorVersion = cpu_to_le32 (RNDIS_MINOR_VERSION);
-	resp->DeviceFlags = cpu_to_le32 (RNDIS_DF_CONNECTIONLESS);
-	resp->Medium = cpu_to_le32 (RNDIS_MEDIUM_802_3);
-	resp->MaxPacketsPerTransfer = cpu_to_le32 (1);
-	resp->MaxTransferSize = cpu_to_le32 (
+	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
+	resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION);
+	resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
+	resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
+	resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
+	resp->MaxPacketsPerTransfer = cpu_to_le32(1);
+	resp->MaxTransferSize = cpu_to_le32(
 		  params->dev->mtu
-		+ sizeof (struct ethhdr)
-		+ sizeof (struct rndis_packet_msg_type)
+		+ sizeof(struct ethhdr)
+		+ sizeof(struct rndis_packet_msg_type)
 		+ 22);
-	resp->PacketAlignmentFactor = cpu_to_le32 (0);
-	resp->AFListOffset = cpu_to_le32 (0);
-	resp->AFListSize = cpu_to_le32 (0);
+	resp->PacketAlignmentFactor = cpu_to_le32(0);
+	resp->AFListOffset = cpu_to_le32(0);
+	resp->AFListSize = cpu_to_le32(0);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
+static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
 {
 	rndis_query_cmplt_type *resp;
-	rndis_resp_t            *r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
 	/* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */
 	if (!params->dev)
@@ -616,47 +616,46 @@
 	 * rndis_query_cmplt_type followed by data.
 	 * oid_supported_list is the largest data reply
 	 */
-	r = rndis_add_response (configNr,
-		sizeof (oid_supported_list) + sizeof(rndis_query_cmplt_type));
+	r = rndis_add_response(configNr,
+		sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_query_cmplt_type *) r->buf;
+	resp = (rndis_query_cmplt_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
 
-	if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID),
+	if (gen_ndis_query_resp(configNr, le32_to_cpu(buf->OID),
 			le32_to_cpu(buf->InformationBufferOffset)
-					+ 8 + (u8 *) buf,
+					+ 8 + (u8 *)buf,
 			le32_to_cpu(buf->InformationBufferLength),
 			r)) {
 		/* OID not supported */
-		resp->Status = cpu_to_le32 (
-				RNDIS_STATUS_NOT_SUPPORTED);
-		resp->MessageLength = cpu_to_le32 (sizeof *resp);
-		resp->InformationBufferLength = cpu_to_le32 (0);
-		resp->InformationBufferOffset = cpu_to_le32 (0);
+		resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
+		resp->MessageLength = cpu_to_le32(sizeof *resp);
+		resp->InformationBufferLength = cpu_to_le32(0);
+		resp->InformationBufferOffset = cpu_to_le32(0);
 	} else
-		resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+		resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
+static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
 {
-	u32			BufLength, BufOffset;
-	rndis_set_cmplt_type	*resp;
-	rndis_resp_t		*r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	u32 BufLength, BufOffset;
+	rndis_set_cmplt_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
-	r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
+	r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_set_cmplt_type *) r->buf;
+	resp = (rndis_set_cmplt_type *)r->buf;
 
-	BufLength = le32_to_cpu (buf->InformationBufferLength);
-	BufOffset = le32_to_cpu (buf->InformationBufferOffset);
+	BufLength = le32_to_cpu(buf->InformationBufferLength);
+	BufOffset = le32_to_cpu(buf->InformationBufferOffset);
 
 #ifdef	VERBOSE_DEBUG
 	pr_debug("%s: Length: %d\n", __func__, BufLength);
@@ -670,59 +669,59 @@
 	pr_debug("\n");
 #endif
 
-	resp->MessageType = cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
-	resp->MessageLength = cpu_to_le32 (16);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_SET_CMPLT);
+	resp->MessageLength = cpu_to_le32(16);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID),
-			((u8 *) buf) + 8 + BufOffset, BufLength, r))
-		resp->Status = cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
+	if (gen_ndis_set_resp(configNr, le32_to_cpu(buf->OID),
+			((u8 *)buf) + 8 + BufOffset, BufLength, r))
+		resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
 	else
-		resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+		resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
+static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
 {
-	rndis_reset_cmplt_type	*resp;
-	rndis_resp_t		*r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_reset_cmplt_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
-	r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
+	r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_reset_cmplt_type *) r->buf;
+	resp = (rndis_reset_cmplt_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);
-	resp->MessageLength = cpu_to_le32 (16);
-	resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_RESET_CMPLT);
+	resp->MessageLength = cpu_to_le32(16);
+	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 	/* resent information */
-	resp->AddressingReset = cpu_to_le32 (1);
+	resp->AddressingReset = cpu_to_le32(1);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-static int rndis_keepalive_response (int configNr,
-				rndis_keepalive_msg_type *buf)
+static int rndis_keepalive_response(int configNr,
+				    rndis_keepalive_msg_type *buf)
 {
-	rndis_keepalive_cmplt_type	*resp;
-	rndis_resp_t			*r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_keepalive_cmplt_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
 	/* host "should" check only in RNDIS_DATA_INITIALIZED state */
 
-	r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
+	r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_keepalive_cmplt_type *) r->buf;
+	resp = (rndis_keepalive_cmplt_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (
+	resp->MessageType = cpu_to_le32(
 			REMOTE_NDIS_KEEPALIVE_CMPLT);
-	resp->MessageLength = cpu_to_le32 (16);
+	resp->MessageLength = cpu_to_le32(16);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	resp->Status = cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 
 	params->resp_avail(params->v);
 	return 0;
@@ -732,86 +731,85 @@
 /*
  * Device to Host Comunication
  */
-static int rndis_indicate_status_msg (int configNr, u32 status)
+static int rndis_indicate_status_msg(int configNr, u32 status)
 {
-	rndis_indicate_status_msg_type	*resp;
-	rndis_resp_t			*r;
-	struct rndis_params	*params = rndis_per_dev_params + configNr;
+	rndis_indicate_status_msg_type *resp;
+	rndis_resp_t *r;
+	struct rndis_params *params = rndis_per_dev_params + configNr;
 
 	if (params->state == RNDIS_UNINITIALIZED)
 		return -ENOTSUPP;
 
-	r = rndis_add_response (configNr,
-				sizeof (rndis_indicate_status_msg_type));
+	r = rndis_add_response(configNr,
+				sizeof(rndis_indicate_status_msg_type));
 	if (!r)
 		return -ENOMEM;
-	resp = (rndis_indicate_status_msg_type *) r->buf;
+	resp = (rndis_indicate_status_msg_type *)r->buf;
 
-	resp->MessageType = cpu_to_le32 (
-			REMOTE_NDIS_INDICATE_STATUS_MSG);
-	resp->MessageLength = cpu_to_le32 (20);
-	resp->Status = cpu_to_le32 (status);
-	resp->StatusBufferLength = cpu_to_le32 (0);
-	resp->StatusBufferOffset = cpu_to_le32 (0);
+	resp->MessageType = cpu_to_le32(REMOTE_NDIS_INDICATE_STATUS_MSG);
+	resp->MessageLength = cpu_to_le32(20);
+	resp->Status = cpu_to_le32(status);
+	resp->StatusBufferLength = cpu_to_le32(0);
+	resp->StatusBufferOffset = cpu_to_le32(0);
 
 	params->resp_avail(params->v);
 	return 0;
 }
 
-int rndis_signal_connect (int configNr)
+int rndis_signal_connect(int configNr)
 {
-	rndis_per_dev_params [configNr].media_state
+	rndis_per_dev_params[configNr].media_state
 			= NDIS_MEDIA_STATE_CONNECTED;
-	return rndis_indicate_status_msg (configNr,
+	return rndis_indicate_status_msg(configNr,
 					  RNDIS_STATUS_MEDIA_CONNECT);
 }
 
-int rndis_signal_disconnect (int configNr)
+int rndis_signal_disconnect(int configNr)
 {
-	rndis_per_dev_params [configNr].media_state
+	rndis_per_dev_params[configNr].media_state
 			= NDIS_MEDIA_STATE_DISCONNECTED;
-	return rndis_indicate_status_msg (configNr,
+	return rndis_indicate_status_msg(configNr,
 					  RNDIS_STATUS_MEDIA_DISCONNECT);
 }
 
-void rndis_uninit (int configNr)
+void rndis_uninit(int configNr)
 {
 	u8 *buf;
 	u32 length;
 
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return;
-	rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;
+	rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
 
 	/* drain the response queue */
 	while ((buf = rndis_get_next_response(configNr, &length)))
 		rndis_free_response(configNr, buf);
 }
 
-void rndis_set_host_mac (int configNr, const u8 *addr)
+void rndis_set_host_mac(int configNr, const u8 *addr)
 {
-	rndis_per_dev_params [configNr].host_mac = addr;
+	rndis_per_dev_params[configNr].host_mac = addr;
 }
 
 /*
  * Message Parser
  */
-int rndis_msg_parser (u8 configNr, u8 *buf)
+int rndis_msg_parser(u8 configNr, u8 *buf)
 {
 	u32 MsgType, MsgLength;
 	__le32 *tmp;
-	struct rndis_params		*params;
+	struct rndis_params *params;
 
 	if (!buf)
 		return -ENOMEM;
 
-	tmp = (__le32 *) buf;
+	tmp = (__le32 *)buf;
 	MsgType   = get_unaligned_le32(tmp++);
 	MsgLength = get_unaligned_le32(tmp++);
 
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return -ENOTSUPP;
-	params = &rndis_per_dev_params [configNr];
+	params = &rndis_per_dev_params[configNr];
 
 	/* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
 	 * rx/tx statistics and link status, in addition to KEEPALIVE traffic
@@ -822,41 +820,41 @@
 	switch (MsgType) {
 	case REMOTE_NDIS_INITIALIZE_MSG:
 		pr_debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
-			__func__ );
+			__func__);
 		params->state = RNDIS_INITIALIZED;
-		return  rndis_init_response (configNr,
-					(rndis_init_msg_type *) buf);
+		return rndis_init_response(configNr,
+					(rndis_init_msg_type *)buf);
 
 	case REMOTE_NDIS_HALT_MSG:
 		pr_debug("%s: REMOTE_NDIS_HALT_MSG\n",
-			__func__ );
+			__func__);
 		params->state = RNDIS_UNINITIALIZED;
 		if (params->dev) {
-			netif_carrier_off (params->dev);
-			netif_stop_queue (params->dev);
+			netif_carrier_off(params->dev);
+			netif_stop_queue(params->dev);
 		}
 		return 0;
 
 	case REMOTE_NDIS_QUERY_MSG:
-		return rndis_query_response (configNr,
-					(rndis_query_msg_type *) buf);
+		return rndis_query_response(configNr,
+					(rndis_query_msg_type *)buf);
 
 	case REMOTE_NDIS_SET_MSG:
-		return rndis_set_response (configNr,
-					(rndis_set_msg_type *) buf);
+		return rndis_set_response(configNr,
+					(rndis_set_msg_type *)buf);
 
 	case REMOTE_NDIS_RESET_MSG:
 		pr_debug("%s: REMOTE_NDIS_RESET_MSG\n",
-			__func__ );
-		return rndis_reset_response (configNr,
-					(rndis_reset_msg_type *) buf);
+			__func__);
+		return rndis_reset_response(configNr,
+					(rndis_reset_msg_type *)buf);
 
 	case REMOTE_NDIS_KEEPALIVE_MSG:
 		/* For USB: host does this every 5 seconds */
 		if (rndis_debug > 1)
 			pr_debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
-				__func__ );
-		return rndis_keepalive_response (configNr,
+				__func__);
+		return rndis_keepalive_response(configNr,
 						 (rndis_keepalive_msg_type *)
 						 buf);
 
@@ -866,7 +864,7 @@
 		 * suspending itself.
 		 */
 		pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
-			__func__ , MsgType, MsgLength);
+			__func__, MsgType, MsgLength);
 		{
 			unsigned i;
 			for (i = 0; i < MsgLength; i += 16) {
@@ -901,10 +899,10 @@
 		return -EINVAL;
 
 	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
-		if (!rndis_per_dev_params [i].used) {
-			rndis_per_dev_params [i].used = 1;
-			rndis_per_dev_params [i].resp_avail = resp_avail;
-			rndis_per_dev_params [i].v = v;
+		if (!rndis_per_dev_params[i].used) {
+			rndis_per_dev_params[i].used = 1;
+			rndis_per_dev_params[i].resp_avail = resp_avail;
+			rndis_per_dev_params[i].v = v;
 			pr_debug("%s: configNr = %d\n", __func__, i);
 			return i;
 		}
@@ -914,12 +912,12 @@
 	return -ENODEV;
 }
 
-void rndis_deregister (int configNr)
+void rndis_deregister(int configNr)
 {
-	pr_debug("%s: \n", __func__);
+	pr_debug("%s:\n", __func__);
 
 	if (configNr >= RNDIS_MAX_CONFIGS) return;
-	rndis_per_dev_params [configNr].used = 0;
+	rndis_per_dev_params[configNr].used = 0;
 
 	return;
 }
@@ -931,76 +929,76 @@
 		return -EINVAL;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
-	rndis_per_dev_params [configNr].dev = dev;
-	rndis_per_dev_params [configNr].filter = cdc_filter;
+	rndis_per_dev_params[configNr].dev = dev;
+	rndis_per_dev_params[configNr].filter = cdc_filter;
 
 	return 0;
 }
 
-int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
+int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
 {
 	pr_debug("%s:\n", __func__);
 	if (!vendorDescr) return -1;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
-	rndis_per_dev_params [configNr].vendorID = vendorID;
-	rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
+	rndis_per_dev_params[configNr].vendorID = vendorID;
+	rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
 
 	return 0;
 }
 
-int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
+int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
 {
 	pr_debug("%s: %u %u\n", __func__, medium, speed);
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
-	rndis_per_dev_params [configNr].medium = medium;
-	rndis_per_dev_params [configNr].speed = speed;
+	rndis_per_dev_params[configNr].medium = medium;
+	rndis_per_dev_params[configNr].speed = speed;
 
 	return 0;
 }
 
-void rndis_add_hdr (struct sk_buff *skb)
+void rndis_add_hdr(struct sk_buff *skb)
 {
-	struct rndis_packet_msg_type	*header;
+	struct rndis_packet_msg_type *header;
 
 	if (!skb)
 		return;
-	header = (void *) skb_push (skb, sizeof *header);
-	memset (header, 0, sizeof *header);
+	header = (void *)skb_push(skb, sizeof(*header));
+	memset(header, 0, sizeof *header);
 	header->MessageType = cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
 	header->MessageLength = cpu_to_le32(skb->len);
-	header->DataOffset = cpu_to_le32 (36);
-	header->DataLength = cpu_to_le32(skb->len - sizeof *header);
+	header->DataOffset = cpu_to_le32(36);
+	header->DataLength = cpu_to_le32(skb->len - sizeof(*header));
 }
 
-void rndis_free_response (int configNr, u8 *buf)
+void rndis_free_response(int configNr, u8 *buf)
 {
-	rndis_resp_t		*r;
-	struct list_head	*act, *tmp;
+	rndis_resp_t *r;
+	struct list_head *act, *tmp;
 
-	list_for_each_safe (act, tmp,
-			&(rndis_per_dev_params [configNr].resp_queue))
+	list_for_each_safe(act, tmp,
+			&(rndis_per_dev_params[configNr].resp_queue))
 	{
-		r = list_entry (act, rndis_resp_t, list);
+		r = list_entry(act, rndis_resp_t, list);
 		if (r && r->buf == buf) {
-			list_del (&r->list);
-			kfree (r);
+			list_del(&r->list);
+			kfree(r);
 		}
 	}
 }
 
-u8 *rndis_get_next_response (int configNr, u32 *length)
+u8 *rndis_get_next_response(int configNr, u32 *length)
 {
-	rndis_resp_t		*r;
-	struct list_head	*act, *tmp;
+	rndis_resp_t *r;
+	struct list_head *act, *tmp;
 
 	if (!length) return NULL;
 
-	list_for_each_safe (act, tmp,
-			&(rndis_per_dev_params [configNr].resp_queue))
+	list_for_each_safe(act, tmp,
+			&(rndis_per_dev_params[configNr].resp_queue))
 	{
-		r = list_entry (act, rndis_resp_t, list);
+		r = list_entry(act, rndis_resp_t, list);
 		if (!r->send) {
 			r->send = 1;
 			*length = r->length;
@@ -1011,20 +1009,20 @@
 	return NULL;
 }
 
-static rndis_resp_t *rndis_add_response (int configNr, u32 length)
+static rndis_resp_t *rndis_add_response(int configNr, u32 length)
 {
-	rndis_resp_t	*r;
+	rndis_resp_t *r;
 
-	/* NOTE:  this gets copied into ether.c USB_BUFSIZ bytes ... */
-	r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
+	/* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
+	r = kmalloc(sizeof(rndis_resp_t) + length, GFP_ATOMIC);
 	if (!r) return NULL;
 
-	r->buf = (u8 *) (r + 1);
+	r->buf = (u8 *)(r + 1);
 	r->length = length;
 	r->send = 0;
 
-	list_add_tail (&r->list,
-		&(rndis_per_dev_params [configNr].resp_queue));
+	list_add_tail(&r->list,
+		&(rndis_per_dev_params[configNr].resp_queue));
 	return r;
 }
 
@@ -1033,7 +1031,7 @@
 			struct sk_buff_head *list)
 {
 	/* tmp points to a struct rndis_packet_msg_type */
-	__le32		*tmp = (void *) skb->data;
+	__le32 *tmp = (void *)skb->data;
 
 	/* MessageType, MessageLength */
 	if (cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
@@ -1054,7 +1052,7 @@
 	return 0;
 }
 
-#ifdef	CONFIG_USB_GADGET_DEBUG_FILES
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
 
 static int rndis_proc_show(struct seq_file *m, void *v)
 {
@@ -1087,7 +1085,7 @@
 }
 
 static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
-		size_t count, loff_t *ppos)
+				size_t count, loff_t *ppos)
 {
 	rndis_params *p = PDE(file->f_path.dentry->d_inode)->data;
 	u32 speed = 0;
@@ -1109,11 +1107,11 @@
 		case '8':
 		case '9':
 			fl_speed = 1;
-			speed = speed*10 + c - '0';
+			speed = speed * 10 + c - '0';
 			break;
 		case 'C':
 		case 'c':
-			rndis_signal_connect (p->confignr);
+			rndis_signal_connect(p->confignr);
 			break;
 		case 'D':
 		case 'd':
@@ -1145,11 +1143,11 @@
 	.write		= rndis_proc_write,
 };
 
-#define	NAME_TEMPLATE	"driver/rndis-%03d"
+#define	NAME_TEMPLATE "driver/rndis-%03d"
 
 static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
 
-#endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 
 
 int rndis_init(void)
@@ -1160,42 +1158,40 @@
 #ifdef	CONFIG_USB_GADGET_DEBUG_FILES
 		char name [20];
 
-		sprintf (name, NAME_TEMPLATE, i);
-		if (!(rndis_connect_state [i]
-				= proc_create_data(name, 0660, NULL,
+		sprintf(name, NAME_TEMPLATE, i);
+		rndis_connect_state[i] = proc_create_data(name, 0660, NULL,
 					&rndis_proc_fops,
-					(void *)(rndis_per_dev_params + i))))
-		{
-			pr_debug("%s :remove entries", __func__);
+					(void *)(rndis_per_dev_params + i));
+		if (!rndis_connect_state[i]) {
+			pr_debug("%s: remove entries", __func__);
 			while (i) {
-				sprintf (name, NAME_TEMPLATE, --i);
-				remove_proc_entry (name, NULL);
+				sprintf(name, NAME_TEMPLATE, --i);
+				remove_proc_entry(name, NULL);
 			}
 			pr_debug("\n");
 			return -EIO;
 		}
 #endif
-		rndis_per_dev_params [i].confignr = i;
-		rndis_per_dev_params [i].used = 0;
-		rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;
-		rndis_per_dev_params [i].media_state
+		rndis_per_dev_params[i].confignr = i;
+		rndis_per_dev_params[i].used = 0;
+		rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
+		rndis_per_dev_params[i].media_state
 				= NDIS_MEDIA_STATE_DISCONNECTED;
-		INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue));
+		INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
 	}
 
 	return 0;
 }
 
-void rndis_exit (void)
+void rndis_exit(void)
 {
-#ifdef	CONFIG_USB_GADGET_DEBUG_FILES
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
 	u8 i;
-	char name [20];
+	char name[20];
 
 	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
-		sprintf (name, NAME_TEMPLATE, i);
-		remove_proc_entry (name, NULL);
+		sprintf(name, NAME_TEMPLATE, i);
+		remove_proc_entry(name, NULL);
 	}
 #endif
 }
-
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index a229744..ef825c3 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -2523,7 +2523,8 @@
 	return 0;
 }
 
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct s3c_hsotg *hsotg = our_hsotg;
 	int ret;
@@ -2543,7 +2544,7 @@
 		dev_err(hsotg->dev, "%s: bad speed\n", __func__);
 	}
 
-	if (!driver->bind || !driver->setup) {
+	if (!bind || !driver->setup) {
 		dev_err(hsotg->dev, "%s: missing entry points\n", __func__);
 		return -EINVAL;
 	}
@@ -2562,7 +2563,7 @@
 		goto err;
 	}
 
-	ret = driver->bind(&hsotg->gadget);
+	ret = bind(&hsotg->gadget);
 	if (ret) {
 		dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name);
 
@@ -2687,7 +2688,7 @@
 	hsotg->gadget.dev.driver = NULL;
 	return ret;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index ea2b3c7..c244895 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -1632,15 +1632,15 @@
 }
 
 /*
- *	usb_gadget_register_driver
+ *	usb_gadget_probe_driver
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	struct s3c2410_udc *udc = the_controller;
 	int		retval;
 
-	dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",
-		driver->driver.name);
+	dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
 
 	/* Sanity checks */
 	if (!udc)
@@ -1649,10 +1649,9 @@
 	if (udc->driver)
 		return -EBUSY;
 
-	if (!driver->bind || !driver->setup
-			|| driver->speed < USB_SPEED_FULL) {
+	if (!bind || !driver->setup || driver->speed < USB_SPEED_FULL) {
 		printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
-			driver->bind, driver->setup, driver->speed);
+			bind, driver->setup, driver->speed);
 		return -EINVAL;
 	}
 #if defined(MODULE)
@@ -1675,7 +1674,7 @@
 	dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
 		driver->driver.name);
 
-	if ((retval = driver->bind (&udc->gadget)) != 0) {
+	if ((retval = bind(&udc->gadget)) != 0) {
 		device_del(&udc->gadget.dev);
 		goto register_error;
 	}
@@ -1690,6 +1689,7 @@
 	udc->gadget.dev.driver = NULL;
 	return retval;
 }
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 /*
  *	usb_gadget_unregister_driver
@@ -2049,7 +2049,6 @@
 }
 
 EXPORT_SYMBOL(usb_gadget_unregister_driver);
-EXPORT_SYMBOL(usb_gadget_register_driver);
 
 module_init(udc_init);
 module_exit(udc_exit);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index b22eedb..1ac57a9 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -137,7 +137,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref serial_bind_config(struct usb_configuration *c)
+static int __init serial_bind_config(struct usb_configuration *c)
 {
 	unsigned i;
 	int status = 0;
@@ -155,13 +155,12 @@
 
 static struct usb_configuration serial_config_driver = {
 	/* .label = f(use_acm) */
-	.bind		= serial_bind_config,
 	/* .bConfigurationValue = f(use_acm) */
 	/* .iConfiguration = DYNAMIC */
 	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
 };
 
-static int __ref gs_bind(struct usb_composite_dev *cdev)
+static int __init gs_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -225,7 +224,8 @@
 	}
 
 	/* register our configuration */
-	status = usb_add_config(cdev, &serial_config_driver);
+	status = usb_add_config(cdev, &serial_config_driver,
+			serial_bind_config);
 	if (status < 0)
 		goto fail;
 
@@ -242,7 +242,6 @@
 	.name		= "g_serial",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= gs_bind,
 };
 
 static int __init init(void)
@@ -271,7 +270,7 @@
 	}
 	strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
 
-	return usb_composite_register(&gserial_driver);
+	return usb_composite_probe(&gserial_driver, gs_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 484acfb..3b513ba 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -26,7 +26,6 @@
  * be defined (each of type pointer to char):
  *  - fsg_string_manufacturer -- name of the manufacturer
  *  - fsg_string_product      -- name of the product
- *  - fsg_string_serial       -- product's serial
  *  - fsg_string_config       -- name of the configuration
  *  - fsg_string_interface    -- name of the interface
  * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
@@ -54,6 +53,8 @@
  */
 
 
+#include <linux/usb/storage.h>
+#include <scsi/scsi.h>
 #include <asm/unaligned.h>
 
 
@@ -153,23 +154,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* SCSI device types */
-#define TYPE_DISK	0x00
-#define TYPE_CDROM	0x05
-
-/* USB protocol value = the transport method */
-#define USB_PR_CBI	0x00		/* Control/Bulk/Interrupt */
-#define USB_PR_CB	0x01		/* Control/Bulk w/o interrupt */
-#define USB_PR_BULK	0x50		/* Bulk-only */
-
-/* USB subclass value = the protocol encapsulation */
-#define USB_SC_RBC	0x01		/* Reduced Block Commands (flash) */
-#define USB_SC_8020	0x02		/* SFF-8020i, MMC-2, ATAPI (CD-ROM) */
-#define USB_SC_QIC	0x03		/* QIC-157 (tape) */
-#define USB_SC_UFI	0x04		/* UFI (floppy) */
-#define USB_SC_8070	0x05		/* SFF-8070i (removable) */
-#define USB_SC_SCSI	0x06		/* Transparent SCSI */
-
 /* Bulk-only data structures */
 
 /* Command Block Wrapper */
@@ -221,33 +205,6 @@
 /* Length of a SCSI Command Data Block */
 #define MAX_COMMAND_SIZE	16
 
-/* SCSI commands that we recognize */
-#define SC_FORMAT_UNIT			0x04
-#define SC_INQUIRY			0x12
-#define SC_MODE_SELECT_6		0x15
-#define SC_MODE_SELECT_10		0x55
-#define SC_MODE_SENSE_6			0x1a
-#define SC_MODE_SENSE_10		0x5a
-#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL	0x1e
-#define SC_READ_6			0x08
-#define SC_READ_10			0x28
-#define SC_READ_12			0xa8
-#define SC_READ_CAPACITY		0x25
-#define SC_READ_FORMAT_CAPACITIES	0x23
-#define SC_READ_HEADER			0x44
-#define SC_READ_TOC			0x43
-#define SC_RELEASE			0x17
-#define SC_REQUEST_SENSE		0x03
-#define SC_RESERVE			0x16
-#define SC_SEND_DIAGNOSTIC		0x1d
-#define SC_START_STOP_UNIT		0x1b
-#define SC_SYNCHRONIZE_CACHE		0x35
-#define SC_TEST_UNIT_READY		0x00
-#define SC_VERIFY			0x2f
-#define SC_WRITE_6			0x0a
-#define SC_WRITE_10			0x2a
-#define SC_WRITE_12			0xaa
-
 /* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
 #define SS_NO_SENSE				0
 #define SS_COMMUNICATION_FAILURE		0x040800
@@ -552,7 +509,7 @@
 #ifndef FSG_NO_DEVICE_STRINGS
 	{FSG_STRING_MANUFACTURER,	fsg_string_manufacturer},
 	{FSG_STRING_PRODUCT,		fsg_string_product},
-	{FSG_STRING_SERIAL,		fsg_string_serial},
+	{FSG_STRING_SERIAL,		""},
 	{FSG_STRING_CONFIG,		fsg_string_config},
 #endif
 	{FSG_STRING_INTERFACE,		fsg_string_interface},
diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c
index de1deb7..a5a0fdb 100644
--- a/drivers/usb/gadget/webcam.c
+++ b/drivers/usb/gadget/webcam.c
@@ -308,7 +308,7 @@
  * USB configuration
  */
 
-static int __ref
+static int __init
 webcam_config_bind(struct usb_configuration *c)
 {
 	return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls,
@@ -317,7 +317,6 @@
 
 static struct usb_configuration webcam_config_driver = {
 	.label			= webcam_config_label,
-	.bind			= webcam_config_bind,
 	.bConfigurationValue	= 1,
 	.iConfiguration		= 0, /* dynamic */
 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
@@ -330,7 +329,7 @@
 	return 0;
 }
 
-static int __ref
+static int __init
 webcam_bind(struct usb_composite_dev *cdev)
 {
 	int ret;
@@ -354,7 +353,8 @@
 	webcam_config_driver.iConfiguration = ret;
 
 	/* Register our configuration. */
-	if ((ret = usb_add_config(cdev, &webcam_config_driver)) < 0)
+	if ((ret = usb_add_config(cdev, &webcam_config_driver,
+					webcam_config_bind)) < 0)
 		goto error;
 
 	INFO(cdev, "Webcam Video Gadget\n");
@@ -373,14 +373,13 @@
 	.name		= "g_webcam",
 	.dev		= &webcam_device_descriptor,
 	.strings	= webcam_device_strings,
-	.bind		= webcam_bind,
 	.unbind		= webcam_unbind,
 };
 
 static int __init
 webcam_init(void)
 {
-	return usb_composite_register(&webcam_driver);
+	return usb_composite_probe(&webcam_driver, webcam_bind);
 }
 
 static void __exit
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index cf353920..6d16db9 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -264,7 +264,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __ref zero_bind(struct usb_composite_dev *cdev)
+static int __init zero_bind(struct usb_composite_dev *cdev)
 {
 	int			gcnum;
 	struct usb_gadget	*gadget = cdev->gadget;
@@ -340,7 +340,6 @@
 	.name		= "zero",
 	.dev		= &device_desc,
 	.strings	= dev_strings,
-	.bind		= zero_bind,
 	.unbind		= zero_unbind,
 	.suspend	= zero_suspend,
 	.resume		= zero_resume,
@@ -351,7 +350,7 @@
 
 static int __init init(void)
 {
-	return usb_composite_register(&zero_driver);
+	return usb_composite_probe(&zero_driver, zero_bind);
 }
 module_init(init);
 
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 2d926ce..bf2e7d2 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -93,12 +93,14 @@
 
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
-	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
+	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || \
+				    XPS_USB_HCD_XILINX || PPC_MPC512x)
 	default y
 
 config USB_EHCI_BIG_ENDIAN_DESC
 	bool
-	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
+	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
+				    PPC_MPC512x)
 	default y
 
 config XPS_USB_HCD_XILINX
@@ -112,10 +114,14 @@
 		support both high speed and full speed devices, or high speed
 		devices only.
 
+config USB_FSL_MPH_DR_OF
+	tristate
+
 config USB_EHCI_FSL
 	bool "Support for Freescale on-chip EHCI USB controller"
 	depends on USB_EHCI_HCD && FSL_SOC
 	select USB_EHCI_ROOT_HUB_TT
+	select USB_FSL_MPH_DR_OF
 	---help---
 	  Variation of ARC USB block used in some Freescale chips.
 
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index b6315aa..91c5a1b 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -2,17 +2,17 @@
 # Makefile for USB Host Controller Drivers
 #
 
-ifeq ($(CONFIG_USB_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
-isp1760-objs := isp1760-hcd.o isp1760-if.o
-fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \
-	     fhci-tds.o fhci-sched.o
-ifeq ($(CONFIG_FHCI_DEBUG),y)
-fhci-objs += fhci-dbg.o
-endif
-xhci-hcd-objs := xhci.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o
+isp1760-y := isp1760-hcd.o isp1760-if.o
+
+fhci-y := fhci-hcd.o fhci-hub.o fhci-q.o
+fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o
+
+fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o
+
+xhci-hcd-y := xhci.o xhci-mem.o xhci-pci.o
+xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
 
 obj-$(CONFIG_USB_WHCI_HCD)	+= whci/
 
@@ -33,4 +33,4 @@
 obj-$(CONFIG_USB_ISP1760_HCD)	+= isp1760.o
 obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o
 obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o
-
+obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 76b7fd2..86afdc7 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -369,18 +369,21 @@
 	.open		= debug_async_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_periodic_fops = {
 	.owner		= THIS_MODULE,
 	.open		= debug_periodic_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_registers_fops = {
 	.owner		= THIS_MODULE,
 	.open		= debug_registers_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_lpm_fops = {
 	.owner		= THIS_MODULE,
@@ -388,6 +391,7 @@
 	.read		= debug_lpm_read,
 	.write		= debug_lpm_write,
 	.release	= debug_lpm_close,
+	.llseek		= noop_llseek,
 };
 
 static struct dentry *ehci_debug_root;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index a416421..86e4289 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -116,13 +116,33 @@
 		goto err3;
 	}
 
-	/* Enable USB controller */
-	temp = in_be32(hcd->regs + 0x500);
-	out_be32(hcd->regs + 0x500, temp | 0x4);
+	pdata->regs = hcd->regs;
 
-	/* Set to Host mode */
-	temp = in_le32(hcd->regs + 0x1a8);
-	out_le32(hcd->regs + 0x1a8, temp | 0x3);
+	/*
+	 * do platform specific init: check the clock, grab/config pins, etc.
+	 */
+	if (pdata->init && pdata->init(pdev)) {
+		retval = -ENODEV;
+		goto err3;
+	}
+
+	/*
+	 * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs
+	 * flag for 83xx or 8536 system interface registers.
+	 */
+	if (pdata->big_endian_mmio)
+		temp = in_be32(hcd->regs + FSL_SOC_USB_ID);
+	else
+		temp = in_le32(hcd->regs + FSL_SOC_USB_ID);
+
+	if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK))
+		pdata->have_sysif_regs = 1;
+
+	/* Enable USB controller, 83xx or 8536 */
+	if (pdata->have_sysif_regs)
+		setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
+
+	/* Don't need to set host mode here. It will be done by tdi_reset() */
 
 	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (retval != 0)
@@ -137,6 +157,8 @@
 	usb_put_hcd(hcd);
       err1:
 	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
+	if (pdata->exit)
+		pdata->exit(pdev);
 	return retval;
 }
 
@@ -154,17 +176,30 @@
 static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
 			       struct platform_device *pdev)
 {
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
 	usb_remove_hcd(hcd);
+
+	/*
+	 * do platform specific un-initialization:
+	 * release iomux pins, disable clock, etc.
+	 */
+	if (pdata->exit)
+		pdata->exit(pdev);
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 }
 
-static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
-			      enum fsl_usb2_phy_modes phy_mode,
-			      unsigned int port_offset)
+static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
+			       enum fsl_usb2_phy_modes phy_mode,
+			       unsigned int port_offset)
 {
-	u32 portsc = 0;
+	u32 portsc;
+
+	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
+	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
+
 	switch (phy_mode) {
 	case FSL_USB2_PHY_ULPI:
 		portsc |= PORT_PTS_ULPI;
@@ -184,20 +219,21 @@
 	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 }
 
-static void mpc83xx_usb_setup(struct usb_hcd *hcd)
+static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 {
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct usb_hcd *hcd = ehci_to_hcd(ehci);
 	struct fsl_usb2_platform_data *pdata;
 	void __iomem *non_ehci = hcd->regs;
 	u32 temp;
 
-	pdata =
-	    (struct fsl_usb2_platform_data *)hcd->self.controller->
-	    platform_data;
+	pdata = hcd->self.controller->platform_data;
+
 	/* Enable PHY interface in the control reg. */
-	temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
-	out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
-	out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+	if (pdata->have_sysif_regs) {
+		temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+		out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
+		out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+	}
 
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
 	/*
@@ -214,7 +250,7 @@
 
 	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
 			(pdata->operating_mode == FSL_USB2_DR_OTG))
-		mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+		ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
 
 	if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
 		unsigned int chip, rev, svr;
@@ -228,27 +264,27 @@
 			ehci->has_fsl_port_bug = 1;
 
 		if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
-			mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
 		if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
-			mpc83xx_setup_phy(ehci, pdata->phy_mode, 1);
+			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
 	}
 
-	/* put controller in host mode. */
-	ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
+	if (pdata->have_sysif_regs) {
 #ifdef CONFIG_PPC_85xx
-	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
-	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
+		out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
+		out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
 #else
-	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
-	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
+		out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
+		out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
 #endif
-	out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+		out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+	}
 }
 
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 {
-	mpc83xx_usb_setup(ehci_to_hcd(ehci));
+	ehci_fsl_usb_setup(ehci);
 	ehci_port_power(ehci, 0);
 
 	return 0;
@@ -259,6 +295,11 @@
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
+	struct fsl_usb2_platform_data *pdata;
+
+	pdata = hcd->self.controller->platform_data;
+	ehci->big_endian_desc = pdata->big_endian_desc;
+	ehci->big_endian_mmio = pdata->big_endian_mmio;
 
 	/* EHCI registers start at offset 0x100 */
 	ehci->caps = hcd->regs + 0x100;
@@ -270,6 +311,8 @@
 	/* cache this readonly data; minimize chip reads */
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
+	hcd->has_tt = 1;
+
 	retval = ehci_halt(ehci);
 	if (retval)
 		return retval;
@@ -279,8 +322,6 @@
 	if (retval)
 		return retval;
 
-	hcd->has_tt = 1;
-
 	ehci->sbrn = 0x20;
 
 	ehci_reset(ehci);
@@ -372,7 +413,7 @@
 	 * generic hardware linkage
 	 */
 	.irq = ehci_irq,
-	.flags = HCD_USB2,
+	.flags = HCD_USB2 | HCD_MEMORY,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index b5e59db..2c83537 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005 freescale semiconductor
+/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
  * Copyright (c) 2005 MontaVista Software
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -19,6 +19,9 @@
 #define _EHCI_FSL_H
 
 /* offsets for the non-ehci registers in the FSL SOC USB controller */
+#define FSL_SOC_USB_ID		0x0
+#define ID_MSK			0x3f
+#define NID_MSK			0x3f00
 #define FSL_SOC_USB_ULPIVP	0x170
 #define FSL_SOC_USB_PORTSC1	0x184
 #define PORT_PTS_MSK		(3<<30)
@@ -27,7 +30,14 @@
 #define	PORT_PTS_SERIAL		(3<<30)
 #define PORT_PTS_PTW		(1<<28)
 #define FSL_SOC_USB_PORTSC2	0x188
-#define FSL_SOC_USB_USBMODE	0x1a8
+
+#define FSL_SOC_USB_USBGENCTRL	0x200
+#define USBGENCTRL_PPP		(1 << 3)
+#define USBGENCTRL_PFP		(1 << 2)
+#define FSL_SOC_USB_ISIPHYCTRL	0x204
+#define ISIPHYCTRL_PXE		(1)
+#define ISIPHYCTRL_PHYE		(1 << 4)
+
 #define FSL_SOC_USB_SNOOP1	0x400	/* NOTE: big-endian */
 #define FSL_SOC_USB_SNOOP2	0x404	/* NOTE: big-endian */
 #define FSL_SOC_USB_AGECNTTHRSH	0x408	/* NOTE: big-endian */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 34a928d..15fe3ec 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -194,6 +194,17 @@
 	return -ETIMEDOUT;
 }
 
+/* check TDI/ARC silicon is in host mode */
+static int tdi_in_host_mode (struct ehci_hcd *ehci)
+{
+	u32 __iomem	*reg_ptr;
+	u32		tmp;
+
+	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
+	tmp = ehci_readl(ehci, reg_ptr);
+	return (tmp & 3) == USBMODE_CM_HC;
+}
+
 /* force HC to halt state from unknown (EHCI spec section 2.3) */
 static int ehci_halt (struct ehci_hcd *ehci)
 {
@@ -202,6 +213,10 @@
 	/* disable any irqs left enabled by previous code */
 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
 
+	if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) {
+		return 0;
+	}
+
 	if ((temp & STS_HALT) != 0)
 		return 0;
 
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 1f3f01e..d36e4e7 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -40,7 +40,7 @@
 {
 	memset (qtd, 0, sizeof *qtd);
 	qtd->qtd_dma = dma;
-	qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
+	qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
 	qtd->hw_next = EHCI_LIST_END(ehci);
 	qtd->hw_alt_next = EHCI_LIST_END(ehci);
 	INIT_LIST_HEAD (&qtd->qtd_list);
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index a8ad8ac..ac9c4d7 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -26,9 +26,6 @@
 #include <mach/mxc_ehci.h>
 
 #define ULPI_VIEWPORT_OFFSET	0x170
-#define PORTSC_OFFSET		0x184
-#define USBMODE_OFFSET		0x1a8
-#define USBMODE_CM_HOST		3
 
 struct ehci_mxc_priv {
 	struct clk *usbclk, *ahbclk;
@@ -51,6 +48,8 @@
 	/* cache this readonly data; minimize chip reads */
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
+	hcd->has_tt = 1;
+
 	retval = ehci_halt(ehci);
 	if (retval)
 		return retval;
@@ -60,8 +59,6 @@
 	if (retval)
 		return retval;
 
-	hcd->has_tt = 1;
-
 	ehci->sbrn = 0x20;
 
 	ehci_reset(ehci);
@@ -191,12 +188,8 @@
 		clk_enable(priv->ahbclk);
 	}
 
-	/* set USBMODE to host mode */
-	temp = readl(hcd->regs + USBMODE_OFFSET);
-	writel(temp | USBMODE_CM_HOST, hcd->regs + USBMODE_OFFSET);
-
 	/* set up the PORTSCx register */
-	writel(pdata->portsc, hcd->regs + PORTSC_OFFSET);
+	ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);
 	mdelay(10);
 
 	/* setup specific usb hw */
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
new file mode 100644
index 0000000..574b99e
--- /dev/null
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -0,0 +1,308 @@
+/*
+ * Setup platform devices needed by the Freescale multi-port host
+ * and/or dual-role USB controller modules based on the description
+ * in flat device tree.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+
+struct fsl_usb2_dev_data {
+	char *dr_mode;		/* controller mode */
+	char *drivers[3];	/* drivers to instantiate for this mode */
+	enum fsl_usb2_operating_modes op_mode;	/* operating mode */
+};
+
+struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
+	{
+		.dr_mode = "host",
+		.drivers = { "fsl-ehci", NULL, NULL, },
+		.op_mode = FSL_USB2_DR_HOST,
+	},
+	{
+		.dr_mode = "otg",
+		.drivers = { "fsl-usb2-otg", "fsl-ehci", "fsl-usb2-udc", },
+		.op_mode = FSL_USB2_DR_OTG,
+	},
+	{
+		.dr_mode = "peripheral",
+		.drivers = { "fsl-usb2-udc", NULL, NULL, },
+		.op_mode = FSL_USB2_DR_DEVICE,
+	},
+};
+
+struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
+{
+	const unsigned char *prop;
+	int i;
+
+	prop = of_get_property(np, "dr_mode", NULL);
+	if (prop) {
+		for (i = 0; i < ARRAY_SIZE(dr_mode_data); i++) {
+			if (!strcmp(prop, dr_mode_data[i].dr_mode))
+				return &dr_mode_data[i];
+		}
+	}
+	pr_warn("%s: Invalid 'dr_mode' property, fallback to host mode\n",
+		np->full_name);
+	return &dr_mode_data[0]; /* mode not specified, use host */
+}
+
+static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
+{
+	if (!phy_type)
+		return FSL_USB2_PHY_NONE;
+	if (!strcasecmp(phy_type, "ulpi"))
+		return FSL_USB2_PHY_ULPI;
+	if (!strcasecmp(phy_type, "utmi"))
+		return FSL_USB2_PHY_UTMI;
+	if (!strcasecmp(phy_type, "utmi_wide"))
+		return FSL_USB2_PHY_UTMI_WIDE;
+	if (!strcasecmp(phy_type, "serial"))
+		return FSL_USB2_PHY_SERIAL;
+
+	return FSL_USB2_PHY_NONE;
+}
+
+struct platform_device * __devinit fsl_usb2_device_register(
+					struct platform_device *ofdev,
+					struct fsl_usb2_platform_data *pdata,
+					const char *name, int id)
+{
+	struct platform_device *pdev;
+	const struct resource *res = ofdev->resource;
+	unsigned int num = ofdev->num_resources;
+	int retval;
+
+	pdev = platform_device_alloc(name, id);
+	if (!pdev) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	pdev->dev.parent = &ofdev->dev;
+
+	pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
+	pdev->dev.dma_mask = &pdev->archdata.dma_mask;
+	*pdev->dev.dma_mask = *ofdev->dev.dma_mask;
+
+	retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+	if (retval)
+		goto error;
+
+	if (num) {
+		retval = platform_device_add_resources(pdev, res, num);
+		if (retval)
+			goto error;
+	}
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto error;
+
+	return pdev;
+
+error:
+	platform_device_put(pdev);
+	return ERR_PTR(retval);
+}
+
+static const struct of_device_id fsl_usb2_mph_dr_of_match[];
+
+static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+{
+	struct device_node *np = ofdev->dev.of_node;
+	struct platform_device *usb_dev;
+	struct fsl_usb2_platform_data data, *pdata;
+	struct fsl_usb2_dev_data *dev_data;
+	const struct of_device_id *match;
+	const unsigned char *prop;
+	static unsigned int idx;
+	int i;
+
+	if (!of_device_is_available(np))
+		return -ENODEV;
+
+	match = of_match_device(fsl_usb2_mph_dr_of_match, &ofdev->dev);
+	if (!match)
+		return -ENODEV;
+
+	pdata = &data;
+	if (match->data)
+		memcpy(pdata, match->data, sizeof(data));
+	else
+		memset(pdata, 0, sizeof(data));
+
+	dev_data = get_dr_mode_data(np);
+
+	if (of_device_is_compatible(np, "fsl-usb2-mph")) {
+		if (of_get_property(np, "port0", NULL))
+			pdata->port_enables |= FSL_USB2_PORT0_ENABLED;
+
+		if (of_get_property(np, "port1", NULL))
+			pdata->port_enables |= FSL_USB2_PORT1_ENABLED;
+
+		pdata->operating_mode = FSL_USB2_MPH_HOST;
+	} else {
+		if (of_get_property(np, "fsl,invert-drvvbus", NULL))
+			pdata->invert_drvvbus = 1;
+
+		if (of_get_property(np, "fsl,invert-pwr-fault", NULL))
+			pdata->invert_pwr_fault = 1;
+
+		/* setup mode selected in the device tree */
+		pdata->operating_mode = dev_data->op_mode;
+	}
+
+	prop = of_get_property(np, "phy_type", NULL);
+	pdata->phy_mode = determine_usb_phy(prop);
+
+	for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
+		if (!dev_data->drivers[i])
+			continue;
+		usb_dev = fsl_usb2_device_register(ofdev, pdata,
+					dev_data->drivers[i], idx);
+		if (IS_ERR(usb_dev)) {
+			dev_err(&ofdev->dev, "Can't register usb device\n");
+			return PTR_ERR(usb_dev);
+		}
+	}
+	idx++;
+	return 0;
+}
+
+static int __devexit __unregister_subdev(struct device *dev, void *d)
+{
+	platform_device_unregister(to_platform_device(dev));
+	return 0;
+}
+
+static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
+{
+	device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);
+	return 0;
+}
+
+#ifdef CONFIG_PPC_MPC512x
+
+#define USBGENCTRL		0x200		/* NOTE: big endian */
+#define GC_WU_INT_CLR		(1 << 5)	/* Wakeup int clear */
+#define GC_ULPI_SEL		(1 << 4)	/* ULPI i/f select (usb0 only)*/
+#define GC_PPP			(1 << 3)	/* Inv. Port Power Polarity */
+#define GC_PFP			(1 << 2)	/* Inv. Power Fault Polarity */
+#define GC_WU_ULPI_EN		(1 << 1)	/* Wakeup on ULPI event */
+#define GC_WU_IE		(1 << 1)	/* Wakeup interrupt enable */
+
+#define ISIPHYCTRL		0x204		/* NOTE: big endian */
+#define PHYCTRL_PHYE		(1 << 4)	/* On-chip UTMI PHY enable */
+#define PHYCTRL_BSENH		(1 << 3)	/* Bit Stuff Enable High */
+#define PHYCTRL_BSEN		(1 << 2)	/* Bit Stuff Enable */
+#define PHYCTRL_LSFE		(1 << 1)	/* Line State Filter Enable */
+#define PHYCTRL_PXE		(1 << 0)	/* PHY oscillator enable */
+
+int fsl_usb2_mpc5121_init(struct platform_device *pdev)
+{
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct clk *clk;
+	char clk_name[10];
+	int base, clk_num;
+
+	base = pdev->resource->start & 0xf000;
+	if (base == 0x3000)
+		clk_num = 1;
+	else if (base == 0x4000)
+		clk_num = 2;
+	else
+		return -ENODEV;
+
+	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
+	clk = clk_get(&pdev->dev, clk_name);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clk\n");
+		return PTR_ERR(clk);
+	}
+
+	clk_enable(clk);
+	pdata->clk = clk;
+
+	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
+		u32 reg = 0;
+
+		if (pdata->invert_drvvbus)
+			reg |= GC_PPP;
+
+		if (pdata->invert_pwr_fault)
+			reg |= GC_PFP;
+
+		out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE);
+		out_be32(pdata->regs + USBGENCTRL, reg);
+	}
+	return 0;
+}
+
+static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
+{
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+	pdata->regs = NULL;
+
+	if (pdata->clk) {
+		clk_disable(pdata->clk);
+		clk_put(pdata->clk);
+	}
+}
+
+struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
+	.big_endian_desc = 1,
+	.big_endian_mmio = 1,
+	.es = 1,
+	.le_setup_buf = 1,
+	.init = fsl_usb2_mpc5121_init,
+	.exit = fsl_usb2_mpc5121_exit,
+};
+#endif /* CONFIG_PPC_MPC512x */
+
+static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
+	{ .compatible = "fsl-usb2-mph", },
+	{ .compatible = "fsl-usb2-dr", },
+#ifdef CONFIG_PPC_MPC512x
+	{ .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, },
+#endif
+	{},
+};
+
+static struct platform_driver fsl_usb2_mph_dr_driver = {
+	.driver = {
+		.name = "fsl-usb2-mph-dr",
+		.owner = THIS_MODULE,
+		.of_match_table = fsl_usb2_mph_dr_of_match,
+	},
+	.probe	= fsl_usb2_mph_dr_of_probe,
+	.remove	= __devexit_p(fsl_usb2_mph_dr_of_remove),
+};
+
+static int __init fsl_usb2_mph_dr_init(void)
+{
+	return platform_driver_register(&fsl_usb2_mph_dr_driver);
+}
+module_init(fsl_usb2_mph_dr_init);
+
+static void __exit fsl_usb2_mph_dr_exit(void)
+{
+	platform_driver_unregister(&fsl_usb2_mph_dr_driver);
+}
+module_exit(fsl_usb2_mph_dr_exit);
+
+MODULE_DESCRIPTION("FSL MPH DR OF devices driver");
+MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index 3e56303..1dfb2c8 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -57,6 +57,7 @@
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
+#include <linux/dma-mapping.h>
 
 #include "imx21-hcd.h"
 
@@ -136,9 +137,18 @@
 	return wrap_frame(readl(imx21->regs + USBH_FRMNUB));
 }
 
+static inline bool unsuitable_for_dma(dma_addr_t addr)
+{
+	return (addr & 3) != 0;
+}
 
 #include "imx21-dbg.c"
 
+static void nonisoc_urb_completed_for_etd(
+	struct imx21 *imx21, struct etd_priv *etd, int status);
+static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb);
+static void free_dmem(struct imx21 *imx21, struct etd_priv *etd);
+
 /* =========================================== */
 /* ETD management				*/
 /* ===========================================	*/
@@ -185,7 +195,8 @@
 		etd_writel(imx21, num, i, 0);
 	etd->urb = NULL;
 	etd->ep = NULL;
-	etd->td = NULL;;
+	etd->td = NULL;
+	etd->bounce_buffer = NULL;
 }
 
 static void free_etd(struct imx21 *imx21, int num)
@@ -221,26 +232,94 @@
 		((u32) maxpacket << DW0_MAXPKTSIZ));
 }
 
-static void activate_etd(struct imx21 *imx21,
-	int etd_num, dma_addr_t dma, u8 dir)
+/**
+ * Copy buffer to data controller data memory.
+ * We cannot use memcpy_toio() because the hardware requires 32bit writes
+ */
+static void copy_to_dmem(
+	struct imx21 *imx21, int dmem_offset, void *src, int count)
+{
+	void __iomem *dmem = imx21->regs + USBOTG_DMEM + dmem_offset;
+	u32 word = 0;
+	u8 *p = src;
+	int byte = 0;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		byte = i % 4;
+		word += (*p++ << (byte * 8));
+		if (byte == 3) {
+			writel(word, dmem);
+			dmem += 4;
+			word = 0;
+		}
+	}
+
+	if (count && byte != 3)
+		writel(word, dmem);
+}
+
+static void activate_etd(struct imx21 *imx21, int etd_num, u8 dir)
 {
 	u32 etd_mask = 1 << etd_num;
 	struct etd_priv *etd = &imx21->etd[etd_num];
 
+	if (etd->dma_handle && unsuitable_for_dma(etd->dma_handle)) {
+		/* For non aligned isoc the condition below is always true */
+		if (etd->len <= etd->dmem_size) {
+			/* Fits into data memory, use PIO */
+			if (dir != TD_DIR_IN) {
+				copy_to_dmem(imx21,
+						etd->dmem_offset,
+						etd->cpu_buffer, etd->len);
+			}
+			etd->dma_handle = 0;
+
+		} else {
+			/* Too big for data memory, use bounce buffer */
+			enum dma_data_direction dmadir;
+
+			if (dir == TD_DIR_IN) {
+				dmadir = DMA_FROM_DEVICE;
+				etd->bounce_buffer = kmalloc(etd->len,
+								GFP_ATOMIC);
+			} else {
+				dmadir = DMA_TO_DEVICE;
+				etd->bounce_buffer = kmemdup(etd->cpu_buffer,
+								etd->len,
+								GFP_ATOMIC);
+			}
+			if (!etd->bounce_buffer) {
+				dev_err(imx21->dev, "failed bounce alloc\n");
+				goto err_bounce_alloc;
+			}
+
+			etd->dma_handle =
+				dma_map_single(imx21->dev,
+						etd->bounce_buffer,
+						etd->len,
+						dmadir);
+			if (dma_mapping_error(imx21->dev, etd->dma_handle)) {
+				dev_err(imx21->dev, "failed bounce map\n");
+				goto err_bounce_map;
+			}
+		}
+	}
+
 	clear_toggle_bit(imx21, USBH_ETDDONESTAT, etd_mask);
 	set_register_bits(imx21, USBH_ETDDONEEN, etd_mask);
 	clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
 	clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
 
-	if (dma) {
+	if (etd->dma_handle) {
 		set_register_bits(imx21, USB_ETDDMACHANLCLR, etd_mask);
 		clear_toggle_bit(imx21, USBH_XBUFSTAT, etd_mask);
 		clear_toggle_bit(imx21, USBH_YBUFSTAT, etd_mask);
-		writel(dma, imx21->regs + USB_ETDSMSA(etd_num));
+		writel(etd->dma_handle, imx21->regs + USB_ETDSMSA(etd_num));
 		set_register_bits(imx21, USB_ETDDMAEN, etd_mask);
 	} else {
 		if (dir != TD_DIR_IN) {
-			/* need to set for ZLP */
+			/* need to set for ZLP and PIO */
 			set_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
 			set_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
 		}
@@ -263,6 +342,14 @@
 
 	etd->active_count = 1;
 	writel(etd_mask, imx21->regs + USBH_ETDENSET);
+	return;
+
+err_bounce_map:
+	kfree(etd->bounce_buffer);
+
+err_bounce_alloc:
+	free_dmem(imx21, etd);
+	nonisoc_urb_completed_for_etd(imx21, etd, -ENOMEM);
 }
 
 /* ===========================================	*/
@@ -323,16 +410,23 @@
 	etd_writel(imx21, etd_num, 1,
 	    ((dmem_offset + maxpacket) << DW1_YBUFSRTAD) | dmem_offset);
 
+	etd->dmem_offset = dmem_offset;
 	urb_priv->active = 1;
-	activate_etd(imx21, etd_num, etd->dma_handle, dir);
+	activate_etd(imx21, etd_num, dir);
 }
 
-static void free_dmem(struct imx21 *imx21, int offset)
+static void free_dmem(struct imx21 *imx21, struct etd_priv *etd)
 {
 	struct imx21_dmem_area *area;
-	struct etd_priv *etd, *tmp;
+	struct etd_priv *tmp;
 	int found = 0;
+	int offset;
 
+	if (!etd->dmem_size)
+		return;
+	etd->dmem_size = 0;
+
+	offset = etd->dmem_offset;
 	list_for_each_entry(area, &imx21->dmem_list, list) {
 		if (area->offset == offset) {
 			debug_dmem_freed(imx21, area->size);
@@ -378,20 +472,23 @@
 /* ===========================================	*/
 /* End handling 				*/
 /* ===========================================	*/
-static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb);
 
 /* Endpoint now idle - release it's ETD(s) or asssign to queued request */
 static void ep_idle(struct imx21 *imx21, struct ep_priv *ep_priv)
 {
-	int etd_num;
 	int i;
 
 	for (i = 0; i < NUM_ISO_ETDS; i++) {
-		etd_num = ep_priv->etd[i];
+		int etd_num = ep_priv->etd[i];
+		struct etd_priv *etd;
 		if (etd_num < 0)
 			continue;
 
+		etd = &imx21->etd[etd_num];
 		ep_priv->etd[i] = -1;
+
+		free_dmem(imx21, etd); /* for isoc */
+
 		if (list_empty(&imx21->queue_for_etd)) {
 			free_etd(imx21, etd_num);
 			continue;
@@ -437,6 +534,24 @@
 		ep_idle(imx21, ep_priv);
 }
 
+static void nonisoc_urb_completed_for_etd(
+	struct imx21 *imx21, struct etd_priv *etd, int status)
+{
+	struct usb_host_endpoint *ep = etd->ep;
+
+	urb_done(imx21->hcd, etd->urb, status);
+	etd->urb = NULL;
+
+	if (!list_empty(&ep->urb_list)) {
+		struct urb *urb = list_first_entry(
+					&ep->urb_list, struct urb, urb_list);
+
+		dev_vdbg(imx21->dev, "next URB %p\n", urb);
+		schedule_nonisoc_etd(imx21, urb);
+	}
+}
+
+
 /* ===========================================	*/
 /* ISOC Handling ... 				*/
 /* ===========================================	*/
@@ -489,6 +604,8 @@
 		etd->ep = td->ep;
 		etd->urb = td->urb;
 		etd->len = td->len;
+		etd->dma_handle = td->dma_handle;
+		etd->cpu_buffer = td->cpu_buffer;
 
 		debug_isoc_submitted(imx21, cur_frame, td);
 
@@ -502,16 +619,17 @@
 			(TD_NOTACCESSED << DW3_COMPCODE0) |
 			(td->len << DW3_PKTLEN0));
 
-		activate_etd(imx21, etd_num, td->data, dir);
+		activate_etd(imx21, etd_num, dir);
 	}
 }
 
-static void isoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
+static void isoc_etd_done(struct usb_hcd *hcd, int etd_num)
 {
 	struct imx21 *imx21 = hcd_to_imx21(hcd);
 	int etd_mask = 1 << etd_num;
-	struct urb_priv *urb_priv = urb->hcpriv;
 	struct etd_priv *etd = imx21->etd + etd_num;
+	struct urb *urb = etd->urb;
+	struct urb_priv *urb_priv = urb->hcpriv;
 	struct td *td = etd->td;
 	struct usb_host_endpoint *ep = etd->ep;
 	int isoc_index = td->isoc_index;
@@ -545,8 +663,13 @@
 			bytes_xfrd, td->len, urb, etd_num, isoc_index);
 	}
 
-	if (dir_in)
+	if (dir_in) {
 		clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
+		if (!etd->dma_handle)
+			memcpy_fromio(etd->cpu_buffer,
+				imx21->regs + USBOTG_DMEM + etd->dmem_offset,
+				bytes_xfrd);
+	}
 
 	urb->actual_length += bytes_xfrd;
 	urb->iso_frame_desc[isoc_index].actual_length = bytes_xfrd;
@@ -569,30 +692,43 @@
 	int i;
 
 	ep_priv = kzalloc(sizeof(struct ep_priv), GFP_ATOMIC);
-	if (ep_priv == NULL)
+	if (!ep_priv)
 		return NULL;
 
-	/* Allocate the ETDs */
-	for (i = 0; i < NUM_ISO_ETDS; i++) {
-		ep_priv->etd[i] = alloc_etd(imx21);
-		if (ep_priv->etd[i] < 0) {
-			int j;
-			dev_err(imx21->dev, "isoc: Couldn't allocate etd\n");
-			for (j = 0; j < i; j++)
-				free_etd(imx21, ep_priv->etd[j]);
-			goto alloc_etd_failed;
-		}
-		imx21->etd[ep_priv->etd[i]].ep = ep;
-	}
+	for (i = 0; i < NUM_ISO_ETDS; i++)
+		ep_priv->etd[i] = -1;
 
 	INIT_LIST_HEAD(&ep_priv->td_list);
 	ep_priv->ep = ep;
 	ep->hcpriv = ep_priv;
 	return ep_priv;
+}
+
+static int alloc_isoc_etds(struct imx21 *imx21, struct ep_priv *ep_priv)
+{
+	int i, j;
+	int etd_num;
+
+	/* Allocate the ETDs if required */
+	for (i = 0; i < NUM_ISO_ETDS; i++) {
+		if (ep_priv->etd[i] < 0) {
+			etd_num = alloc_etd(imx21);
+			if (etd_num < 0)
+				goto alloc_etd_failed;
+
+			ep_priv->etd[i] = etd_num;
+			imx21->etd[etd_num].ep = ep_priv->ep;
+		}
+	}
+	return 0;
 
 alloc_etd_failed:
-	kfree(ep_priv);
-	return NULL;
+	dev_err(imx21->dev, "isoc: Couldn't allocate etd\n");
+	for (j = 0; j < i; j++) {
+		free_etd(imx21, ep_priv->etd[j]);
+		ep_priv->etd[j] = -1;
+	}
+	return -ENOMEM;
 }
 
 static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
@@ -632,6 +768,10 @@
 		ep_priv = ep->hcpriv;
 	}
 
+	ret = alloc_isoc_etds(imx21, ep_priv);
+	if (ret)
+		goto alloc_etd_failed;
+
 	ret = usb_hcd_link_urb_to_ep(hcd, urb);
 	if (ret)
 		goto link_failed;
@@ -688,12 +828,14 @@
 	/* set up transfers */
 	td = urb_priv->isoc_td;
 	for (i = 0; i < urb->number_of_packets; i++, td++) {
+		unsigned int offset = urb->iso_frame_desc[i].offset;
 		td->ep = ep;
 		td->urb = urb;
 		td->len = urb->iso_frame_desc[i].length;
 		td->isoc_index = i;
 		td->frame = wrap_frame(urb->start_frame + urb->interval * i);
-		td->data = urb->transfer_dma + urb->iso_frame_desc[i].offset;
+		td->dma_handle = urb->transfer_dma + offset;
+		td->cpu_buffer = urb->transfer_buffer + offset;
 		list_add_tail(&td->list, &ep_priv->td_list);
 	}
 
@@ -711,6 +853,7 @@
 	usb_hcd_unlink_urb_from_ep(hcd, urb);
 
 link_failed:
+alloc_etd_failed:
 alloc_ep_failed:
 	spin_unlock_irqrestore(&imx21->lock, flags);
 	kfree(urb_priv->isoc_td);
@@ -734,9 +877,7 @@
 				struct etd_priv *etd = imx21->etd + etd_num;
 
 				reset_etd(imx21, etd_num);
-				if (etd->dmem_size)
-					free_dmem(imx21, etd->dmem_offset);
-				etd->dmem_size = 0;
+				free_dmem(imx21, etd);
 			}
 		}
 	}
@@ -761,7 +902,6 @@
 	int state = urb_priv->state;
 	int etd_num = ep_priv->etd[0];
 	struct etd_priv *etd;
-	int dmem_offset;
 	u32 count;
 	u16 etd_buf_size;
 	u16 maxpacket;
@@ -786,13 +926,15 @@
 	if (usb_pipecontrol(pipe) && (state != US_CTRL_DATA)) {
 		if (state == US_CTRL_SETUP) {
 			dir = TD_DIR_SETUP;
+			if (unsuitable_for_dma(urb->setup_dma))
+				unmap_urb_setup_for_dma(imx21->hcd, urb);
 			etd->dma_handle = urb->setup_dma;
+			etd->cpu_buffer = urb->setup_packet;
 			bufround = 0;
 			count = 8;
 			datatoggle = TD_TOGGLE_DATA0;
 		} else {	/* US_CTRL_ACK */
 			dir = usb_pipeout(pipe) ? TD_DIR_IN : TD_DIR_OUT;
-			etd->dma_handle = urb->transfer_dma;
 			bufround = 0;
 			count = 0;
 			datatoggle = TD_TOGGLE_DATA1;
@@ -800,7 +942,11 @@
 	} else {
 		dir = usb_pipeout(pipe) ? TD_DIR_OUT : TD_DIR_IN;
 		bufround = (dir == TD_DIR_IN) ? 1 : 0;
+		if (unsuitable_for_dma(urb->transfer_dma))
+			unmap_urb_for_dma(imx21->hcd, urb);
+
 		etd->dma_handle = urb->transfer_dma;
+		etd->cpu_buffer = urb->transfer_buffer;
 		if (usb_pipebulk(pipe) && (state == US_BULK0))
 			count = 0;
 		else
@@ -855,8 +1001,8 @@
 
 	/* allocate x and y buffer space at once */
 	etd->dmem_size = (count > maxpacket) ? maxpacket * 2 : maxpacket;
-	dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep);
-	if (dmem_offset < 0) {
+	etd->dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep);
+	if (etd->dmem_offset < 0) {
 		/* Setup everything we can in HW and update when we get DMEM */
 		etd_writel(imx21, etd_num, 1, (u32)maxpacket << 16);
 
@@ -867,26 +1013,26 @@
 	}
 
 	etd_writel(imx21, etd_num, 1,
-		(((u32) dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) |
-		(u32) dmem_offset);
+		(((u32) etd->dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) |
+		(u32) etd->dmem_offset);
 
 	urb_priv->active = 1;
 
 	/* enable the ETD to kick off transfer */
 	dev_vdbg(imx21->dev, "Activating etd %d for %d bytes %s\n",
 		etd_num, count, dir != TD_DIR_IN ? "out" : "in");
-	activate_etd(imx21, etd_num, etd->dma_handle, dir);
+	activate_etd(imx21, etd_num, dir);
 
 }
 
-static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
+static void nonisoc_etd_done(struct usb_hcd *hcd, int etd_num)
 {
 	struct imx21 *imx21 = hcd_to_imx21(hcd);
 	struct etd_priv *etd = &imx21->etd[etd_num];
+	struct urb *urb = etd->urb;
 	u32 etd_mask = 1 << etd_num;
 	struct urb_priv *urb_priv = urb->hcpriv;
 	int dir;
-	u16 xbufaddr;
 	int cc;
 	u32 bytes_xfrd;
 	int etd_done;
@@ -894,7 +1040,6 @@
 	disactivate_etd(imx21, etd_num);
 
 	dir = (etd_readl(imx21, etd_num, 0) >> DW0_DIRECT) & 0x3;
-	xbufaddr = etd_readl(imx21, etd_num, 1) & 0xffff;
 	cc = (etd_readl(imx21, etd_num, 2) >> DW2_COMPCODE) & 0xf;
 	bytes_xfrd = etd->len - (etd_readl(imx21, etd_num, 3) & 0x1fffff);
 
@@ -906,8 +1051,21 @@
 	if (dir == TD_DIR_IN) {
 		clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
 		clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
+
+		if (etd->bounce_buffer) {
+			memcpy(etd->cpu_buffer, etd->bounce_buffer, bytes_xfrd);
+			dma_unmap_single(imx21->dev,
+				etd->dma_handle, etd->len, DMA_FROM_DEVICE);
+		} else if (!etd->dma_handle && bytes_xfrd) {/* PIO */
+			memcpy_fromio(etd->cpu_buffer,
+				imx21->regs + USBOTG_DMEM + etd->dmem_offset,
+				bytes_xfrd);
+		}
 	}
-	free_dmem(imx21, xbufaddr);
+
+	kfree(etd->bounce_buffer);
+	etd->bounce_buffer = NULL;
+	free_dmem(imx21, etd);
 
 	urb->error_count = 0;
 	if (!(urb->transfer_flags & URB_SHORT_NOT_OK)
@@ -964,24 +1122,15 @@
 		break;
 	}
 
-	if (!etd_done) {
+	if (etd_done)
+		nonisoc_urb_completed_for_etd(imx21, etd, cc_to_error[cc]);
+	else {
 		dev_vdbg(imx21->dev, "next state=%d\n", urb_priv->state);
 		schedule_nonisoc_etd(imx21, urb);
-	} else {
-		struct usb_host_endpoint *ep = urb->ep;
-
-		urb_done(hcd, urb, cc_to_error[cc]);
-		etd->urb = NULL;
-
-		if (!list_empty(&ep->urb_list)) {
-			urb = list_first_entry(&ep->urb_list,
-				struct urb, urb_list);
-			dev_vdbg(imx21->dev, "next URB %p\n", urb);
-			schedule_nonisoc_etd(imx21, urb);
-		}
 	}
 }
 
+
 static struct ep_priv *alloc_ep(void)
 {
 	int i;
@@ -1007,7 +1156,6 @@
 	struct etd_priv *etd;
 	int ret;
 	unsigned long flags;
-	int new_ep = 0;
 
 	dev_vdbg(imx21->dev,
 		"enqueue urb=%p ep=%p len=%d "
@@ -1035,7 +1183,6 @@
 		}
 		ep->hcpriv = ep_priv;
 		ep_priv->ep = ep;
-		new_ep = 1;
 	}
 
 	ret = usb_hcd_link_urb_to_ep(hcd, urb);
@@ -1124,9 +1271,13 @@
 	} else if (urb_priv->active) {
 		int etd_num = ep_priv->etd[0];
 		if (etd_num != -1) {
+			struct etd_priv *etd = &imx21->etd[etd_num];
+
 			disactivate_etd(imx21, etd_num);
-			free_dmem(imx21, etd_readl(imx21, etd_num, 1) & 0xffff);
-			imx21->etd[etd_num].urb = NULL;
+			free_dmem(imx21, etd);
+			etd->urb = NULL;
+			kfree(etd->bounce_buffer);
+			etd->bounce_buffer = NULL;
 		}
 	}
 
@@ -1226,9 +1377,9 @@
 		}
 
 		if (usb_pipeisoc(etd->urb->pipe))
-			isoc_etd_done(hcd, etd->urb, etd_num);
+			isoc_etd_done(hcd, etd_num);
 		else
-			nonisoc_etd_done(hcd, etd->urb, etd_num);
+			nonisoc_etd_done(hcd, etd_num);
 	}
 
 	/* only enable SOF interrupt if it may be needed for the kludge */
@@ -1696,6 +1847,7 @@
 	}
 
 	imx21 = hcd_to_imx21(hcd);
+	imx21->hcd = hcd;
 	imx21->dev = &pdev->dev;
 	imx21->pdata = pdev->dev.platform_data;
 	if (!imx21->pdata)
@@ -1754,7 +1906,7 @@
 failed_clock_get:
 	iounmap(imx21->regs);
 failed_ioremap:
-	release_mem_region(res->start, res->end - res->start);
+	release_mem_region(res->start, resource_size(res));
 failed_request_mem:
 	remove_debug_files(imx21);
 	usb_put_hcd(hcd);
diff --git a/drivers/usb/host/imx21-hcd.h b/drivers/usb/host/imx21-hcd.h
index 1b0d913..87b29fd 100644
--- a/drivers/usb/host/imx21-hcd.h
+++ b/drivers/usb/host/imx21-hcd.h
@@ -250,6 +250,7 @@
 #define USBCTRL_USB_BYP			(1 << 2)
 #define USBCTRL_HOST1_TXEN_OE		(1 << 1)
 
+#define USBOTG_DMEM		0x1000
 
 /* Values in TD blocks */
 #define TD_DIR_SETUP	    0
@@ -346,8 +347,8 @@
 	struct list_head list;
 	struct urb *urb;
 	struct usb_host_endpoint *ep;
-	dma_addr_t data;
-	unsigned long buf_addr;
+	dma_addr_t dma_handle;
+	void *cpu_buffer;
 	int len;
 	int frame;
 	int isoc_index;
@@ -360,6 +361,8 @@
 	struct td *td;
 	struct list_head queue;
 	dma_addr_t dma_handle;
+	void *cpu_buffer;
+	void *bounce_buffer;
 	int alloc;
 	int len;
 	int dmem_size;
@@ -412,6 +415,7 @@
 struct imx21 {
 	spinlock_t lock;
 	struct device *dev;
+	struct usb_hcd *hcd;
 	struct mx21_usbh_platform_data *pdata;
 	struct list_head dmem_list;
 	struct list_head queue_for_etd; /* eps queued due to etd shortage */
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index d9e8212..0da7fc0 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1557,8 +1557,6 @@
 	return 0;
 }
 
-#define resource_len(r) (((r)->end - (r)->start) + 1)
-
 static int __devinit isp116x_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
@@ -1597,7 +1595,7 @@
 		ret = -EBUSY;
 		goto err1;
 	}
-	addr_reg = ioremap(addr->start, resource_len(addr));
+	addr_reg = ioremap(addr->start, resource_size(addr));
 	if (addr_reg == NULL) {
 		ret = -ENOMEM;
 		goto err2;
@@ -1606,7 +1604,7 @@
 		ret = -EBUSY;
 		goto err3;
 	}
-	data_reg = ioremap(data->start, resource_len(data));
+	data_reg = ioremap(data->start, resource_size(data));
 	if (data_reg == NULL) {
 		ret = -ENOMEM;
 		goto err4;
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 0587ad4..8196fa1 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -1676,13 +1676,6 @@
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
 			_DBG(0, "USB_PORT_FEAT_SUSPEND\n");
-#ifdef	CONFIG_USB_OTG
-			if (ohci->hcd.self.otg_port == (wIndex + 1) &&
-			    ohci->hcd.self.b_hnp_enable) {
-				start_hnp(ohci);
-				break;
-			}
-#endif
 			spin_lock_irqsave(&isp1362_hcd->lock, flags);
 			isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PSS);
 			isp1362_hcd->rhport[wIndex] =
@@ -2656,8 +2649,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define resource_len(r) (((r)->end - (r)->start) + 1)
-
 static int __devexit isp1362_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
@@ -2679,12 +2670,12 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start);
 	if (res)
-		release_mem_region(res->start, resource_len(res));
+		release_mem_region(res->start, resource_size(res));
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start);
 	if (res)
-		release_mem_region(res->start, resource_len(res));
+		release_mem_region(res->start, resource_size(res));
 
 	DBG(0, "%s: put_hcd\n", __func__);
 	usb_put_hcd(hcd);
@@ -2730,21 +2721,21 @@
 		goto err1;
 	}
 
-	if (!request_mem_region(addr->start, resource_len(addr), hcd_name)) {
+	if (!request_mem_region(addr->start, resource_size(addr), hcd_name)) {
 		retval = -EBUSY;
 		goto err1;
 	}
-	addr_reg = ioremap(addr->start, resource_len(addr));
+	addr_reg = ioremap(addr->start, resource_size(addr));
 	if (addr_reg == NULL) {
 		retval = -ENOMEM;
 		goto err2;
 	}
 
-	if (!request_mem_region(data->start, resource_len(data), hcd_name)) {
+	if (!request_mem_region(data->start, resource_size(data), hcd_name)) {
 		retval = -EBUSY;
 		goto err3;
 	}
-	data_reg = ioremap(data->start, resource_len(data));
+	data_reg = ioremap(data->start, resource_size(data));
 	if (data_reg == NULL) {
 		retval = -ENOMEM;
 		goto err4;
@@ -2802,13 +2793,13 @@
 	iounmap(data_reg);
  err4:
 	DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start);
-	release_mem_region(data->start, resource_len(data));
+	release_mem_region(data->start, resource_size(data));
  err3:
 	DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__, addr_reg);
 	iounmap(addr_reg);
  err2:
 	DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start);
-	release_mem_region(addr->start, resource_len(addr));
+	release_mem_region(addr->start, resource_size(addr));
  err1:
 	pr_err("%s: init error, %d\n", __func__, retval);
 
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 36abd2b..d7d3449 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -413,18 +413,21 @@
 	.open		= debug_async_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_periodic_fops = {
 	.owner		= THIS_MODULE,
 	.open		= debug_periodic_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 static const struct file_operations debug_registers_fops = {
 	.owner		= THIS_MODULE,
 	.open		= debug_registers_open,
 	.read		= debug_output,
 	.release	= debug_close,
+	.llseek		= default_llseek,
 };
 
 static struct dentry *ohci_debug_root;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index c3b4ccc..3b57850 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -398,7 +398,14 @@
 
 	ohci = hcd_to_ohci (hcd);
 	ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-	ohci_usb_reset (ohci);
+	ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+
+	/* If the SHUTDOWN quirk is set, don't put the controller in RESET */
+	ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
+			OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
+			OHCI_CTRL_RWC);
+	ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
+
 	/* flush the writes */
 	(void) ohci_readl (ohci, &ohci->regs->control);
 }
@@ -1270,6 +1277,9 @@
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
+#ifdef OMAP3_PLATFORM_DRIVER
+	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
+#endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 6bdc8b2..36ee9a6 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -201,6 +201,20 @@
 	return 0;
 }
 
+/* nVidia controllers continue to drive Reset signalling on the bus
+ * even after system shutdown, wasting power.  This flag tells the
+ * shutdown routine to leave the controller OPERATIONAL instead of RESET.
+ */
+static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+
+	ohci->flags |= OHCI_QUIRK_SHUTDOWN;
+	ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
+
+	return 0;
+}
+
 /*
  * The hardware normally enables the A-link power management feature, which
  * lets the system lower the power consumption in idle states.
@@ -332,6 +346,10 @@
 		PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
 		.driver_data = (unsigned long)ohci_quirk_amd700,
 	},
+	{
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
+		.driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
+	},
 
 	/* FIXME for some of the early AMD 760 southbridges, OHCI
 	 * won't work at all.  blacklist them.
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
index 60f03cc..0b35d22 100644
--- a/drivers/usb/host/ohci-sh.c
+++ b/drivers/usb/host/ohci-sh.c
@@ -77,7 +77,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define resource_len(r) (((r)->end - (r)->start) + 1)
 static int ohci_hcd_sh_probe(struct platform_device *pdev)
 {
 	struct resource *res = NULL;
@@ -109,7 +108,7 @@
 
 	hcd->regs = (void __iomem *)res->start;
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_len(res);
+	hcd->rsrc_len = resource_size(res);
 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
 	if (ret != 0) {
 		err("Failed to add hcd");
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index cff2363..041d30f30 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -168,7 +168,7 @@
 
 	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (retval)
-		goto err4;
+		goto err5;
 
 	/* enable power and unmask interrupts */
 
@@ -176,6 +176,8 @@
 	sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0);
 
 	return 0;
+err5:
+	iounmap(hcd->regs);
 err4:
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err3:
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 5bf15fe..51facb9 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -403,6 +403,7 @@
 #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */
 #define	OHCI_QUIRK_AMD_ISO	0x200			/* ISO transfers*/
 #define	OHCI_QUIRK_AMD_PREFETCH	0x400			/* pre-fetch for ISO transfer */
+#define	OHCI_QUIRK_SHUTDOWN	0x800			/* nVidia power bug */
 	// there are also chip quirks/bugs in init logic
 
 	struct work_struct	nec_work;	/* Worker for NEC quirk */
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index d9c85a2..d32c3ea 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -3696,7 +3696,7 @@
 static int oxu_verify_id(struct platform_device *pdev, void *base)
 {
 	u32 id;
-	char *bo[] = {
+	static const char * const bo[] = {
 		"reserved",
 		"128-pin LQFP",
 		"84-pin TFBGA",
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 83b5f9c..464ed97 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -169,6 +169,7 @@
 static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 {
 	void __iomem *base;
+	u32 control;
 
 	if (!mmio_resource_enabled(pdev, 0))
 		return;
@@ -177,10 +178,14 @@
 	if (base == NULL)
 		return;
 
+	control = readl(base + OHCI_CONTROL);
+
 /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
-#ifndef __hppa__
-{
-	u32 control = readl(base + OHCI_CONTROL);
+#ifdef __hppa__
+#define	OHCI_CTRL_MASK		(OHCI_CTRL_RWC | OHCI_CTRL_IR)
+#else
+#define	OHCI_CTRL_MASK		OHCI_CTRL_RWC
+
 	if (control & OHCI_CTRL_IR) {
 		int wait_time = 500; /* arbitrary; 5 seconds */
 		writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
@@ -194,13 +199,12 @@
 			dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
 					" (BIOS bug?) %08x\n",
 					readl(base + OHCI_CONTROL));
-
-		/* reset controller, preserving RWC */
-		writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
 	}
-}
 #endif
 
+	/* reset controller, preserving RWC (and possibly IR) */
+	writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
+
 	/*
 	 * disable interrupts
 	 */
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index 95d0f5a..25563e9 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -227,7 +227,7 @@
 		int odd = len & 0x0001;
 
 		len = len / 2;
-		ioread16_rep(fifoaddr, buf, len);
+		iowrite16_rep(fifoaddr, buf, len);
 		if (unlikely(odd)) {
 			buf = &buf[len];
 			iowrite8((unsigned char)*buf, fifoaddr);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index d3ade40..2090b45 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -917,10 +917,13 @@
 	unsigned long destination, status;
 	int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize);
 	int len = urb->transfer_buffer_length;
-	dma_addr_t data = urb->transfer_dma;
+	int this_sg_len;
+	dma_addr_t data;
 	__le32 *plink;
 	struct urb_priv *urbp = urb->hcpriv;
 	unsigned int toggle;
+	struct scatterlist  *sg;
+	int i;
 
 	if (len < 0)
 		return -EINVAL;
@@ -937,12 +940,26 @@
 	if (usb_pipein(urb->pipe))
 		status |= TD_CTRL_SPD;
 
+	i = urb->num_sgs;
+	if (len > 0 && i > 0) {
+		sg = urb->sg;
+		data = sg_dma_address(sg);
+
+		/* urb->transfer_buffer_length may be smaller than the
+		 * size of the scatterlist (or vice versa)
+		 */
+		this_sg_len = min_t(int, sg_dma_len(sg), len);
+	} else {
+		sg = NULL;
+		data = urb->transfer_dma;
+		this_sg_len = len;
+	}
 	/*
 	 * Build the DATA TDs
 	 */
 	plink = NULL;
 	td = qh->dummy_td;
-	do {	/* Allow zero length packets */
+	for (;;) {	/* Allow zero length packets */
 		int pktsze = maxsze;
 
 		if (len <= pktsze) {		/* The last packet */
@@ -965,10 +982,18 @@
 		plink = &td->link;
 		status |= TD_CTRL_ACTIVE;
 
-		data += pktsze;
-		len -= maxsze;
 		toggle ^= 1;
-	} while (len > 0);
+		data += pktsze;
+		this_sg_len -= pktsze;
+		len -= maxsze;
+		if (this_sg_len <= 0) {
+			if (--i <= 0 || len <= 0)
+				break;
+			sg = sg_next(sg);
+			data = sg_dma_address(sg);
+			this_sg_len = min_t(int, sg_dma_len(sg), len);
+		}
+	}
 
 	/*
 	 * URB_ZERO_PACKET means adding a 0-length packet, if direction
diff --git a/drivers/usb/host/whci/Kbuild b/drivers/usb/host/whci/Kbuild
index 11e5040..26df013 100644
--- a/drivers/usb/host/whci/Kbuild
+++ b/drivers/usb/host/whci/Kbuild
@@ -3,7 +3,7 @@
 whci-hcd-y := \
 	asl.o	\
 	debug.o \
-	hcd.o 	\
+	hcd.o	\
 	hw.o	\
 	init.o	\
 	int.o	\
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index a1a7a97..fef5a1f 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -24,6 +24,10 @@
 
 #include "xhci.h"
 
+#define	PORT_WAKE_BITS	(PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E)
+#define	PORT_RWC_BITS	(PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
+			 PORT_RC | PORT_PLC | PORT_PE)
+
 static void xhci_hub_descriptor(struct xhci_hcd *xhci,
 		struct usb_hub_descriptor *desc)
 {
@@ -123,12 +127,105 @@
  * writing a 0 clears the bit and writing a 1 sets the bit (RWS).
  * For all other types (RW1S, RW1CS, RW, and RZ), writing a '0' has no effect.
  */
-static u32 xhci_port_state_to_neutral(u32 state)
+u32 xhci_port_state_to_neutral(u32 state)
 {
 	/* Save read-only status and port state */
 	return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS);
 }
 
+/*
+ * find slot id based on port number.
+ */
+int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port)
+{
+	int slot_id;
+	int i;
+
+	slot_id = 0;
+	for (i = 0; i < MAX_HC_SLOTS; i++) {
+		if (!xhci->devs[i])
+			continue;
+		if (xhci->devs[i]->port == port) {
+			slot_id = i;
+			break;
+		}
+	}
+
+	return slot_id;
+}
+
+/*
+ * Stop device
+ * It issues stop endpoint command for EP 0 to 30. And wait the last command
+ * to complete.
+ * suspend will set to 1, if suspend bit need to set in command.
+ */
+static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
+{
+	struct xhci_virt_device *virt_dev;
+	struct xhci_command *cmd;
+	unsigned long flags;
+	int timeleft;
+	int ret;
+	int i;
+
+	ret = 0;
+	virt_dev = xhci->devs[slot_id];
+	cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
+	if (!cmd) {
+		xhci_dbg(xhci, "Couldn't allocate command structure.\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&xhci->lock, flags);
+	for (i = LAST_EP_INDEX; i > 0; i--) {
+		if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
+			xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
+	}
+	cmd->command_trb = xhci->cmd_ring->enqueue;
+	list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
+	xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
+	xhci_ring_cmd_db(xhci);
+	spin_unlock_irqrestore(&xhci->lock, flags);
+
+	/* Wait for last stop endpoint command to finish */
+	timeleft = wait_for_completion_interruptible_timeout(
+			cmd->completion,
+			USB_CTRL_SET_TIMEOUT);
+	if (timeleft <= 0) {
+		xhci_warn(xhci, "%s while waiting for stop endpoint command\n",
+				timeleft == 0 ? "Timeout" : "Signal");
+		spin_lock_irqsave(&xhci->lock, flags);
+		/* The timeout might have raced with the event ring handler, so
+		 * only delete from the list if the item isn't poisoned.
+		 */
+		if (cmd->cmd_list.next != LIST_POISON1)
+			list_del(&cmd->cmd_list);
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		ret = -ETIME;
+		goto command_cleanup;
+	}
+
+command_cleanup:
+	xhci_free_command(xhci, cmd);
+	return ret;
+}
+
+/*
+ * Ring device, it rings the all doorbells unconditionally.
+ */
+void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
+{
+	int i;
+
+	for (i = 0; i < LAST_EP_INDEX + 1; i++)
+		if (xhci->devs[slot_id]->eps[i].ring &&
+		    xhci->devs[slot_id]->eps[i].ring->dequeue)
+			xhci_ring_ep_doorbell(xhci, slot_id, i, 0);
+
+	return;
+}
+
 static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
 		u32 __iomem *addr, u32 port_status)
 {
@@ -162,6 +259,10 @@
 		status = PORT_PEC;
 		port_change_bit = "enable/disable";
 		break;
+	case USB_PORT_FEAT_C_SUSPEND:
+		status = PORT_PLC;
+		port_change_bit = "suspend/resume";
+		break;
 	default:
 		/* Should never happen */
 		return;
@@ -179,9 +280,10 @@
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int ports;
 	unsigned long flags;
-	u32 temp, status;
+	u32 temp, temp1, status;
 	int retval = 0;
 	u32 __iomem *addr;
+	int slot_id;
 
 	ports = HCS_MAX_PORTS(xhci->hcs_params1);
 
@@ -211,9 +313,49 @@
 		if ((temp & PORT_OCC))
 			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
 		/*
-		 * FIXME ignoring suspend, reset, and USB 2.1/3.0 specific
+		 * FIXME ignoring reset and USB 2.1/3.0 specific
 		 * changes
 		 */
+		if ((temp & PORT_PLS_MASK) == XDEV_U3
+			&& (temp & PORT_POWER))
+			status |= 1 << USB_PORT_FEAT_SUSPEND;
+		if ((temp & PORT_PLS_MASK) == XDEV_RESUME) {
+			if ((temp & PORT_RESET) || !(temp & PORT_PE))
+				goto error;
+			if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies,
+						xhci->resume_done[wIndex])) {
+				xhci_dbg(xhci, "Resume USB2 port %d\n",
+					wIndex + 1);
+				xhci->resume_done[wIndex] = 0;
+				temp1 = xhci_port_state_to_neutral(temp);
+				temp1 &= ~PORT_PLS_MASK;
+				temp1 |= PORT_LINK_STROBE | XDEV_U0;
+				xhci_writel(xhci, temp1, addr);
+
+				xhci_dbg(xhci, "set port %d resume\n",
+					wIndex + 1);
+				slot_id = xhci_find_slot_id_by_port(xhci,
+								 wIndex + 1);
+				if (!slot_id) {
+					xhci_dbg(xhci, "slot_id is zero\n");
+					goto error;
+				}
+				xhci_ring_device(xhci, slot_id);
+				xhci->port_c_suspend[wIndex >> 5] |=
+						1 << (wIndex & 31);
+				xhci->suspended_ports[wIndex >> 5] &=
+						~(1 << (wIndex & 31));
+			}
+		}
+		if ((temp & PORT_PLS_MASK) == XDEV_U0
+			&& (temp & PORT_POWER)
+			&& (xhci->suspended_ports[wIndex >> 5] &
+			    (1 << (wIndex & 31)))) {
+			xhci->suspended_ports[wIndex >> 5] &=
+					~(1 << (wIndex & 31));
+			xhci->port_c_suspend[wIndex >> 5] |=
+					1 << (wIndex & 31);
+		}
 		if (temp & PORT_CONNECT) {
 			status |= USB_PORT_STAT_CONNECTION;
 			status |= xhci_port_speed(temp);
@@ -226,6 +368,8 @@
 			status |= USB_PORT_STAT_RESET;
 		if (temp & PORT_POWER)
 			status |= USB_PORT_STAT_POWER;
+		if (xhci->port_c_suspend[wIndex >> 5] & (1 << (wIndex & 31)))
+			status |= 1 << USB_PORT_FEAT_C_SUSPEND;
 		xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
 		put_unaligned(cpu_to_le32(status), (__le32 *) buf);
 		break;
@@ -238,6 +382,42 @@
 		temp = xhci_readl(xhci, addr);
 		temp = xhci_port_state_to_neutral(temp);
 		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			temp = xhci_readl(xhci, addr);
+			/* In spec software should not attempt to suspend
+			 * a port unless the port reports that it is in the
+			 * enabled (PED = ‘1’,PLS < ‘3’) state.
+			 */
+			if ((temp & PORT_PE) == 0 || (temp & PORT_RESET)
+				|| (temp & PORT_PLS_MASK) >= XDEV_U3) {
+				xhci_warn(xhci, "USB core suspending device "
+					  "not in U0/U1/U2.\n");
+				goto error;
+			}
+
+			slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+			if (!slot_id) {
+				xhci_warn(xhci, "slot_id is zero\n");
+				goto error;
+			}
+			/* unlock to execute stop endpoint commands */
+			spin_unlock_irqrestore(&xhci->lock, flags);
+			xhci_stop_device(xhci, slot_id, 1);
+			spin_lock_irqsave(&xhci->lock, flags);
+
+			temp = xhci_port_state_to_neutral(temp);
+			temp &= ~PORT_PLS_MASK;
+			temp |= PORT_LINK_STROBE | XDEV_U3;
+			xhci_writel(xhci, temp, addr);
+
+			spin_unlock_irqrestore(&xhci->lock, flags);
+			msleep(10); /* wait device to enter */
+			spin_lock_irqsave(&xhci->lock, flags);
+
+			temp = xhci_readl(xhci, addr);
+			xhci->suspended_ports[wIndex >> 5] |=
+					1 << (wIndex & (31));
+			break;
 		case USB_PORT_FEAT_POWER:
 			/*
 			 * Turn on ports, even if there isn't per-port switching.
@@ -271,6 +451,52 @@
 		temp = xhci_readl(xhci, addr);
 		temp = xhci_port_state_to_neutral(temp);
 		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			temp = xhci_readl(xhci, addr);
+			xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n");
+			xhci_dbg(xhci, "PORTSC %04x\n", temp);
+			if (temp & PORT_RESET)
+				goto error;
+			if (temp & XDEV_U3) {
+				if ((temp & PORT_PE) == 0)
+					goto error;
+				if (DEV_SUPERSPEED(temp)) {
+					temp = xhci_port_state_to_neutral(temp);
+					temp &= ~PORT_PLS_MASK;
+					temp |= PORT_LINK_STROBE | XDEV_U0;
+					xhci_writel(xhci, temp, addr);
+					xhci_readl(xhci, addr);
+				} else {
+					temp = xhci_port_state_to_neutral(temp);
+					temp &= ~PORT_PLS_MASK;
+					temp |= PORT_LINK_STROBE | XDEV_RESUME;
+					xhci_writel(xhci, temp, addr);
+
+					spin_unlock_irqrestore(&xhci->lock,
+							       flags);
+					msleep(20);
+					spin_lock_irqsave(&xhci->lock, flags);
+
+					temp = xhci_readl(xhci, addr);
+					temp = xhci_port_state_to_neutral(temp);
+					temp &= ~PORT_PLS_MASK;
+					temp |= PORT_LINK_STROBE | XDEV_U0;
+					xhci_writel(xhci, temp, addr);
+				}
+				xhci->port_c_suspend[wIndex >> 5] |=
+						1 << (wIndex & 31);
+			}
+
+			slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+			if (!slot_id) {
+				xhci_dbg(xhci, "slot_id is zero\n");
+				goto error;
+			}
+			xhci_ring_device(xhci, slot_id);
+			break;
+		case USB_PORT_FEAT_C_SUSPEND:
+			xhci->port_c_suspend[wIndex >> 5] &=
+					~(1 << (wIndex & 31));
 		case USB_PORT_FEAT_C_RESET:
 		case USB_PORT_FEAT_C_CONNECTION:
 		case USB_PORT_FEAT_C_OVER_CURRENT:
@@ -306,6 +532,7 @@
 {
 	unsigned long flags;
 	u32 temp, status;
+	u32 mask;
 	int i, retval;
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int ports;
@@ -318,13 +545,18 @@
 	memset(buf, 0, retval);
 	status = 0;
 
+	mask = PORT_CSC | PORT_PEC | PORT_OCC;
+
 	spin_lock_irqsave(&xhci->lock, flags);
 	/* For each port, did anything change?  If so, set that bit in buf. */
 	for (i = 0; i < ports; i++) {
 		addr = &xhci->op_regs->port_status_base +
 			NUM_PORT_REGS*i;
 		temp = xhci_readl(xhci, addr);
-		if (temp & (PORT_CSC | PORT_PEC | PORT_OCC)) {
+		if ((temp & mask) != 0 ||
+			(xhci->port_c_suspend[i >> 5] &	1 << (i & 31)) ||
+			(xhci->resume_done[i] && time_after_eq(
+			    jiffies, xhci->resume_done[i]))) {
 			buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
 			status = 1;
 		}
@@ -332,3 +564,182 @@
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	return status ? retval : 0;
 }
+
+#ifdef CONFIG_PM
+
+int xhci_bus_suspend(struct usb_hcd *hcd)
+{
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int port;
+	unsigned long flags;
+
+	xhci_dbg(xhci, "suspend root hub\n");
+
+	spin_lock_irqsave(&xhci->lock, flags);
+
+	if (hcd->self.root_hub->do_remote_wakeup) {
+		port = HCS_MAX_PORTS(xhci->hcs_params1);
+		while (port--) {
+			if (xhci->resume_done[port] != 0) {
+				spin_unlock_irqrestore(&xhci->lock, flags);
+				xhci_dbg(xhci, "suspend failed because "
+						"port %d is resuming\n",
+						port + 1);
+				return -EBUSY;
+			}
+		}
+	}
+
+	port = HCS_MAX_PORTS(xhci->hcs_params1);
+	xhci->bus_suspended = 0;
+	while (port--) {
+		/* suspend the port if the port is not suspended */
+		u32 __iomem *addr;
+		u32 t1, t2;
+		int slot_id;
+
+		addr = &xhci->op_regs->port_status_base +
+			NUM_PORT_REGS * (port & 0xff);
+		t1 = xhci_readl(xhci, addr);
+		t2 = xhci_port_state_to_neutral(t1);
+
+		if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) {
+			xhci_dbg(xhci, "port %d not suspended\n", port);
+			slot_id = xhci_find_slot_id_by_port(xhci, port + 1);
+			if (slot_id) {
+				spin_unlock_irqrestore(&xhci->lock, flags);
+				xhci_stop_device(xhci, slot_id, 1);
+				spin_lock_irqsave(&xhci->lock, flags);
+			}
+			t2 &= ~PORT_PLS_MASK;
+			t2 |= PORT_LINK_STROBE | XDEV_U3;
+			set_bit(port, &xhci->bus_suspended);
+		}
+		if (hcd->self.root_hub->do_remote_wakeup) {
+			if (t1 & PORT_CONNECT) {
+				t2 |= PORT_WKOC_E | PORT_WKDISC_E;
+				t2 &= ~PORT_WKCONN_E;
+			} else {
+				t2 |= PORT_WKOC_E | PORT_WKCONN_E;
+				t2 &= ~PORT_WKDISC_E;
+			}
+		} else
+			t2 &= ~PORT_WAKE_BITS;
+
+		t1 = xhci_port_state_to_neutral(t1);
+		if (t1 != t2)
+			xhci_writel(xhci, t2, addr);
+
+		if (DEV_HIGHSPEED(t1)) {
+			/* enable remote wake up for USB 2.0 */
+			u32 __iomem *addr;
+			u32 tmp;
+
+			addr = &xhci->op_regs->port_power_base +
+				NUM_PORT_REGS * (port & 0xff);
+			tmp = xhci_readl(xhci, addr);
+			tmp |= PORT_RWE;
+			xhci_writel(xhci, tmp, addr);
+		}
+	}
+	hcd->state = HC_STATE_SUSPENDED;
+	xhci->next_statechange = jiffies + msecs_to_jiffies(10);
+	spin_unlock_irqrestore(&xhci->lock, flags);
+	return 0;
+}
+
+int xhci_bus_resume(struct usb_hcd *hcd)
+{
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int port;
+	u32 temp;
+	unsigned long flags;
+
+	xhci_dbg(xhci, "resume root hub\n");
+
+	if (time_before(jiffies, xhci->next_statechange))
+		msleep(5);
+
+	spin_lock_irqsave(&xhci->lock, flags);
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	/* delay the irqs */
+	temp = xhci_readl(xhci, &xhci->op_regs->command);
+	temp &= ~CMD_EIE;
+	xhci_writel(xhci, temp, &xhci->op_regs->command);
+
+	port = HCS_MAX_PORTS(xhci->hcs_params1);
+	while (port--) {
+		/* Check whether need resume ports. If needed
+		   resume port and disable remote wakeup */
+		u32 __iomem *addr;
+		u32 temp;
+		int slot_id;
+
+		addr = &xhci->op_regs->port_status_base +
+			NUM_PORT_REGS * (port & 0xff);
+		temp = xhci_readl(xhci, addr);
+		if (DEV_SUPERSPEED(temp))
+			temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
+		else
+			temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+		if (test_bit(port, &xhci->bus_suspended) &&
+		    (temp & PORT_PLS_MASK)) {
+			if (DEV_SUPERSPEED(temp)) {
+				temp = xhci_port_state_to_neutral(temp);
+				temp &= ~PORT_PLS_MASK;
+				temp |= PORT_LINK_STROBE | XDEV_U0;
+				xhci_writel(xhci, temp, addr);
+			} else {
+				temp = xhci_port_state_to_neutral(temp);
+				temp &= ~PORT_PLS_MASK;
+				temp |= PORT_LINK_STROBE | XDEV_RESUME;
+				xhci_writel(xhci, temp, addr);
+
+				spin_unlock_irqrestore(&xhci->lock, flags);
+				msleep(20);
+				spin_lock_irqsave(&xhci->lock, flags);
+
+				temp = xhci_readl(xhci, addr);
+				temp = xhci_port_state_to_neutral(temp);
+				temp &= ~PORT_PLS_MASK;
+				temp |= PORT_LINK_STROBE | XDEV_U0;
+				xhci_writel(xhci, temp, addr);
+			}
+			slot_id = xhci_find_slot_id_by_port(xhci, port + 1);
+			if (slot_id)
+				xhci_ring_device(xhci, slot_id);
+		} else
+			xhci_writel(xhci, temp, addr);
+
+		if (DEV_HIGHSPEED(temp)) {
+			/* disable remote wake up for USB 2.0 */
+			u32 __iomem *addr;
+			u32 tmp;
+
+			addr = &xhci->op_regs->port_power_base +
+				NUM_PORT_REGS * (port & 0xff);
+			tmp = xhci_readl(xhci, addr);
+			tmp &= ~PORT_RWE;
+			xhci_writel(xhci, tmp, addr);
+		}
+	}
+
+	(void) xhci_readl(xhci, &xhci->op_regs->command);
+
+	xhci->next_statechange = jiffies + msecs_to_jiffies(5);
+	hcd->state = HC_STATE_RUNNING;
+	/* re-enable irqs */
+	temp = xhci_readl(xhci, &xhci->op_regs->command);
+	temp |= CMD_EIE;
+	xhci_writel(xhci, temp, &xhci->op_regs->command);
+	temp = xhci_readl(xhci, &xhci->op_regs->command);
+
+	spin_unlock_irqrestore(&xhci->lock, flags);
+	return 0;
+}
+
+#endif	/* CONFIG_PM */
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 4e51343..2027706 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -778,6 +778,7 @@
 
 	init_completion(&dev->cmd_completion);
 	INIT_LIST_HEAD(&dev->cmd_list);
+	dev->udev = udev;
 
 	/* Point to output device context in dcbaa. */
 	xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
@@ -866,6 +867,7 @@
 			top_dev = top_dev->parent)
 		/* Found device below root hub */;
 	slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
+	dev->port = top_dev->portnum;
 	xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum);
 
 	/* Is this a LS/FS device under a HS hub? */
@@ -1443,6 +1445,7 @@
 	scratchpad_free(xhci);
 	xhci->page_size = 0;
 	xhci->page_shift = 0;
+	xhci->bus_suspended = 0;
 }
 
 static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
@@ -1801,6 +1804,8 @@
 	init_completion(&xhci->addr_dev);
 	for (i = 0; i < MAX_HC_SLOTS; ++i)
 		xhci->devs[i] = NULL;
+	for (i = 0; i < MAX_HC_PORTS; ++i)
+		xhci->resume_done[i] = 0;
 
 	if (scratchpad_alloc(xhci, flags))
 		goto fail;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index f7efe02..bb668a8 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -116,6 +116,30 @@
 	return xhci_pci_reinit(xhci, pdev);
 }
 
+#ifdef CONFIG_PM
+static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+{
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int	retval = 0;
+
+	if (hcd->state != HC_STATE_SUSPENDED)
+		return -EINVAL;
+
+	retval = xhci_suspend(xhci);
+
+	return retval;
+}
+
+static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
+{
+	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
+	int			retval = 0;
+
+	retval = xhci_resume(xhci, hibernated);
+	return retval;
+}
+#endif /* CONFIG_PM */
+
 static const struct hc_driver xhci_pci_hc_driver = {
 	.description =		hcd_name,
 	.product_desc =		"xHCI Host Controller",
@@ -132,7 +156,10 @@
 	 */
 	.reset =		xhci_pci_setup,
 	.start =		xhci_run,
-	/* suspend and resume implemented later */
+#ifdef CONFIG_PM
+	.pci_suspend =          xhci_pci_suspend,
+	.pci_resume =           xhci_pci_resume,
+#endif
 	.stop =			xhci_stop,
 	.shutdown =		xhci_shutdown,
 
@@ -152,7 +179,7 @@
 	.reset_bandwidth =	xhci_reset_bandwidth,
 	.address_device =	xhci_address_device,
 	.update_hub_device =	xhci_update_hub_device,
-	.reset_device =		xhci_reset_device,
+	.reset_device =		xhci_discover_or_reset_device,
 
 	/*
 	 * scheduling support
@@ -162,6 +189,8 @@
 	/* Root hub support */
 	.hub_control =		xhci_hub_control,
 	.hub_status_data =	xhci_hub_status_data,
+	.bus_suspend =		xhci_bus_suspend,
+	.bus_resume =		xhci_bus_resume,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -186,6 +215,11 @@
 	/* suspend and resume implemented later */
 
 	.shutdown = 	usb_hcd_pci_shutdown,
+#ifdef CONFIG_PM_SLEEP
+	.driver = {
+		.pm = &usb_hcd_pci_pm_ops
+	},
+#endif
 };
 
 int xhci_register_pci(void)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 48e60d1..9f3115e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -68,6 +68,10 @@
 #include <linux/slab.h>
 #include "xhci.h"
 
+static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
+		struct xhci_virt_device *virt_dev,
+		struct xhci_event_cmd *event);
+
 /*
  * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA
  * address of the TRB.
@@ -313,7 +317,7 @@
 	xhci_readl(xhci, &xhci->dba->doorbell[0]);
 }
 
-static void ring_ep_doorbell(struct xhci_hcd *xhci,
+void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
 		unsigned int slot_id,
 		unsigned int ep_index,
 		unsigned int stream_id)
@@ -353,7 +357,7 @@
 	/* A ring has pending URBs if its TD list is not empty */
 	if (!(ep->ep_state & EP_HAS_STREAMS)) {
 		if (!(list_empty(&ep->ring->td_list)))
-			ring_ep_doorbell(xhci, slot_id, ep_index, 0);
+			xhci_ring_ep_doorbell(xhci, slot_id, ep_index, 0);
 		return;
 	}
 
@@ -361,7 +365,8 @@
 			stream_id++) {
 		struct xhci_stream_info *stream_info = ep->stream_info;
 		if (!list_empty(&stream_info->stream_rings[stream_id]->td_list))
-			ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
+			xhci_ring_ep_doorbell(xhci, slot_id, ep_index,
+						stream_id);
 	}
 }
 
@@ -626,10 +631,11 @@
  *     bit cleared) so that the HW will skip over them.
  */
 static void handle_stopped_endpoint(struct xhci_hcd *xhci,
-		union xhci_trb *trb)
+		union xhci_trb *trb, struct xhci_event_cmd *event)
 {
 	unsigned int slot_id;
 	unsigned int ep_index;
+	struct xhci_virt_device *virt_dev;
 	struct xhci_ring *ep_ring;
 	struct xhci_virt_ep *ep;
 	struct list_head *entry;
@@ -638,6 +644,21 @@
 
 	struct xhci_dequeue_state deq_state;
 
+	if (unlikely(TRB_TO_SUSPEND_PORT(
+			xhci->cmd_ring->dequeue->generic.field[3]))) {
+		slot_id = TRB_TO_SLOT_ID(
+			xhci->cmd_ring->dequeue->generic.field[3]);
+		virt_dev = xhci->devs[slot_id];
+		if (virt_dev)
+			handle_cmd_in_cmd_wait_list(xhci, virt_dev,
+				event);
+		else
+			xhci_warn(xhci, "Stop endpoint command "
+				"completion for disabled slot %u\n",
+				slot_id);
+		return;
+	}
+
 	memset(&deq_state, 0, sizeof(deq_state));
 	slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
 	ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
@@ -1091,7 +1112,7 @@
 		complete(&xhci->addr_dev);
 		break;
 	case TRB_TYPE(TRB_STOP_RING):
-		handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue);
+		handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue, event);
 		break;
 	case TRB_TYPE(TRB_SET_DEQ):
 		handle_set_deq_completion(xhci, event, xhci->cmd_ring->dequeue);
@@ -1144,17 +1165,72 @@
 static void handle_port_status(struct xhci_hcd *xhci,
 		union xhci_trb *event)
 {
+	struct usb_hcd *hcd = xhci_to_hcd(xhci);
 	u32 port_id;
+	u32 temp, temp1;
+	u32 __iomem *addr;
+	int ports;
+	int slot_id;
 
 	/* Port status change events always have a successful completion code */
 	if (GET_COMP_CODE(event->generic.field[2]) != COMP_SUCCESS) {
 		xhci_warn(xhci, "WARN: xHC returned failed port status event\n");
 		xhci->error_bitmask |= 1 << 8;
 	}
-	/* FIXME: core doesn't care about all port link state changes yet */
 	port_id = GET_PORT_ID(event->generic.field[0]);
 	xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id);
 
+	ports = HCS_MAX_PORTS(xhci->hcs_params1);
+	if ((port_id <= 0) || (port_id > ports)) {
+		xhci_warn(xhci, "Invalid port id %d\n", port_id);
+		goto cleanup;
+	}
+
+	addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS * (port_id - 1);
+	temp = xhci_readl(xhci, addr);
+	if ((temp & PORT_CONNECT) && (hcd->state == HC_STATE_SUSPENDED)) {
+		xhci_dbg(xhci, "resume root hub\n");
+		usb_hcd_resume_root_hub(hcd);
+	}
+
+	if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) {
+		xhci_dbg(xhci, "port resume event for port %d\n", port_id);
+
+		temp1 = xhci_readl(xhci, &xhci->op_regs->command);
+		if (!(temp1 & CMD_RUN)) {
+			xhci_warn(xhci, "xHC is not running.\n");
+			goto cleanup;
+		}
+
+		if (DEV_SUPERSPEED(temp)) {
+			xhci_dbg(xhci, "resume SS port %d\n", port_id);
+			temp = xhci_port_state_to_neutral(temp);
+			temp &= ~PORT_PLS_MASK;
+			temp |= PORT_LINK_STROBE | XDEV_U0;
+			xhci_writel(xhci, temp, addr);
+			slot_id = xhci_find_slot_id_by_port(xhci, port_id);
+			if (!slot_id) {
+				xhci_dbg(xhci, "slot_id is zero\n");
+				goto cleanup;
+			}
+			xhci_ring_device(xhci, slot_id);
+			xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
+			/* Clear PORT_PLC */
+			temp = xhci_readl(xhci, addr);
+			temp = xhci_port_state_to_neutral(temp);
+			temp |= PORT_PLC;
+			xhci_writel(xhci, temp, addr);
+		} else {
+			xhci_dbg(xhci, "resume HS port %d\n", port_id);
+			xhci->resume_done[port_id - 1] = jiffies +
+				msecs_to_jiffies(20);
+			mod_timer(&hcd->rh_timer,
+				  xhci->resume_done[port_id - 1]);
+			/* Do the rest in GetPortStatus */
+		}
+	}
+
+cleanup:
 	/* Update event ring dequeue pointer before dropping the lock */
 	inc_deq(xhci, xhci->event_ring, true);
 
@@ -2347,7 +2423,7 @@
 	 */
 	wmb();
 	start_trb->field[3] |= start_cycle;
-	ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
+	xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
 }
 
 /*
@@ -2931,7 +3007,7 @@
 	wmb();
 	start_trb->field[3] |= start_cycle;
 
-	ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id);
+	xhci_ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id);
 	return 0;
 }
 
@@ -3108,15 +3184,20 @@
 			false);
 }
 
+/*
+ * Suspend is set to indicate "Stop Endpoint Command" is being issued to stop
+ * activity on an endpoint that is about to be suspended.
+ */
 int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
-		unsigned int ep_index)
+		unsigned int ep_index, int suspend)
 {
 	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
 	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
 	u32 type = TRB_TYPE(TRB_STOP_RING);
+	u32 trb_suspend = SUSPEND_PORT_FOR_TRB(suspend);
 
 	return queue_command(xhci, 0, 0, 0,
-			trb_slot_id | trb_ep_index | type, false);
+			trb_slot_id | trb_ep_index | type | trb_suspend, false);
 }
 
 /* Set Transfer Ring Dequeue Pointer command.
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index d5c550e..5d7d4e9 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -551,6 +551,218 @@
 		    xhci_readl(xhci, &xhci->op_regs->status));
 }
 
+#ifdef CONFIG_PM
+static void xhci_save_registers(struct xhci_hcd *xhci)
+{
+	xhci->s3.command = xhci_readl(xhci, &xhci->op_regs->command);
+	xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification);
+	xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
+	xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg);
+	xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+	xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
+	xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size);
+	xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
+	xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+}
+
+static void xhci_restore_registers(struct xhci_hcd *xhci)
+{
+	xhci_writel(xhci, xhci->s3.command, &xhci->op_regs->command);
+	xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
+	xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
+	xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg);
+	xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
+	xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
+	xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size);
+	xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
+}
+
+/*
+ * Stop HC (not bus-specific)
+ *
+ * This is called when the machine transition into S3/S4 mode.
+ *
+ */
+int xhci_suspend(struct xhci_hcd *xhci)
+{
+	int			rc = 0;
+	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
+	u32			command;
+
+	spin_lock_irq(&xhci->lock);
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	/* step 1: stop endpoint */
+	/* skipped assuming that port suspend has done */
+
+	/* step 2: clear Run/Stop bit */
+	command = xhci_readl(xhci, &xhci->op_regs->command);
+	command &= ~CMD_RUN;
+	xhci_writel(xhci, command, &xhci->op_regs->command);
+	if (handshake(xhci, &xhci->op_regs->status,
+		      STS_HALT, STS_HALT, 100*100)) {
+		xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
+		spin_unlock_irq(&xhci->lock);
+		return -ETIMEDOUT;
+	}
+
+	/* step 3: save registers */
+	xhci_save_registers(xhci);
+
+	/* step 4: set CSS flag */
+	command = xhci_readl(xhci, &xhci->op_regs->command);
+	command |= CMD_CSS;
+	xhci_writel(xhci, command, &xhci->op_regs->command);
+	if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) {
+		xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n");
+		spin_unlock_irq(&xhci->lock);
+		return -ETIMEDOUT;
+	}
+	/* step 5: remove core well power */
+	xhci_cleanup_msix(xhci);
+	spin_unlock_irq(&xhci->lock);
+
+	return rc;
+}
+
+/*
+ * start xHC (not bus-specific)
+ *
+ * This is called when the machine transition from S3/S4 mode.
+ *
+ */
+int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+{
+	u32			command, temp = 0;
+	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
+	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
+	u64	val_64;
+	int	old_state, retval;
+
+	old_state = hcd->state;
+	if (time_before(jiffies, xhci->next_statechange))
+		msleep(100);
+
+	spin_lock_irq(&xhci->lock);
+
+	if (!hibernated) {
+		/* step 1: restore register */
+		xhci_restore_registers(xhci);
+		/* step 2: initialize command ring buffer */
+		val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+		val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
+			 (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+					       xhci->cmd_ring->dequeue) &
+			 (u64) ~CMD_RING_RSVD_BITS) |
+			 xhci->cmd_ring->cycle_state;
+		xhci_dbg(xhci, "// Setting command ring address to 0x%llx\n",
+				(long unsigned long) val_64);
+		xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
+		/* step 3: restore state and start state*/
+		/* step 3: set CRS flag */
+		command = xhci_readl(xhci, &xhci->op_regs->command);
+		command |= CMD_CRS;
+		xhci_writel(xhci, command, &xhci->op_regs->command);
+		if (handshake(xhci, &xhci->op_regs->status,
+			      STS_RESTORE, 0, 10*100)) {
+			xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n");
+			spin_unlock_irq(&xhci->lock);
+			return -ETIMEDOUT;
+		}
+		temp = xhci_readl(xhci, &xhci->op_regs->status);
+	}
+
+	/* If restore operation fails, re-initialize the HC during resume */
+	if ((temp & STS_SRE) || hibernated) {
+		usb_root_hub_lost_power(hcd->self.root_hub);
+
+		xhci_dbg(xhci, "Stop HCD\n");
+		xhci_halt(xhci);
+		xhci_reset(xhci);
+		if (hibernated)
+			xhci_cleanup_msix(xhci);
+		spin_unlock_irq(&xhci->lock);
+
+#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
+		/* Tell the event ring poll function not to reschedule */
+		xhci->zombie = 1;
+		del_timer_sync(&xhci->event_ring_timer);
+#endif
+
+		xhci_dbg(xhci, "// Disabling event ring interrupts\n");
+		temp = xhci_readl(xhci, &xhci->op_regs->status);
+		xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status);
+		temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+		xhci_writel(xhci, ER_IRQ_DISABLE(temp),
+				&xhci->ir_set->irq_pending);
+		xhci_print_ir_set(xhci, xhci->ir_set, 0);
+
+		xhci_dbg(xhci, "cleaning up memory\n");
+		xhci_mem_cleanup(xhci);
+		xhci_dbg(xhci, "xhci_stop completed - status = %x\n",
+			    xhci_readl(xhci, &xhci->op_regs->status));
+
+		xhci_dbg(xhci, "Initialize the HCD\n");
+		retval = xhci_init(hcd);
+		if (retval)
+			return retval;
+
+		xhci_dbg(xhci, "Start the HCD\n");
+		retval = xhci_run(hcd);
+		if (!retval)
+			set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+		hcd->state = HC_STATE_SUSPENDED;
+		return retval;
+	}
+
+	/* Re-setup MSI-X */
+	if (hcd->irq)
+		free_irq(hcd->irq, hcd);
+	hcd->irq = -1;
+
+	retval = xhci_setup_msix(xhci);
+	if (retval)
+		/* fall back to msi*/
+		retval = xhci_setup_msi(xhci);
+
+	if (retval) {
+		/* fall back to legacy interrupt*/
+		retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
+					hcd->irq_descr, hcd);
+		if (retval) {
+			xhci_err(xhci, "request interrupt %d failed\n",
+					pdev->irq);
+			return retval;
+		}
+		hcd->irq = pdev->irq;
+	}
+
+	/* step 4: set Run/Stop bit */
+	command = xhci_readl(xhci, &xhci->op_regs->command);
+	command |= CMD_RUN;
+	xhci_writel(xhci, command, &xhci->op_regs->command);
+	handshake(xhci, &xhci->op_regs->status, STS_HALT,
+		  0, 250 * 1000);
+
+	/* step 5: walk topology and initialize portsc,
+	 * portpmsc and portli
+	 */
+	/* this is done in bus_resume */
+
+	/* step 6: restart each of the previously
+	 * Running endpoints by ringing their doorbells
+	 */
+
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	if (!hibernated)
+		hcd->state = old_state;
+	else
+		hcd->state = HC_STATE_SUSPENDED;
+
+	spin_unlock_irq(&xhci->lock);
+	return 0;
+}
+#endif	/* CONFIG_PM */
+
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -607,7 +819,11 @@
  * returns 0 this is a root hub; returns -EINVAL for NULL pointers.
  */
 int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
-		struct usb_host_endpoint *ep, int check_ep, const char *func) {
+		struct usb_host_endpoint *ep, int check_ep, bool check_virt_dev,
+		const char *func) {
+	struct xhci_hcd	*xhci;
+	struct xhci_virt_device	*virt_dev;
+
 	if (!hcd || (check_ep && !ep) || !udev) {
 		printk(KERN_DEBUG "xHCI %s called with invalid args\n",
 				func);
@@ -618,11 +834,24 @@
 				func);
 		return 0;
 	}
-	if (!udev->slot_id) {
-		printk(KERN_DEBUG "xHCI %s called with unaddressed device\n",
-				func);
-		return -EINVAL;
+
+	if (check_virt_dev) {
+		xhci = hcd_to_xhci(hcd);
+		if (!udev->slot_id || !xhci->devs
+			|| !xhci->devs[udev->slot_id]) {
+			printk(KERN_DEBUG "xHCI %s called with unaddressed "
+						"device\n", func);
+			return -EINVAL;
+		}
+
+		virt_dev = xhci->devs[udev->slot_id];
+		if (virt_dev->udev != udev) {
+			printk(KERN_DEBUG "xHCI %s called with udev and "
+					  "virt_dev does not match\n", func);
+			return -EINVAL;
+		}
 	}
+
 	return 1;
 }
 
@@ -704,18 +933,13 @@
 	struct urb_priv	*urb_priv;
 	int size, i;
 
-	if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
+	if (!urb || xhci_check_args(hcd, urb->dev, urb->ep,
+					true, true, __func__) <= 0)
 		return -EINVAL;
 
 	slot_id = urb->dev->slot_id;
 	ep_index = xhci_get_endpoint_index(&urb->ep->desc);
 
-	if (!xhci->devs || !xhci->devs[slot_id]) {
-		if (!in_interrupt())
-			dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n");
-		ret = -EINVAL;
-		goto exit;
-	}
 	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		if (!in_interrupt())
 			xhci_dbg(xhci, "urb submitted during PCI suspend\n");
@@ -956,7 +1180,7 @@
 		ep->stop_cmd_timer.expires = jiffies +
 			XHCI_STOP_EP_CMD_TIMEOUT * HZ;
 		add_timer(&ep->stop_cmd_timer);
-		xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index);
+		xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index, 0);
 		xhci_ring_cmd_db(xhci);
 	}
 done:
@@ -991,7 +1215,7 @@
 	u32 new_add_flags, new_drop_flags, new_slot_info;
 	int ret;
 
-	ret = xhci_check_args(hcd, udev, ep, 1, __func__);
+	ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
 	if (ret <= 0)
 		return ret;
 	xhci = hcd_to_xhci(hcd);
@@ -1004,12 +1228,6 @@
 		return 0;
 	}
 
-	if (!xhci->devs || !xhci->devs[udev->slot_id]) {
-		xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-				__func__);
-		return -EINVAL;
-	}
-
 	in_ctx = xhci->devs[udev->slot_id]->in_ctx;
 	out_ctx = xhci->devs[udev->slot_id]->out_ctx;
 	ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
@@ -1078,7 +1296,7 @@
 	u32 new_add_flags, new_drop_flags, new_slot_info;
 	int ret = 0;
 
-	ret = xhci_check_args(hcd, udev, ep, 1, __func__);
+	ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
 	if (ret <= 0) {
 		/* So we won't queue a reset ep command for a root hub */
 		ep->hcpriv = NULL;
@@ -1098,12 +1316,6 @@
 		return 0;
 	}
 
-	if (!xhci->devs || !xhci->devs[udev->slot_id]) {
-		xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-				__func__);
-		return -EINVAL;
-	}
-
 	in_ctx = xhci->devs[udev->slot_id]->in_ctx;
 	out_ctx = xhci->devs[udev->slot_id]->out_ctx;
 	ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
@@ -1346,16 +1558,11 @@
 	struct xhci_input_control_ctx *ctrl_ctx;
 	struct xhci_slot_ctx *slot_ctx;
 
-	ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+	ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
 	if (ret <= 0)
 		return ret;
 	xhci = hcd_to_xhci(hcd);
 
-	if (!udev->slot_id || !xhci->devs || !xhci->devs[udev->slot_id]) {
-		xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-				__func__);
-		return -EINVAL;
-	}
 	xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
 	virt_dev = xhci->devs[udev->slot_id];
 
@@ -1405,16 +1612,11 @@
 	struct xhci_virt_device	*virt_dev;
 	int i, ret;
 
-	ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+	ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
 	if (ret <= 0)
 		return;
 	xhci = hcd_to_xhci(hcd);
 
-	if (!xhci->devs || !xhci->devs[udev->slot_id]) {
-		xhci_warn(xhci, "xHCI %s called with unaddressed device\n",
-				__func__);
-		return;
-	}
 	xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
 	virt_dev = xhci->devs[udev->slot_id];
 	/* Free any rings allocated for added endpoints */
@@ -1575,7 +1777,7 @@
 
 	if (!ep)
 		return -EINVAL;
-	ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, __func__);
+	ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, true, __func__);
 	if (ret <= 0)
 		return -EINVAL;
 	if (ep->ss_ep_comp.bmAttributes == 0) {
@@ -1953,8 +2155,13 @@
  * Wait for the Reset Device command to finish.  Remove all structures
  * associated with the endpoints that were disabled.  Clear the input device
  * structure?  Cache the rings?  Reset the control endpoint 0 max packet size?
+ *
+ * If the virt_dev to be reset does not exist or does not match the udev,
+ * it means the device is lost, possibly due to the xHC restore error and
+ * re-initialization during S3/S4. In this case, call xhci_alloc_dev() to
+ * re-allocate the device.
  */
-int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
+int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 {
 	int ret, i;
 	unsigned long flags;
@@ -1965,16 +2172,35 @@
 	int timeleft;
 	int last_freed_endpoint;
 
-	ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+	ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__);
 	if (ret <= 0)
 		return ret;
 	xhci = hcd_to_xhci(hcd);
 	slot_id = udev->slot_id;
 	virt_dev = xhci->devs[slot_id];
 	if (!virt_dev) {
-		xhci_dbg(xhci, "%s called with invalid slot ID %u\n",
-				__func__, slot_id);
-		return -EINVAL;
+		xhci_dbg(xhci, "The device to be reset with slot ID %u does "
+				"not exist. Re-allocate the device\n", slot_id);
+		ret = xhci_alloc_dev(hcd, udev);
+		if (ret == 1)
+			return 0;
+		else
+			return -EINVAL;
+	}
+
+	if (virt_dev->udev != udev) {
+		/* If the virt_dev and the udev does not match, this virt_dev
+		 * may belong to another udev.
+		 * Re-allocate the device.
+		 */
+		xhci_dbg(xhci, "The device to be reset with slot ID %u does "
+				"not match the udev. Re-allocate the device\n",
+				slot_id);
+		ret = xhci_alloc_dev(hcd, udev);
+		if (ret == 1)
+			return 0;
+		else
+			return -EINVAL;
 	}
 
 	xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
@@ -2077,13 +2303,13 @@
 	struct xhci_virt_device *virt_dev;
 	unsigned long flags;
 	u32 state;
-	int i;
+	int i, ret;
 
-	if (udev->slot_id == 0)
+	ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
+	if (ret <= 0)
 		return;
+
 	virt_dev = xhci->devs[udev->slot_id];
-	if (!virt_dev)
-		return;
 
 	/* Stop any wayward timer functions (which may grab the lock) */
 	for (i = 0; i < 31; ++i) {
@@ -2191,12 +2417,17 @@
 
 	virt_dev = xhci->devs[udev->slot_id];
 
-	/* If this is a Set Address to an unconfigured device, setup ep 0 */
-	if (!udev->config)
+	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+	/*
+	 * If this is the first Set Address since device plug-in or
+	 * virt_device realloaction after a resume with an xHCI power loss,
+	 * then set up the slot context.
+	 */
+	if (!slot_ctx->dev_info)
 		xhci_setup_addressable_virt_dev(xhci, udev);
+	/* Otherwise, update the control endpoint ring enqueue pointer. */
 	else
 		xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
-	/* Otherwise, assume the core has the device configured how it wants */
 	xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
 	xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
 
@@ -2268,15 +2499,15 @@
 	 * address given back to us by the HC.
 	 */
 	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
-	udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
+	/* Use kernel assigned address for devices; store xHC assigned
+	 * address locally. */
+	virt_dev->address = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
 	/* Zero the input context control for later use */
 	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
 	ctrl_ctx->add_flags = 0;
 	ctrl_ctx->drop_flags = 0;
 
-	xhci_dbg(xhci, "Device address = %d\n", udev->devnum);
-	/* XXX Meh, not sure if anyone else but choose_address uses this. */
-	set_bit(udev->devnum, udev->bus->devmap.devicemap);
+	xhci_dbg(xhci, "Internal device address = %d\n", virt_dev->address);
 
 	return 0;
 }
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 34a60d9..93d3bf4 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -191,7 +191,7 @@
 /* bits 4:6 are reserved (and should be preserved on writes). */
 /* light reset (port status stays unchanged) - reset completed when this is 0 */
 #define CMD_LRESET	(1 << 7)
-/* FIXME: ignoring host controller save/restore state for now. */
+/* host controller save/restore state. */
 #define CMD_CSS		(1 << 8)
 #define CMD_CRS		(1 << 9)
 /* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */
@@ -269,6 +269,10 @@
  * A read gives the current link PM state of the port,
  * a write with Link State Write Strobe set sets the link state.
  */
+#define PORT_PLS_MASK	(0xf << 5)
+#define XDEV_U0		(0x0 << 5)
+#define XDEV_U3		(0x3 << 5)
+#define XDEV_RESUME	(0xf << 5)
 /* true: port has power (see HCC_PPC) */
 #define PORT_POWER	(1 << 9)
 /* bits 10:13 indicate device speed:
@@ -353,6 +357,8 @@
 #define PORT_U2_TIMEOUT(p)	(((p) & 0xff) << 8)
 /* Bits 24:31 for port testing */
 
+/* USB2 Protocol PORTSPMSC */
+#define PORT_RWE	(1 << 0x3)
 
 /**
  * struct xhci_intr_reg - Interrupt Register Set
@@ -510,6 +516,7 @@
 #define MAX_EXIT	(0xffff)
 /* Root hub port number that is needed to access the USB device */
 #define ROOT_HUB_PORT(p)	(((p) & 0xff) << 16)
+#define DEVINFO_TO_ROOT_HUB_PORT(p)	(((p) >> 16) & 0xff)
 /* Maximum number of ports under a hub device */
 #define XHCI_MAX_PORTS(p)	(((p) & 0xff) << 24)
 
@@ -731,6 +738,7 @@
 };
 
 struct xhci_virt_device {
+	struct usb_device		*udev;
 	/*
 	 * Commands to the hardware are passed an "input context" that
 	 * tells the hardware what to change in its data structures.
@@ -745,12 +753,15 @@
 	/* Rings saved to ensure old alt settings can be re-instated */
 	struct xhci_ring		**ring_cache;
 	int				num_rings_cached;
+	/* Store xHC assigned device address */
+	int				address;
 #define	XHCI_MAX_RINGS_CACHED	31
 	struct xhci_virt_ep		eps[31];
 	struct completion		cmd_completion;
 	/* Status of the last command issued for this device */
 	u32				cmd_status;
 	struct list_head		cmd_list;
+	u8				port;
 };
 
 
@@ -881,6 +892,10 @@
 #define TRB_TO_EP_INDEX(p)		((((p) & (0x1f << 16)) >> 16) - 1)
 #define	EP_ID_FOR_TRB(p)		((((p) + 1) & 0x1f) << 16)
 
+#define SUSPEND_PORT_FOR_TRB(p)		(((p) & 1) << 23)
+#define TRB_TO_SUSPEND_PORT(p)		(((p) & (1 << 23)) >> 23)
+#define LAST_EP_INDEX			30
+
 /* Set TR Dequeue Pointer command TRB fields */
 #define TRB_TO_STREAM_ID(p)		((((p) & (0xffff << 16)) >> 16))
 #define STREAM_ID_FOR_TRB(p)		((((p)) & 0xffff) << 16)
@@ -1115,6 +1130,17 @@
 #define XHCI_STOP_EP_CMD_TIMEOUT	5
 /* XXX: Make these module parameters */
 
+struct s3_save {
+	u32	command;
+	u32	dev_nt;
+	u64	dcbaa_ptr;
+	u32	config_reg;
+	u32	irq_pending;
+	u32	irq_control;
+	u32	erst_size;
+	u64	erst_base;
+	u64	erst_dequeue;
+};
 
 /* There is one ehci_hci structure per controller */
 struct xhci_hcd {
@@ -1178,6 +1204,12 @@
 #endif
 	/* Host controller watchdog timer structures */
 	unsigned int		xhc_state;
+
+	unsigned long		bus_suspended;
+	unsigned long		next_statechange;
+
+	u32			command;
+	struct s3_save		s3;
 /* Host controller is dying - not responding to commands. "I'm not dead yet!"
  *
  * xHC interrupts have been disabled and a watchdog timer will (or has already)
@@ -1199,6 +1231,10 @@
 #define	XHCI_LINK_TRB_QUIRK	(1 << 0)
 #define XHCI_RESET_EP_QUIRK	(1 << 1)
 #define XHCI_NEC_HOST		(1 << 2)
+	u32			port_c_suspend[8];	/* port suspend change*/
+	u32			suspended_ports[8];	/* which ports are
+							   suspended */
+	unsigned long		resume_done[MAX_HC_PORTS];
 };
 
 /* For testing purposes */
@@ -1369,6 +1405,15 @@
 int xhci_run(struct usb_hcd *hcd);
 void xhci_stop(struct usb_hcd *hcd);
 void xhci_shutdown(struct usb_hcd *hcd);
+
+#ifdef	CONFIG_PM
+int xhci_suspend(struct xhci_hcd *xhci);
+int xhci_resume(struct xhci_hcd *xhci, bool hibernated);
+#else
+#define	xhci_suspend	NULL
+#define	xhci_resume	NULL
+#endif
+
 int xhci_get_frame(struct usb_hcd *hcd);
 irqreturn_t xhci_irq(struct usb_hcd *hcd);
 irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd);
@@ -1388,7 +1433,7 @@
 int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
 int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
 void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
-int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev);
+int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev);
 int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 
@@ -1406,7 +1451,7 @@
 int xhci_queue_vendor_command(struct xhci_hcd *xhci,
 		u32 field1, u32 field2, u32 field3, u32 field4);
 int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
-		unsigned int ep_index);
+		unsigned int ep_index, int suspend);
 int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
 		int slot_id, unsigned int ep_index);
 int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
@@ -1436,12 +1481,26 @@
 		unsigned int slot_id, unsigned int ep_index,
 		struct xhci_dequeue_state *deq_state);
 void xhci_stop_endpoint_command_watchdog(unsigned long arg);
+void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
+		unsigned int ep_index, unsigned int stream_id);
 
 /* xHCI roothub code */
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
 		char *buf, u16 wLength);
 int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
 
+#ifdef CONFIG_PM
+int xhci_bus_suspend(struct usb_hcd *hcd);
+int xhci_bus_resume(struct usb_hcd *hcd);
+#else
+#define	xhci_bus_suspend	NULL
+#define	xhci_bus_resume		NULL
+#endif	/* CONFIG_PM */
+
+u32 xhci_port_state_to_neutral(u32 state);
+int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port);
+void xhci_ring_device(struct xhci_hcd *xhci, int slot_id);
+
 /* xHCI contexts */
 struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
 struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index e192e8f..575b56c 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -963,6 +963,7 @@
 	.write =	mdc800_device_write,
 	.open =		mdc800_device_open,
 	.release =	mdc800_device_release,
+	.llseek =	noop_llseek,
 };
 
 
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 55660ea..1bfcd02 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -231,3 +231,16 @@
 	  driver beforehand. Tools for doing so are available at
 	  http://bersace03.free.fr
 
+config USB_YUREX
+	tristate "USB YUREX driver support"
+	depends on USB
+	help
+	  Say Y here if you want to connect a YUREX to your computer's
+	  USB port. The YUREX is a leg-shakes sensor. See
+	  <http://bbu.kayac.com/en/> for further information.
+	  This driver supports read/write of leg-shakes counter and
+	  fasync for the counter update via a device file /dev/yurex*.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called yurex.
+
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 717703e..796ce7eb 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -3,28 +3,27 @@
 # (the ones that don't fit into any other categories)
 #
 
-obj-$(CONFIG_USB_ADUTUX)	+= adutux.o
-obj-$(CONFIG_USB_APPLEDISPLAY)	+= appledisplay.o
-obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
-obj-$(CONFIG_USB_CYTHERM)	+= cytherm.o
-obj-$(CONFIG_USB_EMI26)		+= emi26.o
-obj-$(CONFIG_USB_EMI62)		+= emi62.o
-obj-$(CONFIG_USB_FTDI_ELAN)	+= ftdi-elan.o
-obj-$(CONFIG_USB_IDMOUSE)	+= idmouse.o
-obj-$(CONFIG_USB_IOWARRIOR)	+= iowarrior.o
-obj-$(CONFIG_USB_ISIGHTFW)	+= isight_firmware.o
-obj-$(CONFIG_USB_LCD)		+= usblcd.o
-obj-$(CONFIG_USB_LD)		+= ldusb.o
-obj-$(CONFIG_USB_LED)		+= usbled.o
-obj-$(CONFIG_USB_LEGOTOWER)	+= legousbtower.o
-obj-$(CONFIG_USB_RIO500)	+= rio500.o
-obj-$(CONFIG_USB_TEST)		+= usbtest.o
+ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
+
+obj-$(CONFIG_USB_ADUTUX)		+= adutux.o
+obj-$(CONFIG_USB_APPLEDISPLAY)		+= appledisplay.o
+obj-$(CONFIG_USB_CYPRESS_CY7C63)	+= cypress_cy7c63.o
+obj-$(CONFIG_USB_CYTHERM)		+= cytherm.o
+obj-$(CONFIG_USB_EMI26)			+= emi26.o
+obj-$(CONFIG_USB_EMI62)			+= emi62.o
+obj-$(CONFIG_USB_FTDI_ELAN)		+= ftdi-elan.o
+obj-$(CONFIG_USB_IDMOUSE)		+= idmouse.o
+obj-$(CONFIG_USB_IOWARRIOR)		+= iowarrior.o
+obj-$(CONFIG_USB_ISIGHTFW)		+= isight_firmware.o
+obj-$(CONFIG_USB_LCD)			+= usblcd.o
+obj-$(CONFIG_USB_LD)			+= ldusb.o
+obj-$(CONFIG_USB_LED)			+= usbled.o
+obj-$(CONFIG_USB_LEGOTOWER)		+= legousbtower.o
+obj-$(CONFIG_USB_RIO500)		+= rio500.o
+obj-$(CONFIG_USB_TEST)			+= usbtest.o
 obj-$(CONFIG_USB_TRANCEVIBRATOR)	+= trancevibrator.o
-obj-$(CONFIG_USB_USS720)	+= uss720.o
-obj-$(CONFIG_USB_SEVSEG)	+= usbsevseg.o
+obj-$(CONFIG_USB_USS720)		+= uss720.o
+obj-$(CONFIG_USB_SEVSEG)		+= usbsevseg.o
+obj-$(CONFIG_USB_YUREX)			+= yurex.o
 
-obj-$(CONFIG_USB_SISUSBVGA)	+= sisusbvga/
-
-ifeq ($(CONFIG_USB_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 801324a..44f8b922 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -679,6 +679,7 @@
 	.write = adu_write,
 	.open = adu_open,
 	.release = adu_release,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index aecf380..c8eec9c 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -2769,7 +2769,7 @@
         ftdi->sequence_num = ++ftdi_instances;
         mutex_unlock(&ftdi_module_lock);
         ftdi_elan_init_kref(ftdi);
-        init_MUTEX(&ftdi->sw_lock);
+	sema_init(&ftdi->sw_lock, 1);
         ftdi->udev = usb_get_dev(interface_to_usbdev(interface));
         ftdi->interface = interface;
         mutex_init(&ftdi->u132_lock);
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index a54c3cb..c6184b4 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -105,6 +105,7 @@
 	.read = idmouse_read,
 	.open = idmouse_open,
 	.release = idmouse_release,
+	.llseek = default_llseek,
 };
 
 /* class driver information */
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index bc88c79..3756641 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -374,7 +374,7 @@
 	case USB_DEVICE_ID_CODEMERCS_IOWPV2:
 	case USB_DEVICE_ID_CODEMERCS_IOW40:
 		/* IOW24 and IOW40 use a synchronous call */
-		buf = kmalloc(8, GFP_KERNEL);	/* 8 bytes are enough for both products */
+		buf = kmalloc(count, GFP_KERNEL);
 		if (!buf) {
 			retval = -ENOMEM;
 			goto exit;
@@ -730,6 +730,7 @@
 	.open = iowarrior_open,
 	.release = iowarrior_release,
 	.poll = iowarrior_poll,
+	.llseek = noop_llseek,
 };
 
 static char *iowarrior_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index dd41d87..edffef6 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -613,6 +613,7 @@
 	.open =		ld_usb_open,
 	.release =	ld_usb_release,
 	.poll =		ld_usb_poll,
+	.llseek =	no_llseek,
 };
 
 /*
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index cc13ae6..4e23d38 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -439,6 +439,7 @@
 	.unlocked_ioctl = ioctl_rio,
 	.open =		open_rio,
 	.release =	close_rio,
+	.llseek =	noop_llseek,
 };
 
 static struct usb_class_driver usb_rio_class = {
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
index 7f934cf..3142476 100644
--- a/drivers/usb/misc/sisusbvga/Makefile
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -4,5 +4,4 @@
 
 obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga.o
 
-sisusbvga-objs := sisusb.o sisusb_init.o sisusb_con.o
-
+sisusbvga-y := sisusb.o sisusb_init.o sisusb_con.o
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index d00dde1..5164815 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -282,6 +282,7 @@
         .open =         lcd_open,
 	.unlocked_ioctl = lcd_ioctl,
         .release =      lcd_release,
+        .llseek =	 noop_llseek,
 };
 
 /*
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index eef370e..a35b427 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -13,17 +13,16 @@
 
 /*-------------------------------------------------------------------------*/
 
-// FIXME make these public somewhere; usbdevfs.h?
-//
+/* FIXME make these public somewhere; usbdevfs.h? */
 struct usbtest_param {
-	// inputs
+	/* inputs */
 	unsigned		test_num;	/* 0..(TEST_CASES-1) */
 	unsigned		iterations;
 	unsigned		length;
 	unsigned		vary;
 	unsigned		sglen;
 
-	// outputs
+	/* outputs */
 	struct timeval		duration;
 };
 #define USBTEST_REQUEST	_IOWR('U', 100, struct usbtest_param)
@@ -45,9 +44,9 @@
 	const char		*name;
 	u8			ep_in;		/* bulk/intr source */
 	u8			ep_out;		/* bulk/intr sink */
-	unsigned		autoconf : 1;
-	unsigned		ctrl_out : 1;
-	unsigned		iso : 1;	/* try iso in/out */
+	unsigned		autoconf:1;
+	unsigned		ctrl_out:1;
+	unsigned		iso:1;		/* try iso in/out */
 	int			alt;
 };
 
@@ -71,9 +70,9 @@
 	u8			*buf;
 };
 
-static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test)
+static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test)
 {
-	return interface_to_usbdev (test->intf);
+	return interface_to_usbdev(test->intf);
 }
 
 /* set up all urbs so they can be used with either bulk or interrupt */
@@ -87,7 +86,7 @@
 /*-------------------------------------------------------------------------*/
 
 static int
-get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
+get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf)
 {
 	int				tmp;
 	struct usb_host_interface	*alt;
@@ -115,7 +114,7 @@
 			case USB_ENDPOINT_XFER_ISOC:
 				if (dev->info->iso)
 					goto try_iso;
-				// FALLTHROUGH
+				/* FALLTHROUGH */
 			default:
 				continue;
 			}
@@ -142,9 +141,9 @@
 	return -EINVAL;
 
 found:
-	udev = testdev_to_usbdev (dev);
+	udev = testdev_to_usbdev(dev);
 	if (alt->desc.bAlternateSetting != 0) {
-		tmp = usb_set_interface (udev,
+		tmp = usb_set_interface(udev,
 				alt->desc.bInterfaceNumber,
 				alt->desc.bAlternateSetting);
 		if (tmp < 0)
@@ -152,21 +151,21 @@
 	}
 
 	if (in) {
-		dev->in_pipe = usb_rcvbulkpipe (udev,
+		dev->in_pipe = usb_rcvbulkpipe(udev,
 			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-		dev->out_pipe = usb_sndbulkpipe (udev,
+		dev->out_pipe = usb_sndbulkpipe(udev,
 			out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
 	}
 	if (iso_in) {
 		dev->iso_in = &iso_in->desc;
-		dev->in_iso_pipe = usb_rcvisocpipe (udev,
+		dev->in_iso_pipe = usb_rcvisocpipe(udev,
 				iso_in->desc.bEndpointAddress
 					& USB_ENDPOINT_NUMBER_MASK);
 	}
 
 	if (iso_out) {
 		dev->iso_out = &iso_out->desc;
-		dev->out_iso_pipe = usb_sndisocpipe (udev,
+		dev->out_iso_pipe = usb_sndisocpipe(udev,
 				iso_out->desc.bEndpointAddress
 					& USB_ENDPOINT_NUMBER_MASK);
 	}
@@ -182,12 +181,12 @@
  * them with non-zero test data (or test for it) when appropriate.
  */
 
-static void simple_callback (struct urb *urb)
+static void simple_callback(struct urb *urb)
 {
 	complete(urb->context);
 }
 
-static struct urb *simple_alloc_urb (
+static struct urb *simple_alloc_urb(
 	struct usb_device	*udev,
 	int			pipe,
 	unsigned long		bytes
@@ -195,32 +194,32 @@
 {
 	struct urb		*urb;
 
-	urb = usb_alloc_urb (0, GFP_KERNEL);
+	urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!urb)
 		return urb;
-	usb_fill_bulk_urb (urb, udev, pipe, NULL, bytes, simple_callback, NULL);
+	usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, NULL);
 	urb->interval = (udev->speed == USB_SPEED_HIGH)
 			? (INTERRUPT_RATE << 3)
 			: INTERRUPT_RATE;
 	urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-	if (usb_pipein (pipe))
+	if (usb_pipein(pipe))
 		urb->transfer_flags |= URB_SHORT_NOT_OK;
-	urb->transfer_buffer = usb_alloc_coherent (udev, bytes, GFP_KERNEL,
+	urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL,
 			&urb->transfer_dma);
 	if (!urb->transfer_buffer) {
-		usb_free_urb (urb);
+		usb_free_urb(urb);
 		urb = NULL;
 	} else
-		memset (urb->transfer_buffer, 0, bytes);
+		memset(urb->transfer_buffer, 0, bytes);
 	return urb;
 }
 
-static unsigned pattern = 0;
+static unsigned pattern;
 static unsigned mod_pattern;
 module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(mod_pattern, "i/o pattern (0 == zeroes)");
 
-static inline void simple_fill_buf (struct urb *urb)
+static inline void simple_fill_buf(struct urb *urb)
 {
 	unsigned	i;
 	u8		*buf = urb->transfer_buffer;
@@ -228,9 +227,9 @@
 
 	switch (pattern) {
 	default:
-		// FALLTHROUGH
+		/* FALLTHROUGH */
 	case 0:
-		memset (buf, 0, len);
+		memset(buf, 0, len);
 		break;
 	case 1:			/* mod63 */
 		for (i = 0; i < len; i++)
@@ -273,14 +272,14 @@
 	return 0;
 }
 
-static void simple_free_urb (struct urb *urb)
+static void simple_free_urb(struct urb *urb)
 {
 	usb_free_coherent(urb->dev, urb->transfer_buffer_length,
 			  urb->transfer_buffer, urb->transfer_dma);
-	usb_free_urb (urb);
+	usb_free_urb(urb);
 }
 
-static int simple_io (
+static int simple_io(
 	struct usbtest_dev	*tdev,
 	struct urb		*urb,
 	int			iterations,
@@ -296,17 +295,18 @@
 
 	urb->context = &completion;
 	while (retval == 0 && iterations-- > 0) {
-		init_completion (&completion);
-		if (usb_pipeout (urb->pipe))
-			simple_fill_buf (urb);
-		if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0)
+		init_completion(&completion);
+		if (usb_pipeout(urb->pipe))
+			simple_fill_buf(urb);
+		retval = usb_submit_urb(urb, GFP_KERNEL);
+		if (retval != 0)
 			break;
 
 		/* NOTE:  no timeouts; can't be broken out of by interrupt */
-		wait_for_completion (&completion);
+		wait_for_completion(&completion);
 		retval = urb->status;
 		urb->dev = udev;
-		if (retval == 0 && usb_pipein (urb->pipe))
+		if (retval == 0 && usb_pipein(urb->pipe))
 			retval = simple_check_buf(tdev, urb);
 
 		if (vary) {
@@ -337,7 +337,7 @@
  * Yes, this also tests the scatterlist primitives.
  */
 
-static void free_sglist (struct scatterlist *sg, int nents)
+static void free_sglist(struct scatterlist *sg, int nents)
 {
 	unsigned		i;
 
@@ -346,19 +346,19 @@
 	for (i = 0; i < nents; i++) {
 		if (!sg_page(&sg[i]))
 			continue;
-		kfree (sg_virt(&sg[i]));
+		kfree(sg_virt(&sg[i]));
 	}
-	kfree (sg);
+	kfree(sg);
 }
 
 static struct scatterlist *
-alloc_sglist (int nents, int max, int vary)
+alloc_sglist(int nents, int max, int vary)
 {
 	struct scatterlist	*sg;
 	unsigned		i;
 	unsigned		size = max;
 
-	sg = kmalloc (nents * sizeof *sg, GFP_KERNEL);
+	sg = kmalloc(nents * sizeof *sg, GFP_KERNEL);
 	if (!sg)
 		return NULL;
 	sg_init_table(sg, nents);
@@ -367,9 +367,9 @@
 		char		*buf;
 		unsigned	j;
 
-		buf = kzalloc (size, GFP_KERNEL);
+		buf = kzalloc(size, GFP_KERNEL);
 		if (!buf) {
-			free_sglist (sg, i);
+			free_sglist(sg, i);
 			return NULL;
 		}
 
@@ -397,7 +397,7 @@
 	return sg;
 }
 
-static int perform_sglist (
+static int perform_sglist(
 	struct usbtest_dev	*tdev,
 	unsigned		iterations,
 	int			pipe,
@@ -410,7 +410,7 @@
 	int			retval = 0;
 
 	while (retval == 0 && iterations-- > 0) {
-		retval = usb_sg_init (req, udev, pipe,
+		retval = usb_sg_init(req, udev, pipe,
 				(udev->speed == USB_SPEED_HIGH)
 					? (INTERRUPT_RATE << 3)
 					: INTERRUPT_RATE,
@@ -418,7 +418,7 @@
 
 		if (retval)
 			break;
-		usb_sg_wait (req);
+		usb_sg_wait(req);
 		retval = req->status;
 
 		/* FIXME check resulting data pattern */
@@ -426,9 +426,9 @@
 		/* FIXME if endpoint halted, clear halt (and log) */
 	}
 
-	// FIXME for unlink or fault handling tests, don't report
-	// failure if retval is as we expected ...
-
+	/* FIXME for unlink or fault handling tests, don't report
+	 * failure if retval is as we expected ...
+	 */
 	if (retval)
 		ERROR(tdev, "perform_sglist failed, "
 				"iterations left %d, status %d\n",
@@ -452,31 +452,31 @@
  */
 
 static unsigned realworld = 1;
-module_param (realworld, uint, 0);
-MODULE_PARM_DESC (realworld, "clear to demand stricter spec compliance");
+module_param(realworld, uint, 0);
+MODULE_PARM_DESC(realworld, "clear to demand stricter spec compliance");
 
-static int get_altsetting (struct usbtest_dev *dev)
+static int get_altsetting(struct usbtest_dev *dev)
 {
 	struct usb_interface	*iface = dev->intf;
-	struct usb_device	*udev = interface_to_usbdev (iface);
+	struct usb_device	*udev = interface_to_usbdev(iface);
 	int			retval;
 
-	retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0),
+	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 			USB_REQ_GET_INTERFACE, USB_DIR_IN|USB_RECIP_INTERFACE,
-			0, iface->altsetting [0].desc.bInterfaceNumber,
+			0, iface->altsetting[0].desc.bInterfaceNumber,
 			dev->buf, 1, USB_CTRL_GET_TIMEOUT);
 	switch (retval) {
 	case 1:
-		return dev->buf [0];
+		return dev->buf[0];
 	case 0:
 		retval = -ERANGE;
-		// FALLTHROUGH
+		/* FALLTHROUGH */
 	default:
 		return retval;
 	}
 }
 
-static int set_altsetting (struct usbtest_dev *dev, int alternate)
+static int set_altsetting(struct usbtest_dev *dev, int alternate)
 {
 	struct usb_interface		*iface = dev->intf;
 	struct usb_device		*udev;
@@ -484,9 +484,9 @@
 	if (alternate < 0 || alternate >= 256)
 		return -EINVAL;
 
-	udev = interface_to_usbdev (iface);
-	return usb_set_interface (udev,
-			iface->altsetting [0].desc.bInterfaceNumber,
+	udev = interface_to_usbdev(iface);
+	return usb_set_interface(udev,
+			iface->altsetting[0].desc.bInterfaceNumber,
 			alternate);
 }
 
@@ -519,9 +519,9 @@
 		return 0;
 	}
 
-	if (le16_to_cpu(config->wTotalLength) == len)		/* read it all */
+	if (le16_to_cpu(config->wTotalLength) == len)	/* read it all */
 		return 1;
-	if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE)		/* max partial read */
+	if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE)	/* max partial read */
 		return 1;
 	ERROR(tdev, "bogus config descriptor read size\n");
 	return 0;
@@ -542,10 +542,10 @@
  * to see if usbcore, hcd, and device all behave right.  such testing would
  * involve varied read sizes and other operation sequences.
  */
-static int ch9_postconfig (struct usbtest_dev *dev)
+static int ch9_postconfig(struct usbtest_dev *dev)
 {
 	struct usb_interface	*iface = dev->intf;
-	struct usb_device	*udev = interface_to_usbdev (iface);
+	struct usb_device	*udev = interface_to_usbdev(iface);
 	int			i, alt, retval;
 
 	/* [9.2.3] if there's more than one altsetting, we need to be able to
@@ -554,7 +554,7 @@
 	for (i = 0; i < iface->num_altsetting; i++) {
 
 		/* 9.2.3 constrains the range here */
-		alt = iface->altsetting [i].desc.bAlternateSetting;
+		alt = iface->altsetting[i].desc.bAlternateSetting;
 		if (alt < 0 || alt >= iface->num_altsetting) {
 			dev_err(&iface->dev,
 					"invalid alt [%d].bAltSetting = %d\n",
@@ -566,7 +566,7 @@
 			continue;
 
 		/* [9.4.10] set_interface */
-		retval = set_altsetting (dev, alt);
+		retval = set_altsetting(dev, alt);
 		if (retval) {
 			dev_err(&iface->dev, "can't set_interface = %d, %d\n",
 					alt, retval);
@@ -574,7 +574,7 @@
 		}
 
 		/* [9.4.4] get_interface always works */
-		retval = get_altsetting (dev);
+		retval = get_altsetting(dev);
 		if (retval != alt) {
 			dev_err(&iface->dev, "get alt should be %d, was %d\n",
 					alt, retval);
@@ -591,11 +591,11 @@
 		 * ... although some cheap devices (like one TI Hub I've got)
 		 * won't return config descriptors except before set_config.
 		 */
-		retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0),
+		retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 				USB_REQ_GET_CONFIGURATION,
 				USB_DIR_IN | USB_RECIP_DEVICE,
 				0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT);
-		if (retval != 1 || dev->buf [0] != expected) {
+		if (retval != 1 || dev->buf[0] != expected) {
 			dev_err(&iface->dev, "get config --> %d %d (1 %d)\n",
 				retval, dev->buf[0], expected);
 			return (retval < 0) ? retval : -EDOM;
@@ -603,7 +603,7 @@
 	}
 
 	/* there's always [9.4.3] a device descriptor [9.6.1] */
-	retval = usb_get_descriptor (udev, USB_DT_DEVICE, 0,
+	retval = usb_get_descriptor(udev, USB_DT_DEVICE, 0,
 			dev->buf, sizeof udev->descriptor);
 	if (retval != sizeof udev->descriptor) {
 		dev_err(&iface->dev, "dev descriptor --> %d\n", retval);
@@ -612,7 +612,7 @@
 
 	/* there's always [9.4.3] at least one config descriptor [9.6.3] */
 	for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
-		retval = usb_get_descriptor (udev, USB_DT_CONFIG, i,
+		retval = usb_get_descriptor(udev, USB_DT_CONFIG, i,
 				dev->buf, TBUF_SIZE);
 		if (!is_good_config(dev, retval)) {
 			dev_err(&iface->dev,
@@ -621,18 +621,19 @@
 			return (retval < 0) ? retval : -EDOM;
 		}
 
-		// FIXME cross-checking udev->config[i] to make sure usbcore
-		// parsed it right (etc) would be good testing paranoia
+		/* FIXME cross-checking udev->config[i] to make sure usbcore
+		 * parsed it right (etc) would be good testing paranoia
+		 */
 	}
 
 	/* and sometimes [9.2.6.6] speed dependent descriptors */
 	if (le16_to_cpu(udev->descriptor.bcdUSB) == 0x0200) {
-		struct usb_qualifier_descriptor		*d = NULL;
+		struct usb_qualifier_descriptor *d = NULL;
 
 		/* device qualifier [9.6.2] */
-		retval = usb_get_descriptor (udev,
+		retval = usb_get_descriptor(udev,
 				USB_DT_DEVICE_QUALIFIER, 0, dev->buf,
-				sizeof (struct usb_qualifier_descriptor));
+				sizeof(struct usb_qualifier_descriptor));
 		if (retval == -EPIPE) {
 			if (udev->speed == USB_SPEED_HIGH) {
 				dev_err(&iface->dev,
@@ -641,7 +642,7 @@
 				return (retval < 0) ? retval : -EDOM;
 			}
 			/* usb2.0 but not high-speed capable; fine */
-		} else if (retval != sizeof (struct usb_qualifier_descriptor)) {
+		} else if (retval != sizeof(struct usb_qualifier_descriptor)) {
 			dev_err(&iface->dev, "dev qualifier --> %d\n", retval);
 			return (retval < 0) ? retval : -EDOM;
 		} else
@@ -651,7 +652,7 @@
 		if (d) {
 			unsigned max = d->bNumConfigurations;
 			for (i = 0; i < max; i++) {
-				retval = usb_get_descriptor (udev,
+				retval = usb_get_descriptor(udev,
 					USB_DT_OTHER_SPEED_CONFIG, i,
 					dev->buf, TBUF_SIZE);
 				if (!is_good_config(dev, retval)) {
@@ -663,25 +664,26 @@
 			}
 		}
 	}
-	// FIXME fetch strings from at least the device descriptor
+	/* FIXME fetch strings from at least the device descriptor */
 
 	/* [9.4.5] get_status always works */
-	retval = usb_get_status (udev, USB_RECIP_DEVICE, 0, dev->buf);
+	retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf);
 	if (retval != 2) {
 		dev_err(&iface->dev, "get dev status --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
 
-	// FIXME configuration.bmAttributes says if we could try to set/clear
-	// the device's remote wakeup feature ... if we can, test that here
+	/* FIXME configuration.bmAttributes says if we could try to set/clear
+	 * the device's remote wakeup feature ... if we can, test that here
+	 */
 
-	retval = usb_get_status (udev, USB_RECIP_INTERFACE,
-			iface->altsetting [0].desc.bInterfaceNumber, dev->buf);
+	retval = usb_get_status(udev, USB_RECIP_INTERFACE,
+			iface->altsetting[0].desc.bInterfaceNumber, dev->buf);
 	if (retval != 2) {
 		dev_err(&iface->dev, "get interface status --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
-	// FIXME get status for each endpoint in the interface
+	/* FIXME get status for each endpoint in the interface */
 
 	return 0;
 }
@@ -717,7 +719,7 @@
 	int			expected;
 };
 
-static void ctrl_complete (struct urb *urb)
+static void ctrl_complete(struct urb *urb)
 {
 	struct ctrl_ctx		*ctx = urb->context;
 	struct usb_ctrlrequest	*reqp;
@@ -725,9 +727,9 @@
 	int			status = urb->status;
 
 	reqp = (struct usb_ctrlrequest *)urb->setup_packet;
-	subcase = container_of (reqp, struct subcase, setup);
+	subcase = container_of(reqp, struct subcase, setup);
 
-	spin_lock (&ctx->lock);
+	spin_lock(&ctx->lock);
 	ctx->count--;
 	ctx->pending--;
 
@@ -787,14 +789,14 @@
 
 			/* unlink whatever's still pending */
 			for (i = 1; i < ctx->param->sglen; i++) {
-				struct urb	*u = ctx->urb [
-						(i + subcase->number)
-						% ctx->param->sglen];
+				struct urb *u = ctx->urb[
+							(i + subcase->number)
+							% ctx->param->sglen];
 
 				if (u == urb || !u->dev)
 					continue;
 				spin_unlock(&ctx->lock);
-				status = usb_unlink_urb (u);
+				status = usb_unlink_urb(u);
 				spin_lock(&ctx->lock);
 				switch (status) {
 				case -EINPROGRESS:
@@ -812,7 +814,8 @@
 
 	/* resubmit if we need to, else mark this as done */
 	if ((status == 0) && (ctx->pending < ctx->count)) {
-		if ((status = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
+		status = usb_submit_urb(urb, GFP_ATOMIC);
+		if (status != 0) {
 			ERROR(ctx->dev,
 				"can't resubmit ctrl %02x.%02x, err %d\n",
 				reqp->bRequestType, reqp->bRequest, status);
@@ -824,21 +827,21 @@
 
 	/* signal completion when nothing's queued */
 	if (ctx->pending == 0)
-		complete (&ctx->complete);
-	spin_unlock (&ctx->lock);
+		complete(&ctx->complete);
+	spin_unlock(&ctx->lock);
 }
 
 static int
-test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
+test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param)
 {
-	struct usb_device	*udev = testdev_to_usbdev (dev);
+	struct usb_device	*udev = testdev_to_usbdev(dev);
 	struct urb		**urb;
 	struct ctrl_ctx		context;
 	int			i;
 
-	spin_lock_init (&context.lock);
+	spin_lock_init(&context.lock);
 	context.dev = dev;
-	init_completion (&context.complete);
+	init_completion(&context.complete);
 	context.count = param->sglen * param->iterations;
 	context.pending = 0;
 	context.status = -ENOMEM;
@@ -853,7 +856,7 @@
 	if (!urb)
 		return -ENOMEM;
 	for (i = 0; i < param->sglen; i++) {
-		int			pipe = usb_rcvctrlpipe (udev, 0);
+		int			pipe = usb_rcvctrlpipe(udev, 0);
 		unsigned		len;
 		struct urb		*u;
 		struct usb_ctrlrequest	req;
@@ -869,104 +872,108 @@
 		 * device, but some are chosen to trigger protocol stalls
 		 * or short reads.
 		 */
-		memset (&req, 0, sizeof req);
+		memset(&req, 0, sizeof req);
 		req.bRequest = USB_REQ_GET_DESCRIPTOR;
 		req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE;
 
 		switch (i % NUM_SUBCASES) {
-		case 0:		// get device descriptor
-			req.wValue = cpu_to_le16 (USB_DT_DEVICE << 8);
-			len = sizeof (struct usb_device_descriptor);
+		case 0:		/* get device descriptor */
+			req.wValue = cpu_to_le16(USB_DT_DEVICE << 8);
+			len = sizeof(struct usb_device_descriptor);
 			break;
-		case 1:		// get first config descriptor (only)
-			req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
-			len = sizeof (struct usb_config_descriptor);
+		case 1:		/* get first config descriptor (only) */
+			req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
+			len = sizeof(struct usb_config_descriptor);
 			break;
-		case 2:		// get altsetting (OFTEN STALLS)
+		case 2:		/* get altsetting (OFTEN STALLS) */
 			req.bRequest = USB_REQ_GET_INTERFACE;
 			req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE;
-			// index = 0 means first interface
+			/* index = 0 means first interface */
 			len = 1;
 			expected = EPIPE;
 			break;
-		case 3:		// get interface status
+		case 3:		/* get interface status */
 			req.bRequest = USB_REQ_GET_STATUS;
 			req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE;
-			// interface 0
+			/* interface 0 */
 			len = 2;
 			break;
-		case 4:		// get device status
+		case 4:		/* get device status */
 			req.bRequest = USB_REQ_GET_STATUS;
 			req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE;
 			len = 2;
 			break;
-		case 5:		// get device qualifier (MAY STALL)
+		case 5:		/* get device qualifier (MAY STALL) */
 			req.wValue = cpu_to_le16 (USB_DT_DEVICE_QUALIFIER << 8);
-			len = sizeof (struct usb_qualifier_descriptor);
+			len = sizeof(struct usb_qualifier_descriptor);
 			if (udev->speed != USB_SPEED_HIGH)
 				expected = EPIPE;
 			break;
-		case 6:		// get first config descriptor, plus interface
-			req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
-			len = sizeof (struct usb_config_descriptor);
-			len += sizeof (struct usb_interface_descriptor);
+		case 6:		/* get first config descriptor, plus interface */
+			req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
+			len = sizeof(struct usb_config_descriptor);
+			len += sizeof(struct usb_interface_descriptor);
 			break;
-		case 7:		// get interface descriptor (ALWAYS STALLS)
+		case 7:		/* get interface descriptor (ALWAYS STALLS) */
 			req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8);
-			// interface == 0
-			len = sizeof (struct usb_interface_descriptor);
+			/* interface == 0 */
+			len = sizeof(struct usb_interface_descriptor);
 			expected = -EPIPE;
 			break;
-		// NOTE: two consecutive stalls in the queue here.
-		// that tests fault recovery a bit more aggressively.
-		case 8:		// clear endpoint halt (MAY STALL)
+		/* NOTE: two consecutive stalls in the queue here.
+		 *  that tests fault recovery a bit more aggressively. */
+		case 8:		/* clear endpoint halt (MAY STALL) */
 			req.bRequest = USB_REQ_CLEAR_FEATURE;
 			req.bRequestType = USB_RECIP_ENDPOINT;
-			// wValue 0 == ep halt
-			// wIndex 0 == ep0 (shouldn't halt!)
+			/* wValue 0 == ep halt */
+			/* wIndex 0 == ep0 (shouldn't halt!) */
 			len = 0;
-			pipe = usb_sndctrlpipe (udev, 0);
+			pipe = usb_sndctrlpipe(udev, 0);
 			expected = EPIPE;
 			break;
-		case 9:		// get endpoint status
+		case 9:		/* get endpoint status */
 			req.bRequest = USB_REQ_GET_STATUS;
 			req.bRequestType = USB_DIR_IN|USB_RECIP_ENDPOINT;
-			// endpoint 0
+			/* endpoint 0 */
 			len = 2;
 			break;
-		case 10:	// trigger short read (EREMOTEIO)
-			req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
+		case 10:	/* trigger short read (EREMOTEIO) */
+			req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
 			len = 1024;
 			expected = -EREMOTEIO;
 			break;
-		// NOTE: two consecutive _different_ faults in the queue.
-		case 11:	// get endpoint descriptor (ALWAYS STALLS)
-			req.wValue = cpu_to_le16 (USB_DT_ENDPOINT << 8);
-			// endpoint == 0
-			len = sizeof (struct usb_interface_descriptor);
+		/* NOTE: two consecutive _different_ faults in the queue. */
+		case 11:	/* get endpoint descriptor (ALWAYS STALLS) */
+			req.wValue = cpu_to_le16(USB_DT_ENDPOINT << 8);
+			/* endpoint == 0 */
+			len = sizeof(struct usb_interface_descriptor);
 			expected = EPIPE;
 			break;
-		// NOTE: sometimes even a third fault in the queue!
-		case 12:	// get string 0 descriptor (MAY STALL)
-			req.wValue = cpu_to_le16 (USB_DT_STRING << 8);
-			// string == 0, for language IDs
-			len = sizeof (struct usb_interface_descriptor);
-			// may succeed when > 4 languages
-			expected = EREMOTEIO;	// or EPIPE, if no strings
+		/* NOTE: sometimes even a third fault in the queue! */
+		case 12:	/* get string 0 descriptor (MAY STALL) */
+			req.wValue = cpu_to_le16(USB_DT_STRING << 8);
+			/* string == 0, for language IDs */
+			len = sizeof(struct usb_interface_descriptor);
+			/* may succeed when > 4 languages */
+			expected = EREMOTEIO;	/* or EPIPE, if no strings */
 			break;
-		case 13:	// short read, resembling case 10
-			req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
-			// last data packet "should" be DATA1, not DATA0
+		case 13:	/* short read, resembling case 10 */
+			req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
+			/* last data packet "should" be DATA1, not DATA0 */
 			len = 1024 - udev->descriptor.bMaxPacketSize0;
 			expected = -EREMOTEIO;
 			break;
-		case 14:	// short read; try to fill the last packet
-			req.wValue = cpu_to_le16 ((USB_DT_DEVICE << 8) | 0);
+		case 14:	/* short read; try to fill the last packet */
+			req.wValue = cpu_to_le16((USB_DT_DEVICE << 8) | 0);
 			/* device descriptor size == 18 bytes */
 			len = udev->descriptor.bMaxPacketSize0;
 			switch (len) {
-			case 8:		len = 24; break;
-			case 16:	len = 32; break;
+			case 8:
+				len = 24;
+				break;
+			case 16:
+				len = 32;
+				break;
 			}
 			expected = -EREMOTEIO;
 			break;
@@ -975,8 +982,8 @@
 			context.status = -EINVAL;
 			goto cleanup;
 		}
-		req.wLength = cpu_to_le16 (len);
-		urb [i] = u = simple_alloc_urb (udev, pipe, len);
+		req.wLength = cpu_to_le16(len);
+		urb[i] = u = simple_alloc_urb(udev, pipe, len);
 		if (!u)
 			goto cleanup;
 
@@ -994,9 +1001,9 @@
 
 	/* queue the urbs */
 	context.urb = urb;
-	spin_lock_irq (&context.lock);
+	spin_lock_irq(&context.lock);
 	for (i = 0; i < param->sglen; i++) {
-		context.status = usb_submit_urb (urb [i], GFP_ATOMIC);
+		context.status = usb_submit_urb(urb[i], GFP_ATOMIC);
 		if (context.status != 0) {
 			ERROR(dev, "can't submit urb[%d], status %d\n",
 					i, context.status);
@@ -1005,23 +1012,23 @@
 		}
 		context.pending++;
 	}
-	spin_unlock_irq (&context.lock);
+	spin_unlock_irq(&context.lock);
 
 	/* FIXME  set timer and time out; provide a disconnect hook */
 
 	/* wait for the last one to complete */
 	if (context.pending > 0)
-		wait_for_completion (&context.complete);
+		wait_for_completion(&context.complete);
 
 cleanup:
 	for (i = 0; i < param->sglen; i++) {
-		if (!urb [i])
+		if (!urb[i])
 			continue;
-		urb [i]->dev = udev;
+		urb[i]->dev = udev;
 		kfree(urb[i]->setup_packet);
-		simple_free_urb (urb [i]);
+		simple_free_urb(urb[i]);
 	}
-	kfree (urb);
+	kfree(urb);
 	return context.status;
 }
 #undef NUM_SUBCASES
@@ -1029,27 +1036,27 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void unlink1_callback (struct urb *urb)
+static void unlink1_callback(struct urb *urb)
 {
 	int	status = urb->status;
 
-	// we "know" -EPIPE (stall) never happens
+	/* we "know" -EPIPE (stall) never happens */
 	if (!status)
-		status = usb_submit_urb (urb, GFP_ATOMIC);
+		status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		urb->status = status;
 		complete(urb->context);
 	}
 }
 
-static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
+static int unlink1(struct usbtest_dev *dev, int pipe, int size, int async)
 {
 	struct urb		*urb;
 	struct completion	completion;
 	int			retval = 0;
 
-	init_completion (&completion);
-	urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
+	init_completion(&completion);
+	urb = simple_alloc_urb(testdev_to_usbdev(dev), pipe, size);
 	if (!urb)
 		return -ENOMEM;
 	urb->context = &completion;
@@ -1061,7 +1068,8 @@
 	 * FIXME want additional tests for when endpoint is STALLing
 	 * due to errors, or is just NAKing requests.
 	 */
-	if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) {
+	retval = usb_submit_urb(urb, GFP_KERNEL);
+	if (retval != 0) {
 		dev_err(&dev->intf->dev, "submit fail %d\n", retval);
 		return retval;
 	}
@@ -1069,7 +1077,7 @@
 	/* unlinking that should always work.  variable delay tests more
 	 * hcd states and code paths, even with little other system load.
 	 */
-	msleep (jiffies % (2 * INTERRUPT_RATE));
+	msleep(jiffies % (2 * INTERRUPT_RATE));
 	if (async) {
 		while (!completion_done(&completion)) {
 			retval = usb_unlink_urb(urb);
@@ -1098,11 +1106,11 @@
 			break;
 		}
 	} else
-		usb_kill_urb (urb);
+		usb_kill_urb(urb);
 
-	wait_for_completion (&completion);
+	wait_for_completion(&completion);
 	retval = urb->status;
-	simple_free_urb (urb);
+	simple_free_urb(urb);
 
 	if (async)
 		return (retval == -ECONNRESET) ? 0 : retval - 1000;
@@ -1111,14 +1119,14 @@
 				0 : retval - 2000;
 }
 
-static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
+static int unlink_simple(struct usbtest_dev *dev, int pipe, int len)
 {
 	int			retval = 0;
 
 	/* test sync and async paths */
-	retval = unlink1 (dev, pipe, len, 1);
+	retval = unlink1(dev, pipe, len, 1);
 	if (!retval)
-		retval = unlink1 (dev, pipe, len, 0);
+		retval = unlink1(dev, pipe, len, 0);
 	return retval;
 }
 
@@ -1130,7 +1138,7 @@
 	u16	status;
 
 	/* shouldn't look or act halted */
-	retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
+	retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status);
 	if (retval < 0) {
 		ERROR(tdev, "ep %02x couldn't get no-halt status, %d\n",
 				ep, retval);
@@ -1152,7 +1160,7 @@
 	u16	status;
 
 	/* should look and act halted */
-	retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
+	retval = usb_get_status(urb->dev, USB_RECIP_ENDPOINT, ep, &status);
 	if (retval < 0) {
 		ERROR(tdev, "ep %02x couldn't get halt status, %d\n",
 				ep, retval);
@@ -1182,7 +1190,7 @@
 		return retval;
 
 	/* set halt (protocol test only), verify it worked */
-	retval = usb_control_msg (urb->dev, usb_sndctrlpipe (urb->dev, 0),
+	retval = usb_control_msg(urb->dev, usb_sndctrlpipe(urb->dev, 0),
 			USB_REQ_SET_FEATURE, USB_RECIP_ENDPOINT,
 			USB_ENDPOINT_HALT, ep,
 			NULL, 0, USB_CTRL_SET_TIMEOUT);
@@ -1195,7 +1203,7 @@
 		return retval;
 
 	/* clear halt (tests API + protocol), verify it worked */
-	retval = usb_clear_halt (urb->dev, urb->pipe);
+	retval = usb_clear_halt(urb->dev, urb->pipe);
 	if (retval < 0) {
 		ERROR(tdev, "ep %02x couldn't clear halt, %d\n", ep, retval);
 		return retval;
@@ -1209,18 +1217,18 @@
 	return 0;
 }
 
-static int halt_simple (struct usbtest_dev *dev)
+static int halt_simple(struct usbtest_dev *dev)
 {
 	int		ep;
 	int		retval = 0;
 	struct urb	*urb;
 
-	urb = simple_alloc_urb (testdev_to_usbdev (dev), 0, 512);
+	urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512);
 	if (urb == NULL)
 		return -ENOMEM;
 
 	if (dev->in_pipe) {
-		ep = usb_pipeendpoint (dev->in_pipe) | USB_DIR_IN;
+		ep = usb_pipeendpoint(dev->in_pipe) | USB_DIR_IN;
 		urb->pipe = dev->in_pipe;
 		retval = test_halt(dev, ep, urb);
 		if (retval < 0)
@@ -1228,12 +1236,12 @@
 	}
 
 	if (dev->out_pipe) {
-		ep = usb_pipeendpoint (dev->out_pipe);
+		ep = usb_pipeendpoint(dev->out_pipe);
 		urb->pipe = dev->out_pipe;
 		retval = test_halt(dev, ep, urb);
 	}
 done:
-	simple_free_urb (urb);
+	simple_free_urb(urb);
 	return retval;
 }
 
@@ -1247,7 +1255,7 @@
  * need to be able to handle more than one OUT data packet.  We'll
  * try whatever we're told to try.
  */
-static int ctrl_out (struct usbtest_dev *dev,
+static int ctrl_out(struct usbtest_dev *dev,
 		unsigned count, unsigned length, unsigned vary)
 {
 	unsigned		i, j, len;
@@ -1263,7 +1271,7 @@
 	if (!buf)
 		return -ENOMEM;
 
-	udev = testdev_to_usbdev (dev);
+	udev = testdev_to_usbdev(dev);
 	len = length;
 	retval = 0;
 
@@ -1273,8 +1281,8 @@
 	for (i = 0; i < count; i++) {
 		/* write patterned data */
 		for (j = 0; j < len; j++)
-			buf [j] = i + j;
-		retval = usb_control_msg (udev, usb_sndctrlpipe (udev,0),
+			buf[j] = i + j;
+		retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				0x5b, USB_DIR_OUT|USB_TYPE_VENDOR,
 				0, 0, buf, len, USB_CTRL_SET_TIMEOUT);
 		if (retval != len) {
@@ -1288,7 +1296,7 @@
 		}
 
 		/* read it back -- assuming nothing intervened!!  */
-		retval = usb_control_msg (udev, usb_rcvctrlpipe (udev,0),
+		retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 				0x5c, USB_DIR_IN|USB_TYPE_VENDOR,
 				0, 0, buf, len, USB_CTRL_GET_TIMEOUT);
 		if (retval != len) {
@@ -1303,9 +1311,9 @@
 
 		/* fail if we can't verify */
 		for (j = 0; j < len; j++) {
-			if (buf [j] != (u8) (i + j)) {
+			if (buf[j] != (u8) (i + j)) {
 				ERROR(dev, "ctrl_out, byte %d is %d not %d\n",
-					j, buf [j], (u8) i + j);
+					j, buf[j], (u8) i + j);
 				retval = -EBADMSG;
 				break;
 			}
@@ -1326,10 +1334,10 @@
 	}
 
 	if (retval < 0)
-		ERROR (dev, "ctrl_out %s failed, code %d, count %d\n",
+		ERROR(dev, "ctrl_out %s failed, code %d, count %d\n",
 			what, retval, i);
 
-	kfree (buf);
+	kfree(buf);
 	return retval;
 }
 
@@ -1351,7 +1359,7 @@
 	struct usbtest_dev	*dev;
 };
 
-static void iso_callback (struct urb *urb)
+static void iso_callback(struct urb *urb)
 {
 	struct iso_context	*ctx = urb->context;
 
@@ -1363,10 +1371,12 @@
 		ctx->errors += urb->error_count;
 	else if (urb->status != 0)
 		ctx->errors += urb->number_of_packets;
+	else if (urb->actual_length != urb->transfer_buffer_length)
+		ctx->errors++;
 
 	if (urb->status == 0 && ctx->count > (ctx->pending - 1)
 			&& !ctx->submit_error) {
-		int status = usb_submit_urb (urb, GFP_ATOMIC);
+		int status = usb_submit_urb(urb, GFP_ATOMIC);
 		switch (status) {
 		case 0:
 			goto done;
@@ -1388,13 +1398,13 @@
 			dev_err(&ctx->dev->intf->dev,
 				"iso test, %lu errors out of %lu\n",
 				ctx->errors, ctx->packet_count);
-		complete (&ctx->done);
+		complete(&ctx->done);
 	}
 done:
 	spin_unlock(&ctx->lock);
 }
 
-static struct urb *iso_alloc_urb (
+static struct urb *iso_alloc_urb(
 	struct usb_device	*udev,
 	int			pipe,
 	struct usb_endpoint_descriptor	*desc,
@@ -1410,7 +1420,7 @@
 	maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11));
 	packets = DIV_ROUND_UP(bytes, maxp);
 
-	urb = usb_alloc_urb (packets, GFP_KERNEL);
+	urb = usb_alloc_urb(packets, GFP_KERNEL);
 	if (!urb)
 		return urb;
 	urb->dev = udev;
@@ -1418,30 +1428,30 @@
 
 	urb->number_of_packets = packets;
 	urb->transfer_buffer_length = bytes;
-	urb->transfer_buffer = usb_alloc_coherent (udev, bytes, GFP_KERNEL,
+	urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL,
 			&urb->transfer_dma);
 	if (!urb->transfer_buffer) {
-		usb_free_urb (urb);
+		usb_free_urb(urb);
 		return NULL;
 	}
-	memset (urb->transfer_buffer, 0, bytes);
+	memset(urb->transfer_buffer, 0, bytes);
 	for (i = 0; i < packets; i++) {
 		/* here, only the last packet will be short */
-		urb->iso_frame_desc[i].length = min ((unsigned) bytes, maxp);
+		urb->iso_frame_desc[i].length = min((unsigned) bytes, maxp);
 		bytes -= urb->iso_frame_desc[i].length;
 
 		urb->iso_frame_desc[i].offset = maxp * i;
 	}
 
 	urb->complete = iso_callback;
-	// urb->context = SET BY CALLER
+	/* urb->context = SET BY CALLER */
 	urb->interval = 1 << (desc->bInterval - 1);
 	urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 	return urb;
 }
 
 static int
-test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
+test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
 		int pipe, struct usb_endpoint_descriptor *desc)
 {
 	struct iso_context	context;
@@ -1457,11 +1467,11 @@
 	memset(&context, 0, sizeof context);
 	context.count = param->iterations * param->sglen;
 	context.dev = dev;
-	init_completion (&context.done);
-	spin_lock_init (&context.lock);
+	init_completion(&context.done);
+	spin_lock_init(&context.lock);
 
-	memset (urbs, 0, sizeof urbs);
-	udev = testdev_to_usbdev (dev);
+	memset(urbs, 0, sizeof urbs);
+	udev = testdev_to_usbdev(dev);
 	dev_info(&dev->intf->dev,
 		"... iso period %d %sframes, wMaxPacket %04x\n",
 		1 << (desc->bInterval - 1),
@@ -1469,14 +1479,14 @@
 		le16_to_cpu(desc->wMaxPacketSize));
 
 	for (i = 0; i < param->sglen; i++) {
-		urbs [i] = iso_alloc_urb (udev, pipe, desc,
+		urbs[i] = iso_alloc_urb(udev, pipe, desc,
 				param->length);
-		if (!urbs [i]) {
+		if (!urbs[i]) {
 			status = -ENOMEM;
 			goto fail;
 		}
 		packets += urbs[i]->number_of_packets;
-		urbs [i]->context = &context;
+		urbs[i]->context = &context;
 	}
 	packets *= param->iterations;
 	dev_info(&dev->intf->dev,
@@ -1485,27 +1495,27 @@
 			/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
 		packets);
 
-	spin_lock_irq (&context.lock);
+	spin_lock_irq(&context.lock);
 	for (i = 0; i < param->sglen; i++) {
 		++context.pending;
-		status = usb_submit_urb (urbs [i], GFP_ATOMIC);
+		status = usb_submit_urb(urbs[i], GFP_ATOMIC);
 		if (status < 0) {
-			ERROR (dev, "submit iso[%d], error %d\n", i, status);
+			ERROR(dev, "submit iso[%d], error %d\n", i, status);
 			if (i == 0) {
-				spin_unlock_irq (&context.lock);
+				spin_unlock_irq(&context.lock);
 				goto fail;
 			}
 
-			simple_free_urb (urbs [i]);
+			simple_free_urb(urbs[i]);
 			urbs[i] = NULL;
 			context.pending--;
 			context.submit_error = 1;
 			break;
 		}
 	}
-	spin_unlock_irq (&context.lock);
+	spin_unlock_irq(&context.lock);
 
-	wait_for_completion (&context.done);
+	wait_for_completion(&context.done);
 
 	for (i = 0; i < param->sglen; i++) {
 		if (urbs[i])
@@ -1526,8 +1536,8 @@
 
 fail:
 	for (i = 0; i < param->sglen; i++) {
-		if (urbs [i])
-			simple_free_urb (urbs [i]);
+		if (urbs[i])
+			simple_free_urb(urbs[i]);
 	}
 	return status;
 }
@@ -1557,10 +1567,10 @@
 
 /* No BKL needed */
 static int
-usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
+usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
 {
-	struct usbtest_dev	*dev = usb_get_intfdata (intf);
-	struct usb_device	*udev = testdev_to_usbdev (dev);
+	struct usbtest_dev	*dev = usb_get_intfdata(intf);
+	struct usb_device	*udev = testdev_to_usbdev(dev);
 	struct usbtest_param	*param = buf;
 	int			retval = -EOPNOTSUPP;
 	struct urb		*urb;
@@ -1569,7 +1579,7 @@
 	struct timeval		start;
 	unsigned		i;
 
-	// FIXME USBDEVFS_CONNECTINFO doesn't say how fast the device is.
+	/* FIXME USBDEVFS_CONNECTINFO doesn't say how fast the device is. */
 
 	pattern = mod_pattern;
 
@@ -1595,9 +1605,9 @@
 			mutex_unlock(&dev->lock);
 			return -ENODEV;
 		}
-		res = set_altsetting (dev, dev->info->alt);
+		res = set_altsetting(dev, dev->info->alt);
 		if (res) {
-			dev_err (&intf->dev,
+			dev_err(&intf->dev,
 					"set altsetting to %d failed, %d\n",
 					dev->info->alt, res);
 			mutex_unlock(&dev->lock);
@@ -1614,7 +1624,7 @@
 	 * FIXME add more tests!  cancel requests, verify the data, control
 	 * queueing, concurrent read+write threads, and so on.
 	 */
-	do_gettimeofday (&start);
+	do_gettimeofday(&start);
 	switch (param->test_num) {
 
 	case 0:
@@ -1629,14 +1639,14 @@
 		dev_info(&intf->dev,
 				"TEST 1:  write %d bytes %u times\n",
 				param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
+		urb = simple_alloc_urb(udev, dev->out_pipe, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk sink (maybe accepts short writes)
+		/* FIRMWARE:  bulk sink (maybe accepts short writes) */
 		retval = simple_io(dev, urb, param->iterations, 0, 0, "test1");
-		simple_free_urb (urb);
+		simple_free_urb(urb);
 		break;
 	case 2:
 		if (dev->in_pipe == 0)
@@ -1644,14 +1654,14 @@
 		dev_info(&intf->dev,
 				"TEST 2:  read %d bytes %u times\n",
 				param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
+		urb = simple_alloc_urb(udev, dev->in_pipe, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk source (maybe generates short writes)
+		/* FIRMWARE:  bulk source (maybe generates short writes) */
 		retval = simple_io(dev, urb, param->iterations, 0, 0, "test2");
-		simple_free_urb (urb);
+		simple_free_urb(urb);
 		break;
 	case 3:
 		if (dev->out_pipe == 0 || param->vary == 0)
@@ -1659,15 +1669,15 @@
 		dev_info(&intf->dev,
 				"TEST 3:  write/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
+		urb = simple_alloc_urb(udev, dev->out_pipe, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk sink (maybe accepts short writes)
+		/* FIRMWARE:  bulk sink (maybe accepts short writes) */
 		retval = simple_io(dev, urb, param->iterations, param->vary,
 					0, "test3");
-		simple_free_urb (urb);
+		simple_free_urb(urb);
 		break;
 	case 4:
 		if (dev->in_pipe == 0 || param->vary == 0)
@@ -1675,15 +1685,15 @@
 		dev_info(&intf->dev,
 				"TEST 4:  read/%d 0..%d bytes %u times\n",
 				param->vary, param->length, param->iterations);
-		urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
+		urb = simple_alloc_urb(udev, dev->in_pipe, param->length);
 		if (!urb) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk source (maybe generates short writes)
+		/* FIRMWARE:  bulk source (maybe generates short writes) */
 		retval = simple_io(dev, urb, param->iterations, param->vary,
 					0, "test4");
-		simple_free_urb (urb);
+		simple_free_urb(urb);
 		break;
 
 	/* Queued bulk I/O tests */
@@ -1694,15 +1704,15 @@
 			"TEST 5:  write %d sglists %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
-		sg = alloc_sglist (param->sglen, param->length, 0);
+		sg = alloc_sglist(param->sglen, param->length, 0);
 		if (!sg) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk sink (maybe accepts short writes)
+		/* FIRMWARE:  bulk sink (maybe accepts short writes) */
 		retval = perform_sglist(dev, param->iterations, dev->out_pipe,
 				&req, sg, param->sglen);
-		free_sglist (sg, param->sglen);
+		free_sglist(sg, param->sglen);
 		break;
 
 	case 6:
@@ -1712,15 +1722,15 @@
 			"TEST 6:  read %d sglists %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
-		sg = alloc_sglist (param->sglen, param->length, 0);
+		sg = alloc_sglist(param->sglen, param->length, 0);
 		if (!sg) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk source (maybe generates short writes)
+		/* FIRMWARE:  bulk source (maybe generates short writes) */
 		retval = perform_sglist(dev, param->iterations, dev->in_pipe,
 				&req, sg, param->sglen);
-		free_sglist (sg, param->sglen);
+		free_sglist(sg, param->sglen);
 		break;
 	case 7:
 		if (dev->out_pipe == 0 || param->sglen == 0 || param->vary == 0)
@@ -1729,15 +1739,15 @@
 			"TEST 7:  write/%d %d sglists %d entries 0..%d bytes\n",
 				param->vary, param->iterations,
 				param->sglen, param->length);
-		sg = alloc_sglist (param->sglen, param->length, param->vary);
+		sg = alloc_sglist(param->sglen, param->length, param->vary);
 		if (!sg) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk sink (maybe accepts short writes)
+		/* FIRMWARE:  bulk sink (maybe accepts short writes) */
 		retval = perform_sglist(dev, param->iterations, dev->out_pipe,
 				&req, sg, param->sglen);
-		free_sglist (sg, param->sglen);
+		free_sglist(sg, param->sglen);
 		break;
 	case 8:
 		if (dev->in_pipe == 0 || param->sglen == 0 || param->vary == 0)
@@ -1746,15 +1756,15 @@
 			"TEST 8:  read/%d %d sglists %d entries 0..%d bytes\n",
 				param->vary, param->iterations,
 				param->sglen, param->length);
-		sg = alloc_sglist (param->sglen, param->length, param->vary);
+		sg = alloc_sglist(param->sglen, param->length, param->vary);
 		if (!sg) {
 			retval = -ENOMEM;
 			break;
 		}
-		// FIRMWARE:  bulk source (maybe generates short writes)
+		/* FIRMWARE:  bulk source (maybe generates short writes) */
 		retval = perform_sglist(dev, param->iterations, dev->in_pipe,
 				&req, sg, param->sglen);
-		free_sglist (sg, param->sglen);
+		free_sglist(sg, param->sglen);
 		break;
 
 	/* non-queued sanity tests for control (chapter 9 subset) */
@@ -1764,7 +1774,7 @@
 			"TEST 9:  ch9 (subset) control tests, %d times\n",
 				param->iterations);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = ch9_postconfig (dev);
+			retval = ch9_postconfig(dev);
 		if (retval)
 			dev_err(&intf->dev, "ch9 subset failed, "
 					"iterations left %d\n", i);
@@ -1779,7 +1789,7 @@
 				"TEST 10:  queue %d control calls, %d times\n",
 				param->sglen,
 				param->iterations);
-		retval = test_ctrl_queue (dev, param);
+		retval = test_ctrl_queue(dev, param);
 		break;
 
 	/* simple non-queued unlinks (ring with one urb) */
@@ -1790,7 +1800,7 @@
 		dev_info(&intf->dev, "TEST 11:  unlink %d reads of %d\n",
 				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = unlink_simple (dev, dev->in_pipe,
+			retval = unlink_simple(dev, dev->in_pipe,
 						param->length);
 		if (retval)
 			dev_err(&intf->dev, "unlink reads failed %d, "
@@ -1803,7 +1813,7 @@
 		dev_info(&intf->dev, "TEST 12:  unlink %d writes of %d\n",
 				param->iterations, param->length);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = unlink_simple (dev, dev->out_pipe,
+			retval = unlink_simple(dev, dev->out_pipe,
 						param->length);
 		if (retval)
 			dev_err(&intf->dev, "unlink writes failed %d, "
@@ -1818,7 +1828,7 @@
 		dev_info(&intf->dev, "TEST 13:  set/clear %d halts\n",
 				param->iterations);
 		for (i = param->iterations; retval == 0 && i--; /* NOP */)
-			retval = halt_simple (dev);
+			retval = halt_simple(dev);
 
 		if (retval)
 			ERROR(dev, "halts failed, iterations left %d\n", i);
@@ -1844,8 +1854,8 @@
 			"TEST 15:  write %d iso, %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
-		// FIRMWARE:  iso sink
-		retval = test_iso_queue (dev, param,
+		/* FIRMWARE:  iso sink */
+		retval = test_iso_queue(dev, param,
 				dev->out_iso_pipe, dev->iso_out);
 		break;
 
@@ -1857,17 +1867,17 @@
 			"TEST 16:  read %d iso, %d entries of %d bytes\n",
 				param->iterations,
 				param->sglen, param->length);
-		// FIRMWARE:  iso source
-		retval = test_iso_queue (dev, param,
+		/* FIRMWARE:  iso source */
+		retval = test_iso_queue(dev, param,
 				dev->in_iso_pipe, dev->iso_in);
 		break;
 
-	// FIXME unlink from queue (ring with N urbs)
+	/* FIXME unlink from queue (ring with N urbs) */
 
-	// FIXME scatterlist cancel (needs helper thread)
+	/* FIXME scatterlist cancel (needs helper thread) */
 
 	}
-	do_gettimeofday (&param->duration);
+	do_gettimeofday(&param->duration);
 	param->duration.tv_sec -= start.tv_sec;
 	param->duration.tv_usec -= start.tv_usec;
 	if (param->duration.tv_usec < 0) {
@@ -1880,22 +1890,22 @@
 
 /*-------------------------------------------------------------------------*/
 
-static unsigned force_interrupt = 0;
-module_param (force_interrupt, uint, 0);
-MODULE_PARM_DESC (force_interrupt, "0 = test default; else interrupt");
+static unsigned force_interrupt;
+module_param(force_interrupt, uint, 0);
+MODULE_PARM_DESC(force_interrupt, "0 = test default; else interrupt");
 
 #ifdef	GENERIC
 static unsigned short vendor;
 module_param(vendor, ushort, 0);
-MODULE_PARM_DESC (vendor, "vendor code (from usb-if)");
+MODULE_PARM_DESC(vendor, "vendor code (from usb-if)");
 
 static unsigned short product;
 module_param(product, ushort, 0);
-MODULE_PARM_DESC (product, "product code (from vendor)");
+MODULE_PARM_DESC(product, "product code (from vendor)");
 #endif
 
 static int
-usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
+usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device	*udev;
 	struct usbtest_dev	*dev;
@@ -1903,7 +1913,7 @@
 	char			*rtest, *wtest;
 	char			*irtest, *iwtest;
 
-	udev = interface_to_usbdev (intf);
+	udev = interface_to_usbdev(intf);
 
 #ifdef	GENERIC
 	/* specify devices by module parameters? */
@@ -1930,8 +1940,9 @@
 	dev->intf = intf;
 
 	/* cacheline-aligned scratch for i/o */
-	if ((dev->buf = kmalloc (TBUF_SIZE, GFP_KERNEL)) == NULL) {
-		kfree (dev);
+	dev->buf = kmalloc(TBUF_SIZE, GFP_KERNEL);
+	if (dev->buf == NULL) {
+		kfree(dev);
 		return -ENOMEM;
 	}
 
@@ -1943,18 +1954,18 @@
 	irtest = iwtest = "";
 	if (force_interrupt || udev->speed == USB_SPEED_LOW) {
 		if (info->ep_in) {
-			dev->in_pipe = usb_rcvintpipe (udev, info->ep_in);
+			dev->in_pipe = usb_rcvintpipe(udev, info->ep_in);
 			rtest = " intr-in";
 		}
 		if (info->ep_out) {
-			dev->out_pipe = usb_sndintpipe (udev, info->ep_out);
+			dev->out_pipe = usb_sndintpipe(udev, info->ep_out);
 			wtest = " intr-out";
 		}
 	} else {
 		if (info->autoconf) {
 			int status;
 
-			status = get_endpoints (dev, intf);
+			status = get_endpoints(dev, intf);
 			if (status < 0) {
 				WARNING(dev, "couldn't get endpoints, %d\n",
 						status);
@@ -1963,10 +1974,10 @@
 			/* may find bulk or ISO pipes */
 		} else {
 			if (info->ep_in)
-				dev->in_pipe = usb_rcvbulkpipe (udev,
+				dev->in_pipe = usb_rcvbulkpipe(udev,
 							info->ep_in);
 			if (info->ep_out)
-				dev->out_pipe = usb_sndbulkpipe (udev,
+				dev->out_pipe = usb_sndbulkpipe(udev,
 							info->ep_out);
 		}
 		if (dev->in_pipe)
@@ -1979,15 +1990,23 @@
 			iwtest = " iso-out";
 	}
 
-	usb_set_intfdata (intf, dev);
-	dev_info (&intf->dev, "%s\n", info->name);
-	dev_info (&intf->dev, "%s speed {control%s%s%s%s%s} tests%s\n",
+	usb_set_intfdata(intf, dev);
+	dev_info(&intf->dev, "%s\n", info->name);
+	dev_info(&intf->dev, "%s speed {control%s%s%s%s%s} tests%s\n",
 			({ char *tmp;
 			switch (udev->speed) {
-			case USB_SPEED_LOW: tmp = "low"; break;
-			case USB_SPEED_FULL: tmp = "full"; break;
-			case USB_SPEED_HIGH: tmp = "high"; break;
-			default: tmp = "unknown"; break;
+			case USB_SPEED_LOW:
+				tmp = "low";
+				break;
+			case USB_SPEED_FULL:
+				tmp = "full";
+				break;
+			case USB_SPEED_HIGH:
+				tmp = "high";
+				break;
+			default:
+				tmp = "unknown";
+				break;
 			}; tmp; }),
 			info->ctrl_out ? " in/out" : "",
 			rtest, wtest,
@@ -1996,24 +2015,24 @@
 	return 0;
 }
 
-static int usbtest_suspend (struct usb_interface *intf, pm_message_t message)
+static int usbtest_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	return 0;
 }
 
-static int usbtest_resume (struct usb_interface *intf)
+static int usbtest_resume(struct usb_interface *intf)
 {
 	return 0;
 }
 
 
-static void usbtest_disconnect (struct usb_interface *intf)
+static void usbtest_disconnect(struct usb_interface *intf)
 {
-	struct usbtest_dev	*dev = usb_get_intfdata (intf);
+	struct usbtest_dev	*dev = usb_get_intfdata(intf);
 
-	usb_set_intfdata (intf, NULL);
-	dev_dbg (&intf->dev, "disconnect\n");
-	kfree (dev);
+	usb_set_intfdata(intf, NULL);
+	dev_dbg(&intf->dev, "disconnect\n");
+	kfree(dev);
 }
 
 /* Basic testing only needs a device that can source or sink bulk traffic.
@@ -2050,9 +2069,9 @@
 	.ep_in		= 2,
 	.ep_out		= 2,
 	.alt		= 1,
-	.autoconf	= 1,		// iso and ctrl_out need autoconf
+	.autoconf	= 1,		/* iso and ctrl_out need autoconf */
 	.ctrl_out	= 1,
-	.iso		= 1,		// iso_ep's are #8 in/out
+	.iso		= 1,		/* iso_ep's are #8 in/out */
 };
 
 /* peripheral running Linux and 'zero.c' test firmware, or
@@ -2109,56 +2128,56 @@
 	 */
 
 	/* generic EZ-USB FX controller */
-	{ USB_DEVICE (0x0547, 0x2235),
+	{ USB_DEVICE(0x0547, 0x2235),
 		.driver_info = (unsigned long) &ez1_info,
-		},
+	},
 
 	/* CY3671 development board with EZ-USB FX */
-	{ USB_DEVICE (0x0547, 0x0080),
+	{ USB_DEVICE(0x0547, 0x0080),
 		.driver_info = (unsigned long) &ez1_info,
-		},
+	},
 
 	/* generic EZ-USB FX2 controller (or development board) */
-	{ USB_DEVICE (0x04b4, 0x8613),
+	{ USB_DEVICE(0x04b4, 0x8613),
 		.driver_info = (unsigned long) &ez2_info,
-		},
+	},
 
 	/* re-enumerated usb test device firmware */
-	{ USB_DEVICE (0xfff0, 0xfff0),
+	{ USB_DEVICE(0xfff0, 0xfff0),
 		.driver_info = (unsigned long) &fw_info,
-		},
+	},
 
 	/* "Gadget Zero" firmware runs under Linux */
-	{ USB_DEVICE (0x0525, 0xa4a0),
+	{ USB_DEVICE(0x0525, 0xa4a0),
 		.driver_info = (unsigned long) &gz_info,
-		},
+	},
 
 	/* so does a user-mode variant */
-	{ USB_DEVICE (0x0525, 0xa4a4),
+	{ USB_DEVICE(0x0525, 0xa4a4),
 		.driver_info = (unsigned long) &um_info,
-		},
+	},
 
 	/* ... and a user-mode variant that talks iso */
-	{ USB_DEVICE (0x0525, 0xa4a3),
+	{ USB_DEVICE(0x0525, 0xa4a3),
 		.driver_info = (unsigned long) &um2_info,
-		},
+	},
 
 #ifdef KEYSPAN_19Qi
 	/* Keyspan 19qi uses an21xx (original EZ-USB) */
-	// this does not coexist with the real Keyspan 19qi driver!
-	{ USB_DEVICE (0x06cd, 0x010b),
+	/* this does not coexist with the real Keyspan 19qi driver! */
+	{ USB_DEVICE(0x06cd, 0x010b),
 		.driver_info = (unsigned long) &ez1_info,
-		},
+	},
 #endif
 
 	/*-------------------------------------------------------------*/
 
 #ifdef IBOT2
 	/* iBOT2 makes a nice source of high speed bulk-in data */
-	// this does not coexist with a real iBOT2 driver!
-	{ USB_DEVICE (0x0b62, 0x0059),
+	/* this does not coexist with a real iBOT2 driver! */
+	{ USB_DEVICE(0x0b62, 0x0059),
 		.driver_info = (unsigned long) &ibot2_info,
-		},
+	},
 #endif
 
 	/*-------------------------------------------------------------*/
@@ -2172,7 +2191,7 @@
 
 	{ }
 };
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver usbtest_driver = {
 	.name =		"usbtest",
@@ -2186,22 +2205,22 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int __init usbtest_init (void)
+static int __init usbtest_init(void)
 {
 #ifdef GENERIC
 	if (vendor)
 		pr_debug("params: vend=0x%04x prod=0x%04x\n", vendor, product);
 #endif
-	return usb_register (&usbtest_driver);
+	return usb_register(&usbtest_driver);
 }
-module_init (usbtest_init);
+module_init(usbtest_init);
 
-static void __exit usbtest_exit (void)
+static void __exit usbtest_exit(void)
 {
-	usb_deregister (&usbtest_driver);
+	usb_deregister(&usbtest_driver);
 }
-module_exit (usbtest_exit);
+module_exit(usbtest_exit);
 
-MODULE_DESCRIPTION ("USB Core/HCD Testing Driver");
-MODULE_LICENSE ("GPL");
+MODULE_DESCRIPTION("USB Core/HCD Testing Driver");
+MODULE_LICENSE("GPL");
 
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
new file mode 100644
index 0000000..719c618
--- /dev/null
+++ b/drivers/usb/misc/yurex.c
@@ -0,0 +1,563 @@
+/*
+ * Driver for Meywa-Denki & KAYAC YUREX
+ *
+ * Copyright (C) 2010 Tomoki Sekiyama (tomoki.sekiyama@gmail.com)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+
+#define DRIVER_AUTHOR "Tomoki Sekiyama"
+#define DRIVER_DESC "Driver for Meywa-Denki & KAYAC YUREX"
+
+#define YUREX_VENDOR_ID		0x0c45
+#define YUREX_PRODUCT_ID	0x1010
+
+#define CMD_ACK		'!'
+#define CMD_ANIMATE	'A'
+#define CMD_COUNT	'C'
+#define CMD_LED		'L'
+#define CMD_READ	'R'
+#define CMD_SET		'S'
+#define CMD_VERSION	'V'
+#define CMD_EOF		0x0d
+#define CMD_PADDING	0xff
+
+#define YUREX_BUF_SIZE		8
+#define YUREX_WRITE_TIMEOUT	(HZ*2)
+
+/* table of devices that work with this driver */
+static struct usb_device_id yurex_table[] = {
+	{ USB_DEVICE(YUREX_VENDOR_ID, YUREX_PRODUCT_ID) },
+	{ }					/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, yurex_table);
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define YUREX_MINOR_BASE	0
+#else
+#define YUREX_MINOR_BASE	192
+#endif
+
+/* Structure to hold all of our device specific stuff */
+struct usb_yurex {
+	struct usb_device	*udev;
+	struct usb_interface	*interface;
+	__u8			int_in_endpointAddr;
+	struct urb		*urb;		/* URB for interrupt in */
+	unsigned char           *int_buffer;	/* buffer for intterupt in */
+	struct urb		*cntl_urb;	/* URB for control msg */
+	struct usb_ctrlrequest	*cntl_req;	/* req for control msg */
+	unsigned char		*cntl_buffer;	/* buffer for control msg */
+
+	struct kref		kref;
+	struct mutex		io_mutex;
+	struct fasync_struct	*async_queue;
+	wait_queue_head_t	waitq;
+
+	spinlock_t		lock;
+	__s64			bbu;		/* BBU from device */
+};
+#define to_yurex_dev(d) container_of(d, struct usb_yurex, kref)
+
+static struct usb_driver yurex_driver;
+static const struct file_operations yurex_fops;
+
+
+static void yurex_control_callback(struct urb *urb)
+{
+	struct usb_yurex *dev = urb->context;
+	int status = urb->status;
+
+	if (status) {
+		err("%s - control failed: %d\n", __func__, status);
+		wake_up_interruptible(&dev->waitq);
+		return;
+	}
+	/* on success, sender woken up by CMD_ACK int in, or timeout */
+}
+
+static void yurex_delete(struct kref *kref)
+{
+	struct usb_yurex *dev = to_yurex_dev(kref);
+
+	dbg("yurex_delete");
+
+	usb_put_dev(dev->udev);
+	if (dev->cntl_urb) {
+		usb_kill_urb(dev->cntl_urb);
+		if (dev->cntl_req)
+			usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
+				dev->cntl_req, dev->cntl_urb->setup_dma);
+		if (dev->cntl_buffer)
+			usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
+				dev->cntl_buffer, dev->cntl_urb->transfer_dma);
+		usb_free_urb(dev->cntl_urb);
+	}
+	if (dev->urb) {
+		usb_kill_urb(dev->urb);
+		if (dev->int_buffer)
+			usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
+				dev->int_buffer, dev->urb->transfer_dma);
+		usb_free_urb(dev->urb);
+	}
+	kfree(dev);
+}
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
+static struct usb_class_driver yurex_class = {
+	.name =		"yurex%d",
+	.fops =		&yurex_fops,
+	.minor_base =	YUREX_MINOR_BASE,
+};
+
+static void yurex_interrupt(struct urb *urb)
+{
+	struct usb_yurex *dev = urb->context;
+	unsigned char *buf = dev->int_buffer;
+	int status = urb->status;
+	unsigned long flags;
+	int retval, i;
+
+	switch (status) {
+	case 0: /*success*/
+		break;
+	case -EOVERFLOW:
+		err("%s - overflow with length %d, actual length is %d",
+		    __func__, YUREX_BUF_SIZE, dev->urb->actual_length);
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+	case -EILSEQ:
+		/* The device is terminated, clean up */
+		return;
+	default:
+		err("%s - unknown status received: %d", __func__, status);
+		goto exit;
+	}
+
+	/* handle received message */
+	switch (buf[0]) {
+	case CMD_COUNT:
+	case CMD_READ:
+		if (buf[6] == CMD_EOF) {
+			spin_lock_irqsave(&dev->lock, flags);
+			dev->bbu = 0;
+			for (i = 1; i < 6; i++) {
+				dev->bbu += buf[i];
+				if (i != 5)
+					dev->bbu <<= 8;
+			}
+			dbg("%s count: %lld", __func__, dev->bbu);
+			spin_unlock_irqrestore(&dev->lock, flags);
+
+			kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
+		}
+		else
+			dbg("data format error - no EOF");
+		break;
+	case CMD_ACK:
+		dbg("%s ack: %c", __func__, buf[1]);
+		wake_up_interruptible(&dev->waitq);
+		break;
+	}
+
+exit:
+	retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+	if (retval) {
+		err("%s - usb_submit_urb failed: %d",
+			__func__, retval);
+	}
+}
+
+static int yurex_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct usb_yurex *dev;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int retval = -ENOMEM;
+	int i;
+	DEFINE_WAIT(wait);
+
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		err("Out of memory");
+		goto error;
+	}
+	kref_init(&dev->kref);
+	mutex_init(&dev->io_mutex);
+	spin_lock_init(&dev->lock);
+	init_waitqueue_head(&dev->waitq);
+
+	dev->udev = usb_get_dev(interface_to_usbdev(interface));
+	dev->interface = interface;
+
+	/* set up the endpoint information */
+	iface_desc = interface->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		if (usb_endpoint_is_int_in(endpoint)) {
+			dev->int_in_endpointAddr = endpoint->bEndpointAddress;
+			break;
+		}
+	}
+	if (!dev->int_in_endpointAddr) {
+		retval = -ENODEV;
+		err("Could not find endpoints");
+		goto error;
+	}
+
+
+	/* allocate control URB */
+	dev->cntl_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->cntl_urb) {
+		err("Could not allocate control URB");
+		goto error;
+	}
+
+	/* allocate buffer for control req */
+	dev->cntl_req = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
+					   GFP_KERNEL,
+					   &dev->cntl_urb->setup_dma);
+	if (!dev->cntl_req) {
+		err("Could not allocate cntl_req");
+		goto error;
+	}
+
+	/* allocate buffer for control msg */
+	dev->cntl_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
+					      GFP_KERNEL,
+					      &dev->cntl_urb->transfer_dma);
+	if (!dev->cntl_buffer) {
+		err("Could not allocate cntl_buffer");
+		goto error;
+	}
+
+	/* configure control URB */
+	dev->cntl_req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS |
+				      USB_RECIP_INTERFACE;
+	dev->cntl_req->bRequest	= HID_REQ_SET_REPORT;
+	dev->cntl_req->wValue	= cpu_to_le16((HID_OUTPUT_REPORT + 1) << 8);
+	dev->cntl_req->wIndex	= cpu_to_le16(iface_desc->desc.bInterfaceNumber);
+	dev->cntl_req->wLength	= cpu_to_le16(YUREX_BUF_SIZE);
+
+	usb_fill_control_urb(dev->cntl_urb, dev->udev,
+			     usb_sndctrlpipe(dev->udev, 0),
+			     (void *)dev->cntl_req, dev->cntl_buffer,
+			     YUREX_BUF_SIZE, yurex_control_callback, dev);
+	dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+
+	/* allocate interrupt URB */
+	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->urb) {
+		err("Could not allocate URB");
+		goto error;
+	}
+
+	/* allocate buffer for interrupt in */
+	dev->int_buffer = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
+					GFP_KERNEL, &dev->urb->transfer_dma);
+	if (!dev->int_buffer) {
+		err("Could not allocate int_buffer");
+		goto error;
+	}
+
+	/* configure interrupt URB */
+	usb_fill_int_urb(dev->urb, dev->udev,
+			 usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr),
+			 dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt,
+			 dev, 1);
+	dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	if (usb_submit_urb(dev->urb, GFP_KERNEL)) {
+		retval = -EIO;
+		err("Could not submitting URB");
+		goto error;
+	}
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
+
+	/* we can register the device now, as it is ready */
+	retval = usb_register_dev(interface, &yurex_class);
+	if (retval) {
+		err("Not able to get a minor for this device.");
+		usb_set_intfdata(interface, NULL);
+		goto error;
+	}
+
+	dev->bbu = -1;
+
+	dev_info(&interface->dev,
+		 "USB YUREX device now attached to Yurex #%d\n",
+		 interface->minor);
+
+	return 0;
+
+error:
+	if (dev)
+		/* this frees allocated memory */
+		kref_put(&dev->kref, yurex_delete);
+	return retval;
+}
+
+static void yurex_disconnect(struct usb_interface *interface)
+{
+	struct usb_yurex *dev;
+	int minor = interface->minor;
+
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	/* give back our minor */
+	usb_deregister_dev(interface, &yurex_class);
+
+	/* prevent more I/O from starting */
+	mutex_lock(&dev->io_mutex);
+	dev->interface = NULL;
+	mutex_unlock(&dev->io_mutex);
+
+	/* wakeup waiters */
+	kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
+	wake_up_interruptible(&dev->waitq);
+
+	/* decrement our usage count */
+	kref_put(&dev->kref, yurex_delete);
+
+	dev_info(&interface->dev, "USB YUREX #%d now disconnected\n", minor);
+}
+
+static struct usb_driver yurex_driver = {
+	.name =		"yurex",
+	.probe =	yurex_probe,
+	.disconnect =	yurex_disconnect,
+	.id_table =	yurex_table,
+};
+
+
+static int yurex_fasync(int fd, struct file *file, int on)
+{
+	struct usb_yurex *dev;
+
+	dev = (struct usb_yurex *)file->private_data;
+	return fasync_helper(fd, file, on, &dev->async_queue);
+}
+
+static int yurex_open(struct inode *inode, struct file *file)
+{
+	struct usb_yurex *dev;
+	struct usb_interface *interface;
+	int subminor;
+	int retval = 0;
+
+	subminor = iminor(inode);
+
+	interface = usb_find_interface(&yurex_driver, subminor);
+	if (!interface) {
+		err("%s - error, can't find device for minor %d",
+		    __func__, subminor);
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	dev = usb_get_intfdata(interface);
+	if (!dev) {
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	/* increment our usage count for the device */
+	kref_get(&dev->kref);
+
+	/* save our object in the file's private structure */
+	mutex_lock(&dev->io_mutex);
+	file->private_data = dev;
+	mutex_unlock(&dev->io_mutex);
+
+exit:
+	return retval;
+}
+
+static int yurex_release(struct inode *inode, struct file *file)
+{
+	struct usb_yurex *dev;
+
+	dev = (struct usb_yurex *)file->private_data;
+	if (dev == NULL)
+		return -ENODEV;
+
+	yurex_fasync(-1, file, 0);
+
+	/* decrement the count on our device */
+	kref_put(&dev->kref, yurex_delete);
+	return 0;
+}
+
+static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct usb_yurex *dev;
+	int retval = 0;
+	int bytes_read = 0;
+	char in_buffer[20];
+	unsigned long flags;
+
+	dev = (struct usb_yurex *)file->private_data;
+
+	mutex_lock(&dev->io_mutex);
+	if (!dev->interface) {		/* already disconnected */
+		retval = -ENODEV;
+		goto exit;
+	}
+
+	spin_lock_irqsave(&dev->lock, flags);
+	bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (*ppos < bytes_read) {
+		if (copy_to_user(buffer, in_buffer + *ppos, bytes_read - *ppos))
+			retval = -EFAULT;
+		else {
+			retval = bytes_read - *ppos;
+			*ppos += bytes_read;
+		}
+	}
+
+exit:
+	mutex_unlock(&dev->io_mutex);
+	return retval;
+}
+
+static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
+{
+	struct usb_yurex *dev;
+	int i, set = 0, retval = 0;
+	char buffer[16];
+	char *data = buffer;
+	unsigned long long c, c2 = 0;
+	signed long timeout = 0;
+	DEFINE_WAIT(wait);
+
+	count = min(sizeof(buffer), count);
+	dev = (struct usb_yurex *)file->private_data;
+
+	/* verify that we actually have some data to write */
+	if (count == 0)
+		goto error;
+
+	mutex_lock(&dev->io_mutex);
+	if (!dev->interface) {		/* alreaday disconnected */
+		mutex_unlock(&dev->io_mutex);
+		retval = -ENODEV;
+		goto error;
+	}
+
+	if (copy_from_user(buffer, user_buffer, count)) {
+		mutex_unlock(&dev->io_mutex);
+		retval = -EFAULT;
+		goto error;
+	}
+	memset(dev->cntl_buffer, CMD_PADDING, YUREX_BUF_SIZE);
+
+	switch (buffer[0]) {
+	case CMD_ANIMATE:
+	case CMD_LED:
+		dev->cntl_buffer[0] = buffer[0];
+		dev->cntl_buffer[1] = buffer[1];
+		dev->cntl_buffer[2] = CMD_EOF;
+		break;
+	case CMD_READ:
+	case CMD_VERSION:
+		dev->cntl_buffer[0] = buffer[0];
+		dev->cntl_buffer[1] = 0x00;
+		dev->cntl_buffer[2] = CMD_EOF;
+		break;
+	case CMD_SET:
+		data++;
+		/* FALL THROUGH */
+	case '0' ... '9':
+		set = 1;
+		c = c2 = simple_strtoull(data, NULL, 0);
+		dev->cntl_buffer[0] = CMD_SET;
+		for (i = 1; i < 6; i++) {
+			dev->cntl_buffer[i] = (c>>32) & 0xff;
+			c <<= 8;
+		}
+		buffer[6] = CMD_EOF;
+		break;
+	default:
+		mutex_unlock(&dev->io_mutex);
+		return -EINVAL;
+	}
+
+	/* send the data as the control msg */
+	prepare_to_wait(&dev->waitq, &wait, TASK_INTERRUPTIBLE);
+	dbg("%s - submit %c", __func__, dev->cntl_buffer[0]);
+	retval = usb_submit_urb(dev->cntl_urb, GFP_KERNEL);
+	if (retval >= 0)
+		timeout = schedule_timeout(YUREX_WRITE_TIMEOUT);
+	finish_wait(&dev->waitq, &wait);
+
+	mutex_unlock(&dev->io_mutex);
+
+	if (retval < 0) {
+		err("%s - failed to send bulk msg, error %d", __func__, retval);
+		goto error;
+	}
+	if (set && timeout)
+		dev->bbu = c2;
+	return timeout ? count : -EIO;
+
+error:
+	return retval;
+}
+
+static const struct file_operations yurex_fops = {
+	.owner =	THIS_MODULE,
+	.read =		yurex_read,
+	.write =	yurex_write,
+	.open =		yurex_open,
+	.release =	yurex_release,
+	.fasync	=	yurex_fasync,
+};
+
+
+static int __init usb_yurex_init(void)
+{
+	int result;
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&yurex_driver);
+	if (result)
+		err("usb_register failed. Error number %d", result);
+
+	return result;
+}
+
+static void __exit usb_yurex_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&yurex_driver);
+}
+
+module_init(usb_yurex_init);
+module_exit(usb_yurex_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
index 384b198..8ed24ab 100644
--- a/drivers/usb/mon/Makefile
+++ b/drivers/usb/mon/Makefile
@@ -2,6 +2,6 @@
 # Makefile for USB monitor
 #
 
-usbmon-objs	:= mon_main.o mon_stat.o mon_text.o mon_bin.o
+usbmon-y := mon_main.o mon_stat.o mon_text.o mon_bin.o
 
 obj-$(CONFIG_USB_MON)	+= usbmon.o
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index cfd38ed..341a37a 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -45,6 +45,9 @@
 comment "DaVinci 35x and 644x USB support"
 	depends on USB_MUSB_HDRC && ARCH_DAVINCI_DMx
 
+comment "DA8xx/OMAP-L1x USB support"
+	depends on USB_MUSB_HDRC && ARCH_DAVINCI_DA8XX
+
 comment "OMAP 243x high speed USB support"
 	depends on USB_MUSB_HDRC && ARCH_OMAP2430
 
@@ -57,6 +60,17 @@
 comment "Blackfin high speed USB Support"
 	depends on USB_MUSB_HDRC && ((BF54x && !BF544) || (BF52x && !BF522 && !BF523))
 
+config USB_MUSB_AM35X
+	bool
+	depends on USB_MUSB_HDRC && !ARCH_OMAP2430 && !ARCH_OMAP4
+	select NOP_USB_XCEIV
+	default MACH_OMAP3517EVM
+	help
+	  Select this option if your platform is based on AM35x. As
+	  AM35x has an updated MUSB with CPPI4.1 DMA so this config
+	  is introduced to differentiate musb ip between OMAP3x and
+	  AM35x platforms.
+
 config USB_TUSB6010
 	boolean "TUSB 6010 support"
 	depends on USB_MUSB_HDRC && !USB_MUSB_SOC
@@ -144,7 +158,7 @@
 config MUSB_PIO_ONLY
 	bool 'Disable DMA (always use PIO)'
 	depends on USB_MUSB_HDRC
-	default y if USB_TUSB6010
+	default USB_TUSB6010 || ARCH_DAVINCI_DA8XX || USB_MUSB_AM35X
 	help
 	  All data is copied between memory and FIFO by the CPU.
 	  DMA controllers are ignored.
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 9705f71..ce164e8 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -2,49 +2,27 @@
 # for USB OTG silicon based on Mentor Graphics INVENTRA designs
 #
 
-musb_hdrc-objs := musb_core.o
+ccflags-$(CONFIG_USB_MUSB_DEBUG) := -DDEBUG
 
-obj-$(CONFIG_USB_MUSB_HDRC)	+= musb_hdrc.o
+obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o
 
-ifeq ($(CONFIG_ARCH_DAVINCI_DMx),y)
-	musb_hdrc-objs	+= davinci.o
+musb_hdrc-y := musb_core.o
+
+musb_hdrc-$(CONFIG_ARCH_DAVINCI_DMx)		+= davinci.o
+musb_hdrc-$(CONFIG_ARCH_DAVINCI_DA8XX)		+= da8xx.o
+musb_hdrc-$(CONFIG_USB_TUSB6010)		+= tusb6010.o
+musb_hdrc-$(CONFIG_ARCH_OMAP2430)		+= omap2430.o
+ifeq ($(CONFIG_USB_MUSB_AM35X),y)
+	musb_hdrc-$(CONFIG_ARCH_OMAP3430)	+= am35x.o
+else
+	musb_hdrc-$(CONFIG_ARCH_OMAP3430)	+= omap2430.o
 endif
-
-ifeq ($(CONFIG_USB_TUSB6010),y)
-	musb_hdrc-objs	+= tusb6010.o
-endif
-
-ifeq ($(CONFIG_ARCH_OMAP2430),y)
-	musb_hdrc-objs	+= omap2430.o
-endif
-
-ifeq ($(CONFIG_ARCH_OMAP3430),y)
-	musb_hdrc-objs	+= omap2430.o
-endif
-
-ifeq ($(CONFIG_ARCH_OMAP4),y)
-	musb_hdrc-objs  += omap2430.o
-endif
-
-ifeq ($(CONFIG_BF54x),y)
-	musb_hdrc-objs	+= blackfin.o
-endif
-
-ifeq ($(CONFIG_BF52x),y)
-	musb_hdrc-objs	+= blackfin.o
-endif
-
-ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y)
-	musb_hdrc-objs		+= musb_gadget_ep0.o musb_gadget.o
-endif
-
-ifeq ($(CONFIG_USB_MUSB_HDRC_HCD),y)
-	musb_hdrc-objs		+= musb_virthub.o musb_host.o
-endif
-
-ifeq ($(CONFIG_DEBUG_FS),y)
-	musb_hdrc-objs		+= musb_debugfs.o
-endif
+musb_hdrc-$(CONFIG_ARCH_OMAP4)			+= omap2430.o
+musb_hdrc-$(CONFIG_BF54x)			+= blackfin.o
+musb_hdrc-$(CONFIG_BF52x)			+= blackfin.o
+musb_hdrc-$(CONFIG_USB_GADGET_MUSB_HDRC)	+= musb_gadget_ep0.o musb_gadget.o
+musb_hdrc-$(CONFIG_USB_MUSB_HDRC_HCD)		+= musb_virthub.o musb_host.o
+musb_hdrc-$(CONFIG_DEBUG_FS)			+= musb_debugfs.o
 
 # the kconfig must guarantee that only one of the
 # possible I/O schemes will be enabled at a time ...
@@ -54,26 +32,17 @@
 ifneq ($(CONFIG_MUSB_PIO_ONLY),y)
 
   ifeq ($(CONFIG_USB_INVENTRA_DMA),y)
-    musb_hdrc-objs		+= musbhsdma.o
+    musb_hdrc-y			+= musbhsdma.o
 
   else
     ifeq ($(CONFIG_USB_TI_CPPI_DMA),y)
-      musb_hdrc-objs		+= cppi_dma.o
+      musb_hdrc-y		+= cppi_dma.o
 
     else
       ifeq ($(CONFIG_USB_TUSB_OMAP_DMA),y)
-        musb_hdrc-objs		+= tusb6010_omap.o
+	musb_hdrc-y		+= tusb6010_omap.o
 
       endif
     endif
   endif
 endif
-
-
-################################################################################
-
-# Debugging
-
-ifeq ($(CONFIG_USB_MUSB_DEBUG),y)
-	EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
new file mode 100644
index 0000000..b0aabf3
--- /dev/null
+++ b/drivers/usb/musb/am35x.c
@@ -0,0 +1,524 @@
+/*
+ * Texas Instruments AM35x "glue layer"
+ *
+ * Copyright (c) 2010, by Texas Instruments
+ *
+ * Based on the DA8xx "glue layer" code.
+ * Copyright (c) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ * The Inventra Controller Driver for Linux is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR 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 Inventra Controller Driver for Linux ; 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/clk.h>
+#include <linux/io.h>
+
+#include <plat/control.h>
+#include <plat/usb.h>
+
+#include "musb_core.h"
+
+/*
+ * AM35x specific definitions
+ */
+/* USB 2.0 OTG module registers */
+#define USB_REVISION_REG	0x00
+#define USB_CTRL_REG		0x04
+#define USB_STAT_REG		0x08
+#define USB_EMULATION_REG	0x0c
+/* 0x10 Reserved */
+#define USB_AUTOREQ_REG		0x14
+#define USB_SRP_FIX_TIME_REG	0x18
+#define USB_TEARDOWN_REG	0x1c
+#define EP_INTR_SRC_REG		0x20
+#define EP_INTR_SRC_SET_REG	0x24
+#define EP_INTR_SRC_CLEAR_REG	0x28
+#define EP_INTR_MASK_REG	0x2c
+#define EP_INTR_MASK_SET_REG	0x30
+#define EP_INTR_MASK_CLEAR_REG	0x34
+#define EP_INTR_SRC_MASKED_REG	0x38
+#define CORE_INTR_SRC_REG	0x40
+#define CORE_INTR_SRC_SET_REG	0x44
+#define CORE_INTR_SRC_CLEAR_REG	0x48
+#define CORE_INTR_MASK_REG	0x4c
+#define CORE_INTR_MASK_SET_REG	0x50
+#define CORE_INTR_MASK_CLEAR_REG 0x54
+#define CORE_INTR_SRC_MASKED_REG 0x58
+/* 0x5c Reserved */
+#define USB_END_OF_INTR_REG	0x60
+
+/* Control register bits */
+#define AM35X_SOFT_RESET_MASK	1
+
+/* USB interrupt register bits */
+#define AM35X_INTR_USB_SHIFT	16
+#define AM35X_INTR_USB_MASK	(0x1ff << AM35X_INTR_USB_SHIFT)
+#define AM35X_INTR_DRVVBUS	0x100
+#define AM35X_INTR_RX_SHIFT	16
+#define AM35X_INTR_TX_SHIFT	0
+#define AM35X_TX_EP_MASK	0xffff		/* EP0 + 15 Tx EPs */
+#define AM35X_RX_EP_MASK	0xfffe		/* 15 Rx EPs */
+#define AM35X_TX_INTR_MASK	(AM35X_TX_EP_MASK << AM35X_INTR_TX_SHIFT)
+#define AM35X_RX_INTR_MASK	(AM35X_RX_EP_MASK << AM35X_INTR_RX_SHIFT)
+
+#define USB_MENTOR_CORE_OFFSET	0x400
+
+static inline void phy_on(void)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(100);
+	u32 devconf2;
+
+	/*
+	 * Start the on-chip PHY and its PLL.
+	 */
+	devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+	devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
+	devconf2 |= CONF2_PHY_PLLON;
+
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+	DBG(1, "Waiting for PHY clock good...\n");
+	while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
+			& CONF2_PHYCLKGD)) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout)) {
+			DBG(1, "musb PHY clock good timed out\n");
+			break;
+		}
+	}
+}
+
+static inline void phy_off(void)
+{
+	u32 devconf2;
+
+	/*
+	 * Power down the on-chip PHY.
+	 */
+	devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+	devconf2 &= ~CONF2_PHY_PLLON;
+	devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+}
+
+/*
+ * musb_platform_enable - enable interrupts
+ */
+void musb_platform_enable(struct musb *musb)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+	u32 epmask;
+
+	/* Workaround: setup IRQs through both register sets. */
+	epmask = ((musb->epmask & AM35X_TX_EP_MASK) << AM35X_INTR_TX_SHIFT) |
+	       ((musb->epmask & AM35X_RX_EP_MASK) << AM35X_INTR_RX_SHIFT);
+
+	musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask);
+	musb_writel(reg_base, CORE_INTR_MASK_SET_REG, AM35X_INTR_USB_MASK);
+
+	/* Force the DRVVBUS IRQ so we can start polling for ID change. */
+	if (is_otg_enabled(musb))
+		musb_writel(reg_base, CORE_INTR_SRC_SET_REG,
+			    AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT);
+}
+
+/*
+ * musb_platform_disable - disable HDRC and flush interrupts
+ */
+void musb_platform_disable(struct musb *musb)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+
+	musb_writel(reg_base, CORE_INTR_MASK_CLEAR_REG, AM35X_INTR_USB_MASK);
+	musb_writel(reg_base, EP_INTR_MASK_CLEAR_REG,
+			 AM35X_TX_INTR_MASK | AM35X_RX_INTR_MASK);
+	musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+	musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
+}
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+#define portstate(stmt)		stmt
+#else
+#define portstate(stmt)
+#endif
+
+static void am35x_set_vbus(struct musb *musb, int is_on)
+{
+	WARN_ON(is_on && is_peripheral_active(musb));
+}
+
+#define	POLL_SECONDS	2
+
+static struct timer_list otg_workaround;
+
+static void otg_timer(unsigned long _musb)
+{
+	struct musb		*musb = (void *)_musb;
+	void __iomem		*mregs = musb->mregs;
+	u8			devctl;
+	unsigned long		flags;
+
+	/*
+	 * We poll because AM35x's won't expose several OTG-critical
+	 * status change events (from the transceiver) otherwise.
+	 */
+	devctl = musb_readb(mregs, MUSB_DEVCTL);
+	DBG(7, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
+
+	spin_lock_irqsave(&musb->lock, flags);
+	switch (musb->xceiv->state) {
+	case OTG_STATE_A_WAIT_BCON:
+		devctl &= ~MUSB_DEVCTL_SESSION;
+		musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+		if (devctl & MUSB_DEVCTL_BDEVICE) {
+			musb->xceiv->state = OTG_STATE_B_IDLE;
+			MUSB_DEV_MODE(musb);
+		} else {
+			musb->xceiv->state = OTG_STATE_A_IDLE;
+			MUSB_HST_MODE(musb);
+		}
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+		musb_writel(musb->ctrl_base, CORE_INTR_SRC_SET_REG,
+			    MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT);
+		break;
+	case OTG_STATE_B_IDLE:
+		if (!is_peripheral_enabled(musb))
+			break;
+
+		devctl = musb_readb(mregs, MUSB_DEVCTL);
+		if (devctl & MUSB_DEVCTL_BDEVICE)
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+		else
+			musb->xceiv->state = OTG_STATE_A_IDLE;
+		break;
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+{
+	static unsigned long last_timer;
+
+	if (!is_otg_enabled(musb))
+		return;
+
+	if (timeout == 0)
+		timeout = jiffies + msecs_to_jiffies(3);
+
+	/* Never idle if active, or when VBUS timeout is not set as host */
+	if (musb->is_active || (musb->a_wait_bcon == 0 &&
+				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+		DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+		del_timer(&otg_workaround);
+		last_timer = jiffies;
+		return;
+	}
+
+	if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) {
+		DBG(4, "Longer idle timer already pending, ignoring...\n");
+		return;
+	}
+	last_timer = timeout;
+
+	DBG(4, "%s inactive, starting idle timer for %u ms\n",
+	    otg_state_string(musb), jiffies_to_msecs(timeout - jiffies));
+	mod_timer(&otg_workaround, timeout);
+}
+
+static irqreturn_t am35x_interrupt(int irq, void *hci)
+{
+	struct musb  *musb = hci;
+	void __iomem *reg_base = musb->ctrl_base;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+	u32 epintr, usbintr, lvl_intr;
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	/* Get endpoint interrupts */
+	epintr = musb_readl(reg_base, EP_INTR_SRC_MASKED_REG);
+
+	if (epintr) {
+		musb_writel(reg_base, EP_INTR_SRC_CLEAR_REG, epintr);
+
+		musb->int_rx =
+			(epintr & AM35X_RX_INTR_MASK) >> AM35X_INTR_RX_SHIFT;
+		musb->int_tx =
+			(epintr & AM35X_TX_INTR_MASK) >> AM35X_INTR_TX_SHIFT;
+	}
+
+	/* Get usb core interrupts */
+	usbintr = musb_readl(reg_base, CORE_INTR_SRC_MASKED_REG);
+	if (!usbintr && !epintr)
+		goto eoi;
+
+	if (usbintr) {
+		musb_writel(reg_base, CORE_INTR_SRC_CLEAR_REG, usbintr);
+
+		musb->int_usb =
+			(usbintr & AM35X_INTR_USB_MASK) >> AM35X_INTR_USB_SHIFT;
+	}
+	/*
+	 * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
+	 * AM35x's missing ID change IRQ.  We need an ID change IRQ to
+	 * switch appropriately between halves of the OTG state machine.
+	 * Managing DEVCTL.SESSION per Mentor docs requires that we know its
+	 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
+	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
+	 */
+	if (usbintr & (AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT)) {
+		int drvvbus = musb_readl(reg_base, USB_STAT_REG);
+		void __iomem *mregs = musb->mregs;
+		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
+		int err;
+
+		err = is_host_enabled(musb) && (musb->int_usb &
+						MUSB_INTR_VBUSERROR);
+		if (err) {
+			/*
+			 * The Mentor core doesn't debounce VBUS as needed
+			 * to cope with device connect current spikes. This
+			 * means it's not uncommon for bus-powered devices
+			 * to get VBUS errors during enumeration.
+			 *
+			 * This is a workaround, but newer RTL from Mentor
+			 * seems to allow a better one: "re"-starting sessions
+			 * without waiting for VBUS to stop registering in
+			 * devctl.
+			 */
+			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+			WARNING("VBUS error workaround (delay coming)\n");
+		} else if (is_host_enabled(musb) && drvvbus) {
+			MUSB_HST_MODE(musb);
+			musb->xceiv->default_a = 1;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+			portstate(musb->port1_status |= USB_PORT_STAT_POWER);
+			del_timer(&otg_workaround);
+		} else {
+			musb->is_active = 0;
+			MUSB_DEV_MODE(musb);
+			musb->xceiv->default_a = 0;
+			musb->xceiv->state = OTG_STATE_B_IDLE;
+			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
+		}
+
+		/* NOTE: this must complete power-on within 100 ms. */
+		DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
+				drvvbus ? "on" : "off",
+				otg_state_string(musb),
+				err ? " ERROR" : "",
+				devctl);
+		ret = IRQ_HANDLED;
+	}
+
+	if (musb->int_tx || musb->int_rx || musb->int_usb)
+		ret |= musb_interrupt(musb);
+
+eoi:
+	/* EOI needs to be written for the IRQ to be re-asserted. */
+	if (ret == IRQ_HANDLED || epintr || usbintr) {
+		/* clear level interrupt */
+		lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+		lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
+		omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+		/* write EOI */
+		musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
+	}
+
+	/* Poll for ID change */
+	if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
+		mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+
+	spin_unlock_irqrestore(&musb->lock, flags);
+
+	return ret;
+}
+
+int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+{
+	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+	devconf2 &= ~CONF2_OTGMODE;
+	switch (musb_mode) {
+#ifdef	CONFIG_USB_MUSB_HDRC_HCD
+	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
+		devconf2 |= CONF2_FORCE_HOST;
+		break;
+#endif
+#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
+	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
+		devconf2 |= CONF2_FORCE_DEVICE;
+		break;
+#endif
+#ifdef	CONFIG_USB_MUSB_OTG
+	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
+		devconf2 |= CONF2_NO_OVERRIDE;
+		break;
+#endif
+	default:
+		DBG(2, "Trying to set unsupported mode %u\n", musb_mode);
+	}
+
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+	return 0;
+}
+
+int __init musb_platform_init(struct musb *musb, void *board_data)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+	u32 rev, lvl_intr, sw_reset;
+	int status;
+
+	musb->mregs += USB_MENTOR_CORE_OFFSET;
+
+	clk_enable(musb->clock);
+	DBG(2, "musb->clock=%lud\n", clk_get_rate(musb->clock));
+
+	musb->phy_clock = clk_get(musb->controller, "fck");
+	if (IS_ERR(musb->phy_clock)) {
+		status = PTR_ERR(musb->phy_clock);
+		goto exit0;
+	}
+	clk_enable(musb->phy_clock);
+	DBG(2, "musb->phy_clock=%lud\n", clk_get_rate(musb->phy_clock));
+
+	/* Returns zero if e.g. not clocked */
+	rev = musb_readl(reg_base, USB_REVISION_REG);
+	if (!rev) {
+		status = -ENODEV;
+		goto exit1;
+	}
+
+	usb_nop_xceiv_register();
+	musb->xceiv = otg_get_transceiver();
+	if (!musb->xceiv) {
+		status = -ENODEV;
+		goto exit1;
+	}
+
+	if (is_host_enabled(musb))
+		setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
+
+	musb->board_set_vbus = am35x_set_vbus;
+
+	/* Global reset */
+	sw_reset = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+
+	sw_reset |= AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
+
+	sw_reset &= ~AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(sw_reset, AM35XX_CONTROL_IP_SW_RESET);
+
+	/* Reset the controller */
+	musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK);
+
+	/* Start the on-chip PHY and its PLL. */
+	phy_on();
+
+	msleep(5);
+
+	musb->isr = am35x_interrupt;
+
+	/* clear level interrupt */
+	lvl_intr = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+	lvl_intr |= AM35XX_USBOTGSS_INT_CLR;
+	omap_ctrl_writel(lvl_intr, AM35XX_CONTROL_LVL_INTR_CLEAR);
+	return 0;
+exit1:
+	clk_disable(musb->phy_clock);
+	clk_put(musb->phy_clock);
+exit0:
+	clk_disable(musb->clock);
+	return status;
+}
+
+int musb_platform_exit(struct musb *musb)
+{
+	if (is_host_enabled(musb))
+		del_timer_sync(&otg_workaround);
+
+	phy_off();
+
+	otg_put_transceiver(musb->xceiv);
+	usb_nop_xceiv_unregister();
+
+	clk_disable(musb->clock);
+
+	clk_disable(musb->phy_clock);
+	clk_put(musb->phy_clock);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+void musb_platform_save_context(struct musb *musb,
+	struct musb_context_registers *musb_context)
+{
+	phy_off();
+}
+
+void musb_platform_restore_context(struct musb *musb,
+	struct musb_context_registers *musb_context)
+{
+	phy_on();
+}
+#endif
+
+/* AM35x supports only 32bit read operation */
+void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
+{
+	void __iomem *fifo = hw_ep->fifo;
+	u32		val;
+	int		i;
+
+	/* Read for 32bit-aligned destination address */
+	if (likely((0x03 & (unsigned long) dst) == 0) && len >= 4) {
+		readsl(fifo, dst, len >> 2);
+		dst += len & ~0x03;
+		len &= 0x03;
+	}
+	/*
+	 * Now read the remaining 1 to 3 byte or complete length if
+	 * unaligned address.
+	 */
+	if (len > 4) {
+		for (i = 0; i < (len >> 2); i++) {
+			*(u32 *) dst = musb_readl(fifo, 0);
+			dst += 4;
+		}
+		len &= 0x03;
+	}
+	if (len > 0) {
+		val = musb_readl(fifo, 0);
+		memcpy(dst, &val, len);
+	}
+}
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index b611420..611a9d2 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -342,8 +342,10 @@
 
 	usb_nop_xceiv_register();
 	musb->xceiv = otg_get_transceiver();
-	if (!musb->xceiv)
+	if (!musb->xceiv) {
+		gpio_free(musb->config->gpio_vrsel);
 		return -ENODEV;
+	}
 
 	if (ANOMALY_05000346) {
 		bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
@@ -394,8 +396,9 @@
 
 int musb_platform_exit(struct musb *musb)
 {
-
 	gpio_free(musb->config->gpio_vrsel);
 
+	otg_put_transceiver(musb->xceiv);
+	usb_nop_xceiv_unregister();
 	return 0;
 }
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index 5ab5bb8..f5a65ff 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -1156,7 +1156,7 @@
 	struct musb_hw_ep	*hw_ep = NULL;
 	u32			rx, tx;
 	int			i, index;
-	unsigned long		flags;
+	unsigned long		uninitialized_var(flags);
 
 	cppi = container_of(musb->dma_controller, struct cppi, controller);
 	if (cppi->irq)
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
new file mode 100644
index 0000000..84427be
--- /dev/null
+++ b/drivers/usb/musb/da8xx.c
@@ -0,0 +1,469 @@
+/*
+ * Texas Instruments DA8xx/OMAP-L1x "glue layer"
+ *
+ * Copyright (c) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * Based on the DaVinci "glue layer" code.
+ * Copyright (C) 2005-2006 by Texas Instruments
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ *
+ * The Inventra Controller Driver for Linux is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR 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 Inventra Controller Driver for Linux ; 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/clk.h>
+#include <linux/io.h>
+
+#include <mach/da8xx.h>
+#include <mach/usb.h>
+
+#include "musb_core.h"
+
+/*
+ * DA8XX specific definitions
+ */
+
+/* USB 2.0 OTG module registers */
+#define DA8XX_USB_REVISION_REG	0x00
+#define DA8XX_USB_CTRL_REG	0x04
+#define DA8XX_USB_STAT_REG	0x08
+#define DA8XX_USB_EMULATION_REG 0x0c
+#define DA8XX_USB_MODE_REG	0x10	/* Transparent, CDC, [Generic] RNDIS */
+#define DA8XX_USB_AUTOREQ_REG	0x14
+#define DA8XX_USB_SRP_FIX_TIME_REG 0x18
+#define DA8XX_USB_TEARDOWN_REG	0x1c
+#define DA8XX_USB_INTR_SRC_REG	0x20
+#define DA8XX_USB_INTR_SRC_SET_REG 0x24
+#define DA8XX_USB_INTR_SRC_CLEAR_REG 0x28
+#define DA8XX_USB_INTR_MASK_REG 0x2c
+#define DA8XX_USB_INTR_MASK_SET_REG 0x30
+#define DA8XX_USB_INTR_MASK_CLEAR_REG 0x34
+#define DA8XX_USB_INTR_SRC_MASKED_REG 0x38
+#define DA8XX_USB_END_OF_INTR_REG 0x3c
+#define DA8XX_USB_GENERIC_RNDIS_EP_SIZE_REG(n) (0x50 + (((n) - 1) << 2))
+
+/* Control register bits */
+#define DA8XX_SOFT_RESET_MASK	1
+
+#define DA8XX_USB_TX_EP_MASK	0x1f		/* EP0 + 4 Tx EPs */
+#define DA8XX_USB_RX_EP_MASK	0x1e		/* 4 Rx EPs */
+
+/* USB interrupt register bits */
+#define DA8XX_INTR_USB_SHIFT	16
+#define DA8XX_INTR_USB_MASK	(0x1ff << DA8XX_INTR_USB_SHIFT) /* 8 Mentor */
+					/* interrupts and DRVVBUS interrupt */
+#define DA8XX_INTR_DRVVBUS	0x100
+#define DA8XX_INTR_RX_SHIFT	8
+#define DA8XX_INTR_RX_MASK	(DA8XX_USB_RX_EP_MASK << DA8XX_INTR_RX_SHIFT)
+#define DA8XX_INTR_TX_SHIFT	0
+#define DA8XX_INTR_TX_MASK	(DA8XX_USB_TX_EP_MASK << DA8XX_INTR_TX_SHIFT)
+
+#define DA8XX_MENTOR_CORE_OFFSET 0x400
+
+#define CFGCHIP2	IO_ADDRESS(DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP2_REG)
+
+/*
+ * REVISIT (PM): we should be able to keep the PHY in low power mode most
+ * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0
+ * and, when in host mode, autosuspending idle root ports... PHY_PLLON
+ * (overriding SUSPENDM?) then likely needs to stay off.
+ */
+
+static inline void phy_on(void)
+{
+	u32 cfgchip2 = __raw_readl(CFGCHIP2);
+
+	/*
+	 * Start the on-chip PHY and its PLL.
+	 */
+	cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN);
+	cfgchip2 |= CFGCHIP2_PHY_PLLON;
+	__raw_writel(cfgchip2, CFGCHIP2);
+
+	pr_info("Waiting for USB PHY clock good...\n");
+	while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD))
+		cpu_relax();
+}
+
+static inline void phy_off(void)
+{
+	u32 cfgchip2 = __raw_readl(CFGCHIP2);
+
+	/*
+	 * Ensure that USB 1.1 reference clock is not being sourced from
+	 * USB 2.0 PHY.  Otherwise do not power down the PHY.
+	 */
+	if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX) &&
+	     (cfgchip2 & CFGCHIP2_USB1SUSPENDM)) {
+		pr_warning("USB 1.1 clocked from USB 2.0 PHY -- "
+			   "can't power it down\n");
+		return;
+	}
+
+	/*
+	 * Power down the on-chip PHY.
+	 */
+	cfgchip2 |= CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN;
+	__raw_writel(cfgchip2, CFGCHIP2);
+}
+
+/*
+ * Because we don't set CTRL.UINT, it's "important" to:
+ *	- not read/write INTRUSB/INTRUSBE (except during
+ *	  initial setup, as a workaround);
+ *	- use INTSET/INTCLR instead.
+ */
+
+/**
+ * musb_platform_enable - enable interrupts
+ */
+void musb_platform_enable(struct musb *musb)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+	u32 mask;
+
+	/* Workaround: setup IRQs through both register sets. */
+	mask = ((musb->epmask & DA8XX_USB_TX_EP_MASK) << DA8XX_INTR_TX_SHIFT) |
+	       ((musb->epmask & DA8XX_USB_RX_EP_MASK) << DA8XX_INTR_RX_SHIFT) |
+	       DA8XX_INTR_USB_MASK;
+	musb_writel(reg_base, DA8XX_USB_INTR_MASK_SET_REG, mask);
+
+	/* Force the DRVVBUS IRQ so we can start polling for ID change. */
+	if (is_otg_enabled(musb))
+		musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG,
+			    DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT);
+}
+
+/**
+ * musb_platform_disable - disable HDRC and flush interrupts
+ */
+void musb_platform_disable(struct musb *musb)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+
+	musb_writel(reg_base, DA8XX_USB_INTR_MASK_CLEAR_REG,
+		    DA8XX_INTR_USB_MASK |
+		    DA8XX_INTR_TX_MASK | DA8XX_INTR_RX_MASK);
+	musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+	musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
+}
+
+#ifdef CONFIG_USB_MUSB_HDRC_HCD
+#define portstate(stmt) 	stmt
+#else
+#define portstate(stmt)
+#endif
+
+static void da8xx_set_vbus(struct musb *musb, int is_on)
+{
+	WARN_ON(is_on && is_peripheral_active(musb));
+}
+
+#define	POLL_SECONDS	2
+
+static struct timer_list otg_workaround;
+
+static void otg_timer(unsigned long _musb)
+{
+	struct musb		*musb = (void *)_musb;
+	void __iomem		*mregs = musb->mregs;
+	u8			devctl;
+	unsigned long		flags;
+
+	/*
+	 * We poll because DaVinci's won't expose several OTG-critical
+	 * status change events (from the transceiver) otherwise.
+	 */
+	devctl = musb_readb(mregs, MUSB_DEVCTL);
+	DBG(7, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb));
+
+	spin_lock_irqsave(&musb->lock, flags);
+	switch (musb->xceiv->state) {
+	case OTG_STATE_A_WAIT_BCON:
+		devctl &= ~MUSB_DEVCTL_SESSION;
+		musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+		if (devctl & MUSB_DEVCTL_BDEVICE) {
+			musb->xceiv->state = OTG_STATE_B_IDLE;
+			MUSB_DEV_MODE(musb);
+		} else {
+			musb->xceiv->state = OTG_STATE_A_IDLE;
+			MUSB_HST_MODE(musb);
+		}
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		/*
+		 * Wait till VBUS falls below SessionEnd (~0.2 V); the 1.3
+		 * RTL seems to mis-handle session "start" otherwise (or in
+		 * our case "recover"), in routine "VBUS was valid by the time
+		 * VBUSERR got reported during enumeration" cases.
+		 */
+		if (devctl & MUSB_DEVCTL_VBUS) {
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+			break;
+		}
+		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+		musb_writel(musb->ctrl_base, DA8XX_USB_INTR_SRC_SET_REG,
+			    MUSB_INTR_VBUSERROR << DA8XX_INTR_USB_SHIFT);
+		break;
+	case OTG_STATE_B_IDLE:
+		if (!is_peripheral_enabled(musb))
+			break;
+
+		/*
+		 * There's no ID-changed IRQ, so we have no good way to tell
+		 * when to switch to the A-Default state machine (by setting
+		 * the DEVCTL.Session bit).
+		 *
+		 * Workaround:  whenever we're in B_IDLE, try setting the
+		 * session flag every few seconds.  If it works, ID was
+		 * grounded and we're now in the A-Default state machine.
+		 *
+		 * NOTE: setting the session flag is _supposed_ to trigger
+		 * SRP but clearly it doesn't.
+		 */
+		musb_writeb(mregs, MUSB_DEVCTL, devctl | MUSB_DEVCTL_SESSION);
+		devctl = musb_readb(mregs, MUSB_DEVCTL);
+		if (devctl & MUSB_DEVCTL_BDEVICE)
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+		else
+			musb->xceiv->state = OTG_STATE_A_IDLE;
+		break;
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
+{
+	static unsigned long last_timer;
+
+	if (!is_otg_enabled(musb))
+		return;
+
+	if (timeout == 0)
+		timeout = jiffies + msecs_to_jiffies(3);
+
+	/* Never idle if active, or when VBUS timeout is not set as host */
+	if (musb->is_active || (musb->a_wait_bcon == 0 &&
+				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+		DBG(4, "%s active, deleting timer\n", otg_state_string(musb));
+		del_timer(&otg_workaround);
+		last_timer = jiffies;
+		return;
+	}
+
+	if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) {
+		DBG(4, "Longer idle timer already pending, ignoring...\n");
+		return;
+	}
+	last_timer = timeout;
+
+	DBG(4, "%s inactive, starting idle timer for %u ms\n",
+	    otg_state_string(musb), jiffies_to_msecs(timeout - jiffies));
+	mod_timer(&otg_workaround, timeout);
+}
+
+static irqreturn_t da8xx_interrupt(int irq, void *hci)
+{
+	struct musb		*musb = hci;
+	void __iomem		*reg_base = musb->ctrl_base;
+	unsigned long		flags;
+	irqreturn_t		ret = IRQ_NONE;
+	u32			status;
+
+	spin_lock_irqsave(&musb->lock, flags);
+
+	/*
+	 * NOTE: DA8XX shadows the Mentor IRQs.  Don't manage them through
+	 * the Mentor registers (except for setup), use the TI ones and EOI.
+	 */
+
+	/* Acknowledge and handle non-CPPI interrupts */
+	status = musb_readl(reg_base, DA8XX_USB_INTR_SRC_MASKED_REG);
+	if (!status)
+		goto eoi;
+
+	musb_writel(reg_base, DA8XX_USB_INTR_SRC_CLEAR_REG, status);
+	DBG(4, "USB IRQ %08x\n", status);
+
+	musb->int_rx = (status & DA8XX_INTR_RX_MASK) >> DA8XX_INTR_RX_SHIFT;
+	musb->int_tx = (status & DA8XX_INTR_TX_MASK) >> DA8XX_INTR_TX_SHIFT;
+	musb->int_usb = (status & DA8XX_INTR_USB_MASK) >> DA8XX_INTR_USB_SHIFT;
+
+	/*
+	 * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
+	 * DA8xx's missing ID change IRQ.  We need an ID change IRQ to
+	 * switch appropriately between halves of the OTG state machine.
+	 * Managing DEVCTL.Session per Mentor docs requires that we know its
+	 * value but DEVCTL.BDevice is invalid without DEVCTL.Session set.
+	 * Also, DRVVBUS pulses for SRP (but not at 5 V)...
+	 */
+	if (status & (DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT)) {
+		int drvvbus = musb_readl(reg_base, DA8XX_USB_STAT_REG);
+		void __iomem *mregs = musb->mregs;
+		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
+		int err;
+
+		err = is_host_enabled(musb) && (musb->int_usb &
+						MUSB_INTR_VBUSERROR);
+		if (err) {
+			/*
+			 * The Mentor core doesn't debounce VBUS as needed
+			 * to cope with device connect current spikes. This
+			 * means it's not uncommon for bus-powered devices
+			 * to get VBUS errors during enumeration.
+			 *
+			 * This is a workaround, but newer RTL from Mentor
+			 * seems to allow a better one: "re"-starting sessions
+			 * without waiting for VBUS to stop registering in
+			 * devctl.
+			 */
+			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+			mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+			WARNING("VBUS error workaround (delay coming)\n");
+		} else if (is_host_enabled(musb) && drvvbus) {
+			MUSB_HST_MODE(musb);
+			musb->xceiv->default_a = 1;
+			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+			portstate(musb->port1_status |= USB_PORT_STAT_POWER);
+			del_timer(&otg_workaround);
+		} else {
+			musb->is_active = 0;
+			MUSB_DEV_MODE(musb);
+			musb->xceiv->default_a = 0;
+			musb->xceiv->state = OTG_STATE_B_IDLE;
+			portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
+		}
+
+		DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
+				drvvbus ? "on" : "off",
+				otg_state_string(musb),
+				err ? " ERROR" : "",
+				devctl);
+		ret = IRQ_HANDLED;
+	}
+
+	if (musb->int_tx || musb->int_rx || musb->int_usb)
+		ret |= musb_interrupt(musb);
+
+ eoi:
+	/* EOI needs to be written for the IRQ to be re-asserted. */
+	if (ret == IRQ_HANDLED || status)
+		musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
+
+	/* Poll for ID change */
+	if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
+		mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+
+	spin_unlock_irqrestore(&musb->lock, flags);
+
+	return ret;
+}
+
+int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
+{
+	u32 cfgchip2 = __raw_readl(CFGCHIP2);
+
+	cfgchip2 &= ~CFGCHIP2_OTGMODE;
+	switch (musb_mode) {
+#ifdef	CONFIG_USB_MUSB_HDRC_HCD
+	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
+		cfgchip2 |= CFGCHIP2_FORCE_HOST;
+		break;
+#endif
+#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
+	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
+		cfgchip2 |= CFGCHIP2_FORCE_DEVICE;
+		break;
+#endif
+#ifdef	CONFIG_USB_MUSB_OTG
+	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
+		cfgchip2 |= CFGCHIP2_NO_OVERRIDE;
+		break;
+#endif
+	default:
+		DBG(2, "Trying to set unsupported mode %u\n", musb_mode);
+	}
+
+	__raw_writel(cfgchip2, CFGCHIP2);
+	return 0;
+}
+
+int __init musb_platform_init(struct musb *musb, void *board_data)
+{
+	void __iomem *reg_base = musb->ctrl_base;
+	u32 rev;
+
+	musb->mregs += DA8XX_MENTOR_CORE_OFFSET;
+
+	clk_enable(musb->clock);
+
+	/* Returns zero if e.g. not clocked */
+	rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG);
+	if (!rev)
+		goto fail;
+
+	usb_nop_xceiv_register();
+	musb->xceiv = otg_get_transceiver();
+	if (!musb->xceiv)
+		goto fail;
+
+	if (is_host_enabled(musb))
+		setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);
+
+	musb->board_set_vbus = da8xx_set_vbus;
+
+	/* Reset the controller */
+	musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);
+
+	/* Start the on-chip PHY and its PLL. */
+	phy_on();
+
+	msleep(5);
+
+	/* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */
+	pr_debug("DA8xx OTG revision %08x, PHY %03x, control %02x\n",
+		 rev, __raw_readl(CFGCHIP2),
+		 musb_readb(reg_base, DA8XX_USB_CTRL_REG));
+
+	musb->isr = da8xx_interrupt;
+	return 0;
+fail:
+	clk_disable(musb->clock);
+	return -ENODEV;
+}
+
+int musb_platform_exit(struct musb *musb)
+{
+	if (is_host_enabled(musb))
+		del_timer_sync(&otg_workaround);
+
+	phy_off();
+
+	otg_put_transceiver(musb->xceiv);
+	usb_nop_xceiv_unregister();
+
+	clk_disable(musb->clock);
+
+	return 0;
+}
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 57624361..6e67629 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -446,6 +446,7 @@
 fail:
 	clk_disable(musb->clock);
 
+	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 	return -ENODEV;
 }
@@ -496,6 +497,7 @@
 
 	clk_disable(musb->clock);
 
+	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 
 	return 0;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 540c766..c9f9024 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -272,6 +272,7 @@
 	}
 }
 
+#if !defined(CONFIG_USB_MUSB_AM35X)
 /*
  * Unload an endpoint's FIFO
  */
@@ -309,6 +310,7 @@
 		readsb(fifo, dst, len);
 	}
 }
+#endif
 
 #endif	/* normal PIO */
 
@@ -550,6 +552,11 @@
 	if (int_usb & MUSB_INTR_SESSREQ) {
 		void __iomem *mbase = musb->mregs;
 
+		if (devctl & MUSB_DEVCTL_BDEVICE) {
+			DBG(3, "SessReq while on B state\n");
+			return IRQ_HANDLED;
+		}
+
 		DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb));
 
 		/* IRQ arrives from ID pin sense or (later, if VBUS power
@@ -1921,10 +1928,6 @@
 		dma_controller_destroy(c);
 	}
 
-#ifdef CONFIG_USB_MUSB_OTG
-	put_device(musb->xceiv->dev);
-#endif
-
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
 	usb_put_hcd(musb_to_hcd(musb));
 #else
@@ -2266,6 +2269,7 @@
 {
 	int i;
 	void __iomem *musb_base = musb->mregs;
+	void __iomem *epio;
 
 	if (is_host_enabled(musb)) {
 		musb_context.frame = musb_readw(musb_base, MUSB_FRAME);
@@ -2279,16 +2283,16 @@
 	musb_context.index = musb_readb(musb_base, MUSB_INDEX);
 	musb_context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
 
-	for (i = 0; i < MUSB_C_NUM_EPS; ++i) {
-		musb_writeb(musb_base, MUSB_INDEX, i);
+	for (i = 0; i < musb->config->num_eps; ++i) {
+		epio = musb->endpoints[i].regs;
 		musb_context.index_regs[i].txmaxp =
-			musb_readw(musb_base, 0x10 + MUSB_TXMAXP);
+			musb_readw(epio, MUSB_TXMAXP);
 		musb_context.index_regs[i].txcsr =
-			musb_readw(musb_base, 0x10 + MUSB_TXCSR);
+			musb_readw(epio, MUSB_TXCSR);
 		musb_context.index_regs[i].rxmaxp =
-			musb_readw(musb_base, 0x10 + MUSB_RXMAXP);
+			musb_readw(epio, MUSB_RXMAXP);
 		musb_context.index_regs[i].rxcsr =
-			musb_readw(musb_base, 0x10 + MUSB_RXCSR);
+			musb_readw(epio, MUSB_RXCSR);
 
 		if (musb->dyn_fifo) {
 			musb_context.index_regs[i].txfifoadd =
@@ -2302,13 +2306,13 @@
 		}
 		if (is_host_enabled(musb)) {
 			musb_context.index_regs[i].txtype =
-				musb_readb(musb_base, 0x10 + MUSB_TXTYPE);
+				musb_readb(epio, MUSB_TXTYPE);
 			musb_context.index_regs[i].txinterval =
-				musb_readb(musb_base, 0x10 + MUSB_TXINTERVAL);
+				musb_readb(epio, MUSB_TXINTERVAL);
 			musb_context.index_regs[i].rxtype =
-				musb_readb(musb_base, 0x10 + MUSB_RXTYPE);
+				musb_readb(epio, MUSB_RXTYPE);
 			musb_context.index_regs[i].rxinterval =
-				musb_readb(musb_base, 0x10 + MUSB_RXINTERVAL);
+				musb_readb(epio, MUSB_RXINTERVAL);
 
 			musb_context.index_regs[i].txfunaddr =
 				musb_read_txfunaddr(musb_base, i);
@@ -2326,8 +2330,6 @@
 		}
 	}
 
-	musb_writeb(musb_base, MUSB_INDEX, musb_context.index);
-
 	musb_platform_save_context(musb, &musb_context);
 }
 
@@ -2336,6 +2338,7 @@
 	int i;
 	void __iomem *musb_base = musb->mregs;
 	void __iomem *ep_target_regs;
+	void __iomem *epio;
 
 	musb_platform_restore_context(musb, &musb_context);
 
@@ -2350,15 +2353,15 @@
 	musb_writeb(musb_base, MUSB_INTRUSBE, musb_context.intrusbe);
 	musb_writeb(musb_base, MUSB_DEVCTL, musb_context.devctl);
 
-	for (i = 0; i < MUSB_C_NUM_EPS; ++i) {
-		musb_writeb(musb_base, MUSB_INDEX, i);
-		musb_writew(musb_base, 0x10 + MUSB_TXMAXP,
+	for (i = 0; i < musb->config->num_eps; ++i) {
+		epio = musb->endpoints[i].regs;
+		musb_writew(epio, MUSB_TXMAXP,
 			musb_context.index_regs[i].txmaxp);
-		musb_writew(musb_base, 0x10 + MUSB_TXCSR,
+		musb_writew(epio, MUSB_TXCSR,
 			musb_context.index_regs[i].txcsr);
-		musb_writew(musb_base, 0x10 + MUSB_RXMAXP,
+		musb_writew(epio, MUSB_RXMAXP,
 			musb_context.index_regs[i].rxmaxp);
-		musb_writew(musb_base, 0x10 + MUSB_RXCSR,
+		musb_writew(epio, MUSB_RXCSR,
 			musb_context.index_regs[i].rxcsr);
 
 		if (musb->dyn_fifo) {
@@ -2373,13 +2376,13 @@
 		}
 
 		if (is_host_enabled(musb)) {
-			musb_writeb(musb_base, 0x10 + MUSB_TXTYPE,
+			musb_writeb(epio, MUSB_TXTYPE,
 				musb_context.index_regs[i].txtype);
-			musb_writeb(musb_base, 0x10 + MUSB_TXINTERVAL,
+			musb_writeb(epio, MUSB_TXINTERVAL,
 				musb_context.index_regs[i].txinterval);
-			musb_writeb(musb_base, 0x10 + MUSB_RXTYPE,
+			musb_writeb(epio, MUSB_RXTYPE,
 				musb_context.index_regs[i].rxtype);
-			musb_writeb(musb_base, 0x10 + MUSB_RXINTERVAL,
+			musb_writeb(epio, MUSB_RXINTERVAL,
 
 			musb_context.index_regs[i].rxinterval);
 			musb_write_txfunaddr(musb_base, i,
@@ -2400,8 +2403,6 @@
 				musb_context.index_regs[i].rxhubport);
 		}
 	}
-
-	musb_writeb(musb_base, MUSB_INDEX, musb_context.index);
 }
 
 static int musb_suspend(struct device *dev)
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 91d6779..69797e5 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -330,6 +330,7 @@
 	/* device lock */
 	spinlock_t		lock;
 	struct clk		*clock;
+	struct clk		*phy_clock;
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
 	u16			hwvers;
@@ -599,6 +600,7 @@
 extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode);
 
 #if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \
+	defined(CONFIG_ARCH_DAVINCI_DA8XX) || \
 	defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
 	defined(CONFIG_ARCH_OMAP4)
 extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout);
diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h
index d73afdb..94f6973 100644
--- a/drivers/usb/musb/musb_debug.h
+++ b/drivers/usb/musb/musb_debug.h
@@ -42,11 +42,10 @@
 #define INFO(fmt, args...) yprintk(KERN_INFO, fmt, ## args)
 #define ERR(fmt, args...) yprintk(KERN_ERR, fmt, ## args)
 
-#define xprintk(level, facility, format, args...) do { \
-	if (_dbg_level(level)) { \
-		printk(facility "%s %d: " format , \
-				__func__, __LINE__ , ## args); \
-	} } while (0)
+#define DBG(level, format, args...) do { \
+	if (_dbg_level(level)) \
+		pr_debug("%s %d: " format, __func__, __LINE__, ## args); \
+	} while (0)
 
 extern unsigned musb_debug;
 
@@ -55,8 +54,6 @@
 	return musb_debug >= l;
 }
 
-#define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args)
-
 extern const char *otg_state_string(struct musb *);
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index d065e23..5d81504 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -337,13 +337,15 @@
 					csr |= (MUSB_TXCSR_DMAENAB |
 							MUSB_TXCSR_MODE);
 					/* against programming guide */
-				} else
-					csr |= (MUSB_TXCSR_AUTOSET
-							| MUSB_TXCSR_DMAENAB
+				} else {
+					csr |= (MUSB_TXCSR_DMAENAB
 							| MUSB_TXCSR_DMAMODE
 							| MUSB_TXCSR_MODE);
-
+					if (!musb_ep->hb_mult)
+						csr |= MUSB_TXCSR_AUTOSET;
+				}
 				csr &= ~MUSB_TXCSR_P_UNDERRUN;
+
 				musb_writew(epio, MUSB_TXCSR, csr);
 			}
 		}
@@ -475,40 +477,39 @@
 				epnum, csr, musb_ep->dma->actual_len, request);
 		}
 
-		if (is_dma || request->actual == request->length) {
-			/*
-			 * First, maybe a terminating short packet. Some DMA
-			 * engines might handle this by themselves.
-			 */
-			if ((request->zero && request->length
-				&& request->length % musb_ep->packet_sz == 0)
+		/*
+		 * First, maybe a terminating short packet. Some DMA
+		 * engines might handle this by themselves.
+		 */
+		if ((request->zero && request->length
+			&& (request->length % musb_ep->packet_sz == 0)
+			&& (request->actual == request->length))
 #ifdef CONFIG_USB_INVENTRA_DMA
-				|| (is_dma && (!dma->desired_mode ||
-					(request->actual &
-						(musb_ep->packet_sz - 1))))
+			|| (is_dma && (!dma->desired_mode ||
+				(request->actual &
+					(musb_ep->packet_sz - 1))))
 #endif
-			) {
-				/*
-				 * On DMA completion, FIFO may not be
-				 * available yet...
-				 */
-				if (csr & MUSB_TXCSR_TXPKTRDY)
-					return;
+		) {
+			/*
+			 * On DMA completion, FIFO may not be
+			 * available yet...
+			 */
+			if (csr & MUSB_TXCSR_TXPKTRDY)
+				return;
 
-				DBG(4, "sending zero pkt\n");
-				musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE
-						| MUSB_TXCSR_TXPKTRDY);
-				request->zero = 0;
-			}
+			DBG(4, "sending zero pkt\n");
+			musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE
+					| MUSB_TXCSR_TXPKTRDY);
+			request->zero = 0;
+		}
 
-			if (request->actual == request->length) {
-				musb_g_giveback(musb_ep, request, 0);
-				request = musb_ep->desc ? next_request(musb_ep) : NULL;
-				if (!request) {
-					DBG(4, "%s idle now\n",
-						musb_ep->end_point.name);
-					return;
-				}
+		if (request->actual == request->length) {
+			musb_g_giveback(musb_ep, request, 0);
+			request = musb_ep->desc ? next_request(musb_ep) : NULL;
+			if (!request) {
+				DBG(4, "%s idle now\n",
+					musb_ep->end_point.name);
+				return;
 			}
 		}
 
@@ -643,7 +644,9 @@
 	 */
 
 				csr |= MUSB_RXCSR_DMAENAB;
-				csr |= MUSB_RXCSR_AUTOCLEAR;
+				if (!musb_ep->hb_mult &&
+					musb_ep->hw_ep->rx_double_buffered)
+					csr |= MUSB_RXCSR_AUTOCLEAR;
 #ifdef USE_MODE1
 				/* csr |= MUSB_RXCSR_DMAMODE; */
 
@@ -772,7 +775,7 @@
 		musb_writew(epio, MUSB_RXCSR, csr);
 
 		DBG(3, "%s iso overrun on %p\n", musb_ep->name, request);
-		if (request && request->status == -EINPROGRESS)
+		if (request->status == -EINPROGRESS)
 			request->status = -EOVERFLOW;
 	}
 	if (csr & MUSB_RXCSR_INCOMPRX) {
@@ -825,14 +828,8 @@
 			return;
 	}
 
-	/* analyze request if the ep is hot */
-	if (request)
-		rxstate(musb, to_musb_request(request));
-	else
-		DBG(3, "packet waiting for %s%s request\n",
-				musb_ep->desc ? "" : "inactive ",
-				musb_ep->end_point.name);
-	return;
+	/* Analyze request */
+	rxstate(musb, to_musb_request(request));
 }
 
 /* ------------------------------------------------------------ */
@@ -875,9 +872,25 @@
 
 	/* REVISIT this rules out high bandwidth periodic transfers */
 	tmp = le16_to_cpu(desc->wMaxPacketSize);
-	if (tmp & ~0x07ff)
-		goto fail;
-	musb_ep->packet_sz = tmp;
+	if (tmp & ~0x07ff) {
+		int ok;
+
+		if (usb_endpoint_dir_in(desc))
+			ok = musb->hb_iso_tx;
+		else
+			ok = musb->hb_iso_rx;
+
+		if (!ok) {
+			DBG(4, "%s: not support ISO high bandwidth\n", __func__);
+			goto fail;
+		}
+		musb_ep->hb_mult = (tmp >> 11) & 3;
+	} else {
+		musb_ep->hb_mult = 0;
+	}
+
+	musb_ep->packet_sz = tmp & 0x7ff;
+	tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1);
 
 	/* enable the interrupts for the endpoint, set the endpoint
 	 * packet size (or fail), set the mode, clear the fifo
@@ -890,8 +903,11 @@
 			musb_ep->is_in = 1;
 		if (!musb_ep->is_in)
 			goto fail;
-		if (tmp > hw_ep->max_packet_sz_tx)
+
+		if (tmp > hw_ep->max_packet_sz_tx) {
+			DBG(4, "%s: packet size beyond hw fifo size\n", __func__);
 			goto fail;
+		}
 
 		int_txe |= (1 << epnum);
 		musb_writew(mbase, MUSB_INTRTXE, int_txe);
@@ -906,7 +922,7 @@
 		if (musb->hwvers < MUSB_HWVERS_2000)
 			musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx);
 		else
-			musb_writew(regs, MUSB_TXMAXP, tmp);
+			musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
 
 		csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
 		if (musb_readw(regs, MUSB_TXCSR)
@@ -927,8 +943,11 @@
 			musb_ep->is_in = 0;
 		if (musb_ep->is_in)
 			goto fail;
-		if (tmp > hw_ep->max_packet_sz_rx)
+
+		if (tmp > hw_ep->max_packet_sz_rx) {
+			DBG(4, "%s: packet size beyond hw fifo size\n", __func__);
 			goto fail;
+		}
 
 		int_rxe |= (1 << epnum);
 		musb_writew(mbase, MUSB_INTRRXE, int_rxe);
@@ -942,7 +961,7 @@
 		if (musb->hwvers < MUSB_HWVERS_2000)
 			musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx);
 		else
-			musb_writew(regs, MUSB_RXMAXP, tmp);
+			musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
 
 		/* force shared fifo to OUT-only mode */
 		if (hw_ep->is_shared_fifo) {
@@ -1699,9 +1718,11 @@
  * -ENOMEM no memeory to perform the operation
  *
  * @param driver the gadget driver
+ * @param bind the driver's bind function
  * @return <0 if error, 0 if everything is fine
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
 {
 	int retval;
 	unsigned long flags;
@@ -1709,8 +1730,7 @@
 
 	if (!driver
 			|| driver->speed != USB_SPEED_HIGH
-			|| !driver->bind
-			|| !driver->setup)
+			|| !bind || !driver->setup)
 		return -EINVAL;
 
 	/* driver must be initialized to support peripheral mode */
@@ -1738,7 +1758,7 @@
 	spin_unlock_irqrestore(&musb->lock, flags);
 
 	if (retval == 0) {
-		retval = driver->bind(&musb->g);
+		retval = bind(&musb->g);
 		if (retval != 0) {
 			DBG(3, "bind to driver %s failed --> %d\n",
 					driver->driver.name, retval);
@@ -1786,7 +1806,7 @@
 
 	return retval;
 }
-EXPORT_SYMBOL(usb_gadget_register_driver);
+EXPORT_SYMBOL(usb_gadget_probe_driver);
 
 static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
 {
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h
index 572b1da..dec8dc0 100644
--- a/drivers/usb/musb/musb_gadget.h
+++ b/drivers/usb/musb/musb_gadget.h
@@ -79,6 +79,8 @@
 
 	/* true if lock must be dropped but req_list may not be advanced */
 	u8				busy;
+
+	u8				hb_mult;
 };
 
 static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 9e65c47..4d5bcb4 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -41,6 +41,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/list.h>
+#include <linux/dma-mapping.h>
 
 #include "musb_core.h"
 #include "musb_host.h"
@@ -1119,6 +1120,7 @@
 	u32			status = 0;
 	void __iomem		*mbase = musb->mregs;
 	struct dma_channel	*dma;
+	bool			transfer_pending = false;
 
 	musb_ep_select(mbase, epnum);
 	tx_csr = musb_readw(epio, MUSB_TXCSR);
@@ -1279,7 +1281,7 @@
 				offset = d->offset;
 				length = d->length;
 			}
-		} else if (dma) {
+		} else if (dma && urb->transfer_buffer_length == qh->offset) {
 			done = true;
 		} else {
 			/* see if we need to send more data, or ZLP */
@@ -1292,6 +1294,7 @@
 			if (!done) {
 				offset = qh->offset;
 				length = urb->transfer_buffer_length - offset;
+				transfer_pending = true;
 			}
 		}
 	}
@@ -1311,7 +1314,7 @@
 		urb->actual_length = qh->offset;
 		musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
 		return;
-	} else	if (usb_pipeisoc(pipe) && dma) {
+	} else if ((usb_pipeisoc(pipe) || transfer_pending) && dma) {
 		if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb,
 				offset, length)) {
 			if (is_cppi_enabled() || tusb_dma_omap())
@@ -1332,6 +1335,8 @@
 	 */
 	if (length > qh->maxpacket)
 		length = qh->maxpacket;
+	/* Unmap the buffer so that CPU can use it */
+	unmap_urb_for_dma(musb_to_hcd(musb), urb);
 	musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
 	qh->segsize = length;
 
@@ -1752,6 +1757,8 @@
 #endif	/* Mentor DMA */
 
 		if (!dma) {
+			/* Unmap the buffer so that CPU can use it */
+			unmap_urb_for_dma(musb_to_hcd(musb), urb);
 			done = musb_host_packet_rx(musb, urb,
 					epnum, iso_err);
 			DBG(6, "read %spacket\n", done ? "last " : "");
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index 6dc107f..6f771af 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -91,7 +91,7 @@
 			channel = &(musb_channel->channel);
 			channel->private_data = musb_channel;
 			channel->status = MUSB_DMA_STATUS_FREE;
-			channel->max_len = 0x10000;
+			channel->max_len = 0x100000;
 			/* Tx => mode 1; Rx => mode 0 */
 			channel->desired_mode = transmit;
 			channel->actual_len = 0;
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 2111a24..ed618bd 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -320,5 +320,6 @@
 
 	musb_platform_suspend(musb);
 
+	otg_put_transceiver(musb->xceiv);
 	return 0;
 }
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 3c48e77..bde40ef 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1152,6 +1152,8 @@
 	if (ret < 0) {
 		if (sync)
 			iounmap(sync);
+
+		otg_put_transceiver(musb->xceiv);
 		usb_nop_xceiv_unregister();
 	}
 	return ret;
@@ -1166,6 +1168,8 @@
 		musb->board_set_power(0);
 
 	iounmap(musb->sync_va);
+
+	otg_put_transceiver(musb->xceiv);
 	usb_nop_xceiv_unregister();
 	return 0;
 }
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 3b12895..5ce0752 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -67,4 +67,18 @@
 	 built-in with usb ip or which are autonomous and doesn't require any
 	 phy programming such as ISP1x04 etc.
 
+config USB_LANGWELL_OTG
+	tristate "Intel Langwell USB OTG dual-role support"
+	depends on USB && PCI && INTEL_SCU_IPC
+	select USB_OTG
+	select USB_OTG_UTILS
+	help
+	  Say Y here if you want to build Intel Langwell USB OTG
+	  transciever driver in kernel. This driver implements role
+	  switch between EHCI host driver and Langwell USB OTG
+	  client driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called langwell_otg.
+
 endif # USB || OTG
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index aeb49a8..66f1b83 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -2,6 +2,9 @@
 # OTG infrastructure and transceiver drivers
 #
 
+ccflags-$(CONFIG_USB_DEBUG)		:= -DDEBUG
+ccflags-$(CONFIG_USB_GADGET_DEBUG)	+= -DDEBUG
+
 # infrastructure
 obj-$(CONFIG_USB_OTG_UTILS)	+= otg.o
 
@@ -9,9 +12,6 @@
 obj-$(CONFIG_USB_GPIO_VBUS)	+= gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
+obj-$(CONFIG_USB_LANGWELL_OTG)	+= langwell_otg.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 obj-$(CONFIG_USB_ULPI)		+= ulpi.o
-
-ccflags-$(CONFIG_USB_DEBUG)	+= -DDEBUG
-ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG
-
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c
new file mode 100644
index 0000000..bdc3ea6
--- /dev/null
+++ b/drivers/usb/otg/langwell_otg.c
@@ -0,0 +1,2408 @@
+/*
+ * Intel Langwell USB OTG transceiver driver
+ * Copyright (C) 2008 - 2010, 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+/* This driver helps to switch Langwell OTG controller function between host
+ * and peripheral. It works with EHCI driver and Langwell client controller
+ * driver together.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/hcd.h>
+#include <linux/notifier.h>
+#include <linux/delay.h>
+#include <asm/intel_scu_ipc.h>
+
+#include <linux/usb/langwell_otg.h>
+
+#define	DRIVER_DESC		"Intel Langwell USB OTG transceiver driver"
+#define	DRIVER_VERSION		"July 10, 2010"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+static const char driver_name[] = "langwell_otg";
+
+static int langwell_otg_probe(struct pci_dev *pdev,
+			const struct pci_device_id *id);
+static void langwell_otg_remove(struct pci_dev *pdev);
+static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message);
+static int langwell_otg_resume(struct pci_dev *pdev);
+
+static int langwell_otg_set_host(struct otg_transceiver *otg,
+				struct usb_bus *host);
+static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
+				struct usb_gadget *gadget);
+static int langwell_otg_start_srp(struct otg_transceiver *otg);
+
+static const struct pci_device_id pci_ids[] = {{
+	.class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+	.class_mask =   ~0,
+	.vendor =	0x8086,
+	.device =	0x0811,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+}, { /* end: all zeroes */ }
+};
+
+static struct pci_driver otg_pci_driver = {
+	.name =		(char *) driver_name,
+	.id_table =	pci_ids,
+
+	.probe =	langwell_otg_probe,
+	.remove =	langwell_otg_remove,
+
+	.suspend =	langwell_otg_suspend,
+	.resume =	langwell_otg_resume,
+};
+
+static const char *state_string(enum usb_otg_state state)
+{
+	switch (state) {
+	case OTG_STATE_A_IDLE:
+		return "a_idle";
+	case OTG_STATE_A_WAIT_VRISE:
+		return "a_wait_vrise";
+	case OTG_STATE_A_WAIT_BCON:
+		return "a_wait_bcon";
+	case OTG_STATE_A_HOST:
+		return "a_host";
+	case OTG_STATE_A_SUSPEND:
+		return "a_suspend";
+	case OTG_STATE_A_PERIPHERAL:
+		return "a_peripheral";
+	case OTG_STATE_A_WAIT_VFALL:
+		return "a_wait_vfall";
+	case OTG_STATE_A_VBUS_ERR:
+		return "a_vbus_err";
+	case OTG_STATE_B_IDLE:
+		return "b_idle";
+	case OTG_STATE_B_SRP_INIT:
+		return "b_srp_init";
+	case OTG_STATE_B_PERIPHERAL:
+		return "b_peripheral";
+	case OTG_STATE_B_WAIT_ACON:
+		return "b_wait_acon";
+	case OTG_STATE_B_HOST:
+		return "b_host";
+	default:
+		return "UNDEFINED";
+	}
+}
+
+/* HSM timers */
+static inline struct langwell_otg_timer *otg_timer_initializer
+(void (*function)(unsigned long), unsigned long expires, unsigned long data)
+{
+	struct langwell_otg_timer *timer;
+	timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL);
+	if (timer == NULL)
+		return timer;
+
+	timer->function = function;
+	timer->expires = expires;
+	timer->data = data;
+	return timer;
+}
+
+static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr,
+	*b_se0_srp_tmr, *b_srp_init_tmr;
+
+static struct list_head active_timers;
+
+static struct langwell_otg *the_transceiver;
+
+/* host/client notify transceiver when event affects HNP state */
+void langwell_update_transceiver(void)
+{
+	struct langwell_otg *lnw = the_transceiver;
+
+	dev_dbg(lnw->dev, "transceiver is updated\n");
+
+	if (!lnw->qwork)
+		return ;
+
+	queue_work(lnw->qwork, &lnw->work);
+}
+EXPORT_SYMBOL(langwell_update_transceiver);
+
+static int langwell_otg_set_host(struct otg_transceiver *otg,
+					struct usb_bus *host)
+{
+	otg->host = host;
+
+	return 0;
+}
+
+static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
+					struct usb_gadget *gadget)
+{
+	otg->gadget = gadget;
+
+	return 0;
+}
+
+static int langwell_otg_set_power(struct otg_transceiver *otg,
+				unsigned mA)
+{
+	return 0;
+}
+
+/* A-device drives vbus, controlled through PMIC CHRGCNTL register*/
+static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	u8 r;
+
+	dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off");
+
+	/* FIXME: surely we should cache this on the first read. If not use
+	   readv to avoid two transactions */
+	if (intel_scu_ipc_ioread8(0x00, &r) < 0) {
+		dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2");
+		return -EBUSY;
+	}
+	if ((r & 0x03) != 0x02) {
+		dev_dbg(lnw->dev, "not NEC PMIC attached\n");
+		return -EBUSY;
+	}
+
+	if (intel_scu_ipc_ioread8(0x20, &r) < 0) {
+		dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2");
+		return -EBUSY;
+	}
+
+	if ((r & 0x20) == 0) {
+		dev_dbg(lnw->dev, "no battery attached\n");
+		return -EBUSY;
+	}
+
+	/* Workaround for battery attachment issue */
+	if (r == 0x34) {
+		dev_dbg(lnw->dev, "no battery attached on SH\n");
+		return -EBUSY;
+	}
+
+	dev_dbg(lnw->dev, "battery attached. 2 reg = %x\n", r);
+
+	/* workaround: FW detect writing 0x20/0xc0 to d4 event.
+	 * this is only for NEC PMIC.
+	 */
+
+	if (intel_scu_ipc_iowrite8(0xD4, enabled ? 0x20 : 0xC0))
+		dev_dbg(lnw->dev, "Failed to write PMIC.\n");
+
+	dev_dbg(lnw->dev, "%s --->\n", __func__);
+
+	return 0;
+}
+
+/* charge vbus or discharge vbus through a resistor to ground */
+static void langwell_otg_chrg_vbus(int on)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	u32	val;
+
+	val = readl(lnw->iotg.base + CI_OTGSC);
+
+	if (on)
+		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC,
+				lnw->iotg.base + CI_OTGSC);
+	else
+		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD,
+				lnw->iotg.base + CI_OTGSC);
+}
+
+/* Start SRP */
+static int langwell_otg_start_srp(struct otg_transceiver *otg)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val;
+
+	dev_dbg(lnw->dev, "%s --->\n", __func__);
+
+	val = readl(iotg->base + CI_OTGSC);
+
+	writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP,
+				iotg->base + CI_OTGSC);
+
+	/* Check if the data plus is finished or not */
+	msleep(8);
+	val = readl(iotg->base + CI_OTGSC);
+	if (val & (OTGSC_HADP | OTGSC_DP))
+		dev_dbg(lnw->dev, "DataLine SRP Error\n");
+
+	/* Disable interrupt - b_sess_vld */
+	val = readl(iotg->base + CI_OTGSC);
+	val &= (~(OTGSC_BSVIE | OTGSC_BSEIE));
+	writel(val, iotg->base + CI_OTGSC);
+
+	/* Start VBus SRP, drive vbus to generate VBus pulse */
+	iotg->otg.set_vbus(&iotg->otg, true);
+	msleep(15);
+	iotg->otg.set_vbus(&iotg->otg, false);
+
+	/* Enable interrupt - b_sess_vld*/
+	val = readl(iotg->base + CI_OTGSC);
+	dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val);
+
+	val |= (OTGSC_BSVIE | OTGSC_BSEIE);
+	writel(val, iotg->base + CI_OTGSC);
+
+	/* If Vbus is valid, then update the hsm */
+	if (val & OTGSC_BSV) {
+		dev_dbg(lnw->dev, "no b_sess_vld interrupt\n");
+
+		lnw->iotg.hsm.b_sess_vld = 1;
+		langwell_update_transceiver();
+	}
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+	return 0;
+}
+
+/* stop SOF via bus_suspend */
+static void langwell_otg_loc_sof(int on)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	struct usb_hcd		*hcd;
+	int			err;
+
+	dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume");
+
+	hcd = bus_to_hcd(lnw->iotg.otg.host);
+	if (on)
+		err = hcd->driver->bus_resume(hcd);
+	else
+		err = hcd->driver->bus_suspend(hcd);
+
+	if (err)
+		dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err);
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+}
+
+static int langwell_otg_check_otgsc(void)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	u32				otgsc, usbcfg;
+
+	dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n");
+
+	otgsc = readl(lnw->iotg.base + CI_OTGSC);
+	usbcfg = readl(lnw->usbcfg);
+
+	dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n",
+					otgsc, usbcfg);
+	dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV));
+	dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n",
+					!!(usbcfg & USBCFG_VBUSVAL));
+	dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV));
+	dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n",
+					!!(usbcfg & USBCFG_AVALID));
+	dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV));
+	dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n",
+					!!(usbcfg & USBCFG_BVALID));
+	dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE));
+	dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n",
+					!!(usbcfg & USBCFG_SESEND));
+
+	/* Check USBCFG VBusValid/AValid/BValid/SessEnd */
+	if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) {
+		dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n");
+		goto err;
+	}
+	if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) {
+		dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n");
+		goto err;
+	}
+	if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) {
+		dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n");
+		goto err;
+	}
+	if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) {
+		dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n");
+		goto err;
+	}
+
+	dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n");
+
+	return 0;
+
+err:
+	dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n");
+	return -EPIPE;
+}
+
+
+static void langwell_otg_phy_low_power(int on)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u8				val, phcd;
+	int				retval;
+
+	dev_dbg(lnw->dev, "%s ---> %s mode\n",
+			__func__, on ? "Low power" : "Normal");
+
+	phcd = 0x40;
+
+	val = readb(iotg->base + CI_HOSTPC1 + 2);
+
+	if (on) {
+		/* Due to hardware issue, after set PHCD, sync will failed
+		 * between USBCFG and OTGSC, so before set PHCD, check if
+		 * sync is in process now. If the answer is "yes", then do
+		 * not touch PHCD bit */
+		retval = langwell_otg_check_otgsc();
+		if (retval) {
+			dev_dbg(lnw->dev, "Skip PHCD programming..\n");
+			return ;
+		}
+
+		writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2);
+	} else
+		writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2);
+
+	dev_dbg(lnw->dev, "%s <--- done\n", __func__);
+}
+
+/* After drv vbus, add 2 ms delay to set PHCD */
+static void langwell_otg_phy_low_power_wait(int on)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+
+	dev_dbg(lnw->dev, "add 2ms delay before programing PHCD\n");
+
+	mdelay(2);
+	langwell_otg_phy_low_power(on);
+}
+
+/* Enable/Disable OTG interrupt */
+static void langwell_otg_intr(int on)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val;
+
+	dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
+
+	val = readl(iotg->base + CI_OTGSC);
+
+	/* OTGSC_INT_MASK doesn't contains 1msInt */
+	if (on) {
+		val = val | (OTGSC_INT_MASK);
+		writel(val, iotg->base + CI_OTGSC);
+	} else {
+		val = val & ~(OTGSC_INT_MASK);
+		writel(val, iotg->base + CI_OTGSC);
+	}
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+}
+
+/* set HAAR: Hardware Assist Auto-Reset */
+static void langwell_otg_HAAR(int on)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val;
+
+	dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
+
+	val = readl(iotg->base + CI_OTGSC);
+	if (on)
+		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR,
+					iotg->base + CI_OTGSC);
+	else
+		writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR,
+					iotg->base + CI_OTGSC);
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+}
+
+/* set HABA: Hardware Assist B-Disconnect to A-Connect */
+static void langwell_otg_HABA(int on)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val;
+
+	dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
+
+	val = readl(iotg->base + CI_OTGSC);
+	if (on)
+		writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA,
+					iotg->base + CI_OTGSC);
+	else
+		writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA,
+					iotg->base + CI_OTGSC);
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+}
+
+static int langwell_otg_check_se0_srp(int on)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	int			delay_time = TB_SE0_SRP * 10;
+	u32			val;
+
+	dev_dbg(lnw->dev, "%s --->\n", __func__);
+
+	do {
+		udelay(100);
+		if (!delay_time--)
+			break;
+		val = readl(lnw->iotg.base + CI_PORTSC1);
+		val &= PORTSC_LS;
+	} while (!val);
+
+	dev_dbg(lnw->dev, "%s <---\n", __func__);
+	return val;
+}
+
+/* The timeout callback function to set time out bit */
+static void set_tmout(unsigned long indicator)
+{
+	*(int *)indicator = 1;
+}
+
+void langwell_otg_nsf_msg(unsigned long indicator)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+
+	switch (indicator) {
+	case 2:
+	case 4:
+	case 6:
+	case 7:
+		dev_warn(lnw->dev,
+			"OTG:NSF-%lu - deivce not responding\n", indicator);
+		break;
+	case 3:
+		dev_warn(lnw->dev,
+			"OTG:NSF-%lu - deivce not supported\n", indicator);
+		break;
+	default:
+		dev_warn(lnw->dev, "Do not have this kind of NSF\n");
+		break;
+	}
+}
+
+/* Initialize timers */
+static int langwell_otg_init_timers(struct otg_hsm *hsm)
+{
+	/* HSM used timers */
+	a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
+				(unsigned long)&hsm->a_wait_vrise_tmout);
+	if (a_wait_vrise_tmr == NULL)
+		return -ENOMEM;
+	a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
+				(unsigned long)&hsm->a_aidl_bdis_tmout);
+	if (a_aidl_bdis_tmr == NULL)
+		return -ENOMEM;
+	b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
+				(unsigned long)&hsm->b_se0_srp);
+	if (b_se0_srp_tmr == NULL)
+		return -ENOMEM;
+	b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT,
+				(unsigned long)&hsm->b_srp_init_tmout);
+	if (b_srp_init_tmr == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/* Free timers */
+static void langwell_otg_free_timers(void)
+{
+	kfree(a_wait_vrise_tmr);
+	kfree(a_aidl_bdis_tmr);
+	kfree(b_se0_srp_tmr);
+	kfree(b_srp_init_tmr);
+}
+
+/* The timeout callback function to set time out bit */
+static void langwell_otg_timer_fn(unsigned long indicator)
+{
+	struct langwell_otg *lnw = the_transceiver;
+
+	*(int *)indicator = 1;
+
+	dev_dbg(lnw->dev, "kernel timer - timeout\n");
+
+	langwell_update_transceiver();
+}
+
+/* kernel timer used instead of HW based interrupt */
+static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	unsigned long		j = jiffies;
+	unsigned long		data, time;
+
+	switch (timers) {
+	case TA_WAIT_VRISE_TMR:
+		iotg->hsm.a_wait_vrise_tmout = 0;
+		data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout;
+		time = TA_WAIT_VRISE;
+		break;
+	case TA_WAIT_BCON_TMR:
+		iotg->hsm.a_wait_bcon_tmout = 0;
+		data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout;
+		time = TA_WAIT_BCON;
+		break;
+	case TA_AIDL_BDIS_TMR:
+		iotg->hsm.a_aidl_bdis_tmout = 0;
+		data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout;
+		time = TA_AIDL_BDIS;
+		break;
+	case TB_ASE0_BRST_TMR:
+		iotg->hsm.b_ase0_brst_tmout = 0;
+		data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout;
+		time = TB_ASE0_BRST;
+		break;
+	case TB_SRP_INIT_TMR:
+		iotg->hsm.b_srp_init_tmout = 0;
+		data = (unsigned long)&iotg->hsm.b_srp_init_tmout;
+		time = TB_SRP_INIT;
+		break;
+	case TB_SRP_FAIL_TMR:
+		iotg->hsm.b_srp_fail_tmout = 0;
+		data = (unsigned long)&iotg->hsm.b_srp_fail_tmout;
+		time = TB_SRP_FAIL;
+		break;
+	case TB_BUS_SUSPEND_TMR:
+		iotg->hsm.b_bus_suspend_tmout = 0;
+		data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout;
+		time = TB_BUS_SUSPEND;
+		break;
+	default:
+		dev_dbg(lnw->dev, "unkown timer, cannot enable it\n");
+		return;
+	}
+
+	lnw->hsm_timer.data = data;
+	lnw->hsm_timer.function = langwell_otg_timer_fn;
+	lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */
+
+	add_timer(&lnw->hsm_timer);
+
+	dev_dbg(lnw->dev, "add timer successfully\n");
+}
+
+/* Add timer to timer list */
+static void langwell_otg_add_timer(void *gtimer)
+{
+	struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
+	struct langwell_otg_timer *tmp_timer;
+	struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg;
+	u32	val32;
+
+	/* Check if the timer is already in the active list,
+	 * if so update timer count
+	 */
+	list_for_each_entry(tmp_timer, &active_timers, list)
+		if (tmp_timer == timer) {
+			timer->count = timer->expires;
+			return;
+		}
+	timer->count = timer->expires;
+
+	if (list_empty(&active_timers)) {
+		val32 = readl(iotg->base + CI_OTGSC);
+		writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC);
+	}
+
+	list_add_tail(&timer->list, &active_timers);
+}
+
+/* Remove timer from the timer list; clear timeout status */
+static void langwell_otg_del_timer(void *gtimer)
+{
+	struct langwell_otg *lnw = the_transceiver;
+	struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
+	struct langwell_otg_timer *tmp_timer, *del_tmp;
+	u32 val32;
+
+	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
+		if (tmp_timer == timer)
+			list_del(&timer->list);
+
+	if (list_empty(&active_timers)) {
+		val32 = readl(lnw->iotg.base + CI_OTGSC);
+		writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC);
+	}
+}
+
+/* Reduce timer count by 1, and find timeout conditions.*/
+static int langwell_otg_tick_timer(u32 *int_sts)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	struct langwell_otg_timer *tmp_timer, *del_tmp;
+	int expired = 0;
+
+	list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
+		tmp_timer->count--;
+		/* check if timer expires */
+		if (!tmp_timer->count) {
+			list_del(&tmp_timer->list);
+			tmp_timer->function(tmp_timer->data);
+			expired = 1;
+		}
+	}
+
+	if (list_empty(&active_timers)) {
+		dev_dbg(lnw->dev, "tick timer: disable 1ms int\n");
+		*int_sts = *int_sts & ~OTGSC_1MSE;
+	}
+	return expired;
+}
+
+static void reset_otg(void)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	int			delay_time = 1000;
+	u32			val;
+
+	dev_dbg(lnw->dev, "reseting OTG controller ...\n");
+	val = readl(lnw->iotg.base + CI_USBCMD);
+	writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD);
+	do {
+		udelay(100);
+		if (!delay_time--)
+			dev_dbg(lnw->dev, "reset timeout\n");
+		val = readl(lnw->iotg.base + CI_USBCMD);
+		val &= USBCMD_RST;
+	} while (val != 0);
+	dev_dbg(lnw->dev, "reset done.\n");
+}
+
+static void set_host_mode(void)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	u32			val;
+
+	reset_otg();
+	val = readl(lnw->iotg.base + CI_USBMODE);
+	val = (val & (~USBMODE_CM)) | USBMODE_HOST;
+	writel(val, lnw->iotg.base + CI_USBMODE);
+}
+
+static void set_client_mode(void)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	u32			val;
+
+	reset_otg();
+	val = readl(lnw->iotg.base + CI_USBMODE);
+	val = (val & (~USBMODE_CM)) | USBMODE_DEVICE;
+	writel(val, lnw->iotg.base + CI_USBMODE);
+}
+
+static void init_hsm(void)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val32;
+
+	/* read OTGSC after reset */
+	val32 = readl(lnw->iotg.base + CI_OTGSC);
+	dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32);
+
+	/* set init state */
+	if (val32 & OTGSC_ID) {
+		iotg->hsm.id = 1;
+		iotg->otg.default_a = 0;
+		set_client_mode();
+		iotg->otg.state = OTG_STATE_B_IDLE;
+	} else {
+		iotg->hsm.id = 0;
+		iotg->otg.default_a = 1;
+		set_host_mode();
+		iotg->otg.state = OTG_STATE_A_IDLE;
+	}
+
+	/* set session indicator */
+	if (val32 & OTGSC_BSE)
+		iotg->hsm.b_sess_end = 1;
+	if (val32 & OTGSC_BSV)
+		iotg->hsm.b_sess_vld = 1;
+	if (val32 & OTGSC_ASV)
+		iotg->hsm.a_sess_vld = 1;
+	if (val32 & OTGSC_AVV)
+		iotg->hsm.a_vbus_vld = 1;
+
+	/* defautly power the bus */
+	iotg->hsm.a_bus_req = 1;
+	iotg->hsm.a_bus_drop = 0;
+	/* defautly don't request bus as B device */
+	iotg->hsm.b_bus_req = 0;
+	/* no system error */
+	iotg->hsm.a_clr_err = 0;
+
+	langwell_otg_phy_low_power_wait(1);
+}
+
+static void update_hsm(void)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				val32;
+
+	/* read OTGSC */
+	val32 = readl(lnw->iotg.base + CI_OTGSC);
+	dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32);
+
+	iotg->hsm.id = !!(val32 & OTGSC_ID);
+	iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE);
+	iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV);
+	iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV);
+	iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV);
+}
+
+static irqreturn_t otg_dummy_irq(int irq, void *_dev)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	void __iomem		*reg_base = _dev;
+	u32			val;
+	u32			int_mask = 0;
+
+	val = readl(reg_base + CI_USBMODE);
+	if ((val & USBMODE_CM) != USBMODE_DEVICE)
+		return IRQ_NONE;
+
+	val = readl(reg_base + CI_USBSTS);
+	int_mask = val & INTR_DUMMY_MASK;
+
+	if (int_mask == 0)
+		return IRQ_NONE;
+
+	/* clear hsm.b_conn here since host driver can't detect it
+	*  otg_dummy_irq called means B-disconnect happened.
+	*/
+	if (lnw->iotg.hsm.b_conn) {
+		lnw->iotg.hsm.b_conn = 0;
+		if (spin_trylock(&lnw->wq_lock)) {
+			langwell_update_transceiver();
+			spin_unlock(&lnw->wq_lock);
+		}
+	}
+
+	/* Clear interrupts */
+	writel(int_mask, reg_base + CI_USBSTS);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t otg_irq(int irq, void *_dev)
+{
+	struct langwell_otg		*lnw = _dev;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	u32				int_sts, int_en;
+	u32				int_mask = 0;
+	int				flag = 0;
+
+	int_sts = readl(lnw->iotg.base + CI_OTGSC);
+	int_en = (int_sts & OTGSC_INTEN_MASK) >> 8;
+	int_mask = int_sts & int_en;
+	if (int_mask == 0)
+		return IRQ_NONE;
+
+	if (int_mask & OTGSC_IDIS) {
+		dev_dbg(lnw->dev, "%s: id change int\n", __func__);
+		iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0;
+		dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_DPIS) {
+		dev_dbg(lnw->dev, "%s: data pulse int\n", __func__);
+		iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0;
+		dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_BSEIS) {
+		dev_dbg(lnw->dev, "%s: b session end int\n", __func__);
+		iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0;
+		dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_BSVIS) {
+		dev_dbg(lnw->dev, "%s: b session valid int\n", __func__);
+		iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0;
+		dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_ASVIS) {
+		dev_dbg(lnw->dev, "%s: a session valid int\n", __func__);
+		iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0;
+		dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld);
+		flag = 1;
+	}
+	if (int_mask & OTGSC_AVVIS) {
+		dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__);
+		iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0;
+		dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld);
+		flag = 1;
+	}
+
+	if (int_mask & OTGSC_1MSS) {
+		/* need to schedule otg_work if any timer is expired */
+		if (langwell_otg_tick_timer(&int_sts))
+			flag = 1;
+	}
+
+	writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask,
+					lnw->iotg.base + CI_OTGSC);
+	if (flag)
+		langwell_update_transceiver();
+
+	return IRQ_HANDLED;
+}
+
+static int langwell_otg_iotg_notify(struct notifier_block *nb,
+				unsigned long action, void *data)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = data;
+	int				flag = 0;
+
+	if (iotg == NULL)
+		return NOTIFY_BAD;
+
+	if (lnw == NULL)
+		return NOTIFY_BAD;
+
+	switch (action) {
+	case MID_OTG_NOTIFY_CONNECT:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n");
+		if (iotg->otg.default_a == 1)
+			iotg->hsm.b_conn = 1;
+		else
+			iotg->hsm.a_conn = 1;
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_DISCONN:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n");
+		if (iotg->otg.default_a == 1)
+			iotg->hsm.b_conn = 0;
+		else
+			iotg->hsm.a_conn = 0;
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_HSUSPEND:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n");
+		if (iotg->otg.default_a == 1)
+			iotg->hsm.a_suspend_req = 1;
+		else
+			iotg->hsm.b_bus_req = 0;
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_HRESUME:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n");
+		if (iotg->otg.default_a == 1)
+			iotg->hsm.b_bus_resume = 1;
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_CSUSPEND:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n");
+		if (iotg->otg.default_a == 1) {
+			if (iotg->hsm.b_bus_suspend_vld == 2) {
+				iotg->hsm.b_bus_suspend = 1;
+				iotg->hsm.b_bus_suspend_vld = 0;
+				flag = 1;
+			} else {
+				iotg->hsm.b_bus_suspend_vld++;
+				flag = 0;
+			}
+		} else {
+			if (iotg->hsm.a_bus_suspend == 0) {
+				iotg->hsm.a_bus_suspend = 1;
+				flag = 1;
+			}
+		}
+		break;
+	case MID_OTG_NOTIFY_CRESUME:
+		dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n");
+		if (iotg->otg.default_a == 0)
+			iotg->hsm.a_bus_suspend = 0;
+		flag = 0;
+		break;
+	case MID_OTG_NOTIFY_HOSTADD:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n");
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_HOSTREMOVE:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n");
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_CLIENTADD:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n");
+		flag = 1;
+		break;
+	case MID_OTG_NOTIFY_CLIENTREMOVE:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n");
+		flag = 1;
+		break;
+	default:
+		dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n");
+		return NOTIFY_DONE;
+	}
+
+	if (flag)
+		langwell_update_transceiver();
+
+	return NOTIFY_OK;
+}
+
+static void langwell_otg_work(struct work_struct *work)
+{
+	struct langwell_otg		*lnw;
+	struct intel_mid_otg_xceiv	*iotg;
+	int				retval;
+	struct pci_dev			*pdev;
+
+	lnw = container_of(work, struct langwell_otg, work);
+	iotg = &lnw->iotg;
+	pdev = to_pci_dev(lnw->dev);
+
+	dev_dbg(lnw->dev, "%s: old state = %s\n", __func__,
+			state_string(iotg->otg.state));
+
+	switch (iotg->otg.state) {
+	case OTG_STATE_UNDEFINED:
+	case OTG_STATE_B_IDLE:
+		if (!iotg->hsm.id) {
+			langwell_otg_del_timer(b_srp_init_tmr);
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			langwell_otg_chrg_vbus(0);
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.b_sess_vld) {
+			langwell_otg_del_timer(b_srp_init_tmr);
+			del_timer_sync(&lnw->hsm_timer);
+			iotg->hsm.b_sess_end = 0;
+			iotg->hsm.a_bus_suspend = 0;
+			langwell_otg_chrg_vbus(0);
+
+			if (lnw->iotg.start_peripheral) {
+				lnw->iotg.start_peripheral(&lnw->iotg);
+				iotg->otg.state = OTG_STATE_B_PERIPHERAL;
+			} else
+				dev_dbg(lnw->dev, "client driver not loaded\n");
+
+		} else if (iotg->hsm.b_srp_init_tmout) {
+			iotg->hsm.b_srp_init_tmout = 0;
+			dev_warn(lnw->dev, "SRP init timeout\n");
+		} else if (iotg->hsm.b_srp_fail_tmout) {
+			iotg->hsm.b_srp_fail_tmout = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			/* No silence failure */
+			langwell_otg_nsf_msg(6);
+		} else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) {
+			del_timer_sync(&lnw->hsm_timer);
+			/* workaround for b_se0_srp detection */
+			retval = langwell_otg_check_se0_srp(0);
+			if (retval) {
+				iotg->hsm.b_bus_req = 0;
+				dev_dbg(lnw->dev, "LS isn't SE0, try later\n");
+			} else {
+				/* clear the PHCD before start srp */
+				langwell_otg_phy_low_power(0);
+
+				/* Start SRP */
+				langwell_otg_add_timer(b_srp_init_tmr);
+				iotg->otg.start_srp(&iotg->otg);
+				langwell_otg_del_timer(b_srp_init_tmr);
+				langwell_otg_add_ktimer(TB_SRP_FAIL_TMR);
+
+				/* reset PHY low power mode here */
+				langwell_otg_phy_low_power_wait(1);
+			}
+		}
+		break;
+	case OTG_STATE_B_SRP_INIT:
+		if (!iotg->hsm.id) {
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_chrg_vbus(0);
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.b_sess_vld) {
+			langwell_otg_chrg_vbus(0);
+			if (lnw->iotg.start_peripheral) {
+				lnw->iotg.start_peripheral(&lnw->iotg);
+				iotg->otg.state = OTG_STATE_B_PERIPHERAL;
+			} else
+				dev_dbg(lnw->dev, "client driver not loaded\n");
+		}
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		if (!iotg->hsm.id) {
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			langwell_otg_chrg_vbus(0);
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.b_sess_vld) {
+			iotg->hsm.b_hnp_enable = 0;
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			iotg->otg.state = OTG_STATE_B_IDLE;
+		} else if (iotg->hsm.b_bus_req && iotg->otg.gadget &&
+					iotg->otg.gadget->b_hnp_enable &&
+					iotg->hsm.a_bus_suspend) {
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			langwell_otg_HAAR(1);
+			iotg->hsm.a_conn = 0;
+
+			if (lnw->iotg.start_host) {
+				lnw->iotg.start_host(&lnw->iotg);
+				iotg->otg.state = OTG_STATE_B_WAIT_ACON;
+			} else
+				dev_dbg(lnw->dev,
+						"host driver not loaded.\n");
+
+			iotg->hsm.a_bus_resume = 0;
+			langwell_otg_add_ktimer(TB_ASE0_BRST_TMR);
+		}
+		break;
+
+	case OTG_STATE_B_WAIT_ACON:
+		if (!iotg->hsm.id) {
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			langwell_otg_chrg_vbus(0);
+
+			langwell_otg_HAAR(0);
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.b_sess_vld) {
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->hsm.b_hnp_enable = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			langwell_otg_chrg_vbus(0);
+			langwell_otg_HAAR(0);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+		} else if (iotg->hsm.a_conn) {
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			langwell_otg_HAAR(0);
+			iotg->otg.state = OTG_STATE_B_HOST;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_bus_resume ||
+				iotg->hsm.b_ase0_brst_tmout) {
+			/* delete hsm timer for b_ase0_brst_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			langwell_otg_HAAR(0);
+			langwell_otg_nsf_msg(7);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			iotg->hsm.a_bus_suspend = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			if (lnw->iotg.start_peripheral)
+				lnw->iotg.start_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver not loaded.\n");
+
+			iotg->otg.state = OTG_STATE_B_PERIPHERAL;
+		}
+		break;
+
+	case OTG_STATE_B_HOST:
+		if (!iotg->hsm.id) {
+			iotg->otg.default_a = 1;
+			iotg->hsm.a_srp_det = 0;
+
+			langwell_otg_chrg_vbus(0);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.b_sess_vld) {
+			iotg->hsm.b_hnp_enable = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			langwell_otg_chrg_vbus(0);
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+		} else if ((!iotg->hsm.b_bus_req) ||
+				(!iotg->hsm.a_conn)) {
+			iotg->hsm.b_bus_req = 0;
+			langwell_otg_loc_sof(0);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			iotg->hsm.a_bus_suspend = 0;
+
+			if (lnw->iotg.start_peripheral)
+				lnw->iotg.start_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+						"client driver not loaded.\n");
+
+			iotg->otg.state = OTG_STATE_B_PERIPHERAL;
+		}
+		break;
+
+	case OTG_STATE_A_IDLE:
+		iotg->otg.default_a = 1;
+		if (iotg->hsm.id) {
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+			iotg->hsm.vbus_srp_up = 0;
+
+			langwell_otg_chrg_vbus(0);
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_bus_drop &&
+			(iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) {
+			langwell_otg_phy_low_power(0);
+
+			/* Turn on VBus */
+			iotg->otg.set_vbus(&iotg->otg, true);
+
+			iotg->hsm.vbus_srp_up = 0;
+			iotg->hsm.a_wait_vrise_tmout = 0;
+			langwell_otg_add_timer(a_wait_vrise_tmr);
+			iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) {
+			iotg->hsm.vbus_srp_up = 1;
+		} else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) {
+			msleep(10);
+			langwell_otg_phy_low_power(0);
+
+			/* Turn on VBus */
+			iotg->otg.set_vbus(&iotg->otg, true);
+			iotg->hsm.a_srp_det = 1;
+			iotg->hsm.vbus_srp_up = 0;
+			iotg->hsm.a_wait_vrise_tmout = 0;
+			langwell_otg_add_timer(a_wait_vrise_tmr);
+			iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_sess_vld &&
+				!iotg->hsm.vbus_srp_up) {
+			langwell_otg_phy_low_power(1);
+		}
+		break;
+	case OTG_STATE_A_WAIT_VRISE:
+		if (iotg->hsm.id) {
+			langwell_otg_del_timer(a_wait_vrise_tmr);
+			iotg->hsm.b_bus_req = 0;
+			iotg->otg.default_a = 0;
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+		} else if (iotg->hsm.a_vbus_vld) {
+			langwell_otg_del_timer(a_wait_vrise_tmr);
+			iotg->hsm.b_conn = 0;
+			if (lnw->iotg.start_host)
+				lnw->iotg.start_host(&lnw->iotg);
+			else {
+				dev_dbg(lnw->dev, "host driver not loaded.\n");
+				break;
+			}
+
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+		} else if (iotg->hsm.a_wait_vrise_tmout) {
+			iotg->hsm.b_conn = 0;
+			if (iotg->hsm.a_vbus_vld) {
+				if (lnw->iotg.start_host)
+					lnw->iotg.start_host(&lnw->iotg);
+				else {
+					dev_dbg(lnw->dev,
+						"host driver not loaded.\n");
+					break;
+				}
+				langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+				iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+			} else {
+
+				/* Turn off VBus */
+				iotg->otg.set_vbus(&iotg->otg, false);
+				langwell_otg_phy_low_power_wait(1);
+				iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+			}
+		}
+		break;
+	case OTG_STATE_A_WAIT_BCON:
+		if (iotg->hsm.id) {
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_vbus_vld) {
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+		} else if (iotg->hsm.a_bus_drop ||
+				(iotg->hsm.a_wait_bcon_tmout &&
+				!iotg->hsm.a_bus_req)) {
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+		} else if (iotg->hsm.b_conn) {
+			/* delete hsm timer for a_wait_bcon_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			iotg->hsm.a_suspend_req = 0;
+			iotg->otg.state = OTG_STATE_A_HOST;
+			if (iotg->hsm.a_srp_det && iotg->otg.host &&
+					!iotg->otg.host->b_hnp_enable) {
+				/* SRP capable peripheral-only device */
+				iotg->hsm.a_bus_req = 1;
+				iotg->hsm.a_srp_det = 0;
+			} else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
+					iotg->otg.host->b_hnp_enable) {
+				/* It is not safe enough to do a fast
+				 * transistion from A_WAIT_BCON to
+				 * A_SUSPEND */
+				msleep(10000);
+				if (iotg->hsm.a_bus_req)
+					break;
+
+				if (request_irq(pdev->irq,
+					otg_dummy_irq, IRQF_SHARED,
+					driver_name, iotg->base) != 0) {
+					dev_dbg(lnw->dev,
+						"request interrupt %d fail\n",
+						pdev->irq);
+				}
+
+				langwell_otg_HABA(1);
+				iotg->hsm.b_bus_resume = 0;
+				iotg->hsm.a_aidl_bdis_tmout = 0;
+
+				langwell_otg_loc_sof(0);
+				/* clear PHCD to enable HW timer */
+				langwell_otg_phy_low_power(0);
+				langwell_otg_add_timer(a_aidl_bdis_tmr);
+				iotg->otg.state = OTG_STATE_A_SUSPEND;
+			} else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
+				!iotg->otg.host->b_hnp_enable) {
+				if (lnw->iotg.stop_host)
+					lnw->iotg.stop_host(&lnw->iotg);
+				else
+					dev_dbg(lnw->dev,
+						"host driver removed.\n");
+
+				/* Turn off VBus */
+				iotg->otg.set_vbus(&iotg->otg, false);
+				iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+			}
+		}
+		break;
+	case OTG_STATE_A_HOST:
+		if (iotg->hsm.id) {
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_bus_drop ||
+				(iotg->otg.host &&
+				!iotg->otg.host->b_hnp_enable &&
+					!iotg->hsm.a_bus_req)) {
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+		} else if (!iotg->hsm.a_vbus_vld) {
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+		} else if (iotg->otg.host &&
+				iotg->otg.host->b_hnp_enable &&
+				!iotg->hsm.a_bus_req) {
+			/* Set HABA to enable hardware assistance to signal
+			 *  A-connect after receiver B-disconnect. Hardware
+			 *  will then set client mode and enable URE, SLE and
+			 *  PCE after the assistance. otg_dummy_irq is used to
+			 *  clean these ints when client driver is not resumed.
+			 */
+			if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED,
+					driver_name, iotg->base) != 0) {
+				dev_dbg(lnw->dev,
+					"request interrupt %d failed\n",
+						pdev->irq);
+			}
+
+			/* set HABA */
+			langwell_otg_HABA(1);
+			iotg->hsm.b_bus_resume = 0;
+			iotg->hsm.a_aidl_bdis_tmout = 0;
+			langwell_otg_loc_sof(0);
+			/* clear PHCD to enable HW timer */
+			langwell_otg_phy_low_power(0);
+			langwell_otg_add_timer(a_aidl_bdis_tmr);
+			iotg->otg.state = OTG_STATE_A_SUSPEND;
+		} else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) {
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+		}
+		break;
+	case OTG_STATE_A_SUSPEND:
+		if (iotg->hsm.id) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_bus_req ||
+				iotg->hsm.b_bus_resume) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+			iotg->hsm.a_suspend_req = 0;
+			langwell_otg_loc_sof(1);
+			iotg->otg.state = OTG_STATE_A_HOST;
+		} else if (iotg->hsm.a_aidl_bdis_tmout ||
+				iotg->hsm.a_bus_drop) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+		} else if (!iotg->hsm.b_conn && iotg->otg.host &&
+				iotg->otg.host->b_hnp_enable) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			iotg->hsm.b_bus_suspend = 0;
+			iotg->hsm.b_bus_suspend_vld = 0;
+
+			/* msleep(200); */
+			if (lnw->iotg.start_peripheral)
+				lnw->iotg.start_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver not loaded.\n");
+
+			langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR);
+			iotg->otg.state = OTG_STATE_A_PERIPHERAL;
+			break;
+		} else if (!iotg->hsm.a_vbus_vld) {
+			langwell_otg_del_timer(a_aidl_bdis_tmr);
+			langwell_otg_HABA(0);
+			free_irq(pdev->irq, iotg->base);
+			if (lnw->iotg.stop_host)
+				lnw->iotg.stop_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"host driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+		}
+		break;
+	case OTG_STATE_A_PERIPHERAL:
+		if (iotg->hsm.id) {
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+			iotg->otg.default_a = 0;
+			iotg->hsm.b_bus_req = 0;
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			set_client_mode();
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (!iotg->hsm.a_vbus_vld) {
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			langwell_otg_phy_low_power_wait(1);
+			iotg->otg.state = OTG_STATE_A_VBUS_ERR;
+		} else if (iotg->hsm.a_bus_drop) {
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			/* Turn off VBus */
+			iotg->otg.set_vbus(&iotg->otg, false);
+			iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
+		} else if (iotg->hsm.b_bus_suspend) {
+			/* delete hsm timer for b_bus_suspend_tmr */
+			del_timer_sync(&lnw->hsm_timer);
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			if (lnw->iotg.start_host)
+				lnw->iotg.start_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+						"host driver not loaded.\n");
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+		} else if (iotg->hsm.b_bus_suspend_tmout) {
+			u32	val;
+			val = readl(lnw->iotg.base + CI_PORTSC1);
+			if (!(val & PORTSC_SUSP))
+				break;
+
+			if (lnw->iotg.stop_peripheral)
+				lnw->iotg.stop_peripheral(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+					"client driver has been removed.\n");
+
+			if (lnw->iotg.start_host)
+				lnw->iotg.start_host(&lnw->iotg);
+			else
+				dev_dbg(lnw->dev,
+						"host driver not loaded.\n");
+			langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
+			iotg->otg.state = OTG_STATE_A_WAIT_BCON;
+		}
+		break;
+	case OTG_STATE_A_VBUS_ERR:
+		if (iotg->hsm.id) {
+			iotg->otg.default_a = 0;
+			iotg->hsm.a_clr_err = 0;
+			iotg->hsm.a_srp_det = 0;
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_clr_err) {
+			iotg->hsm.a_clr_err = 0;
+			iotg->hsm.a_srp_det = 0;
+			reset_otg();
+			init_hsm();
+			if (iotg->otg.state == OTG_STATE_A_IDLE)
+				langwell_update_transceiver();
+		} else {
+			/* FW will clear PHCD bit when any VBus
+			 * event detected. Reset PHCD to 1 again */
+			langwell_otg_phy_low_power(1);
+		}
+		break;
+	case OTG_STATE_A_WAIT_VFALL:
+		if (iotg->hsm.id) {
+			iotg->otg.default_a = 0;
+			set_client_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_B_IDLE;
+			langwell_update_transceiver();
+		} else if (iotg->hsm.a_bus_req) {
+
+			/* Turn on VBus */
+			iotg->otg.set_vbus(&iotg->otg, true);
+			iotg->hsm.a_wait_vrise_tmout = 0;
+			langwell_otg_add_timer(a_wait_vrise_tmr);
+			iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
+		} else if (!iotg->hsm.a_sess_vld) {
+			iotg->hsm.a_srp_det = 0;
+			set_host_mode();
+			langwell_otg_phy_low_power(1);
+			iotg->otg.state = OTG_STATE_A_IDLE;
+		}
+		break;
+	default:
+		;
+	}
+
+	dev_dbg(lnw->dev, "%s: new state = %s\n", __func__,
+			state_string(iotg->otg.state));
+}
+
+static ssize_t
+show_registers(struct device *_dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	char			*next;
+	unsigned		size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	t = scnprintf(next, size,
+		"\n"
+		"USBCMD = 0x%08x\n"
+		"USBSTS = 0x%08x\n"
+		"USBINTR = 0x%08x\n"
+		"ASYNCLISTADDR = 0x%08x\n"
+		"PORTSC1 = 0x%08x\n"
+		"HOSTPC1 = 0x%08x\n"
+		"OTGSC = 0x%08x\n"
+		"USBMODE = 0x%08x\n",
+		readl(lnw->iotg.base + 0x30),
+		readl(lnw->iotg.base + 0x34),
+		readl(lnw->iotg.base + 0x38),
+		readl(lnw->iotg.base + 0x48),
+		readl(lnw->iotg.base + 0x74),
+		readl(lnw->iotg.base + 0xb4),
+		readl(lnw->iotg.base + 0xf4),
+		readl(lnw->iotg.base + 0xf8)
+	     );
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
+
+static ssize_t
+show_hsm(struct device *_dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	char				*next;
+	unsigned			size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	if (iotg->otg.host)
+		iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable;
+
+	if (iotg->otg.gadget)
+		iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable;
+
+	t = scnprintf(next, size,
+		"\n"
+		"current state = %s\n"
+		"a_bus_resume = \t%d\n"
+		"a_bus_suspend = \t%d\n"
+		"a_conn = \t%d\n"
+		"a_sess_vld = \t%d\n"
+		"a_srp_det = \t%d\n"
+		"a_vbus_vld = \t%d\n"
+		"b_bus_resume = \t%d\n"
+		"b_bus_suspend = \t%d\n"
+		"b_conn = \t%d\n"
+		"b_se0_srp = \t%d\n"
+		"b_sess_end = \t%d\n"
+		"b_sess_vld = \t%d\n"
+		"id = \t%d\n"
+		"a_set_b_hnp_en = \t%d\n"
+		"b_srp_done = \t%d\n"
+		"b_hnp_enable = \t%d\n"
+		"a_wait_vrise_tmout = \t%d\n"
+		"a_wait_bcon_tmout = \t%d\n"
+		"a_aidl_bdis_tmout = \t%d\n"
+		"b_ase0_brst_tmout = \t%d\n"
+		"a_bus_drop = \t%d\n"
+		"a_bus_req = \t%d\n"
+		"a_clr_err = \t%d\n"
+		"a_suspend_req = \t%d\n"
+		"b_bus_req = \t%d\n"
+		"b_bus_suspend_tmout = \t%d\n"
+		"b_bus_suspend_vld = \t%d\n",
+		state_string(iotg->otg.state),
+		iotg->hsm.a_bus_resume,
+		iotg->hsm.a_bus_suspend,
+		iotg->hsm.a_conn,
+		iotg->hsm.a_sess_vld,
+		iotg->hsm.a_srp_det,
+		iotg->hsm.a_vbus_vld,
+		iotg->hsm.b_bus_resume,
+		iotg->hsm.b_bus_suspend,
+		iotg->hsm.b_conn,
+		iotg->hsm.b_se0_srp,
+		iotg->hsm.b_sess_end,
+		iotg->hsm.b_sess_vld,
+		iotg->hsm.id,
+		iotg->hsm.a_set_b_hnp_en,
+		iotg->hsm.b_srp_done,
+		iotg->hsm.b_hnp_enable,
+		iotg->hsm.a_wait_vrise_tmout,
+		iotg->hsm.a_wait_bcon_tmout,
+		iotg->hsm.a_aidl_bdis_tmout,
+		iotg->hsm.b_ase0_brst_tmout,
+		iotg->hsm.a_bus_drop,
+		iotg->hsm.a_bus_req,
+		iotg->hsm.a_clr_err,
+		iotg->hsm.a_suspend_req,
+		iotg->hsm.b_bus_req,
+		iotg->hsm.b_bus_suspend_tmout,
+		iotg->hsm.b_bus_suspend_vld
+		);
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
+
+static ssize_t
+get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	char			*next;
+	unsigned		size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req);
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_a_bus_req(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+
+	if (!iotg->otg.default_a)
+		return -1;
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '0') {
+		iotg->hsm.a_bus_req = 0;
+		dev_dbg(lnw->dev, "User request: a_bus_req = 0\n");
+	} else if (buf[0] == '1') {
+		/* If a_bus_drop is TRUE, a_bus_req can't be set */
+		if (iotg->hsm.a_bus_drop)
+			return -1;
+		iotg->hsm.a_bus_req = 1;
+		dev_dbg(lnw->dev, "User request: a_bus_req = 1\n");
+	}
+	if (spin_trylock(&lnw->wq_lock)) {
+		langwell_update_transceiver();
+		spin_unlock(&lnw->wq_lock);
+	}
+	return count;
+}
+static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req);
+
+static ssize_t
+get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	char			*next;
+	unsigned		size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop);
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_a_bus_drop(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+
+	if (!iotg->otg.default_a)
+		return -1;
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '0') {
+		iotg->hsm.a_bus_drop = 0;
+		dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n");
+	} else if (buf[0] == '1') {
+		iotg->hsm.a_bus_drop = 1;
+		iotg->hsm.a_bus_req = 0;
+		dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n");
+		dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n");
+	}
+	if (spin_trylock(&lnw->wq_lock)) {
+		langwell_update_transceiver();
+		spin_unlock(&lnw->wq_lock);
+	}
+	return count;
+}
+static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO,
+	get_a_bus_drop, set_a_bus_drop);
+
+static ssize_t
+get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	char			*next;
+	unsigned		size, t;
+
+	next = buf;
+	size = PAGE_SIZE;
+
+	t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req);
+	size -= t;
+	next += t;
+
+	return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_b_bus_req(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+
+	if (iotg->otg.default_a)
+		return -1;
+
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '0') {
+		iotg->hsm.b_bus_req = 0;
+		dev_dbg(lnw->dev, "User request: b_bus_req = 0\n");
+	} else if (buf[0] == '1') {
+		iotg->hsm.b_bus_req = 1;
+		dev_dbg(lnw->dev, "User request: b_bus_req = 1\n");
+	}
+	if (spin_trylock(&lnw->wq_lock)) {
+		langwell_update_transceiver();
+		spin_unlock(&lnw->wq_lock);
+	}
+	return count;
+}
+static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req);
+
+static ssize_t
+set_a_clr_err(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+
+	if (!iotg->otg.default_a)
+		return -1;
+	if (count > 2)
+		return -1;
+
+	if (buf[0] == '1') {
+		iotg->hsm.a_clr_err = 1;
+		dev_dbg(lnw->dev, "User request: a_clr_err = 1\n");
+	}
+	if (spin_trylock(&lnw->wq_lock)) {
+		langwell_update_transceiver();
+		spin_unlock(&lnw->wq_lock);
+	}
+	return count;
+}
+static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err);
+
+static struct attribute *inputs_attrs[] = {
+	&dev_attr_a_bus_req.attr,
+	&dev_attr_a_bus_drop.attr,
+	&dev_attr_b_bus_req.attr,
+	&dev_attr_a_clr_err.attr,
+	NULL,
+};
+
+static struct attribute_group debug_dev_attr_group = {
+	.name = "inputs",
+	.attrs = inputs_attrs,
+};
+
+static int langwell_otg_probe(struct pci_dev *pdev,
+		const struct pci_device_id *id)
+{
+	unsigned long		resource, len;
+	void __iomem		*base = NULL;
+	int			retval;
+	u32			val32;
+	struct langwell_otg	*lnw;
+	char			qname[] = "langwell_otg_queue";
+
+	retval = 0;
+	dev_dbg(&pdev->dev, "\notg controller is detected.\n");
+	if (pci_enable_device(pdev) < 0) {
+		retval = -ENODEV;
+		goto done;
+	}
+
+	lnw = kzalloc(sizeof *lnw, GFP_KERNEL);
+	if (lnw == NULL) {
+		retval = -ENOMEM;
+		goto done;
+	}
+	the_transceiver = lnw;
+
+	/* control register: BAR 0 */
+	resource = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+	if (!request_mem_region(resource, len, driver_name)) {
+		retval = -EBUSY;
+		goto err;
+	}
+	lnw->region = 1;
+
+	base = ioremap_nocache(resource, len);
+	if (base == NULL) {
+		retval = -EFAULT;
+		goto err;
+	}
+	lnw->iotg.base = base;
+
+	if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) {
+		retval = -EBUSY;
+		goto err;
+	}
+	lnw->cfg_region = 1;
+
+	/* For the SCCB.USBCFG register */
+	base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN);
+	if (base == NULL) {
+		retval = -EFAULT;
+		goto err;
+	}
+	lnw->usbcfg = base;
+
+	if (!pdev->irq) {
+		dev_dbg(&pdev->dev, "No IRQ.\n");
+		retval = -ENODEV;
+		goto err;
+	}
+
+	lnw->qwork = create_singlethread_workqueue(qname);
+	if (!lnw->qwork) {
+		dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname);
+		retval = -ENOMEM;
+		goto err;
+	}
+	INIT_WORK(&lnw->work, langwell_otg_work);
+
+	/* OTG common part */
+	lnw->dev = &pdev->dev;
+	lnw->iotg.otg.dev = lnw->dev;
+	lnw->iotg.otg.label = driver_name;
+	lnw->iotg.otg.set_host = langwell_otg_set_host;
+	lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral;
+	lnw->iotg.otg.set_power = langwell_otg_set_power;
+	lnw->iotg.otg.set_vbus = langwell_otg_set_vbus;
+	lnw->iotg.otg.start_srp = langwell_otg_start_srp;
+	lnw->iotg.otg.state = OTG_STATE_UNDEFINED;
+
+	if (otg_set_transceiver(&lnw->iotg.otg)) {
+		dev_dbg(lnw->dev, "can't set transceiver\n");
+		retval = -EBUSY;
+		goto err;
+	}
+
+	reset_otg();
+	init_hsm();
+
+	spin_lock_init(&lnw->lock);
+	spin_lock_init(&lnw->wq_lock);
+	INIT_LIST_HEAD(&active_timers);
+	retval = langwell_otg_init_timers(&lnw->iotg.hsm);
+	if (retval) {
+		dev_dbg(&pdev->dev, "Failed to init timers\n");
+		goto err;
+	}
+
+	init_timer(&lnw->hsm_timer);
+	ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier);
+
+	lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify;
+
+	retval = intel_mid_otg_register_notifier(&lnw->iotg,
+						&lnw->iotg_notifier);
+	if (retval) {
+		dev_dbg(lnw->dev, "Failed to register notifier\n");
+		goto err;
+	}
+
+	if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
+				driver_name, lnw) != 0) {
+		dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq);
+		retval = -EBUSY;
+		goto err;
+	}
+
+	/* enable OTGSC int */
+	val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE |
+		OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU;
+	writel(val32, lnw->iotg.base + CI_OTGSC);
+
+	retval = device_create_file(&pdev->dev, &dev_attr_registers);
+	if (retval < 0) {
+		dev_dbg(lnw->dev,
+			"Can't register sysfs attribute: %d\n", retval);
+		goto err;
+	}
+
+	retval = device_create_file(&pdev->dev, &dev_attr_hsm);
+	if (retval < 0) {
+		dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval);
+		goto err;
+	}
+
+	retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group);
+	if (retval < 0) {
+		dev_dbg(lnw->dev,
+			"Can't register sysfs attr group: %d\n", retval);
+		goto err;
+	}
+
+	if (lnw->iotg.otg.state == OTG_STATE_A_IDLE)
+		langwell_update_transceiver();
+
+	return 0;
+
+err:
+	if (the_transceiver)
+		langwell_otg_remove(pdev);
+done:
+	return retval;
+}
+
+static void langwell_otg_remove(struct pci_dev *pdev)
+{
+	struct langwell_otg *lnw = the_transceiver;
+
+	if (lnw->qwork) {
+		flush_workqueue(lnw->qwork);
+		destroy_workqueue(lnw->qwork);
+	}
+	intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier);
+	langwell_otg_free_timers();
+
+	/* disable OTGSC interrupt as OTGSC doesn't change in reset */
+	writel(0, lnw->iotg.base + CI_OTGSC);
+
+	if (pdev->irq)
+		free_irq(pdev->irq, lnw);
+	if (lnw->usbcfg)
+		iounmap(lnw->usbcfg);
+	if (lnw->cfg_region)
+		release_mem_region(USBCFG_ADDR, USBCFG_LEN);
+	if (lnw->iotg.base)
+		iounmap(lnw->iotg.base);
+	if (lnw->region)
+		release_mem_region(pci_resource_start(pdev, 0),
+				pci_resource_len(pdev, 0));
+
+	otg_set_transceiver(NULL);
+	pci_disable_device(pdev);
+	sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group);
+	device_remove_file(&pdev->dev, &dev_attr_hsm);
+	device_remove_file(&pdev->dev, &dev_attr_registers);
+	kfree(lnw);
+	lnw = NULL;
+}
+
+static void transceiver_suspend(struct pci_dev *pdev)
+{
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+	langwell_otg_phy_low_power(1);
+}
+
+static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
+{
+	struct langwell_otg		*lnw = the_transceiver;
+	struct intel_mid_otg_xceiv	*iotg = &lnw->iotg;
+	int				ret = 0;
+
+	/* Disbale OTG interrupts */
+	langwell_otg_intr(0);
+
+	if (pdev->irq)
+		free_irq(pdev->irq, lnw);
+
+	/* Prevent more otg_work */
+	flush_workqueue(lnw->qwork);
+	destroy_workqueue(lnw->qwork);
+	lnw->qwork = NULL;
+
+	/* start actions */
+	switch (iotg->otg.state) {
+	case OTG_STATE_A_WAIT_VFALL:
+		iotg->otg.state = OTG_STATE_A_IDLE;
+	case OTG_STATE_A_IDLE:
+	case OTG_STATE_B_IDLE:
+	case OTG_STATE_A_VBUS_ERR:
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_WAIT_VRISE:
+		langwell_otg_del_timer(a_wait_vrise_tmr);
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_WAIT_BCON:
+		del_timer_sync(&lnw->hsm_timer);
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev, "host driver has been removed.\n");
+
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_HOST:
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev, "host driver has been removed.\n");
+
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_SUSPEND:
+		langwell_otg_del_timer(a_aidl_bdis_tmr);
+		langwell_otg_HABA(0);
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(lnw->dev, "host driver has been removed.\n");
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_A_PERIPHERAL:
+		del_timer_sync(&lnw->hsm_timer);
+
+		if (lnw->iotg.stop_peripheral)
+			lnw->iotg.stop_peripheral(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev,
+				"client driver has been removed.\n");
+		iotg->hsm.a_srp_det = 0;
+
+		/* Turn off VBus */
+		iotg->otg.set_vbus(&iotg->otg, false);
+		iotg->otg.state = OTG_STATE_A_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_B_HOST:
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev, "host driver has been removed.\n");
+		iotg->hsm.b_bus_req = 0;
+		iotg->otg.state = OTG_STATE_B_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		if (lnw->iotg.stop_peripheral)
+			lnw->iotg.stop_peripheral(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev,
+				"client driver has been removed.\n");
+		iotg->otg.state = OTG_STATE_B_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	case OTG_STATE_B_WAIT_ACON:
+		/* delete hsm timer for b_ase0_brst_tmr */
+		del_timer_sync(&lnw->hsm_timer);
+
+		langwell_otg_HAAR(0);
+
+		if (lnw->iotg.stop_host)
+			lnw->iotg.stop_host(&lnw->iotg);
+		else
+			dev_dbg(&pdev->dev, "host driver has been removed.\n");
+		iotg->hsm.b_bus_req = 0;
+		iotg->otg.state = OTG_STATE_B_IDLE;
+		transceiver_suspend(pdev);
+		break;
+	default:
+		dev_dbg(lnw->dev, "error state before suspend\n");
+		break;
+	}
+
+	return ret;
+}
+
+static void transceiver_resume(struct pci_dev *pdev)
+{
+	pci_restore_state(pdev);
+	pci_set_power_state(pdev, PCI_D0);
+}
+
+static int langwell_otg_resume(struct pci_dev *pdev)
+{
+	struct langwell_otg	*lnw = the_transceiver;
+	int			ret = 0;
+
+	transceiver_resume(pdev);
+
+	lnw->qwork = create_singlethread_workqueue("langwell_otg_queue");
+	if (!lnw->qwork) {
+		dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen");
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
+				driver_name, lnw) != 0) {
+		dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq);
+		ret = -EBUSY;
+		goto error;
+	}
+
+	/* enable OTG interrupts */
+	langwell_otg_intr(1);
+
+	update_hsm();
+
+	langwell_update_transceiver();
+
+	return ret;
+error:
+	langwell_otg_intr(0);
+	transceiver_suspend(pdev);
+	return ret;
+}
+
+static int __init langwell_otg_init(void)
+{
+	return pci_register_driver(&otg_pci_driver);
+}
+module_init(langwell_otg_init);
+
+static void __exit langwell_otg_cleanup(void)
+{
+	pci_unregister_driver(&otg_pci_driver);
+}
+module_exit(langwell_otg_cleanup);
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index ccc8195..059d9ac 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -29,12 +29,23 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 
+
+struct ulpi_info {
+	unsigned int	id;
+	char		*name;
+};
+
 #define ULPI_ID(vendor, product) (((vendor) << 16) | (product))
+#define ULPI_INFO(_id, _name)		\
+	{				\
+		.id	= (_id),	\
+		.name	= (_name),	\
+	}
 
 /* ULPI hardcoded IDs, used for probing */
-static unsigned int ulpi_ids[] = {
-	ULPI_ID(0x04cc, 0x1504),	/* NXP ISP1504 */
-	ULPI_ID(0x0424, 0x0006),        /* SMSC USB3319 */
+static struct ulpi_info ulpi_ids[] = {
+	ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
+	ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB3319"),
 };
 
 static int ulpi_set_otg_flags(struct otg_transceiver *otg)
@@ -137,6 +148,32 @@
 	return ulpi_set_fc_flags(otg);
 }
 
+static int ulpi_check_integrity(struct otg_transceiver *otg)
+{
+	int ret, i;
+	unsigned int val = 0x55;
+
+	for (i = 0; i < 2; i++) {
+		ret = otg_io_write(otg, val, ULPI_SCRATCH);
+		if (ret < 0)
+			return ret;
+
+		ret = otg_io_read(otg, ULPI_SCRATCH);
+		if (ret < 0)
+			return ret;
+
+		if (ret != val) {
+			pr_err("ULPI integrity check: failed!");
+			return -ENODEV;
+		}
+		val = val << 1;
+	}
+
+	pr_info("ULPI integrity check: passed.\n");
+
+	return 0;
+}
+
 static int ulpi_init(struct otg_transceiver *otg)
 {
 	int i, vid, pid, ret;
@@ -153,12 +190,19 @@
 
 	pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
 
-	for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++)
-		if (ulpi_ids[i] == ULPI_ID(vid, pid))
-			return ulpi_set_flags(otg);
+	for (i = 0; i < ARRAY_SIZE(ulpi_ids); i++) {
+		if (ulpi_ids[i].id == ULPI_ID(vid, pid)) {
+			pr_info("Found %s ULPI transceiver.\n",
+				ulpi_ids[i].name);
+			break;
+		}
+	}
 
-	pr_err("ULPI ID does not match any known transceiver.\n");
-	return -ENODEV;
+	ret = ulpi_check_integrity(otg);
+	if (ret)
+		return ret;
+
+	return ulpi_set_flags(otg);
 }
 
 static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host)
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 916b2b6..9505810 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -527,6 +527,15 @@
 	bool "USB Secure Encapsulated Driver - Padded"
 	depends on USB_SERIAL_SAFE
 
+config USB_SERIAL_SAMBA
+	tristate "USB Atmel SAM Boot Assistant (SAM-BA) driver"
+	help
+	  Say Y here if you want to access the SAM-BA boot application of an
+	  Atmel AT91SAM device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sam-ba.
+
 config USB_SERIAL_SIEMENS_MPI
 	tristate "USB Siemens MPI driver"
 	help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 40ebe17..9a2117f 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -6,10 +6,10 @@
 
 obj-$(CONFIG_USB_SERIAL)			+= usbserial.o
 
-usbserial-obj-$(CONFIG_USB_SERIAL_CONSOLE)	+= console.o
-usbserial-obj-$(CONFIG_USB_EZUSB)		+= ezusb.o
+usbserial-y := usb-serial.o generic.o bus.o
 
-usbserial-objs	:= usb-serial.o generic.o bus.o $(usbserial-obj-y)
+usbserial-$(CONFIG_USB_SERIAL_CONSOLE)	+= console.o
+usbserial-$(CONFIG_USB_EZUSB)		+= ezusb.o
 
 obj-$(CONFIG_USB_SERIAL_AIRCABLE)		+= aircable.o
 obj-$(CONFIG_USB_SERIAL_ARK3116)		+= ark3116.o
@@ -48,6 +48,7 @@
 obj-$(CONFIG_USB_SERIAL_QCAUX)			+= qcaux.o
 obj-$(CONFIG_USB_SERIAL_QUALCOMM)		+= qcserial.o
 obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
+obj-$(CONFIG_USB_SERIAL_SAMBA)			+= sam-ba.o
 obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI)		+= siemens_mpi.o
 obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS)		+= sierra.o
 obj-$(CONFIG_USB_SERIAL_SPCP8X5)		+= spcp8x5.o
@@ -58,6 +59,5 @@
 obj-$(CONFIG_USB_SERIAL_VISOR)			+= visor.o
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)		+= whiteheat.o
 obj-$(CONFIG_USB_SERIAL_XIRCOM)			+= keyspan_pda.o
-obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL)	+= vivopay-serial.o
+obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL)		+= vivopay-serial.o
 obj-$(CONFIG_USB_SERIAL_ZIO)			+= zio.o
-
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 4e41a2a..8f1d4fb 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -411,6 +411,26 @@
 	return result;
 }
 
+static int ark3116_get_icount(struct tty_struct *tty,
+					struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ark3116_private *priv = usb_get_serial_port_data(port);
+	struct async_icount cnow = priv->icount;
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+	return 0;
+}
+
 static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
@@ -460,25 +480,6 @@
 				return 0;
 		}
 		break;
-	case TIOCGICOUNT: {
-		struct serial_icounter_struct icount;
-		struct async_icount cnow = priv->icount;
-		memset(&icount, 0, sizeof(icount));
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-		if (copy_to_user(user_arg, &icount, sizeof(icount)))
-			return -EFAULT;
-		return 0;
-	}
 	}
 
 	return -ENOIOCTLCMD;
@@ -736,6 +737,7 @@
 	.ioctl =		ark3116_ioctl,
 	.tiocmget =		ark3116_tiocmget,
 	.tiocmset =		ark3116_tiocmset,
+	.get_icount =		ark3116_get_icount,
 	.open =			ark3116_open,
 	.close =		ark3116_close,
 	.break_ctl = 		ark3116_break_ctl,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 4f1744c..8d7731d 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -54,6 +54,7 @@
 static int debug;
 
 static const struct usb_device_id id_table[] = {
+	{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
 	{ USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
 	{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
 	{ USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
@@ -132,6 +133,7 @@
 	{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
 	{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
 	{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+	{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
 	{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
 	{ } /* Terminating Entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 97cc87d..37b57c7 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -177,6 +177,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
@@ -674,7 +675,6 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
 	{ USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
-	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
@@ -715,8 +715,37 @@
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
 	{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
+
+	/* Papouch devices based on FTDI chip */
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485S_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485C_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_LEC_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB232_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_IRAMP_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK5_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO8x8_PID) },
 	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x2_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO10x1_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO30x3_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO60x3_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x16_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO3x32_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK6_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_UPSUSB_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_MU_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SIMUKEY_PID) },
 	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AD4USB_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMUX_PID) },
+	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMSR_PID) },
+
 	{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) },
 	{ USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) },
@@ -751,6 +780,7 @@
 	{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) },
+	{ USB_DEVICE(FTDI_VID, ACCESIO_COM4SM_PID) },
 	{ USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) },
@@ -761,6 +791,9 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -1559,6 +1592,7 @@
 	ftdi_set_max_packet_size(port);
 	if (read_latency_timer(port) < 0)
 		priv->latency = 16;
+	write_latency_timer(port);
 	create_sysfs_attrs(port);
 	return 0;
 }
@@ -1687,8 +1721,6 @@
 
 	dbg("%s", __func__);
 
-	write_latency_timer(port);
-
 	/* No error checking for this (will get errors later anyway) */
 	/* See ftdi_sio.h for description of what is reset */
 	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -2028,8 +2060,6 @@
 				"urb failed to set to rts/cts flow control\n");
 		}
 
-		/* raise DTR/RTS */
-		set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	} else {
 		/*
 		 * Xon/Xoff code
@@ -2077,8 +2107,6 @@
 			}
 		}
 
-		/* lower DTR/RTS */
-		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	}
 	return;
 }
@@ -2168,6 +2196,7 @@
 	 * - 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.
+	 * (except that the driver doesn't support it !)
 	 *
 	 * This code is borrowed from linux/drivers/char/serial.c
 	 */
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 15a4583..cf1aea1b 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -61,6 +61,7 @@
 #define FTDI_OPENDCC_SNIFFER_PID	0xBFD9
 #define FTDI_OPENDCC_THROTTLE_PID	0xBFDA
 #define FTDI_OPENDCC_GATEWAY_PID	0xBFDB
+#define FTDI_OPENDCC_GBM_PID	0xBFDC
 
 /*
  * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
@@ -1022,9 +1023,34 @@
  */
 
 #define PAPOUCH_VID			0x5050	/* Vendor ID */
+#define PAPOUCH_SB485_PID		0x0100	/* Papouch SB485 USB-485/422 Converter */
+#define PAPOUCH_AP485_PID		0x0101	/* AP485 USB-RS485 Converter */
+#define PAPOUCH_SB422_PID		0x0102	/* Papouch SB422 USB-RS422 Converter  */
+#define PAPOUCH_SB485_2_PID		0x0103	/* Papouch SB485 USB-485/422 Converter */
+#define PAPOUCH_AP485_2_PID		0x0104	/* AP485 USB-RS485 Converter */
+#define PAPOUCH_SB422_2_PID		0x0105	/* Papouch SB422 USB-RS422 Converter  */
+#define PAPOUCH_SB485S_PID		0x0106	/* Papouch SB485S USB-485/422 Converter */
+#define PAPOUCH_SB485C_PID		0x0107	/* Papouch SB485C USB-485/422 Converter */
+#define PAPOUCH_LEC_PID			0x0300	/* LEC USB Converter */
+#define PAPOUCH_SB232_PID		0x0301	/* Papouch SB232 USB-RS232 Converter */
 #define PAPOUCH_TMU_PID			0x0400	/* TMU USB Thermometer */
-#define PAPOUCH_QUIDO4x4_PID		0x0900	/* Quido 4/4 Module */
+#define PAPOUCH_IRAMP_PID		0x0500	/* Papouch IRAmp Duplex */
+#define PAPOUCH_DRAK5_PID		0x0700	/* Papouch DRAK5 */
+#define PAPOUCH_QUIDO8x8_PID		0x0800	/* Papouch Quido 8/8 Module */
+#define PAPOUCH_QUIDO4x4_PID		0x0900	/* Papouch Quido 4/4 Module */
+#define PAPOUCH_QUIDO2x2_PID		0x0a00	/* Papouch Quido 2/2 Module */
+#define PAPOUCH_QUIDO10x1_PID		0x0b00	/* Papouch Quido 10/1 Module */
+#define PAPOUCH_QUIDO30x3_PID		0x0c00	/* Papouch Quido 30/3 Module */
+#define PAPOUCH_QUIDO60x3_PID		0x0d00	/* Papouch Quido 60(100)/3 Module */
+#define PAPOUCH_QUIDO2x16_PID		0x0e00	/* Papouch Quido 2/16 Module */
+#define PAPOUCH_QUIDO3x32_PID		0x0f00	/* Papouch Quido 3/32 Module */
+#define PAPOUCH_DRAK6_PID		0x1000	/* Papouch DRAK6 */
+#define PAPOUCH_UPSUSB_PID		0x8000	/* Papouch UPS-USB adapter */
+#define PAPOUCH_MU_PID			0x8001	/* MU controller */
+#define PAPOUCH_SIMUKEY_PID		0x8002	/* Papouch SimuKey */
 #define PAPOUCH_AD4USB_PID		0x8003	/* AD4USB Measurement Module */
+#define PAPOUCH_GMUX_PID		0x8004	/* Papouch GOLIATH MUX */
+#define PAPOUCH_GMSR_PID		0x8005	/* Papouch GOLIATH MSR */
 
 /*
  * Marvell SheevaPlug
@@ -1063,3 +1089,14 @@
  * Submitted by John G. Rogers
  */
 #define SEGWAY_RMP200_PID	0xe729
+
+
+/*
+ * Accesio USB Data Acquisition products (http://www.accesio.com/)
+ */
+#define ACCESIO_COM4SM_PID 	0xD578
+
+/* www.sciencescope.co.uk educational dataloggers */
+#define FTDI_SCIENCESCOPE_LOGBOOKML_PID		0xFF18
+#define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID	0xFF1C
+#define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID	0xFF1D
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 76e6fb3..a0ab78a 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -222,6 +222,8 @@
 static int  edge_tiocmget(struct tty_struct *tty, struct file *file);
 static int  edge_tiocmset(struct tty_struct *tty, struct file *file,
 					unsigned int set, unsigned int clear);
+static int  edge_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount);
 static int  edge_startup(struct usb_serial *serial);
 static void edge_disconnect(struct usb_serial *serial);
 static void edge_release(struct usb_serial *serial);
@@ -1624,6 +1626,31 @@
 	return result;
 }
 
+static int edge_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+	struct async_icount cnow;
+	cnow = edge_port->icount;
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
+			__func__,  port->number, icount->rx, icount->tx);
+	return 0;
+}
+
 static int get_serial_info(struct edgeport_port *edge_port,
 				struct serial_struct __user *retinfo)
 {
@@ -1650,7 +1677,6 @@
 }
 
 
-
 /*****************************************************************************
  * SerialIoctl
  *	this function handles any ioctl calls to the driver
@@ -1663,7 +1689,6 @@
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	struct async_icount cnow;
 	struct async_icount cprev;
-	struct serial_icounter_struct icount;
 
 	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
@@ -1702,26 +1727,6 @@
 		/* NOTREACHED */
 		break;
 
-	case TIOCGICOUNT:
-		cnow = edge_port->icount;
-		memset(&icount, 0, sizeof(icount));
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-
-		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;
 	}
 	return -ENOIOCTLCMD;
 }
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index feb56a4..6ab2a3f 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -123,6 +123,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -152,6 +153,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -181,6 +183,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
@@ -209,6 +212,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index a7cfc59..4dad27a 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2510,6 +2510,27 @@
 	return result;
 }
 
+static int edge_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+	struct async_icount *ic = &edge_port->icount;
+
+	icount->cts = ic->cts;
+	icount->dsr = ic->dsr;
+	icount->rng = ic->rng;
+	icount->dcd = ic->dcd;
+	icount->tx = ic->tx;
+        icount->rx = ic->rx;
+        icount->frame = ic->frame;
+        icount->parity = ic->parity;
+        icount->overrun = ic->overrun;
+        icount->brk = ic->brk;
+        icount->buf_overrun = ic->buf_overrun;
+	return 0;
+}
+
 static int get_serial_info(struct edgeport_port *edge_port,
 				struct serial_struct __user *retinfo)
 {
@@ -2572,13 +2593,6 @@
 		}
 		/* not reached */
 		break;
-	case TIOCGICOUNT:
-		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;
-		return 0;
 	}
 	return -ENOIOCTLCMD;
 }
@@ -2758,6 +2772,7 @@
 	.set_termios		= edge_set_termios,
 	.tiocmget		= edge_tiocmget,
 	.tiocmset		= edge_tiocmset,
+	.get_icount		= edge_get_icount,
 	.write			= edge_write,
 	.write_room		= edge_write_room,
 	.chars_in_buffer	= edge_chars_in_buffer,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 7aa01b9..2849f8c 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -549,9 +549,12 @@
 {
 	dbg("%s port %d", __func__, port->number);
 
-	usb_serial_generic_close(port);
-	if (port->serial->dev)
+	if (port->serial->dev) {
+		/* shutdown our urbs */
+		usb_kill_urb(port->write_urb);
+		usb_kill_urb(port->read_urb);
 		usb_kill_urb(port->interrupt_in_urb);
+	}
 } /* mct_u232_close */
 
 
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index aa66581..fd0b641 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1896,10 +1896,37 @@
 	return 0;
 }
 
+static int mos7720_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct moschip_port *mos7720_port;
+	struct async_icount cnow;
+
+	mos7720_port = usb_get_serial_port_data(port);
+	cnow = mos7720_port->icount;
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+		port->number, icount->rx, icount->tx);
+	return 0;
+}
+
 static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
 			  unsigned int __user *value)
 {
-	unsigned int mcr ;
+	unsigned int mcr;
 	unsigned int arg;
 
 	struct usb_serial_port *port;
@@ -1973,7 +2000,6 @@
 	struct moschip_port *mos7720_port;
 	struct async_icount cnow;
 	struct async_icount cprev;
-	struct serial_icounter_struct icount;
 
 	mos7720_port = usb_get_serial_port_data(port);
 	if (mos7720_port == NULL)
@@ -2021,29 +2047,6 @@
 		}
 		/* NOTREACHED */
 		break;
-
-	case TIOCGICOUNT:
-		cnow = mos7720_port->icount;
-
-		memset(&icount, 0, sizeof(struct serial_icounter_struct));
-
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-
-		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;
 	}
 
 	return -ENOIOCTLCMD;
@@ -2212,6 +2215,7 @@
 	.ioctl			= mos7720_ioctl,
 	.tiocmget		= mos7720_tiocmget,
 	.tiocmset		= mos7720_tiocmset,
+	.get_icount		= mos7720_get_icount,
 	.set_termios		= mos7720_set_termios,
 	.write			= mos7720_write,
 	.write_room		= mos7720_write_room,
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 1a42bc2..93dad58 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -2209,6 +2209,34 @@
 	return 0;
 }
 
+static int mos7840_get_icount(struct tty_struct *tty,
+			struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct moschip_port *mos7840_port;
+	struct async_icount cnow;
+
+	mos7840_port = mos7840_get_port_private(port);
+	cnow = mos7840_port->icount;
+
+	smp_rmb();
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+		port->number, icount->rx, icount->tx);
+	return 0;
+}
+
 /*****************************************************************************
  * SerialIoctl
  *	this function handles any ioctl calls to the driver
@@ -2223,7 +2251,6 @@
 
 	struct async_icount cnow;
 	struct async_icount cprev;
-	struct serial_icounter_struct icount;
 
 	if (mos7840_port_paranoia_check(port, __func__)) {
 		dbg("%s", "Invalid port");
@@ -2282,29 +2309,6 @@
 		/* NOTREACHED */
 		break;
 
-	case TIOCGICOUNT:
-		cnow = mos7840_port->icount;
-		smp_rmb();
-
-		memset(&icount, 0, sizeof(struct serial_icounter_struct));
-
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-
-		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;
-		return 0;
 	default:
 		break;
 	}
@@ -2674,6 +2678,7 @@
 	.break_ctl = mos7840_break,
 	.tiocmget = mos7840_tiocmget,
 	.tiocmset = mos7840_tiocmset,
+	.get_icount = mos7840_get_icount,
 	.attach = mos7840_startup,
 	.disconnect = mos7840_disconnect,
 	.release = mos7840_release,
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index ed01f3b..eda1f92 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -96,8 +96,8 @@
 			/* real data, send it to the tty layer */
 			tty = tty_port_tty_get(&port->port);
 			if (tty) {
-				tty_insert_flip_string(tty, data,
-							       data_length);
+				tty_insert_flip_string(tty, data + 2,
+						       data_length);
 				tty_flip_buffer_push(tty);
 				tty_kref_put(tty);
 			}
@@ -108,10 +108,10 @@
 				else
 					priv->rts = true;
 			} else {
-			dev_dbg(&priv->udev->dev,
-				"Unknown data packet received from the device:"
-				" %2x %2x\n",
-				data[0], data[1]);
+				dev_dbg(&priv->udev->dev,
+					"Unknown data packet received from the device:"
+					" %2x %2x\n",
+					data[0], data[1]);
 			}
 		}
 	} else {
@@ -130,7 +130,7 @@
 						  priv->bulk_address),
 				  priv->bulk_in_buffer, priv->buffer_size,
 				  opticon_bulk_callback, priv);
-		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
 		if (result)
 			dev_err(&port->dev,
 			    "%s - failed resubmitting read urb, error %d\n",
@@ -187,6 +187,9 @@
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
 	kfree(urb->transfer_buffer);
 
+	/* setup packet may be set if we're using it for writing */
+	kfree(urb->setup_packet);
+
 	if (status)
 		dbg("%s - nonzero write bulk status received: %d",
 		    __func__, status);
@@ -237,10 +240,29 @@
 
 	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
-	usb_fill_bulk_urb(urb, serial->dev,
-			  usb_sndbulkpipe(serial->dev,
-					  port->bulk_out_endpointAddress),
-			  buffer, count, opticon_write_bulk_callback, priv);
+	if (port->bulk_out_endpointAddress) {
+		usb_fill_bulk_urb(urb, serial->dev,
+				  usb_sndbulkpipe(serial->dev,
+						  port->bulk_out_endpointAddress),
+				  buffer, count, opticon_write_bulk_callback, priv);
+	} else {
+		struct usb_ctrlrequest *dr;
+
+		dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+		if (!dr)
+			return -ENOMEM;
+
+		dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
+		dr->bRequest = 0x01;
+		dr->wValue = 0;
+		dr->wIndex = 0;
+		dr->wLength = cpu_to_le16(count);
+
+		usb_fill_control_urb(urb, serial->dev,
+			usb_sndctrlpipe(serial->dev, 0),
+			(unsigned char *)dr, buffer, count,
+			opticon_write_bulk_callback, priv);
+	}
 
 	/* send it down the pipe */
 	status = usb_submit_urb(urb, GFP_ATOMIC);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index c46911a..2297fb1 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -392,6 +392,12 @@
 #define CELOT_VENDOR_ID				0x211f
 #define CELOT_PRODUCT_CT680M			0x6801
 
+/* ONDA Communication vendor id */
+#define ONDA_VENDOR_ID       0x1ee8
+
+/* ONDA MT825UP HSDPA 14.2 modem */
+#define ONDA_MT825UP         0x000b
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
 		OPTION_BLACKLIST_NONE = 0,
@@ -622,6 +628,7 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) },
@@ -633,38 +640,52 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) },
+	/* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0038, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0040, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0044, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0050, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) },
+	/* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0056, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0065, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0079, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0082, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0106, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0108, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff) },
@@ -880,6 +901,8 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
@@ -925,6 +948,7 @@
 	{ USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) },
 	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
 	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
+	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index cde67ca..8858201 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -118,6 +118,8 @@
 
 	spin_lock_init(&data->susp_lock);
 
+	usb_enable_autosuspend(serial->dev);
+
 	switch (nintf) {
 	case 1:
 		/* QDL mode */
@@ -150,7 +152,22 @@
 	case 3:
 	case 4:
 		/* Composite mode */
-		if (ifnum == 2) {
+		/* ifnum == 0 is a broadband network adapter */
+		if (ifnum == 1) {
+			/*
+			 * Diagnostics Monitor (serial line 9600 8N1)
+			 * Qualcomm DM protocol
+			 * use "libqcdm" (ModemManager) for communication
+			 */
+			dbg("Diagnostics Monitor found");
+			retval = usb_set_interface(serial->dev, ifnum, 0);
+			if (retval < 0) {
+				dev_err(&serial->dev->dev,
+					"Could not set interface, error %d\n",
+					retval);
+				retval = -ENODEV;
+			}
+		} else if (ifnum == 2) {
 			dbg("Modem port found");
 			retval = usb_set_interface(serial->dev, ifnum, 0);
 			if (retval < 0) {
@@ -161,6 +178,20 @@
 				kfree(data);
 			}
 			return retval;
+		} else if (ifnum==3) {
+			/*
+			 * NMEA (serial line 9600 8N1)
+			 * # echo "\$GPS_START" > /dev/ttyUSBx
+			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx
+			 */
+			dbg("NMEA GPS interface found");
+			retval = usb_set_interface(serial->dev, ifnum, 0);
+			if (retval < 0) {
+				dev_err(&serial->dev->dev,
+					"Could not set interface, error %d\n",
+					retval);
+				retval = -ENODEV;
+			}
 		}
 		break;
 
diff --git a/drivers/usb/serial/sam-ba.c b/drivers/usb/serial/sam-ba.c
new file mode 100644
index 0000000..e3bba64
--- /dev/null
+++ b/drivers/usb/serial/sam-ba.c
@@ -0,0 +1,206 @@
+/*
+ * Atmel SAM Boot Assistant (SAM-BA) driver
+ *
+ * Copyright (C) 2010 Johan Hovold <jhovold@gmail.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/tty.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+
+#define DRIVER_VERSION	"v1.0"
+#define DRIVER_AUTHOR	"Johan Hovold <jhovold@gmail.com>"
+#define DRIVER_DESC	"Atmel SAM Boot Assistant (SAM-BA) driver"
+
+#define SAMBA_VENDOR_ID		0x3eb
+#define SAMBA_PRODUCT_ID	0x6124
+
+
+static int debug;
+
+static const struct usb_device_id id_table[] = {
+	/*
+	 * NOTE: Only match the CDC Data interface.
+	 */
+	{ USB_DEVICE_AND_INTERFACE_INFO(SAMBA_VENDOR_ID, SAMBA_PRODUCT_ID,
+					USB_CLASS_CDC_DATA, 0, 0) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver samba_driver = {
+	.name		= "sam-ba",
+	.probe		= usb_serial_probe,
+	.disconnect	= usb_serial_disconnect,
+	.id_table	= id_table,
+	.no_dynamic_id	= 1,
+};
+
+
+/*
+ * NOTE: The SAM-BA firmware cannot handle merged write requests so we cannot
+ *       use the generic write implementation (which uses the port write fifo).
+ */
+static int samba_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
+{
+	struct urb *urb;
+	unsigned long flags;
+	int result;
+	int i;
+
+	if (!count)
+		return 0;
+
+	count = min_t(int, count, port->bulk_out_size);
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (!port->write_urbs_free) {
+		spin_unlock_irqrestore(&port->lock, flags);
+		return 0;
+	}
+	i = find_first_bit(&port->write_urbs_free,
+						ARRAY_SIZE(port->write_urbs));
+	__clear_bit(i, &port->write_urbs_free);
+	port->tx_bytes += count;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	urb = port->write_urbs[i];
+	memcpy(urb->transfer_buffer, buf, count);
+	urb->transfer_buffer_length = count;
+	usb_serial_debug_data(debug, &port->dev, __func__, count,
+						urb->transfer_buffer);
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result) {
+		dev_err(&port->dev, "%s - error submitting urb: %d\n",
+						__func__, result);
+		spin_lock_irqsave(&port->lock, flags);
+		__set_bit(i, &port->write_urbs_free);
+		port->tx_bytes -= count;
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		return result;
+	}
+
+	return count;
+}
+
+static int samba_write_room(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	unsigned long flags;
+	unsigned long free;
+	int count;
+	int room;
+
+	spin_lock_irqsave(&port->lock, flags);
+	free = port->write_urbs_free;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	count = hweight_long(free);
+	room = count * port->bulk_out_size;
+
+	dbg("%s - returns %d", __func__, room);
+
+	return room;
+}
+
+static int samba_chars_in_buffer(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	unsigned long flags;
+	int chars;
+
+	spin_lock_irqsave(&port->lock, flags);
+	chars = port->tx_bytes;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	dbg("%s - returns %d", __func__, chars);
+
+	return chars;
+}
+
+static void samba_write_bulk_callback(struct urb *urb)
+{
+	struct usb_serial_port *port = urb->context;
+	unsigned long flags;
+	int i;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
+		if (port->write_urbs[i] == urb)
+			break;
+	}
+	spin_lock_irqsave(&port->lock, flags);
+	__set_bit(i, &port->write_urbs_free);
+	port->tx_bytes -= urb->transfer_buffer_length;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (urb->status)
+		dbg("%s - non-zero urb status: %d", __func__, urb->status);
+
+	usb_serial_port_softint(port);
+}
+
+static struct usb_serial_driver samba_device = {
+	.driver = {
+		.owner		= THIS_MODULE,
+		.name		= "sam-ba",
+	},
+	.usb_driver		= &samba_driver,
+	.id_table		= id_table,
+	.num_ports		= 1,
+	.bulk_in_size		= 512,
+	.bulk_out_size		= 2048,
+	.write			= samba_write,
+	.write_room		= samba_write_room,
+	.chars_in_buffer	= samba_chars_in_buffer,
+	.write_bulk_callback	= samba_write_bulk_callback,
+	.throttle		= usb_serial_generic_throttle,
+	.unthrottle		= usb_serial_generic_unthrottle,
+};
+
+static int __init samba_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&samba_device);
+	if (retval)
+		return retval;
+
+	retval = usb_register(&samba_driver);
+	if (retval) {
+		usb_serial_deregister(&samba_device);
+		return retval;
+	}
+
+	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": "
+							DRIVER_DESC "\n");
+	return 0;
+}
+
+static void __exit samba_exit(void)
+{
+	usb_deregister(&samba_driver);
+	usb_serial_deregister(&samba_device);
+}
+
+module_init(samba_init);
+module_exit(samba_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable verbose debugging messages");
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index e986002..f5312dd333 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -416,12 +416,34 @@
 	return 0;
 }
 
+static int ssu100_get_icount(struct tty_struct *tty,
+			struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
+	struct async_icount cnow = priv->icount;
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
+
+
+
 static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
 		    unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	struct ssu100_port_private *priv = usb_get_serial_port_data(port);
-	void __user *user_arg = (void __user *)arg;
 
 	dbg("%s cmd 0x%04x", __func__, cmd);
 
@@ -433,27 +455,6 @@
 	case TIOCMIWAIT:
 		return wait_modem_info(port, arg);
 
-	case TIOCGICOUNT:
-	{
-		struct serial_icounter_struct icount;
-		struct async_icount cnow = priv->icount;
-		memset(&icount, 0, sizeof(icount));
-		icount.cts = cnow.cts;
-		icount.dsr = cnow.dsr;
-		icount.rng = cnow.rng;
-		icount.dcd = cnow.dcd;
-		icount.rx = cnow.rx;
-		icount.tx = cnow.tx;
-		icount.frame = cnow.frame;
-		icount.overrun = cnow.overrun;
-		icount.parity = cnow.parity;
-		icount.brk = cnow.brk;
-		icount.buf_overrun = cnow.buf_overrun;
-		if (copy_to_user(user_arg, &icount, sizeof(icount)))
-			return -EFAULT;
-		return 0;
-	}
-
 	default:
 		break;
 	}
@@ -726,6 +727,7 @@
 	.process_read_urb    = ssu100_process_read_urb,
 	.tiocmget            = ssu100_tiocmget,
 	.tiocmset            = ssu100_tiocmset,
+	.get_icount	     = ssu100_get_icount,
 	.ioctl               = ssu100_ioctl,
 	.set_termios         = ssu100_set_termios,
 	.disconnect          = usb_serial_generic_disconnect,
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 90979a1..b2902f3 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -108,6 +108,8 @@
 static void ti_unthrottle(struct tty_struct *tty);
 static int ti_ioctl(struct tty_struct *tty, struct file *file,
 		unsigned int cmd, unsigned long arg);
+static int ti_get_icount(struct tty_struct *tty,
+		struct serial_icounter_struct *icount);
 static void ti_set_termios(struct tty_struct *tty,
 		struct usb_serial_port *port, struct ktermios *old_termios);
 static int ti_tiocmget(struct tty_struct *tty, struct file *file);
@@ -237,6 +239,7 @@
 	.set_termios		= ti_set_termios,
 	.tiocmget		= ti_tiocmget,
 	.tiocmset		= ti_tiocmset,
+	.get_icount		= ti_get_icount,
 	.break_ctl		= ti_break,
 	.read_int_callback	= ti_interrupt_callback,
 	.read_bulk_callback	= ti_bulk_in_callback,
@@ -265,6 +268,7 @@
 	.set_termios		= ti_set_termios,
 	.tiocmget		= ti_tiocmget,
 	.tiocmset		= ti_tiocmset,
+	.get_icount		= ti_get_icount,
 	.break_ctl		= ti_break,
 	.read_int_callback	= ti_interrupt_callback,
 	.read_bulk_callback	= ti_bulk_in_callback,
@@ -788,6 +792,31 @@
 	}
 }
 
+static int ti_get_icount(struct tty_struct *tty,
+		struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct ti_port *tport = usb_get_serial_port_data(port);
+	struct async_icount cnow = tport->tp_icount;
+
+	dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
+		__func__, port->number,
+		cnow.rx, cnow.tx);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
 
 static int ti_ioctl(struct tty_struct *tty, struct file *file,
 	unsigned int cmd, unsigned long arg)
@@ -830,14 +859,6 @@
 			cprev = cnow;
 		}
 		break;
-	case TIOCGICOUNT:
-		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;
 	}
 	return -ENOIOCTLCMD;
 }
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 7a2177c..e64da74 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -519,6 +519,18 @@
 	return -EINVAL;
 }
 
+static int serial_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct usb_serial_port *port = tty->driver_data;
+
+	dbg("%s - port %d", __func__, port->number);
+
+	if (port->serial->type->get_icount)
+		return port->serial->type->get_icount(tty, icount);
+	return -EINVAL;
+}
+
 /*
  * We would be calling tty_wakeup here, but unfortunately some line
  * disciplines have an annoying habit of calling tty->write from
@@ -1195,6 +1207,7 @@
 	.chars_in_buffer =	serial_chars_in_buffer,
 	.tiocmget =		serial_tiocmget,
 	.tiocmset =		serial_tiocmset,
+	.get_icount = 		serial_get_icount,
 	.cleanup = 		serial_cleanup,
 	.install = 		serial_install,
 	.proc_fops =		&serial_proc_fops,
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index eb76aae..15a5d89 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -606,6 +606,10 @@
 
 static int clie_5_attach(struct usb_serial *serial)
 {
+	struct usb_serial_port *port;
+	unsigned int pipe;
+	int j;
+
 	dbg("%s", __func__);
 
 	/* TH55 registers 2 ports.
@@ -621,9 +625,14 @@
 		return -1;
 
 	/* port 0 now uses the modified endpoint Address */
-	serial->port[0]->bulk_out_endpointAddress =
+	port = serial->port[0];
+	port->bulk_out_endpointAddress =
 				serial->port[1]->bulk_out_endpointAddress;
 
+	pipe = usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress);
+	for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j)
+		port->write_urbs[j]->pipe = pipe;
+
 	return 0;
 }
 
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 8a372ba..f2767cf 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -172,6 +172,19 @@
 
 	  If this driver is compiled as a module, it will be named ums-cypress.
 
+config USB_UAS
+	tristate "USB Attached SCSI"
+	depends on USB && SCSI
+	help
+	  The USB Attached SCSI protocol is supported by some USB
+	  storage devices.  It permits higher performance by supporting
+	  multiple outstanding commands.
+
+	  If you don't know whether you have a UAS device, it is safe to
+	  say 'Y' or 'M' here and the kernel will use the right driver.
+
+	  If you compile this driver as a module, it will be named uas.
+
 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 ef7e5a8..fcf14cd 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -5,20 +5,21 @@
 # Rewritten to use lists instead of if-statements.
 #
 
-EXTRA_CFLAGS	:= -Idrivers/scsi
+ccflags-y := -Idrivers/scsi
 
+obj-$(CONFIG_USB_UAS)		+= uas.o
 obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
 
-usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
+usb-storage-y := scsiglue.o protocol.o transport.o usb.o
+usb-storage-y += initializers.o sierra_ms.o option_ms.o
 
-usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
-			initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y)
+usb-storage-$(CONFIG_USB_STORAGE_DEBUG) += debug.o
 
 ifeq ($(CONFIG_USB_LIBUSUAL),)
-	usb-storage-objs	+= usual-tables.o
+	usb-storage-y		+= usual-tables.o
 else
 	obj-$(CONFIG_USB)	+= usb-libusual.o
-	usb-libusual-objs	:= libusual.o usual-tables.o
+	usb-libusual-y		:= libusual.o usual-tables.o
 endif
 
 obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= ums-alauda.o
@@ -33,14 +34,14 @@
 obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
 obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
 
-ums-alauda-objs		:= alauda.o
-ums-cypress-objs	:= cypress_atacb.o
-ums-datafab-objs	:= datafab.o
-ums-freecom-objs	:= freecom.o
-ums-isd200-objs		:= isd200.o
-ums-jumpshot-objs	:= jumpshot.o
-ums-karma-objs		:= karma.o
-ums-onetouch-objs	:= onetouch.o
-ums-sddr09-objs		:= sddr09.o
-ums-sddr55-objs		:= sddr55.o
-ums-usbat-objs		:= shuttle_usbat.o
+ums-alauda-y		:= alauda.o
+ums-cypress-y		:= cypress_atacb.o
+ums-datafab-y		:= datafab.o
+ums-freecom-y		:= freecom.o
+ums-isd200-y		:= isd200.o
+ums-jumpshot-y		:= jumpshot.o
+ums-karma-y		:= karma.o
+ums-onetouch-y		:= onetouch.o
+ums-sddr09-y		:= sddr09.o
+ums-sddr55-y		:= sddr55.o
+ums-usbat-y		:= shuttle_usbat.o
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index d8d98cf..a688b1e 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -113,7 +113,7 @@
 	 * Let the scanning code know if this target merely sets
 	 * Peripheral Device Type to 0x1f to indicate no LUN.
 	 */
-	if (us->subclass == US_SC_UFI)
+	if (us->subclass == USB_SC_UFI)
 		sdev->sdev_target->pdt_1f_for_no_lun = 1;
 
 	return 0;
@@ -176,7 +176,7 @@
 		/* 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 && us->subclass != US_SC_CYP_ATACB)
+		if (us->subclass != USB_SC_SCSI && us->subclass != USB_SC_CYP_ATACB)
 			sdev->use_10_for_ms = 1;
 
 		/* Many disks only accept MODE SENSE transfer lengths of
@@ -209,6 +209,10 @@
 		if (us->fflags & US_FL_CAPACITY_HEURISTICS)
 			sdev->guess_capacity = 1;
 
+		/* Some devices cannot handle READ_CAPACITY_16 */
+		if (us->fflags & US_FL_NO_READ_CAPACITY_16)
+			sdev->no_read_capacity_16 = 1;
+
 		/* assume SPC3 or latter devices support sense size > 18 */
 		if (sdev->scsi_level > SCSI_SPC_2)
 			us->fflags |= US_FL_SANE_SENSE;
@@ -245,7 +249,7 @@
 		 * capacity will be decremented or is correct. */
 		if (!(us->fflags & (US_FL_FIX_CAPACITY | US_FL_CAPACITY_OK |
 					US_FL_SCM_MULT_TARG)) &&
-				us->protocol == US_PR_BULK)
+				us->protocol == USB_PR_BULK)
 			us->use_last_sector_hacks = 1;
 	} else {
 
@@ -253,6 +257,10 @@
 		 * or to force 192-byte transfer lengths for MODE SENSE.
 		 * But they do need to use MODE SENSE(10). */
 		sdev->use_10_for_ms = 1;
+
+		/* Some (fake) usb cdrom devices don't like READ_DISC_INFO */
+		if (us->fflags & US_FL_NO_READ_DISC_INFO)
+			sdev->no_read_disc_info = 1;
 	}
 
 	/* The CB and CBI transports have no way to pass LUN values
@@ -261,7 +269,7 @@
 	 * scsi_level == 0 (UNKNOWN).  Hence such devices must necessarily
 	 * be single-LUN.
 	 */
-	if ((us->protocol == US_PR_CB || us->protocol == US_PR_CBI) &&
+	if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_CBI) &&
 			sdev->scsi_level == SCSI_UNKNOWN)
 		us->max_lun = 0;
 
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index ab5f9f3..bcb9a70 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -1760,7 +1760,7 @@
 	if (result)
 		return result;
 
-	if (us->protocol == US_PR_DPCM_USB) {
+	if (us->protocol == USB_PR_DPCM_USB) {
 		us->transport_name = "Control/Bulk-EUSB/SDDR09";
 		us->transport = dpcm_transport;
 		us->transport_reset = usb_stor_CB_reset;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 64ec073..0041899 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -642,7 +642,7 @@
 	 * unless the operation involved a data-in transfer.  Devices
 	 * can signal most data-in errors by stalling the bulk-in pipe.
 	 */
-	if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&
+	if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) &&
 			srb->sc_data_direction != DMA_FROM_DEVICE) {
 		US_DEBUGP("-- CB transport device requiring auto-sense\n");
 		need_auto_sense = 1;
@@ -701,8 +701,8 @@
 		scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
 
 		/* FIXME: we must do the protocol translation here */
-		if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI ||
-				us->subclass == US_SC_CYP_ATACB)
+		if (us->subclass == USB_SC_RBC || us->subclass == USB_SC_SCSI ||
+				us->subclass == USB_SC_CYP_ATACB)
 			srb->cmd_len = 6;
 		else
 			srb->cmd_len = 12;
@@ -926,7 +926,7 @@
 	/* NOTE: CB does not have a status stage.  Silly, I know.  So
 	 * we have to catch this at a higher level.
 	 */
-	if (us->protocol != US_PR_CBI)
+	if (us->protocol != USB_PR_CBI)
 		return USB_STOR_TRANSPORT_GOOD;
 
 	result = usb_stor_intr_transfer(us, us->iobuf, 2);
@@ -942,7 +942,7 @@
 	 * that this means we could be ignoring a real error on these
 	 * commands, but that can't be helped.
 	 */
-	if (us->subclass == US_SC_UFI) {
+	if (us->subclass == USB_SC_UFI) {
 		if (srb->cmnd[0] == REQUEST_SENSE ||
 		    srb->cmnd[0] == INQUIRY)
 			return USB_STOR_TRANSPORT_GOOD;
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
new file mode 100644
index 0000000..2054b1e
--- /dev/null
+++ b/drivers/usb/storage/uas.c
@@ -0,0 +1,751 @@
+/*
+ * USB Attached SCSI
+ * Note that this is not the same as the USB Mass Storage driver
+ *
+ * Copyright Matthew Wilcox for Intel Corp, 2010
+ * Copyright Sarah Sharp for Intel Corp, 2010
+ *
+ * Distributed under the terms of the GNU GPL, version two.
+ */
+
+#include <linux/blkdev.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/usb.h>
+#include <linux/usb/storage.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+/* Common header for all IUs */
+struct iu {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+};
+
+enum {
+	IU_ID_COMMAND		= 0x01,
+	IU_ID_STATUS		= 0x03,
+	IU_ID_RESPONSE		= 0x04,
+	IU_ID_TASK_MGMT		= 0x05,
+	IU_ID_READ_READY	= 0x06,
+	IU_ID_WRITE_READY	= 0x07,
+};
+
+struct command_iu {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+	__u8 prio_attr;
+	__u8 rsvd5;
+	__u8 len;
+	__u8 rsvd7;
+	struct scsi_lun lun;
+	__u8 cdb[16];	/* XXX: Overflow-checking tools may misunderstand */
+};
+
+struct sense_iu {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+	__be16 status_qual;
+	__u8 status;
+	__u8 service_response;
+	__u8 rsvd8[6];
+	__be16 len;
+	__u8 sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+/*
+ * The r00-r01c specs define this version of the SENSE IU data structure.
+ * It's still in use by several different firmware releases.
+ */
+struct sense_iu_old {
+	__u8 iu_id;
+	__u8 rsvd1;
+	__be16 tag;
+	__be16 len;
+	__u8 status;
+	__u8 service_response;
+	__u8 sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+enum {
+	CMD_PIPE_ID		= 1,
+	STATUS_PIPE_ID		= 2,
+	DATA_IN_PIPE_ID		= 3,
+	DATA_OUT_PIPE_ID	= 4,
+
+	UAS_SIMPLE_TAG		= 0,
+	UAS_HEAD_TAG		= 1,
+	UAS_ORDERED_TAG		= 2,
+	UAS_ACA			= 4,
+};
+
+struct uas_dev_info {
+	struct usb_interface *intf;
+	struct usb_device *udev;
+	int qdepth;
+	unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
+	unsigned use_streams:1;
+	unsigned uas_sense_old:1;
+};
+
+enum {
+	ALLOC_SENSE_URB		= (1 << 0),
+	SUBMIT_SENSE_URB	= (1 << 1),
+	ALLOC_DATA_IN_URB	= (1 << 2),
+	SUBMIT_DATA_IN_URB	= (1 << 3),
+	ALLOC_DATA_OUT_URB	= (1 << 4),
+	SUBMIT_DATA_OUT_URB	= (1 << 5),
+	ALLOC_CMD_URB		= (1 << 6),
+	SUBMIT_CMD_URB		= (1 << 7),
+};
+
+/* Overrides scsi_pointer */
+struct uas_cmd_info {
+	unsigned int state;
+	unsigned int stream;
+	struct urb *cmd_urb;
+	struct urb *sense_urb;
+	struct urb *data_in_urb;
+	struct urb *data_out_urb;
+	struct list_head list;
+};
+
+/* I hate forward declarations, but I actually have a loop */
+static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+				struct uas_dev_info *devinfo, gfp_t gfp);
+
+static DEFINE_SPINLOCK(uas_work_lock);
+static LIST_HEAD(uas_work_list);
+
+static void uas_do_work(struct work_struct *work)
+{
+	struct uas_cmd_info *cmdinfo;
+	struct list_head list;
+
+	spin_lock_irq(&uas_work_lock);
+	list_replace_init(&uas_work_list, &list);
+	spin_unlock_irq(&uas_work_lock);
+
+	list_for_each_entry(cmdinfo, &list, list) {
+		struct scsi_pointer *scp = (void *)cmdinfo;
+		struct scsi_cmnd *cmnd = container_of(scp,
+							struct scsi_cmnd, SCp);
+		uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_KERNEL);
+	}
+}
+
+static DECLARE_WORK(uas_work, uas_do_work);
+
+static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
+{
+	struct sense_iu *sense_iu = urb->transfer_buffer;
+	struct scsi_device *sdev = cmnd->device;
+
+	if (urb->actual_length > 16) {
+		unsigned len = be16_to_cpup(&sense_iu->len);
+		if (len + 16 != urb->actual_length) {
+			int newlen = min(len + 16, urb->actual_length) - 16;
+			if (newlen < 0)
+				newlen = 0;
+			sdev_printk(KERN_INFO, sdev, "%s: urb length %d "
+				"disagrees with IU sense data length %d, "
+				"using %d bytes of sense data\n", __func__,
+					urb->actual_length, len, newlen);
+			len = newlen;
+		}
+		memcpy(cmnd->sense_buffer, sense_iu->sense, len);
+	}
+
+	cmnd->result = sense_iu->status;
+	if (sdev->current_cmnd)
+		sdev->current_cmnd = NULL;
+	cmnd->scsi_done(cmnd);
+	usb_free_urb(urb);
+}
+
+static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
+{
+	struct sense_iu_old *sense_iu = urb->transfer_buffer;
+	struct scsi_device *sdev = cmnd->device;
+
+	if (urb->actual_length > 8) {
+		unsigned len = be16_to_cpup(&sense_iu->len) - 2;
+		if (len + 8 != urb->actual_length) {
+			int newlen = min(len + 8, urb->actual_length) - 8;
+			if (newlen < 0)
+				newlen = 0;
+			sdev_printk(KERN_INFO, sdev, "%s: urb length %d "
+				"disagrees with IU sense data length %d, "
+				"using %d bytes of sense data\n", __func__,
+					urb->actual_length, len, newlen);
+			len = newlen;
+		}
+		memcpy(cmnd->sense_buffer, sense_iu->sense, len);
+	}
+
+	cmnd->result = sense_iu->status;
+	if (sdev->current_cmnd)
+		sdev->current_cmnd = NULL;
+	cmnd->scsi_done(cmnd);
+	usb_free_urb(urb);
+}
+
+static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
+							unsigned direction)
+{
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+	int err;
+
+	cmdinfo->state = direction | SUBMIT_SENSE_URB;
+	err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
+	if (err) {
+		spin_lock(&uas_work_lock);
+		list_add_tail(&cmdinfo->list, &uas_work_list);
+		spin_unlock(&uas_work_lock);
+		schedule_work(&uas_work);
+	}
+}
+
+static void uas_stat_cmplt(struct urb *urb)
+{
+	struct iu *iu = urb->transfer_buffer;
+	struct scsi_device *sdev = urb->context;
+	struct uas_dev_info *devinfo = sdev->hostdata;
+	struct scsi_cmnd *cmnd;
+	u16 tag;
+
+	if (urb->status) {
+		dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
+		usb_free_urb(urb);
+		return;
+	}
+
+	tag = be16_to_cpup(&iu->tag) - 1;
+	if (sdev->current_cmnd)
+		cmnd = sdev->current_cmnd;
+	else
+		cmnd = scsi_find_tag(sdev, tag);
+	if (!cmnd)
+		return;
+
+	switch (iu->iu_id) {
+	case IU_ID_STATUS:
+		if (urb->actual_length < 16)
+			devinfo->uas_sense_old = 1;
+		if (devinfo->uas_sense_old)
+			uas_sense_old(urb, cmnd);
+		else
+			uas_sense(urb, cmnd);
+		break;
+	case IU_ID_READ_READY:
+		uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB);
+		break;
+	case IU_ID_WRITE_READY:
+		uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB);
+		break;
+	default:
+		scmd_printk(KERN_ERR, cmnd,
+			"Bogus IU (%d) received on status pipe\n", iu->iu_id);
+	}
+}
+
+static void uas_data_cmplt(struct urb *urb)
+{
+	struct scsi_data_buffer *sdb = urb->context;
+	sdb->resid = sdb->length - urb->actual_length;
+	usb_free_urb(urb);
+}
+
+static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
+				unsigned int pipe, u16 stream_id,
+				struct scsi_data_buffer *sdb,
+				enum dma_data_direction dir)
+{
+	struct usb_device *udev = devinfo->udev;
+	struct urb *urb = usb_alloc_urb(0, gfp);
+
+	if (!urb)
+		goto out;
+	usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt,
+									sdb);
+	if (devinfo->use_streams)
+		urb->stream_id = stream_id;
+	urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
+	urb->sg = sdb->table.sgl;
+ out:
+	return urb;
+}
+
+static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
+					struct scsi_cmnd *cmnd, u16 stream_id)
+{
+	struct usb_device *udev = devinfo->udev;
+	struct urb *urb = usb_alloc_urb(0, gfp);
+	struct sense_iu *iu;
+
+	if (!urb)
+		goto out;
+
+	iu = kmalloc(sizeof(*iu), gfp);
+	if (!iu)
+		goto free;
+
+	usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
+						uas_stat_cmplt, cmnd->device);
+	urb->stream_id = stream_id;
+	urb->transfer_flags |= URB_FREE_BUFFER;
+ out:
+	return urb;
+ free:
+	usb_free_urb(urb);
+	return NULL;
+}
+
+static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
+					struct scsi_cmnd *cmnd, u16 stream_id)
+{
+	struct usb_device *udev = devinfo->udev;
+	struct scsi_device *sdev = cmnd->device;
+	struct urb *urb = usb_alloc_urb(0, gfp);
+	struct command_iu *iu;
+	int len;
+
+	if (!urb)
+		goto out;
+
+	len = cmnd->cmd_len - 16;
+	if (len < 0)
+		len = 0;
+	len = ALIGN(len, 4);
+	iu = kmalloc(sizeof(*iu) + len, gfp);
+	if (!iu)
+		goto free;
+
+	iu->iu_id = IU_ID_COMMAND;
+	iu->tag = cpu_to_be16(stream_id);
+	if (sdev->ordered_tags && (cmnd->request->cmd_flags & REQ_HARDBARRIER))
+		iu->prio_attr = UAS_ORDERED_TAG;
+	else
+		iu->prio_attr = UAS_SIMPLE_TAG;
+	iu->len = len;
+	int_to_scsilun(sdev->lun, &iu->lun);
+	memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);
+
+	usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu) + len,
+							usb_free_urb, NULL);
+	urb->transfer_flags |= URB_FREE_BUFFER;
+ out:
+	return urb;
+ free:
+	usb_free_urb(urb);
+	return NULL;
+}
+
+/*
+ * Why should I request the Status IU before sending the Command IU?  Spec
+ * says to, but also says the device may receive them in any order.  Seems
+ * daft to me.
+ */
+
+static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+					struct uas_dev_info *devinfo, gfp_t gfp)
+{
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+
+	if (cmdinfo->state & ALLOC_SENSE_URB) {
+		cmdinfo->sense_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
+							cmdinfo->stream);
+		if (!cmdinfo->sense_urb)
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		cmdinfo->state &= ~ALLOC_SENSE_URB;
+	}
+
+	if (cmdinfo->state & SUBMIT_SENSE_URB) {
+		if (usb_submit_urb(cmdinfo->sense_urb, gfp)) {
+			scmd_printk(KERN_INFO, cmnd,
+					"sense urb submission failure\n");
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		cmdinfo->state &= ~SUBMIT_SENSE_URB;
+	}
+
+	if (cmdinfo->state & ALLOC_DATA_IN_URB) {
+		cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
+					devinfo->data_in_pipe, cmdinfo->stream,
+					scsi_in(cmnd), DMA_FROM_DEVICE);
+		if (!cmdinfo->data_in_urb)
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		cmdinfo->state &= ~ALLOC_DATA_IN_URB;
+	}
+
+	if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
+		if (usb_submit_urb(cmdinfo->data_in_urb, gfp)) {
+			scmd_printk(KERN_INFO, cmnd,
+					"data in urb submission failure\n");
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
+	}
+
+	if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
+		cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
+					devinfo->data_out_pipe, cmdinfo->stream,
+					scsi_out(cmnd), DMA_TO_DEVICE);
+		if (!cmdinfo->data_out_urb)
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
+	}
+
+	if (cmdinfo->state & SUBMIT_DATA_OUT_URB) {
+		if (usb_submit_urb(cmdinfo->data_out_urb, gfp)) {
+			scmd_printk(KERN_INFO, cmnd,
+					"data out urb submission failure\n");
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
+	}
+
+	if (cmdinfo->state & ALLOC_CMD_URB) {
+		cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd,
+							cmdinfo->stream);
+		if (!cmdinfo->cmd_urb)
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		cmdinfo->state &= ~ALLOC_CMD_URB;
+	}
+
+	if (cmdinfo->state & SUBMIT_CMD_URB) {
+		if (usb_submit_urb(cmdinfo->cmd_urb, gfp)) {
+			scmd_printk(KERN_INFO, cmnd,
+					"cmd urb submission failure\n");
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		cmdinfo->state &= ~SUBMIT_CMD_URB;
+	}
+
+	return 0;
+}
+
+static int uas_queuecommand(struct scsi_cmnd *cmnd,
+					void (*done)(struct scsi_cmnd *))
+{
+	struct scsi_device *sdev = cmnd->device;
+	struct uas_dev_info *devinfo = sdev->hostdata;
+	struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+	int err;
+
+	BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
+
+	if (!cmdinfo->sense_urb && sdev->current_cmnd)
+		return SCSI_MLQUEUE_DEVICE_BUSY;
+
+	if (blk_rq_tagged(cmnd->request)) {
+		cmdinfo->stream = cmnd->request->tag + 1;
+	} else {
+		sdev->current_cmnd = cmnd;
+		cmdinfo->stream = 1;
+	}
+
+	cmnd->scsi_done = done;
+
+	cmdinfo->state = ALLOC_SENSE_URB | SUBMIT_SENSE_URB |
+			ALLOC_CMD_URB | SUBMIT_CMD_URB;
+
+	switch (cmnd->sc_data_direction) {
+	case DMA_FROM_DEVICE:
+		cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
+		break;
+	case DMA_BIDIRECTIONAL:
+		cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
+	case DMA_TO_DEVICE:
+		cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB;
+	case DMA_NONE:
+		break;
+	}
+
+	if (!devinfo->use_streams) {
+		cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
+		cmdinfo->stream = 0;
+	}
+
+	err = uas_submit_urbs(cmnd, devinfo, GFP_ATOMIC);
+	if (err) {
+		/* If we did nothing, give up now */
+		if (cmdinfo->state & SUBMIT_SENSE_URB) {
+			usb_free_urb(cmdinfo->sense_urb);
+			return SCSI_MLQUEUE_DEVICE_BUSY;
+		}
+		spin_lock(&uas_work_lock);
+		list_add_tail(&cmdinfo->list, &uas_work_list);
+		spin_unlock(&uas_work_lock);
+		schedule_work(&uas_work);
+	}
+
+	return 0;
+}
+
+static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
+{
+	struct scsi_device *sdev = cmnd->device;
+	sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
+							cmnd->request->tag);
+
+/* XXX: Send ABORT TASK Task Management command */
+	return FAILED;
+}
+
+static int uas_eh_device_reset_handler(struct scsi_cmnd *cmnd)
+{
+	struct scsi_device *sdev = cmnd->device;
+	sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
+							cmnd->request->tag);
+
+/* XXX: Send LOGICAL UNIT RESET Task Management command */
+	return FAILED;
+}
+
+static int uas_eh_target_reset_handler(struct scsi_cmnd *cmnd)
+{
+	struct scsi_device *sdev = cmnd->device;
+	sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
+							cmnd->request->tag);
+
+/* XXX: Can we reset just the one USB interface?
+ * Would calling usb_set_interface() have the right effect?
+ */
+	return FAILED;
+}
+
+static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
+{
+	struct scsi_device *sdev = cmnd->device;
+	struct uas_dev_info *devinfo = sdev->hostdata;
+	struct usb_device *udev = devinfo->udev;
+
+	sdev_printk(KERN_INFO, sdev, "%s tag %d\n", __func__,
+							cmnd->request->tag);
+
+	if (usb_reset_device(udev))
+		return SUCCESS;
+
+	return FAILED;
+}
+
+static int uas_slave_alloc(struct scsi_device *sdev)
+{
+	sdev->hostdata = (void *)sdev->host->hostdata[0];
+	return 0;
+}
+
+static int uas_slave_configure(struct scsi_device *sdev)
+{
+	struct uas_dev_info *devinfo = sdev->hostdata;
+	scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
+	scsi_activate_tcq(sdev, devinfo->qdepth - 1);
+	return 0;
+}
+
+static struct scsi_host_template uas_host_template = {
+	.module = THIS_MODULE,
+	.name = "uas",
+	.queuecommand = uas_queuecommand,
+	.slave_alloc = uas_slave_alloc,
+	.slave_configure = uas_slave_configure,
+	.eh_abort_handler = uas_eh_abort_handler,
+	.eh_device_reset_handler = uas_eh_device_reset_handler,
+	.eh_target_reset_handler = uas_eh_target_reset_handler,
+	.eh_bus_reset_handler = uas_eh_bus_reset_handler,
+	.can_queue = 65536,	/* Is there a limit on the _host_ ? */
+	.this_id = -1,
+	.sg_tablesize = SG_NONE,
+	.cmd_per_lun = 1,	/* until we override it */
+	.skip_settle_delay = 1,
+	.ordered_tag = 1,
+};
+
+static struct usb_device_id uas_usb_ids[] = {
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) },
+	/* 0xaa is a prototype device I happen to have access to */
+	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, 0xaa) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, uas_usb_ids);
+
+static void uas_configure_endpoints(struct uas_dev_info *devinfo)
+{
+	struct usb_host_endpoint *eps[4] = { };
+	struct usb_interface *intf = devinfo->intf;
+	struct usb_device *udev = devinfo->udev;
+	struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint;
+	unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;
+
+	devinfo->uas_sense_old = 0;
+
+	for (i = 0; i < n_endpoints; i++) {
+		unsigned char *extra = endpoint[i].extra;
+		int len = endpoint[i].extralen;
+		while (len > 1) {
+			if (extra[1] == USB_DT_PIPE_USAGE) {
+				unsigned pipe_id = extra[2];
+				if (pipe_id > 0 && pipe_id < 5)
+					eps[pipe_id - 1] = &endpoint[i];
+				break;
+			}
+			len -= extra[0];
+			extra += extra[0];
+		}
+	}
+
+	/*
+	 * Assume that if we didn't find a control pipe descriptor, we're
+	 * using a device with old firmware that happens to be set up like
+	 * this.
+	 */
+	if (!eps[0]) {
+		devinfo->cmd_pipe = usb_sndbulkpipe(udev, 1);
+		devinfo->status_pipe = usb_rcvbulkpipe(udev, 1);
+		devinfo->data_in_pipe = usb_rcvbulkpipe(udev, 2);
+		devinfo->data_out_pipe = usb_sndbulkpipe(udev, 2);
+
+		eps[1] = usb_pipe_endpoint(udev, devinfo->status_pipe);
+		eps[2] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
+		eps[3] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
+	} else {
+		devinfo->cmd_pipe = usb_sndbulkpipe(udev,
+						eps[0]->desc.bEndpointAddress);
+		devinfo->status_pipe = usb_rcvbulkpipe(udev,
+						eps[1]->desc.bEndpointAddress);
+		devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
+						eps[2]->desc.bEndpointAddress);
+		devinfo->data_out_pipe = usb_sndbulkpipe(udev,
+						eps[3]->desc.bEndpointAddress);
+	}
+
+	devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, 3, 256,
+								GFP_KERNEL);
+	if (devinfo->qdepth < 0) {
+		devinfo->qdepth = 256;
+		devinfo->use_streams = 0;
+	} else {
+		devinfo->use_streams = 1;
+	}
+}
+
+/*
+ * XXX: What I'd like to do here is register a SCSI host for each USB host in
+ * the system.  Follow usb-storage's design of registering a SCSI host for
+ * each USB device for the moment.  Can implement this by walking up the
+ * USB hierarchy until we find a USB host.
+ */
+static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	int result;
+	struct Scsi_Host *shost;
+	struct uas_dev_info *devinfo;
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	if (id->bInterfaceProtocol == 0x50) {
+		int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+/* XXX: Shouldn't assume that 1 is the alternative we want */
+		int ret = usb_set_interface(udev, ifnum, 1);
+		if (ret)
+			return -ENODEV;
+	}
+
+	devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL);
+	if (!devinfo)
+		return -ENOMEM;
+
+	result = -ENOMEM;
+	shost = scsi_host_alloc(&uas_host_template, sizeof(void *));
+	if (!shost)
+		goto free;
+
+	shost->max_cmd_len = 16 + 252;
+	shost->max_id = 1;
+	shost->sg_tablesize = udev->bus->sg_tablesize;
+
+	result = scsi_add_host(shost, &intf->dev);
+	if (result)
+		goto free;
+	shost->hostdata[0] = (unsigned long)devinfo;
+
+	devinfo->intf = intf;
+	devinfo->udev = udev;
+	uas_configure_endpoints(devinfo);
+
+	scsi_scan_host(shost);
+	usb_set_intfdata(intf, shost);
+	return result;
+ free:
+	kfree(devinfo);
+	if (shost)
+		scsi_host_put(shost);
+	return result;
+}
+
+static int uas_pre_reset(struct usb_interface *intf)
+{
+/* XXX: Need to return 1 if it's not our device in error handling */
+	return 0;
+}
+
+static int uas_post_reset(struct usb_interface *intf)
+{
+/* XXX: Need to return 1 if it's not our device in error handling */
+	return 0;
+}
+
+static void uas_disconnect(struct usb_interface *intf)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct usb_host_endpoint *eps[3];
+	struct Scsi_Host *shost = usb_get_intfdata(intf);
+	struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+
+	scsi_remove_host(shost);
+
+	eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
+	eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
+	eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
+	usb_free_streams(intf, eps, 3, GFP_KERNEL);
+
+	kfree(devinfo);
+}
+
+/*
+ * XXX: Should this plug into libusual so we can auto-upgrade devices from
+ * Bulk-Only to UAS?
+ */
+static struct usb_driver uas_driver = {
+	.name = "uas",
+	.probe = uas_probe,
+	.disconnect = uas_disconnect,
+	.pre_reset = uas_pre_reset,
+	.post_reset = uas_post_reset,
+	.id_table = uas_usb_ids,
+};
+
+static int uas_init(void)
+{
+	return usb_register(&uas_driver);
+}
+
+static void uas_exit(void)
+{
+	usb_deregister(&uas_driver);
+}
+
+module_init(uas_init);
+module_exit(uas_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matthew Wilcox and Sarah Sharp");
diff --git a/drivers/usb/storage/unusual_alauda.h b/drivers/usb/storage/unusual_alauda.h
index 8c412f8..fa3e9ed 100644
--- a/drivers/usb/storage/unusual_alauda.h
+++ b/drivers/usb/storage/unusual_alauda.h
@@ -21,11 +21,11 @@
 UNUSUAL_DEV(  0x0584, 0x0008, 0x0102, 0x0102,
 		"Fujifilm",
 		"DPC-R1 (Alauda)",
-		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0),
+		USB_SC_SCSI, USB_PR_ALAUDA, init_alauda, 0),
 
 UNUSUAL_DEV(  0x07b4, 0x010a, 0x0102, 0x0102,
 		"Olympus",
 		"MAUSB-10 (Alauda)",
-		US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0),
+		USB_SC_SCSI, USB_PR_ALAUDA, init_alauda, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_ALAUDA) || ... */
diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h
index 44be6d7..c854fde 100644
--- a/drivers/usb/storage/unusual_cypress.h
+++ b/drivers/usb/storage/unusual_cypress.h
@@ -23,12 +23,12 @@
 UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
 		"Cypress",
 		"Cypress AT2LP",
-		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
+		USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
 
 /* CY7C68310 : support atacb and atacb2 */
 UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x9999,
 		"Cypress",
 		"Cypress ISD-300LP",
-		US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0),
+		USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */
diff --git a/drivers/usb/storage/unusual_datafab.h b/drivers/usb/storage/unusual_datafab.h
index c9298ce..582a603 100644
--- a/drivers/usb/storage/unusual_datafab.h
+++ b/drivers/usb/storage/unusual_datafab.h
@@ -21,7 +21,7 @@
 UNUSUAL_DEV(  0x07c4, 0xa000, 0x0000, 0x0015,
 		"Datafab",
 		"MDCFE-B USB CF Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 /*
@@ -38,45 +38,45 @@
 UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
 		"SIIG/Datafab",
 		"SIIG/Datafab Memory Stick+CF Reader/Writer",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 /* Reported by Josef Reisinger <josef.reisinger@netcologne.de> */
 UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff,
 		"Datafab/Unknown",
 		"MD2/MD3 Disk enclosure",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		US_FL_SINGLE_LUN),
 
 UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
 		"Datafab/Unknown",
 		"Datafab-based Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
 		"Datafab/Unknown",
 		"Datafab-based Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
 		"PNY/Datafab",
 		"PNY/Datafab CF+SM Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
 		"Simple Tech/Datafab",
 		"Simple Tech/Datafab CF+SM Reader",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 /* Submitted by Olaf Hering <olh@suse.de> */
 UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
 		"Datafab Systems, Inc.",
 		"USB to CF + SM Combo (LC1)",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 /* Reported by Felix Moeller <felix@derklecks.de>
@@ -86,13 +86,13 @@
 UNUSUAL_DEV(  0x07c4, 0xa10b, 0x0000, 0xffff,
 		"DataFab Systems Inc.",
 		"USB CF+MS",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		0),
 
 UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
 		"Acomdata",
 		"CF",
-		US_SC_SCSI, US_PR_DATAFAB, NULL,
+		USB_SC_SCSI, USB_PR_DATAFAB, NULL,
 		US_FL_SINGLE_LUN),
 
 #endif /* defined(CONFIG_USB_STORAGE_DATAFAB) || ... */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 2c897ee..6ccdd3d 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -63,26 +63,26 @@
 UNUSUAL_DEV(  0x03eb, 0x2002, 0x0100, 0x0100,
 		"ATMEL",
 		"SND1 Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE),
 
 /* Reported by Rodolfo Quesada <rquesada@roqz.net> */
 UNUSUAL_DEV(  0x03ee, 0x6906, 0x0003, 0x0003,
 		"VIA Technologies Inc.",
 		"Mitsumi multi cardreader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 UNUSUAL_DEV(  0x03f0, 0x0107, 0x0200, 0x0200,
 		"HP",
 		"CD-Writer+",
-		US_SC_8070, US_PR_CB, NULL, 0),
+		USB_SC_8070, USB_PR_CB, NULL, 0),
 
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV(  0x03f0, 0x070c, 0x0000, 0x0000,
 		"HP",
 		"Personal Media Drive",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE ),
 
 /* Reported by Grant Grundler <grundler@parisc-linux.org>
@@ -91,7 +91,7 @@
 UNUSUAL_DEV(  0x03f0, 0x4002, 0x0001, 0x0001,
 		"HP",
 		"PhotoSmart R707",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY),
 
 /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
  * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
@@ -100,14 +100,14 @@
 UNUSUAL_DEV(  0x0409, 0x0040, 0x0000, 0x9999,
 		"NEC",
 		"NEC USB UF000x",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Patch submitted by Mihnea-Costin Grigore <mihnea@zulu.ro> */
 UNUSUAL_DEV(  0x040d, 0x6205, 0x0003, 0x0003,
 		"VIA Technologies Inc.",
 		"USB 2.0 Card Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
@@ -117,40 +117,40 @@
 UNUSUAL_DEV(  0x0411, 0x001c, 0x0113, 0x0113,
 		"Buffalo",
 		"DUB-P40G HDD",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */
 UNUSUAL_DEV(  0x0419, 0x0100, 0x0100, 0x0100,
 		"Samsung Info. Systems America, Inc.",
 		"MP3 Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Orgad Shaneh <orgads@gmail.com> */
 UNUSUAL_DEV(  0x0419, 0xaace, 0x0100, 0x0100,
 		"Samsung", "MP3 Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Christian Leber <christian@leber.de> */
 UNUSUAL_DEV(  0x0419, 0xaaf5, 0x0100, 0x0100,
 		"TrekStor",
 		"i.Beat 115 2.0",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_NOT_LOCKABLE ),
 
 /* Reported by Stefan Werner <dustbln@gmx.de> */
 UNUSUAL_DEV(  0x0419, 0xaaf6, 0x0100, 0x0100,
 		"TrekStor",
 		"i.Beat Joy 2.0",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Pete Zaitcev <zaitcev@redhat.com>, bz#176584 */
 UNUSUAL_DEV(  0x0420, 0x0001, 0x0100, 0x0100,
 		"GENERIC", "MP3 PLAYER", /* MyMusix PD-205 on the outside. */
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Andrew Nayenko <relan@bk.ru>
@@ -158,28 +158,28 @@
 UNUSUAL_DEV(  0x0421, 0x0019, 0x0592, 0x0610,
 		"Nokia",
 		"Nokia 6288",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Reported by Mario Rettig <mariorettig@web.de> */
 UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
 		"Nokia",
 		"Nokia 3250",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by <honkkis@gmail.com> */
 UNUSUAL_DEV(  0x0421, 0x0433, 0x0100, 0x0100,
 		"Nokia",
 		"E70",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Jon Hart <Jon.Hart@web.de> */
 UNUSUAL_DEV(  0x0421, 0x0434, 0x0100, 0x0100,
 		"Nokia",
 		"E60",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Sumedha Swamy <sumedhaswamy@gmail.com> and
@@ -187,7 +187,7 @@
 UNUSUAL_DEV(  0x0421, 0x0444, 0x0100, 0x0100,
 		"Nokia",
 		"N91",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Jiri Slaby <jirislaby@gmail.com> and
@@ -195,42 +195,42 @@
 UNUSUAL_DEV(  0x0421, 0x0446, 0x0100, 0x0100,
 		"Nokia",
 		"N80",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Matthew Bloch <matthew@bytemark.co.uk> */
 UNUSUAL_DEV(  0x0421, 0x044e, 0x0100, 0x0100,
 		"Nokia",
 		"E61",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Bardur Arantsson <bardur@scientician.net> */
 UNUSUAL_DEV(  0x0421, 0x047c, 0x0370, 0x0610,
 		"Nokia",
 		"6131",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Reported by Manuel Osdoba <manuel.osdoba@tu-ilmenau.de> */
 UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x9999,
 		"Nokia",
 		"Nokia 6233",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Reported by Alex Corcoles <alex@corcoles.net> */
 UNUSUAL_DEV(  0x0421, 0x0495, 0x0370, 0x0370,
 		"Nokia",
 		"6234",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 #ifdef NO_SDDR09
 UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 #endif
 
@@ -239,7 +239,7 @@
 UNUSUAL_DEV(  0x0451, 0x5416, 0x0100, 0x0100,
 		"Neuros Audio",
 		"USB 2.0 HD 2.5",
-		US_SC_DEVICE, US_PR_BULK, NULL,
+		USB_SC_DEVICE, USB_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
 /*
@@ -250,7 +250,7 @@
 UNUSUAL_DEV(  0x0457, 0x0150, 0x0100, 0x0100,
 		"USBest Technology",	/* sold by Transcend */
 		"USB Mass Storage Device",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
 
 /*
 * Bohdan Linda <bohdan.linda@gmail.com>
@@ -260,7 +260,7 @@
 UNUSUAL_DEV(  0x0457, 0x0151, 0x0100, 0x0100,
 		"USB 2.0",
 		"Flash Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NOT_LOCKABLE ),
 
 /* Reported by Tamas Kerecsen <kerecsen@bigfoot.com>
@@ -272,7 +272,7 @@
 UNUSUAL_DEV(  0x045e, 0xffff, 0x0000, 0x0000,
 		"Mitac",
 		"GPS",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /*
@@ -284,32 +284,32 @@
 UNUSUAL_DEV(  0x046b, 0xff40, 0x0100, 0x0100,
 		"AMI",
 		"Virtual Floppy",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT),
 
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
 		"Kyocera",
 		"Finecam S3x",
-		US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_8070, USB_PR_CB, NULL, US_FL_FIX_INQUIRY),
 
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0101, 0x0100, 0x0100,
 		"Kyocera",
 		"Finecam S4",
-		US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_8070, USB_PR_CB, NULL, US_FL_FIX_INQUIRY),
 
 /* Patch submitted by Stephane Galles <stephane.galles@free.fr> */
 UNUSUAL_DEV(  0x0482, 0x0103, 0x0100, 0x0100,
 		"Kyocera",
 		"Finecam S5",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
 
 /* Patch submitted by Jens Taprogge <jens.taprogge@taprogge.org> */
 UNUSUAL_DEV(  0x0482, 0x0107, 0x0100, 0x0100,
 		"Kyocera",
 		"CONTAX SL300R T*",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE),
 
 /* Reported by Paul Stewart <stewart@wetlogic.net>
@@ -317,7 +317,7 @@
 UNUSUAL_DEV(  0x04a4, 0x0004, 0x0001, 0x0001,
 		"Hitachi",
 		"DVD-CAM DZ-MV100A Camcorder",
-		US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN),
+		USB_SC_SCSI, USB_PR_CB, NULL, US_FL_SINGLE_LUN),
 
 /* BENQ DC5330
  * Reported by Manuel Fombuena <mfombuena@ya.com> and
@@ -325,7 +325,7 @@
 UNUSUAL_DEV(  0x04a5, 0x3010, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"300_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Patch for Nikon coolpix 2000
@@ -333,14 +333,14 @@
 UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
 		"NIKON",
 		"NIKON DSC E2000",
-		US_SC_DEVICE, US_PR_DEVICE,NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE,NULL,
 		US_FL_NOT_LOCKABLE ),
 
 /* Reported by Doug Maxey (dwm@austin.ibm.com) */
 UNUSUAL_DEV(  0x04b3, 0x4001, 0x0110, 0x0110,
 		"IBM",
 		"IBM RSA2",
-		US_SC_DEVICE, US_PR_CB, NULL,
+		USB_SC_DEVICE, USB_PR_CB, NULL,
 		US_FL_MAX_SECTORS_MIN),
 
 /* Reported by Simon Levitt <simon@whattf.com>
@@ -348,14 +348,14 @@
 UNUSUAL_DEV(  0x04b8, 0x0601, 0x0100, 0x0100,
 		"Epson",
 		"875DC Storage",
-		US_SC_SCSI, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_SCSI, USB_PR_CB, NULL, US_FL_FIX_INQUIRY),
 
 /* Reported by Khalid Aziz <khalid@gonehiking.org>
  * This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x04b8, 0x0602, 0x0110, 0x0110,
 		"Epson",
 		"785EPX Storage",
-		US_SC_SCSI, US_PR_BULK, NULL, US_FL_SINGLE_LUN),
+		USB_SC_SCSI, USB_PR_BULK, NULL, US_FL_SINGLE_LUN),
 
 /* Not sure who reported this originally but
  * Pavel Machek <pavel@ucw.cz> reported that the extra US_FL_SINGLE_LUN
@@ -363,7 +363,7 @@
 UNUSUAL_DEV(  0x04cb, 0x0100, 0x0000, 0x2210,
 		"Fujifilm",
 		"FinePix 1400Zoom",
-		US_SC_UFI, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN),
+		USB_SC_UFI, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY | US_FL_SINGLE_LUN),
 
 /* Reported by Ondrej Zary <linux@rainbow-software.org>
  * The device reports one sector more and breaks when that sector is accessed
@@ -371,7 +371,7 @@
 UNUSUAL_DEV(  0x04ce, 0x0002, 0x026c, 0x026c,
 		"ScanLogic",
 		"SL11R-IDE",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Reported by Kriston Fincher <kriston@airmail.net>
@@ -382,27 +382,27 @@
 UNUSUAL_DEV(  0x04da, 0x0901, 0x0100, 0x0200,
 		"Panasonic",
 		"LS-120 Camera",
-		US_SC_UFI, US_PR_DEVICE, NULL, 0),
+		USB_SC_UFI, USB_PR_DEVICE, NULL, 0),
 
 /* From Yukihiro Nakai, via zaitcev@yahoo.com.
  * This is needed for CB instead of CBI */
 UNUSUAL_DEV(  0x04da, 0x0d05, 0x0000, 0x0000,
 		"Sharp CE-CW05",
 		"CD-R/RW Drive",
-		US_SC_8070, US_PR_CB, NULL, 0),
+		USB_SC_8070, USB_PR_CB, NULL, 0),
 
 /* Reported by Adriaan Penning <a.penning@luon.net> */
 UNUSUAL_DEV(  0x04da, 0x2372, 0x0000, 0x9999,
 		"Panasonic",
 		"DMC-LCx Camera",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
 
 /* Reported by Simeon Simeonov <simeonov_2000@yahoo.com> */
 UNUSUAL_DEV(  0x04da, 0x2373, 0x0000, 0x9999,
 		"LEICA",
 		"D-LUX Camera",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
 
 /* Most of the following entries were developed with the help of
@@ -411,19 +411,19 @@
 UNUSUAL_DEV(  0x04e6, 0x0001, 0x0200, 0x0200,
 		"Matshita",
 		"LS-120",
-		US_SC_8020, US_PR_CB, NULL, 0),
+		USB_SC_8020, USB_PR_CB, NULL, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x0002, 0x0100, 0x0100,
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, 
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ),
 
 #ifdef NO_SDDR09
 UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
 		"SCM Microsystems",
 		"eUSB CompactFlash Adapter",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN),
 #endif
 
@@ -431,54 +431,54 @@
 UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0100,
 		"SCM Microsystems Inc.",
 		"eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN),
 
 /* Reported by Daniel Nouri <dpunktnpunkt@web.de> */
 UNUSUAL_DEV(  0x04e6, 0x0006, 0x0205, 0x0205,
 		"Shuttle",
 		"eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
+		USB_SC_SCSI, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
 UNUSUAL_DEV(  0x04e6, 0x0007, 0x0100, 0x0200,
 		"Sony",
 		"Hifd",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN),
 
 UNUSUAL_DEV(  0x04e6, 0x0009, 0x0200, 0x0200,
 		"Shuttle",
 		"eUSB ATA/ATAPI Adapter",
-		US_SC_8020, US_PR_CB, NULL, 0),
+		USB_SC_8020, USB_PR_CB, NULL, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x000a, 0x0200, 0x0200,
 		"Shuttle",
 		"eUSB CompactFlash Adapter",
-		US_SC_8020, US_PR_CB, NULL, 0),
+		USB_SC_8020, USB_PR_CB, NULL, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x000B, 0x0100, 0x0100,
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ), 
 
 UNUSUAL_DEV(  0x04e6, 0x000C, 0x0100, 0x0100,
 		"Shuttle",
 		"eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ),
 
 UNUSUAL_DEV(  0x04e6, 0x0101, 0x0200, 0x0200,
 		"Shuttle",
 		"CD-RW Device",
-		US_SC_8020, US_PR_CB, NULL, 0),
+		USB_SC_8020, USB_PR_CB, NULL, 0),
 
 /* Reported by Dmitry Khlystov <adminimus@gmail.com> */
 UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,
 		"Samsung",
 		"YP-U3",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64),
 
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
@@ -488,14 +488,14 @@
 UNUSUAL_DEV(  0x04fc, 0x80c2, 0x0100, 0x0100,
 		"Kobian Mercury",
 		"Binocam DCB-132",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BULK32),
 
 /* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */
 UNUSUAL_DEV(  0x050d, 0x0115, 0x0133, 0x0133,
 		"Belkin",
 		"USB SCSI Adaptor",
-		US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+		USB_SC_SCSI, USB_PR_BULK, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ),
 
 /* Iomega Clik! Drive 
@@ -505,14 +505,14 @@
 UNUSUAL_DEV(  0x0525, 0xa140, 0x0100, 0x0100,
 		"Iomega",
 		"USB Clik! 40",
-		US_SC_8070, US_PR_DEVICE, NULL,
+		USB_SC_8070, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Added by Alan Stern <stern@rowland.harvard.edu> */
 COMPLIANT_DEV(0x0525, 0xa4a5, 0x0000, 0x9999,
 		"Linux",
 		"File-backed Storage Gadget",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_CAPACITY_OK ),
 
 /* Yakumo Mega Image 37
@@ -520,7 +520,7 @@
 UNUSUAL_DEV(  0x052b, 0x1801, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"300_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Another Yakumo camera.
@@ -528,14 +528,14 @@
 UNUSUAL_DEV(  0x052b, 0x1804, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"300_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Iacopo Spalletti <avvisi@spalletti.it> */
 UNUSUAL_DEV(  0x052b, 0x1807, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"300_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Yakumo Mega Image 47
@@ -543,7 +543,7 @@
 UNUSUAL_DEV(  0x052b, 0x1905, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"400_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Paul Ortyl <ortylp@3miasto.net>
@@ -551,13 +551,13 @@
 UNUSUAL_DEV(  0x052b, 0x1911, 0x0100, 0x0100,
 		"Tekom Technologies, Inc",
 		"400_CAMERA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450,
 		"Sony",
 		"DSC-S30/S70/S75/505V/F505/F707/F717/P8",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
+		USB_SC_SCSI, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
 
 /* Submitted by Lars Jacob <jacob.lars@googlemail.com>
@@ -565,7 +565,7 @@
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0500, 0x0610,
 		"Sony",
 		"DSC-T1/T5/H5",
-		US_SC_8070, US_PR_DEVICE, NULL,
+		USB_SC_8070, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 
@@ -573,88 +573,88 @@
 UNUSUAL_DEV(  0x054c, 0x0025, 0x0100, 0x0100,
 		"Sony",
 		"Memorystick NW-MS7",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Olaf Hering, <olh@suse.de> SuSE Bugzilla #49049 */
 UNUSUAL_DEV(  0x054c, 0x002c, 0x0501, 0x2000,
 		"Sony",
 		"USB Floppy Drive",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 UNUSUAL_DEV(  0x054c, 0x002d, 0x0100, 0x0100,
 		"Sony",
 		"Memorystick MSAC-US1",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Klaus Mueller <k.mueller@intershop.de> */
 UNUSUAL_DEV(  0x054c, 0x002e, 0x0106, 0x0310,
 		"Sony",
 		"Handycam",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
+		USB_SC_SCSI, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */
 UNUSUAL_DEV(  0x054c, 0x002e, 0x0500, 0x0500,
 		"Sony",
 		"Handycam HC-85",
-		US_SC_UFI, US_PR_DEVICE, NULL,
+		USB_SC_UFI, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 UNUSUAL_DEV(  0x054c, 0x0032, 0x0000, 0x9999,
 		"Sony",
 		"Memorystick MSC-U01N",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Michal Mlotek <mlotek@foobar.pl> */
 UNUSUAL_DEV(  0x054c, 0x0058, 0x0000, 0x9999,
 		"Sony",
 		"PEG N760c Memorystick",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 		
 UNUSUAL_DEV(  0x054c, 0x0069, 0x0000, 0x9999,
 		"Sony",
 		"Memorystick MSC-U03",
-		US_SC_UFI, US_PR_CB, NULL,
+		USB_SC_UFI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Nathan Babb <nathan@lexi.com> */
 UNUSUAL_DEV(  0x054c, 0x006d, 0x0000, 0x9999,
 		"Sony",
 		"PEG Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Submitted by Frank Engel <frankie@cse.unsw.edu.au> */
 UNUSUAL_DEV(  0x054c, 0x0099, 0x0000, 0x9999,
 		"Sony",
 		"PEG Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Submitted by Mike Alborn <malborn@deandra.homeip.net> */
 UNUSUAL_DEV(  0x054c, 0x016a, 0x0000, 0x9999,
 		"Sony",
 		"PEG Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* floppy reports multiple luns */
 UNUSUAL_DEV(  0x055d, 0x2020, 0x0000, 0x0210,
 		"SAMSUNG",
 		"SFD-321U [FW 0C]",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* We keep this entry to force the transport; firmware 3.00 and later is ok. */
 UNUSUAL_DEV(  0x057b, 0x0000, 0x0000, 0x0299,
 		"Y-E Data",
 		"Flashbuster-U",
-		US_SC_DEVICE,  US_PR_CB, NULL,
+		USB_SC_DEVICE,  USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN),
 
 /* Reported by Johann Cardon <johann.cardon@free.fr>
@@ -664,20 +664,20 @@
 UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999,
 		"Y-E Data",
 		"Silicon Media R/W",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0),
 
 /* Reported by RTE <raszilki@yandex.ru> */
 UNUSUAL_DEV(  0x058f, 0x6387, 0x0141, 0x0141,
 		"JetFlash",
 		"TS1GJF2A/120",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Fabrizio Fellini <fello@libero.it> */
 UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
 		"Fujifilm",
 		"Digital Camera EX-20 DSC",
-		US_SC_8070, US_PR_DEVICE, NULL, 0 ),
+		USB_SC_8070, USB_PR_DEVICE, NULL, 0 ),
 
 /* Reported by Andre Welter <a.r.welter@gmx.de>
  * This antique device predates the release of the Bulk-only Transport
@@ -688,14 +688,14 @@
 UNUSUAL_DEV(  0x059b, 0x0001, 0x0100, 0x0100,
 		"Iomega",
 		"ZIP 100",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Reported by <Hendryk.Pfeiffer@gmx.de> */
 UNUSUAL_DEV(  0x059f, 0x0643, 0x0000, 0x0000,
 		"LaCie",
 		"DVD+-RW",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_GO_SLOW ),
 
 /* Submitted by Joel Bourquard <numlock@freesurf.ch>
@@ -705,7 +705,7 @@
 UNUSUAL_DEV(  0x05ab, 0x0060, 0x1104, 0x1110,
 		"In-System",
 		"PyroGate External CD-ROM Enclosure (FCD-523)",
-		US_SC_SCSI, US_PR_BULK, NULL,
+		USB_SC_SCSI, USB_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
 /* Submitted by Sven Anderson <sven-linux@anderson.de>
@@ -717,26 +717,26 @@
 UNUSUAL_DEV( 0x05ac, 0x1202, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* Reported by Avi Kivity <avi@argo.co.il> */
 UNUSUAL_DEV( 0x05ac, 0x1203, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 UNUSUAL_DEV( 0x05ac, 0x1204, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
 
 UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /*
@@ -746,7 +746,7 @@
 UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999,
 		"Apple",
 		"iPod",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* Reported by Dan Williams <dcbw@redhat.com>
@@ -758,14 +758,14 @@
 UNUSUAL_DEV(  0x05c6, 0x1000, 0x0000, 0x9999,
 		"Option N.V.",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, option_ms_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init,
 		0),
 
 /* Reported by Blake Matheny <bmatheny@purdue.edu> */
 UNUSUAL_DEV(  0x05dc, 0xb002, 0x0000, 0x0113,
 		"Lexar",
 		"USB CF Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* The following two entries are for a Genesys USB to IDE
@@ -782,20 +782,20 @@
 UNUSUAL_DEV(  0x05e3, 0x0701, 0x0000, 0xffff,
 		"Genesys Logic",
 		"USB to IDE Optical",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
 		"Genesys Logic",
 		"USB to IDE Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV(  0x05e3, 0x0723, 0x9451, 0x9451,
 		"Genesys Logic",
 		"USB to SATA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE ),
 
 /* Reported by Hanno Boeck <hanno@gmx.de>
@@ -803,33 +803,33 @@
 UNUSUAL_DEV(  0x0636, 0x0003, 0x0000, 0x9999,
 		"Vivitar",
 		"Vivicam 35Xx",
-		US_SC_SCSI, US_PR_BULK, NULL,
+		USB_SC_SCSI, USB_PR_BULK, NULL,
 		US_FL_FIX_INQUIRY ),
 
 UNUSUAL_DEV(  0x0644, 0x0000, 0x0100, 0x0100,
 		"TEAC",
 		"Floppy Drive",
-		US_SC_UFI, US_PR_CB, NULL, 0 ),
+		USB_SC_UFI, USB_PR_CB, NULL, 0 ),
 
 /* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */
 UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
 		"SigmaTel",
 		"USBMSC Audio Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* Reported by Daniel Kukula <daniel.kuku@gmail.com> */
 UNUSUAL_DEV( 0x067b, 0x1063, 0x0100, 0x0100,
 		"Prolific Technology, Inc.",
 		"Prolific Storage Gadget",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BAD_SENSE ),
 
 /* Reported by Rogerio Brito <rbrito@ime.usp.br> */
 UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001,
 		"Prolific Technology, Inc.",
 		"Mass Storage Device",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NOT_LOCKABLE ),
 
 /* Reported by Richard -=[]=- <micro_flyer@hotmail.com> */
@@ -838,46 +838,47 @@
 UNUSUAL_DEV( 0x067b, 0x2507, 0x0001, 0x0100,
 		"Prolific Technology Inc.",
 		"Mass Storage Device",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_GO_SLOW ),
 
 /* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */
 UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0101,
 		"Prolific Technology Inc.",
 		"ATAPI-6 Bridge Controller",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_GO_SLOW ),
 
 /* Submitted by Benny Sjostrand <benny@hostmobility.com> */
 UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
 		"Minolta",
 		"Dimage F300",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+		USB_SC_SCSI, USB_PR_BULK, NULL, 0 ),
 
 /* Reported by Miguel A. Fosas <amn3s1a@ono.com> */
 UNUSUAL_DEV(  0x0686, 0x4017, 0x0001, 0x0001,
 		"Minolta",
 		"DIMAGE E223",
-		US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
+		USB_SC_SCSI, USB_PR_DEVICE, NULL, 0 ),
 
 UNUSUAL_DEV(  0x0693, 0x0005, 0x0100, 0x0100,
 		"Hagiwara",
 		"Flashgate",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+		USB_SC_SCSI, USB_PR_BULK, NULL, 0 ),
 
 /* Reported by David Hamilton <niftimusmaximus@lycos.com> */
 UNUSUAL_DEV(  0x069b, 0x3004, 0x0001, 0x0001,
 		"Thomson Multimedia Inc.",
 		"RCA RD1080 MP3 Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* Reported by Adrian Pilchowiec <adi1981@epf.pl> */
 UNUSUAL_DEV(  0x071b, 0x3203, 0x0000, 0x0000,
 		"RockChip",
 		"MP3",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64 |
+		US_FL_NO_READ_CAPACITY_16),
 
 /* Reported by Jean-Baptiste Onofre <jb@nanthrax.net>
  * Support the following product :
@@ -886,7 +887,7 @@
 UNUSUAL_DEV(  0x071b, 0x32bb, 0x0000, 0x0000,
 		"RockChip",
 		"MTP",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64),
 
 /* Reported by Massimiliano Ghilardi <massimiliano.ghilardi@gmail.com>
@@ -902,59 +903,59 @@
 UNUSUAL_DEV(  0x071b, 0x3203, 0x0100, 0x0100,
 		"RockChip",
 		"ROCK MP3",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_MAX_SECTORS_64),
 
 /* Reported by Olivier Blondeau <zeitoun@gmail.com> */
 UNUSUAL_DEV(  0x0727, 0x0306, 0x0100, 0x0100,
 		"ATMEL",
 		"SND1 Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE),
 
 /* Submitted by Roman Hodek <roman@hodek.net> */
 UNUSUAL_DEV(  0x0781, 0x0001, 0x0200, 0x0200,
 		"Sandisk",
 		"ImageMate SDDR-05a",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
 UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009,
 		"SanDisk Corporation",
 		"ImageMate CompactFlash USB",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
 		"Sandisk",
 		"ImageMate SDDR-12",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Reported by Eero Volotinen <eero@ping-viini.org> */
 UNUSUAL_DEV(  0x07ab, 0xfccd, 0x0000, 0x9999,
 		"Freecom Technologies",
 		"FHD-Classic",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 UNUSUAL_DEV(  0x07af, 0x0004, 0x0100, 0x0133,
 		"Microtech",
 		"USB-SCSI-DB25",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ), 
 
 UNUSUAL_DEV(  0x07af, 0x0005, 0x0100, 0x0100,
 		"Microtech",
 		"USB-SCSI-HD50",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
 		US_FL_SCM_MULT_TARG ),
 
 #ifdef NO_SDDR09
 UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate",
-		US_SC_SCSI, US_PR_CB, NULL,
+		USB_SC_SCSI, USB_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 #endif
 
@@ -967,7 +968,7 @@
 UNUSUAL_DEV(  0x07c4, 0xa400, 0x0000, 0xffff,
 		"Datafab",
 		"KECF-USB",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY ),
 
 /* Reported by Rauch Wolke <rauchwolke@gmx.net>
@@ -976,7 +977,7 @@
 UNUSUAL_DEV(  0x07c4, 0xa4a5, 0x0000, 0xffff,
 		"Simple Tech/Datafab",
 		"CF+SM Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ),
 
 /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant
@@ -986,42 +987,42 @@
  * - They don't like the INQUIRY command. So we must handle this command
  *   of the SCSI layer ourselves.
  * - Some cameras with idProduct=0x1001 and bcdDevice=0x1000 have
- *   bInterfaceProtocol=0x00 (US_PR_CBI) while others have 0x01 (US_PR_CB).
- *   So don't remove the US_PR_CB override!
- * - Cameras with bcdDevice=0x9009 require the US_SC_8070 override.
+ *   bInterfaceProtocol=0x00 (USB_PR_CBI) while others have 0x01 (USB_PR_CB).
+ *   So don't remove the USB_PR_CB override!
+ * - Cameras with bcdDevice=0x9009 require the USB_SC_8070 override.
  */
 UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
 		"Casio",
 		"QV DigitalCamera",
-		US_SC_8070, US_PR_CB, NULL,
+		USB_SC_8070, USB_PR_CB, NULL,
 		US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
 
 /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
 UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
 		"Samsung",
 		"Digimax 410",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY),
 
 /* Reported by Luciano Rocha <luciano@eurotux.com> */
 UNUSUAL_DEV( 0x0840, 0x0082, 0x0001, 0x0001,
 		"Argosy",
 		"Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Reported and patched by Nguyen Anh Quynh <aquynh@gmail.com> */
 UNUSUAL_DEV( 0x0840, 0x0084, 0x0001, 0x0001,
 		"Argosy",
 		"Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Reported by Martijn Hijdra <martijn.hijdra@gmail.com> */
 UNUSUAL_DEV( 0x0840, 0x0085, 0x0001, 0x0001,
 		"Argosy",
 		"Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
@@ -1033,7 +1034,7 @@
 UNUSUAL_DEV(  0x084d, 0x0011, 0x0110, 0x0110,
 		"Grandtech",
 		"DC2MEGA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BULK32),
 
 /* Andrew Lunn <andrew@lunn.ch>
@@ -1044,14 +1045,14 @@
 UNUSUAL_DEV(  0x0851, 0x1543, 0x0200, 0x0200,
 		"PanDigital",
 		"Photo Frame",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NOT_LOCKABLE),
 
 /* Submitted by Jan De Luyck <lkml@kcore.org> */
 UNUSUAL_DEV(  0x08bd, 0x1100, 0x0000, 0x0000,
 		"CITIZEN",
 		"X1DE-USB",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
 /* Submitted by Dylan Taft <d13f00l@gmail.com>
@@ -1060,7 +1061,7 @@
 UNUSUAL_DEV(  0x08ca, 0x3103, 0x0100, 0x0100,
 		"AIPTEK",
 		"Aiptek USB Keychain MP3 Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE),
 
 /* Entry needed for flags. Moreover, all devices with this ID use
@@ -1071,7 +1072,7 @@
 UNUSUAL_DEV(  0x090a, 0x1001, 0x0100, 0x0100,
 		"Trumpion",
 		"t33520 USB Flash Card Controller",
-		US_SC_DEVICE, US_PR_BULK, NULL,
+		USB_SC_DEVICE, USB_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
 /* Reported by Filippo Bardelli <filibard@libero.it>
@@ -1080,21 +1081,21 @@
 UNUSUAL_DEV(  0x090a, 0x1050, 0x0100, 0x0100,
 		"Trumpion Microelectronics, Inc.",
 		"33520 USB Digital Voice Recorder",
-		US_SC_UFI, US_PR_DEVICE, NULL,
+		USB_SC_UFI, USB_PR_DEVICE, NULL,
 		0),
 
 /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
 UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
 		"Trumpion",
 		"MP3 player",
-		US_SC_RBC, US_PR_BULK, NULL,
+		USB_SC_RBC, USB_PR_BULK, NULL,
 		0 ),
 
 /* aeb */
 UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
 		"Feiya",
 		"5-in-1 Card Reader",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
 /* This Pentax still camera is not conformant
@@ -1107,7 +1108,7 @@
 UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
 		"Pentax",
 		"Optio 2/3/400",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* These are virtual windows driver CDs, which the zd1211rw driver
@@ -1115,13 +1116,13 @@
 UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,
 		"ZyXEL",
 		"G-220F USB-WLAN Install",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_DEVICE ),
 
 UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101,
 		"SiteCom",
 		"WL-117 USB-WLAN Install",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_DEVICE ),
 
 /* Reported by Dan Williams <dcbw@redhat.com>
@@ -1133,7 +1134,7 @@
 UNUSUAL_DEV(  0x0af0, 0x6971, 0x0000, 0x9999,
 		"Option N.V.",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, option_ms_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init,
 		0),
 
 /* Reported by F. Aben <f.aben@option.com>
@@ -1143,7 +1144,7 @@
 UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000,
 		"Option",
 		"GI 0401 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 /* Reported by Jan Dumon <j.dumon@option.com>
@@ -1153,104 +1154,104 @@
 UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000,
 		"Option",
 		"GI 0431 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7701, 0x0000, 0x0000,
 		"Option",
 		"GI 0451 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7706, 0x0000, 0x0000,
 		"Option",
 		"GI 0451 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7901, 0x0000, 0x0000,
 		"Option",
 		"GI 0452 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7A01, 0x0000, 0x0000,
 		"Option",
 		"GI 0461 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x7A05, 0x0000, 0x0000,
 		"Option",
 		"GI 0461 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x8300, 0x0000, 0x0000,
 		"Option",
 		"GI 033x SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x8302, 0x0000, 0x0000,
 		"Option",
 		"GI 033x SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0x8304, 0x0000, 0x0000,
 		"Option",
 		"GI 033x SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xc100, 0x0000, 0x0000,
 		"Option",
 		"GI 070x SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd057, 0x0000, 0x0000,
 		"Option",
 		"GI 1505 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd058, 0x0000, 0x0000,
 		"Option",
 		"GI 1509 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd157, 0x0000, 0x0000,
 		"Option",
 		"GI 1515 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd257, 0x0000, 0x0000,
 		"Option",
 		"GI 1215 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 UNUSUAL_DEV( 0x0af0, 0xd357, 0x0000, 0x0000,
 		"Option",
 		"GI 1505 SD-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
 		"Seagate",
 		"FreeAgent Pro",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE ),
 
 UNUSUAL_DEV(  0x0d49, 0x7310, 0x0000, 0x9999,
 		"Maxtor",
 		"USB to SATA",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE),
 
 /*
@@ -1260,14 +1261,14 @@
 UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100,
 		"Unknown",
 		"Unknown",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 
 /* Submitted by Joris Struyve <joris@struyve.be> */
 UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
 		"Medion",
 		"MD 7425",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY),
 
 /*
@@ -1278,13 +1279,13 @@
 UNUSUAL_DEV(  0x0d96, 0x5200, 0x0001, 0x0200,
 		"Jenoptik",
 		"JD 5200 z3",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
 
 /* Reported by  Jason Johnston <killean@shaw.ca> */
 UNUSUAL_DEV(  0x0dc4, 0x0073, 0x0000, 0x0000,
 		"Macpower Technology Co.LTD.",
 		"USB 2.0 3.5\" DEVICE",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* Reported by Lubomir Blaha <tritol@trilogic.cz>
@@ -1295,7 +1296,7 @@
 UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff,
 		"Netac",
 		"USB-CF-Card",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Reported by Edward Chapman (taken from linux-usb mailing list)
@@ -1303,7 +1304,7 @@
 UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999,
 		"Netac",
 		"USB Flash Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 
@@ -1312,28 +1313,28 @@
 UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012,
 		"WINWARD",
 		"Music Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Ian McConnell <ian at emit.demon.co.uk> */
 UNUSUAL_DEV(  0x0dda, 0x0301, 0x0012, 0x0012,
 		"PNP_MP3",
 		"PNP_MP3 PLAYER",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Jim McCloskey <mcclosk@ucsc.edu> */
 UNUSUAL_DEV( 0x0e21, 0x0520, 0x0100, 0x0100,
 		"Cowon Systems",
 		"iAUDIO M5",
-		US_SC_DEVICE, US_PR_BULK, NULL,
+		USB_SC_DEVICE, USB_PR_BULK, NULL,
 		US_FL_NEED_OVERRIDE ),
 
 /* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
 UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
 		"USB",
 		"Solid state disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* Submitted by Daniel Drake <dsd@gentoo.org>
@@ -1341,14 +1342,14 @@
 UNUSUAL_DEV(  0x0ea0, 0x2168, 0x0110, 0x0110,
 		"Ours Technology",
 		"Flash Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Rastislav Stanik <rs_kernel@yahoo.com> */
 UNUSUAL_DEV(  0x0ea0, 0x6828, 0x0110, 0x0110,
 		"USB",
 		"Flash Disk",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Benjamin Schiller <sbenni@gmx.de>
@@ -1356,7 +1357,7 @@
 UNUSUAL_DEV(  0x0ed1, 0x7636, 0x0103, 0x0103,
 		"Typhoon",
 		"My DJ 1820",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64),
 
 /* Patch by Leonid Petrov mail at lpetrov.net
@@ -1367,7 +1368,7 @@
 UNUSUAL_DEV(  0x0f19, 0x0103, 0x0100, 0x0100,
 		"Oracom Co., Ltd",
 		"ORC-200M",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* David Kuehling <dvdkhlng@gmx.de>:
@@ -1377,21 +1378,21 @@
 UNUSUAL_DEV(  0x0f19, 0x0105, 0x0100, 0x0100,
 		"C-MEX",
 		"A-VOX",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Michael Stattmann <michael@stattmann.com> */
 UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"V800-Vodafone 802",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT ),
 
 /* Reported by The Solutor <thesolutor@gmail.com> */
 UNUSUAL_DEV(  0x0fce, 0xd0e1, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"MD400",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_DEVICE),
 
 /* Reported by Jan Mate <mate@fiit.stuba.sk>
@@ -1399,21 +1400,21 @@
 UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"P990i",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
 UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"M600i",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
 
 /* Reported by Ricardo Barberis <ricardo@dattatec.com> */
 UNUSUAL_DEV(  0x0fce, 0xe092, 0x0000, 0x0000,
 		"Sony Ericsson",
 		"P1i",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
@@ -1425,13 +1426,13 @@
 UNUSUAL_DEV(  0x1019, 0x0c55, 0x0000, 0x0110,
 		"Desknote",
 		"UCR-61S2B",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_ucr61s2b_init,
 		0 ),
 
 UNUSUAL_DEV(  0x1058, 0x0704, 0x0000, 0x9999,
 		"Western Digital",
 		"External HDD",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_SANE_SENSE),
 
 /* Reported by Fabio Venturi <f.venturi@tdnet.it>
@@ -1440,7 +1441,7 @@
 UNUSUAL_DEV(  0x10d6, 0x2200, 0x0100, 0x0100,
 		"Actions Semiconductor",
 		"Mtp device",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0),
 
 /* Reported by Pascal Terjan <pterjan@mandriva.com>
@@ -1449,7 +1450,7 @@
 UNUSUAL_DEV(  0x1186, 0x3e04, 0x0000, 0x0000,
            "D-Link",
            "USB Mass Storage",
-           US_SC_DEVICE, US_PR_DEVICE, option_ms_init, US_FL_IGNORE_DEVICE),
+           USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init, US_FL_IGNORE_DEVICE),
 
 /* Reported by Kevin Lloyd <linux@sierrawireless.com>
  * Entry is needed for the initializer function override,
@@ -1459,7 +1460,7 @@
 UNUSUAL_DEV(  0x1199, 0x0fff, 0x0000, 0x9999,
 		"Sierra Wireless",
 		"USB MMC Storage",
-		US_SC_DEVICE, US_PR_DEVICE, sierra_ms_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, sierra_ms_init,
 		0),
 
 /* Reported by Jaco Kroon <jaco@kroon.co.za>
@@ -1469,7 +1470,7 @@
 UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x0100,
 		"Digitech HMG",
 		"DigiTech Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by fangxiaozhi <huananhu@huawei.com>
@@ -1478,353 +1479,353 @@
 UNUSUAL_DEV(  0x12d1, 0x1001, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1003, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1004, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1401, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1402, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1403, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1404, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1405, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1406, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1407, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1408, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1409, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140A, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140B, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140C, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140D, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140E, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x140F, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1410, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1411, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1412, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1413, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1414, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1415, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1416, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1417, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1418, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1419, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141A, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141B, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141C, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141D, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141E, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x141F, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1420, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1421, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1422, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1423, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1424, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1425, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1426, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1427, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1428, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1429, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142A, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142B, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142C, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142D, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142E, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x142F, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1430, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1431, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1432, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1433, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1434, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1435, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1436, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1437, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1438, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x1439, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143A, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143B, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143C, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143D, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143E, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 UNUSUAL_DEV(  0x12d1, 0x143F, 0x0000, 0x0000,
 		"HUAWEI MOBILE",
 		"Mass Storage",
-		US_SC_DEVICE, US_PR_DEVICE, usb_stor_huawei_e220_init,
+		USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
 		0),
 
 /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
 UNUSUAL_DEV(  0x132b, 0x000b, 0x0001, 0x0001,
 		"Minolta",
 		"Dimage Z10",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		0 ),
 
 /* Reported by Kotrla Vitezslav <kotrla@ceb.cz> */
 UNUSUAL_DEV(  0x1370, 0x6828, 0x0110, 0x0110,
 		"SWISSBIT",
 		"Black Silver",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Francesco Foresti <frafore@tiscali.it> */
 UNUSUAL_DEV(  0x14cd, 0x6600, 0x0201, 0x0201,
 		"Super Top",
 		"IDE DEVICE",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Alexandre Oliva <oliva@lsd.ic.unicamp.br>
@@ -1833,7 +1834,7 @@
 UNUSUAL_DEV(  0x152d, 0x2329, 0x0100, 0x0100,
 		"JMicron",
 		"USB to ATA/ATAPI Bridge",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ),
 
 /* Reported by Robert Schedel <r.schedel@yahoo.de>
@@ -1841,7 +1842,7 @@
 UNUSUAL_DEV(  0x1652, 0x6600, 0x0201, 0x0201,
 		"Teac",
 		"HD-35PUK-B",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Hans de Goede <hdegoede@redhat.com>
@@ -1851,18 +1852,23 @@
 UNUSUAL_DEV( 0x1908, 0x1315, 0x0000, 0x0000,
 		"BUILDWIN",
 		"Photo Frame",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BAD_SENSE ),
 UNUSUAL_DEV( 0x1908, 0x1320, 0x0000, 0x0000,
 		"BUILDWIN",
 		"Photo Frame",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_BAD_SENSE ),
+UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
+		"BUILDWIN",
+		"Photo Frame",
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_NO_READ_DISC_INFO ),
 
 UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001,
 		"ST",
 		"2A",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY),
 
 /* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
@@ -1871,7 +1877,7 @@
 UNUSUAL_DEV(  0x22b8, 0x3010, 0x0001, 0x0001,
 		"Motorola",
 		"RAZR V3x",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ),
 
 /*
@@ -1882,14 +1888,14 @@
 UNUSUAL_DEV(  0x22b8, 0x6426, 0x0101, 0x0101,
 		"Motorola",
 		"MSnc.",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY | US_FL_FIX_CAPACITY | US_FL_BULK_IGNORE_TAG),
 
 /* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */
 UNUSUAL_DEV(  0x2735, 0x100b, 0x0000, 0x9999,
 		"MPIO",
 		"HS200",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_GO_SLOW ),
 
 /* Reported by Frederic Marchal <frederic.marchal@wowcompany.com>
@@ -1898,21 +1904,21 @@
 UNUSUAL_DEV(  0x3340, 0xffff, 0x0000, 0x0000,
 		"Mitac",
 		"Mio DigiWalker USB Sync",
-		US_SC_DEVICE,US_PR_DEVICE,NULL,
+		USB_SC_DEVICE,USB_PR_DEVICE,NULL,
 		US_FL_MAX_SECTORS_64 ),
 
 /* Reported by Andrey Rahmatullin <wrar@altlinux.org> */
 UNUSUAL_DEV(  0x4102, 0x1020, 0x0100,  0x0100,
 		"iRiver",
 		"MP3 T10",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Sergey Pinaev <dfo@antex.ru> */
 UNUSUAL_DEV(  0x4102, 0x1059, 0x0000,  0x0000,
                "iRiver",
                "P7K",
-               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_MAX_SECTORS_64 ),
 
 /*
@@ -1922,41 +1928,41 @@
 UNUSUAL_DEV(  0x4146, 0xba01, 0x0100, 0x0100,
 		"Iomega",
 		"Micro Mini 1GB",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
 
 /* Reported by Andrew Simmons <andrew.simmons@gmail.com> */
 UNUSUAL_DEV(  0xed06, 0x4500, 0x0001, 0x0001,
 		"DataStor",
 		"USB4500 FW1.04",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_CAPACITY_HEURISTICS),
 
 /* Reported by Alessio Treglia <quadrispro@ubuntu.com> */
 UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001,
 		"TGE",
 		"Digital MP3 Audio Player",
-		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
 
 /* 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),
-USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_RBC, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8020, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_QIC, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_UFI, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8070, USB_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_SCSI, USB_PR_CB, USB_US_TYPE_STOR),
 
 /* Control/Bulk/Interrupt transport for all SubClass values */
-USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_RBC, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8020, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_QIC, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_UFI, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8070, USB_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_SCSI, USB_PR_CBI, USB_US_TYPE_STOR),
 
 /* Bulk-only transport for all SubClass values */
-USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR),
-USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),
+USUAL_DEV(USB_SC_RBC, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8020, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_QIC, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_UFI, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_8070, USB_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0),
diff --git a/drivers/usb/storage/unusual_freecom.h b/drivers/usb/storage/unusual_freecom.h
index 3758679..59a2611 100644
--- a/drivers/usb/storage/unusual_freecom.h
+++ b/drivers/usb/storage/unusual_freecom.h
@@ -21,6 +21,6 @@
 UNUSUAL_DEV(  0x07ab, 0xfc01, 0x0000, 0x9999,
 		"Freecom",
 		"USB-IDE",
-		US_SC_QIC, US_PR_FREECOM, init_freecom, 0),
+		USB_SC_QIC, USB_PR_FREECOM, init_freecom, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_FREECOM) || ... */
diff --git a/drivers/usb/storage/unusual_isd200.h b/drivers/usb/storage/unusual_isd200.h
index 0d99dde..14cca0c 100644
--- a/drivers/usb/storage/unusual_isd200.h
+++ b/drivers/usb/storage/unusual_isd200.h
@@ -21,37 +21,37 @@
 UNUSUAL_DEV(  0x054c, 0x002b, 0x0100, 0x0110,
 		"Sony",
 		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
 		"In-System",
 		"USB/IDE Bridge (ATA/ATAPI)",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x05ab, 0x0301, 0x0100, 0x0110,
 		"In-System",
 		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x05ab, 0x0351, 0x0100, 0x0110,
 		"In-System",
 		"Portable USB Harddrive V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x05ab, 0x5701, 0x0100, 0x0110,
 		"In-System",
 		"USB Storage Adapter V2",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
 		"ATI",
 		"USB Cable 205",
-		US_SC_ISD200, US_PR_BULK, isd200_Initialization,
+		USB_SC_ISD200, USB_PR_BULK, isd200_Initialization,
 		0),
 
 #endif /* defined(CONFIG_USB_STORAGE_ISD200) || ... */
diff --git a/drivers/usb/storage/unusual_jumpshot.h b/drivers/usb/storage/unusual_jumpshot.h
index 2e549b1..54be78b 100644
--- a/drivers/usb/storage/unusual_jumpshot.h
+++ b/drivers/usb/storage/unusual_jumpshot.h
@@ -21,7 +21,7 @@
 UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
 		"Lexar",
 		"Jumpshot USB CF Reader",
-		US_SC_SCSI, US_PR_JUMPSHOT, NULL,
+		USB_SC_SCSI, USB_PR_JUMPSHOT, NULL,
 		US_FL_NEED_OVERRIDE),
 
 #endif /* defined(CONFIG_USB_STORAGE_JUMPSHOT) || ... */
diff --git a/drivers/usb/storage/unusual_karma.h b/drivers/usb/storage/unusual_karma.h
index 12ae3a0..6df0397 100644
--- a/drivers/usb/storage/unusual_karma.h
+++ b/drivers/usb/storage/unusual_karma.h
@@ -21,6 +21,6 @@
 UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
 		"Rio",
 		"Rio Karma",
-		US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
+		USB_SC_SCSI, USB_PR_KARMA, rio_karma_init, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_KARMA) || ... */
diff --git a/drivers/usb/storage/unusual_onetouch.h b/drivers/usb/storage/unusual_onetouch.h
index bd9306b..0abb819 100644
--- a/drivers/usb/storage/unusual_onetouch.h
+++ b/drivers/usb/storage/unusual_onetouch.h
@@ -24,13 +24,13 @@
 UNUSUAL_DEV(  0x0d49, 0x7000, 0x0000, 0x9999,
 		"Maxtor",
 		"OneTouch External Harddrive",
-		US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+		USB_SC_DEVICE, USB_PR_DEVICE, onetouch_connect_input,
 		0),
 
 UNUSUAL_DEV(  0x0d49, 0x7010, 0x0000, 0x9999,
 		"Maxtor",
 		"OneTouch External Harddrive",
-		US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input,
+		USB_SC_DEVICE, USB_PR_DEVICE, onetouch_connect_input,
 		0),
 
 #endif /* defined(CONFIG_USB_STORAGE_ONETOUCH) || ... */
diff --git a/drivers/usb/storage/unusual_sddr09.h b/drivers/usb/storage/unusual_sddr09.h
index 50cab51..59a7e37 100644
--- a/drivers/usb/storage/unusual_sddr09.h
+++ b/drivers/usb/storage/unusual_sddr09.h
@@ -21,36 +21,36 @@
 UNUSUAL_DEV(  0x0436, 0x0005, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate (DPCM_USB)",
-		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0),
+		USB_SC_SCSI, USB_PR_DPCM_USB, NULL, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x0003, 0x0000, 0x9999,
 		"Sandisk",
 		"ImageMate SDDR09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		USB_SC_SCSI, USB_PR_EUSB_SDDR09, usb_stor_sddr09_init,
 		0),
 
 /* This entry is from Andries.Brouwer@cwi.nl */
 UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x0208,
 		"SCM Microsystems",
 		"eUSB SmartMedia / CompactFlash Adapter",
-		US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
+		USB_SC_SCSI, USB_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
 		0),
 
 UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100,
 		"Olympus",
 		"Camedia MAUSB-2",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		USB_SC_SCSI, USB_PR_EUSB_SDDR09, usb_stor_sddr09_init,
 		0),
 
 UNUSUAL_DEV(  0x0781, 0x0200, 0x0000, 0x9999,
 		"Sandisk",
 		"ImageMate SDDR-09",
-		US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+		USB_SC_SCSI, USB_PR_EUSB_SDDR09, usb_stor_sddr09_init,
 		0),
 
 UNUSUAL_DEV(  0x07af, 0x0006, 0x0100, 0x0100,
 		"Microtech",
 		"CameraMate (DPCM_USB)",
-		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0),
+		USB_SC_SCSI, USB_PR_DPCM_USB, NULL, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_SDDR09) || ... */
diff --git a/drivers/usb/storage/unusual_sddr55.h b/drivers/usb/storage/unusual_sddr55.h
index ae81ef7..fcb7e12 100644
--- a/drivers/usb/storage/unusual_sddr55.h
+++ b/drivers/usb/storage/unusual_sddr55.h
@@ -22,23 +22,23 @@
 UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
 		"Datafab",
 		"MDSM-B reader",
-		US_SC_SCSI, US_PR_SDDR55, NULL,
+		USB_SC_SCSI, USB_PR_SDDR55, NULL,
 		US_FL_FIX_INQUIRY),
 
 /* SM part - aeb <Andries.Brouwer@cwi.nl> */
 UNUSUAL_DEV(  0x07c4, 0xa109, 0x0000, 0xffff,
 		"Datafab Systems, Inc.",
 		"USB to CF + SM Combo (LC1)",
-		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
+		USB_SC_SCSI, USB_PR_SDDR55, NULL, 0),
 
 UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
 		"Acomdata",
 		"SM",
-		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
+		USB_SC_SCSI, USB_PR_SDDR55, NULL, 0),
 
 UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999,
 		"Sandisk",
 		"ImageMate SDDR55",
-		US_SC_SCSI, US_PR_SDDR55, NULL, 0),
+		USB_SC_SCSI, USB_PR_SDDR55, NULL, 0),
 
 #endif /* defined(CONFIG_USB_STORAGE_SDDR55) || ... */
diff --git a/drivers/usb/storage/unusual_usbat.h b/drivers/usb/storage/unusual_usbat.h
index 80e869f..38e79c4 100644
--- a/drivers/usb/storage/unusual_usbat.h
+++ b/drivers/usb/storage/unusual_usbat.h
@@ -21,23 +21,23 @@
 UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001,
 		"HP",
 		"CD-Writer+ 8200e",
-		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+		USB_SC_8070, USB_PR_USBAT, init_usbat_cd, 0),
 
 UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001,
 		"HP",
 		"CD-Writer+ CD-4e",
-		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
+		USB_SC_8070, USB_PR_USBAT, init_usbat_cd, 0),
 
 UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
 		"Shuttle/SCM",
 		"USBAT-02",
-		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+		USB_SC_SCSI, USB_PR_USBAT, init_usbat_flash,
 		US_FL_SINGLE_LUN),
 
 UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
 		"Sandisk",
 		"ImageMate SDDR-05b",
-		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
+		USB_SC_SCSI, USB_PR_USBAT, init_usbat_flash,
 		US_FL_SINGLE_LUN),
 
 #endif /* defined(CONFIG_USB_STORAGE_USBAT) || ... */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 90bb017..4219c19 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -512,10 +512,10 @@
 
 	/* Store the entries */
 	us->unusual_dev = unusual_dev;
-	us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
+	us->subclass = (unusual_dev->useProtocol == USB_SC_DEVICE) ?
 			idesc->bInterfaceSubClass :
 			unusual_dev->useProtocol;
-	us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
+	us->protocol = (unusual_dev->useTransport == USB_PR_DEVICE) ?
 			idesc->bInterfaceProtocol :
 			unusual_dev->useTransport;
 	us->fflags = USB_US_ORIG_FLAGS(id->driver_info);
@@ -552,10 +552,10 @@
 		struct usb_device_descriptor *ddesc = &dev->descriptor;
 		int msg = -1;
 
-		if (unusual_dev->useProtocol != US_SC_DEVICE &&
+		if (unusual_dev->useProtocol != USB_SC_DEVICE &&
 			us->subclass == idesc->bInterfaceSubClass)
 			msg += 1;
-		if (unusual_dev->useTransport != US_PR_DEVICE &&
+		if (unusual_dev->useTransport != USB_PR_DEVICE &&
 			us->protocol == idesc->bInterfaceProtocol)
 			msg += 2;
 		if (msg >= 0 && !(us->fflags & US_FL_NEED_OVERRIDE))
@@ -582,21 +582,21 @@
 static void get_transport(struct us_data *us)
 {
 	switch (us->protocol) {
-	case US_PR_CB:
+	case USB_PR_CB:
 		us->transport_name = "Control/Bulk";
 		us->transport = usb_stor_CB_transport;
 		us->transport_reset = usb_stor_CB_reset;
 		us->max_lun = 7;
 		break;
 
-	case US_PR_CBI:
+	case USB_PR_CBI:
 		us->transport_name = "Control/Bulk/Interrupt";
 		us->transport = usb_stor_CB_transport;
 		us->transport_reset = usb_stor_CB_reset;
 		us->max_lun = 7;
 		break;
 
-	case US_PR_BULK:
+	case USB_PR_BULK:
 		us->transport_name = "Bulk";
 		us->transport = usb_stor_Bulk_transport;
 		us->transport_reset = usb_stor_Bulk_reset;
@@ -608,35 +608,35 @@
 static void get_protocol(struct us_data *us)
 {
 	switch (us->subclass) {
-	case US_SC_RBC:
+	case USB_SC_RBC:
 		us->protocol_name = "Reduced Block Commands (RBC)";
 		us->proto_handler = usb_stor_transparent_scsi_command;
 		break;
 
-	case US_SC_8020:
+	case USB_SC_8020:
 		us->protocol_name = "8020i";
 		us->proto_handler = usb_stor_pad12_command;
 		us->max_lun = 0;
 		break;
 
-	case US_SC_QIC:
+	case USB_SC_QIC:
 		us->protocol_name = "QIC-157";
 		us->proto_handler = usb_stor_pad12_command;
 		us->max_lun = 0;
 		break;
 
-	case US_SC_8070:
+	case USB_SC_8070:
 		us->protocol_name = "8070i";
 		us->proto_handler = usb_stor_pad12_command;
 		us->max_lun = 0;
 		break;
 
-	case US_SC_SCSI:
+	case USB_SC_SCSI:
 		us->protocol_name = "Transparent SCSI";
 		us->proto_handler = usb_stor_transparent_scsi_command;
 		break;
 
-	case US_SC_UFI:
+	case USB_SC_UFI:
 		us->protocol_name = "Uniform Floppy Interface (UFI)";
 		us->proto_handler = usb_stor_ufi_command;
 		break;
@@ -679,7 +679,7 @@
 		}
 	}
 
-	if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) {
+	if (!ep_in || !ep_out || (us->protocol == USB_PR_CBI && !ep_int)) {
 		US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
 		return -EIO;
 	}
@@ -834,7 +834,7 @@
 	if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
 
 		/* For bulk-only devices, determine the max LUN value */
-		if (us->protocol == US_PR_BULK &&
+		if (us->protocol == USB_PR_BULK &&
 				!(us->fflags & US_FL_SINGLE_LUN)) {
 			mutex_lock(&us->dev_mutex);
 			us->max_lun = usb_stor_Bulk_max_lun(us);
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 552679b..e24ce31 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -507,6 +507,7 @@
 	.open =		skel_open,
 	.release =	skel_release,
 	.flush =	skel_flush,
+	.llseek =	noop_llseek,
 };
 
 /*
diff --git a/drivers/usb/wusbcore/Makefile b/drivers/usb/wusbcore/Makefile
index 75f1ade..b3bd3130 100644
--- a/drivers/usb/wusbcore/Makefile
+++ b/drivers/usb/wusbcore/Makefile
@@ -1,9 +1,11 @@
+ccflags-$(CONFIG_USB_WUSB_CBAF_DEBUG) := -DDEBUG
+
 obj-$(CONFIG_USB_WUSB)		+= wusbcore.o
 obj-$(CONFIG_USB_HWA_HCD)	+= wusb-wa.o
 obj-$(CONFIG_USB_WUSB_CBAF)	+= wusb-cbaf.o
 
 
-wusbcore-objs := 	\
+wusbcore-y :=		\
 	crypto.o	\
 	devconnect.o	\
 	dev-sysfs.o	\
@@ -14,13 +16,10 @@
 	security.o	\
 	wusbhc.o
 
-wusb-cbaf-objs := cbaf.o
+wusb-cbaf-y := cbaf.o
 
-wusb-wa-objs :=	wa-hc.o		\
-		wa-nep.o	\
-		wa-rpipe.o	\
-		wa-xfer.o
-
-ifeq ($(CONFIG_USB_WUSB_CBAF_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+wusb-wa-y :=		\
+	wa-hc.o		\
+	wa-nep.o	\
+	wa-rpipe.o	\
+	wa-xfer.o
diff --git a/drivers/uwb/address.c b/drivers/uwb/address.c
index 9733213..8739c4f 100644
--- a/drivers/uwb/address.c
+++ b/drivers/uwb/address.c
@@ -363,10 +363,7 @@
 {
 	size_t result;
 	if (type)
-		result = scnprintf(buf, buf_size,
-				  "%02x:%02x:%02x:%02x:%02x:%02x",
-				  addr[0], addr[1], addr[2],
-				  addr[3], addr[4], addr[5]);
+		result = scnprintf(buf, buf_size, "%pM", addr);
 	else
 		result = scnprintf(buf, buf_size, "%02x:%02x",
 				  addr[1], addr[0]);
diff --git a/drivers/uwb/wlp/wss-lc.c b/drivers/uwb/wlp/wss-lc.c
index a005d2a..67872c8 100644
--- a/drivers/uwb/wlp/wss-lc.c
+++ b/drivers/uwb/wlp/wss-lc.c
@@ -791,11 +791,8 @@
 	} else {
 		if (printk_ratelimit())
 			dev_err(dev, "WLP: Destination neighbor (Ethernet: "
-				"%02x:%02x:%02x:%02x:%02x:%02x, Dev: "
-				"%02x:%02x) is not connected. \n", eth_addr[0],
-				eth_addr[1], eth_addr[2], eth_addr[3],
-				eth_addr[4], eth_addr[5], dev_addr->data[1],
-				dev_addr->data[0]);
+				"%pM, Dev: %02x:%02x) is not connected.\n",
+				eth_addr, dev_addr->data[1], dev_addr->data[0]);
 		result = -EINVAL;
 	}
 	return result;
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 17927b1..861af4a 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -877,6 +877,7 @@
 	.compat_ioctl   = vhost_net_compat_ioctl,
 #endif
 	.open           = vhost_net_open,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice vhost_net_misc = {
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index f3aada2..5b2b5ef 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -1718,11 +1718,9 @@
 			(((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
 			(((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
 			((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
-#ifdef ATAFB_FALCON
 		((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |
 						       ((green & 0xfc00) >> 5) |
 						       ((blue & 0xf800) >> 11));
-#endif
 	}
 	return 0;
 }
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index b066475..42e303f 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1439,6 +1439,7 @@
 #ifdef CONFIG_FB_DEFERRED_IO
 	.fsync =	fb_deferred_io_fsync,
 #endif
+	.llseek =	default_llseek,
 };
 
 struct class *fb_class;
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
index ecad965..12dec76 100644
--- a/drivers/video/mbx/mbxdebugfs.c
+++ b/drivers/video/mbx/mbxdebugfs.c
@@ -175,36 +175,42 @@
 	.read = sysconf_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations clock_fops = {
 	.read = clock_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations display_fops = {
 	.read = display_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations gsctl_fops = {
 	.read = gsctl_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations sdram_fops = {
 	.read = sdram_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations misc_fops = {
 	.read = misc_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
+	.llseek = default_llseek,
 };
 
 static void __devinit mbxfb_debugfs_init(struct fb_info *fbi)
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index fc32c32..f5a39f5 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -28,7 +28,7 @@
 
 #define Q40_PHYS_SCREEN_ADDR 0xFE800000
 
-static struct fb_fix_screeninfo q40fb_fix __initdata = {
+static struct fb_fix_screeninfo q40fb_fix __devinitdata = {
 	.id		= "Q40",
 	.smem_len	= 1024*1024,
 	.type		= FB_TYPE_PACKED_PIXELS,
@@ -37,7 +37,7 @@
 	.accel		= FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo q40fb_var __initdata = {
+static struct fb_var_screeninfo q40fb_var __devinitdata = {
 	.xres		= 1024,
 	.yres		= 512,
 	.xres_virtual	= 1024,
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index c764c52..b292217 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -267,6 +267,7 @@
 	.unlocked_ioctl	= ar7_wdt_ioctl,
 	.open		= ar7_wdt_open,
 	.release	= ar7_wdt_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice ar7_wdt_miscdev = {
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 566343b..eca855a 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -25,7 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -89,6 +89,7 @@
 	} devs[WD_NUMDEVS];
 };
 
+static DEFINE_MUTEX(cpwd_mutex);
 static struct cpwd *cpwd_device;
 
 /* Sun uses Altera PLD EPF8820ATC144-4
@@ -368,7 +369,7 @@
 {
 	struct cpwd *p = cpwd_device;
 
-	lock_kernel();
+	mutex_lock(&cpwd_mutex);
 	switch (iminor(inode)) {
 	case WD0_MINOR:
 	case WD1_MINOR:
@@ -376,7 +377,7 @@
 		break;
 
 	default:
-		unlock_kernel();
+		mutex_unlock(&cpwd_mutex);
 		return -ENODEV;
 	}
 
@@ -386,13 +387,13 @@
 				IRQF_SHARED, DRIVER_NAME, p)) {
 			printk(KERN_ERR PFX "Cannot register IRQ %d\n",
 				p->irq);
-			unlock_kernel();
+			mutex_unlock(&cpwd_mutex);
 			return -EBUSY;
 		}
 		p->initialized = true;
 	}
 
-	unlock_kernel();
+	mutex_unlock(&cpwd_mutex);
 
 	return nonseekable_open(inode, f);
 }
@@ -482,9 +483,9 @@
 	case WIOCSTART:
 	case WIOCSTOP:
 	case WIOCGSTAT:
-		lock_kernel();
+		mutex_lock(&cpwd_mutex);
 		rval = cpwd_ioctl(file, cmd, arg);
-		unlock_kernel();
+		mutex_unlock(&cpwd_mutex);
 		break;
 
 	/* everything else is handled by the generic compat layer */
@@ -524,6 +525,7 @@
 	.write =		cpwd_write,
 	.read =			cpwd_read,
 	.release =		cpwd_release,
+	.llseek =		no_llseek,
 };
 
 static int __devinit cpwd_probe(struct platform_device *op,
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index 59359c9..726b7df 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -188,6 +188,7 @@
 	.unlocked_ioctl	= ep93xx_wdt_ioctl,
 	.open		= ep93xx_wdt_open,
 	.release	= ep93xx_wdt_release,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice ep93xx_wdt_miscdev = {
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 76b58ab..81e3d61 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -258,6 +258,7 @@
 	.unlocked_ioctl = omap_wdt_ioctl,
 	.open = omap_wdt_open,
 	.release = omap_wdt_release,
+	.llseek = no_llseek,
 };
 
 static int __devinit omap_wdt_probe(struct platform_device *pdev)
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
index 66e185c..fec6ba3 100644
--- a/drivers/xen/evtchn.c
+++ b/drivers/xen/evtchn.c
@@ -467,6 +467,7 @@
 	.fasync  = evtchn_fasync,
 	.open    = evtchn_open,
 	.release = evtchn_release,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice evtchn_miscdev = {
diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c
index 78bfab0..bd96340 100644
--- a/drivers/xen/xenfs/super.c
+++ b/drivers/xen/xenfs/super.c
@@ -35,6 +35,7 @@
 
 static const struct file_operations capabilities_file_ops = {
 	.read = capabilities_read,
+	.llseek = default_llseek,
 };
 
 static int xenfs_fill_super(struct super_block *sb, void *data, int silent)
diff --git a/drivers/xen/xenfs/xenbus.c b/drivers/xen/xenfs/xenbus.c
index 3b39c37..1c12360 100644
--- a/drivers/xen/xenfs/xenbus.c
+++ b/drivers/xen/xenfs/xenbus.c
@@ -594,4 +594,5 @@
 	.open = xenbus_file_open,
 	.release = xenbus_file_release,
 	.poll = xenbus_file_poll,
+	.llseek = no_llseek,
 };
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index 6455f3a..e0c2807 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -142,6 +142,7 @@
 	error = device_register(&bus->dev);
 	if (error) {
 		pr_err("Zorro: Error registering zorro_bus\n");
+		put_device(&bus->dev);
 		kfree(bus);
 		return error;
 	}
@@ -175,6 +176,7 @@
 		if (error) {
 			dev_err(&bus->dev, "Error registering device %s\n",
 				z->name);
+			put_device(&z->dev);
 			continue;
 		}
 		error = zorro_create_sysfs_dev_files(z);
diff --git a/fs/Kconfig b/fs/Kconfig
index 3d18530..65781de 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -50,6 +50,7 @@
 config FILE_LOCKING
 	bool "Enable POSIX file locking API" if EMBEDDED
 	default y
+	select BKL # while lockd still uses it.
 	help
 	  This option enables standard file locking support, required
           for filesystems like NFS and for the flock() system
diff --git a/fs/adfs/Kconfig b/fs/adfs/Kconfig
index e55182a..1dd5f34 100644
--- a/fs/adfs/Kconfig
+++ b/fs/adfs/Kconfig
@@ -1,6 +1,7 @@
 config ADFS_FS
 	tristate "ADFS file system support (EXPERIMENTAL)"
 	depends on BLOCK && EXPERIMENTAL
+	depends on BKL # need to fix
 	help
 	  The Acorn Disc Filing System is the standard file system of the
 	  RiscOS operating system which runs on Acorn's ARM-based Risc PC
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 4a3af70..d9803f7 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -352,11 +352,15 @@
 	struct adfs_sb_info *asb;
 	struct inode *root;
 
+	lock_kernel();
+
 	sb->s_flags |= MS_NODIRATIME;
 
 	asb = kzalloc(sizeof(*asb), GFP_KERNEL);
-	if (!asb)
+	if (!asb) {
+		unlock_kernel();
 		return -ENOMEM;
+	}
 	sb->s_fs_info = asb;
 
 	/* set default options */
@@ -474,6 +478,7 @@
 		goto error;
 	} else
 		sb->s_root->d_op = &adfs_dentry_operations;
+	unlock_kernel();
 	return 0;
 
 error_free_bh:
@@ -481,6 +486,7 @@
 error:
 	sb->s_fs_info = NULL;
 	kfree(asb);
+	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 9581ea9..fa4fbe1 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -16,7 +16,6 @@
 #include <linux/parser.h>
 #include <linux/magic.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include "affs.h"
 
@@ -46,8 +45,6 @@
 	struct affs_sb_info *sbi = AFFS_SB(sb);
 	pr_debug("AFFS: put_super()\n");
 
-	lock_kernel();
-
 	if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt)
 		affs_commit_super(sb, 1, 1);
 
@@ -56,8 +53,6 @@
 	affs_brelse(sbi->s_root_bh);
 	kfree(sbi);
 	sb->s_fs_info = NULL;
-
-	unlock_kernel();
 }
 
 static void
@@ -302,6 +297,7 @@
 	sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
+
 	sb->s_fs_info = sbi;
 	mutex_init(&sbi->s_bmlock);
 	spin_lock_init(&sbi->symlink_lock);
@@ -527,7 +523,7 @@
 		kfree(new_opts);
 		return -EINVAL;
 	}
-	lock_kernel();
+
 	replace_mount_options(sb, new_opts);
 
 	sbi->s_flags = mount_flags;
@@ -543,17 +539,15 @@
 	memcpy(sbi->s_volume, volume, 32);
 	spin_unlock(&sbi->symlink_lock);
 
-	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
-		unlock_kernel();
+	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
 		return 0;
-	}
+
 	if (*flags & MS_RDONLY) {
 		affs_write_super(sb);
 		affs_free_bitmap(sb);
 	} else
 		res = affs_init_bitmap(sb, flags);
 
-	unlock_kernel();
 	return res;
 }
 
diff --git a/fs/afs/flock.c b/fs/afs/flock.c
index 0931bc1..757d6645 100644
--- a/fs/afs/flock.c
+++ b/fs/afs/flock.c
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/smp_lock.h>
 #include "internal.h"
 
 #define AFS_LOCK_GRANTED	0
@@ -274,7 +273,7 @@
 
 	type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
 
-	lock_kernel();
+	lock_flocks();
 
 	/* make sure we've got a callback on this file and that our view of the
 	 * data version is up to date */
@@ -421,7 +420,7 @@
 	afs_vnode_fetch_status(vnode, NULL, key);
 
 error:
-	unlock_kernel();
+	unlock_flocks();
 	_leave(" = %d", ret);
 	return ret;
 
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 6d55268..6153417 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -29,6 +29,7 @@
 
 const struct file_operations afs_mntpt_file_operations = {
 	.open		= afs_mntpt_open,
+	.llseek		= noop_llseek,
 };
 
 const struct inode_operations afs_mntpt_inode_operations = {
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 77e1e5a..eacf76d 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -19,7 +19,6 @@
 #include <linux/mount.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/parser.h>
@@ -453,12 +452,8 @@
 
 	_enter("");
 
-	lock_kernel();
-
 	afs_put_volume(as->volume);
 
-	unlock_kernel();
-
 	_leave("");
 }
 
diff --git a/fs/autofs/Kconfig b/fs/autofs/Kconfig
index 5f3bea9..480e210 100644
--- a/fs/autofs/Kconfig
+++ b/fs/autofs/Kconfig
@@ -1,5 +1,6 @@
 config AUTOFS_FS
 	tristate "Kernel automounter support"
+	depends on BKL # unfixable, just use autofs4
 	help
 	  The automounter is a tool to automatically mount remote file systems
 	  on demand. This implementation is partially kernel-based to reduce
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 11b1ea7..0c4ca81 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -27,7 +27,9 @@
 static int autofs_root_rmdir(struct inode *,struct dentry *);
 static int autofs_root_mkdir(struct inode *,struct dentry *,int);
 static long autofs_root_ioctl(struct file *,unsigned int,unsigned long);
+#ifdef CONFIG_COMPAT
 static long autofs_root_compat_ioctl(struct file *,unsigned int,unsigned long);
+#endif
 
 const struct file_operations autofs_root_operations = {
 	.llseek		= generic_file_llseek,
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index ba4a38b..eff9a41 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -724,6 +724,7 @@
 	.unlocked_ioctl	 = autofs_dev_ioctl,
 	.compat_ioctl = autofs_dev_ioctl_compat,
 	.owner	 = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice _autofs_dev_ioctl_misc = {
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index cb1bd38..d5c1401 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -19,7 +19,7 @@
 #include <linux/param.h>
 #include <linux/time.h>
 #include <linux/compat.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include "autofs_i.h"
 
@@ -28,7 +28,9 @@
 static int autofs4_dir_rmdir(struct inode *,struct dentry *);
 static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
 static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long);
+#ifdef CONFIG_COMPAT
 static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
+#endif
 static int autofs4_dir_open(struct inode *inode, struct file *file);
 static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
 static void *autofs4_follow_link(struct dentry *, struct nameidata *);
@@ -978,15 +980,17 @@
 	}
 }
 
+static DEFINE_MUTEX(autofs4_ioctl_mutex);
+
 static long autofs4_root_ioctl(struct file *filp,
 			       unsigned int cmd, unsigned long arg)
 {
 	long ret;
 	struct inode *inode = filp->f_dentry->d_inode;
 
-	lock_kernel();
+	mutex_lock(&autofs4_ioctl_mutex);
 	ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
-	unlock_kernel();
+	mutex_unlock(&autofs4_ioctl_mutex);
 
 	return ret;
 }
@@ -998,13 +1002,13 @@
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	int ret;
 
-	lock_kernel();
+	mutex_lock(&autofs4_ioctl_mutex);
 	if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
 		ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
 	else
 		ret = autofs4_root_ioctl_unlocked(inode, filp, cmd,
 			(unsigned long)compat_ptr(arg));
-	unlock_kernel();
+	mutex_unlock(&autofs4_ioctl_mutex);
 
 	return ret;
 }
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index c4daf0f..883e77a 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -12,7 +12,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
@@ -215,14 +214,10 @@
 	if (!info)
 		return;
 
-	lock_kernel();
-
 	mutex_destroy(&info->bfs_lock);
 	kfree(info->si_imap);
 	kfree(info);
 	s->s_fs_info = NULL;
-
-	unlock_kernel();
 }
 
 static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index fd0cc0b..139fc80 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -576,6 +576,7 @@
 static const struct file_operations bm_entry_operations = {
 	.read		= bm_entry_read,
 	.write		= bm_entry_write,
+	.llseek		= default_llseek,
 };
 
 /* /register */
@@ -643,6 +644,7 @@
 
 static const struct file_operations bm_register_operations = {
 	.write		= bm_register_write,
+	.llseek		= noop_llseek,
 };
 
 /* /status */
@@ -680,6 +682,7 @@
 static const struct file_operations bm_status_operations = {
 	.read		= bm_status_read,
 	.write		= bm_status_write,
+	.llseek		= default_llseek,
 };
 
 /* Superblock handling */
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 50e8c85..b737451 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -370,7 +370,7 @@
 	 */
 	mutex_unlock(&bd_inode->i_mutex);
 
-	error = blkdev_issue_flush(bdev, GFP_KERNEL, NULL, BLKDEV_IFL_WAIT);
+	error = blkdev_issue_flush(bdev, GFP_KERNEL, NULL);
 	if (error == -EOPNOTSUPP)
 		error = 0;
 
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 64f1008..5e789f4 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2063,7 +2063,7 @@
 	if (uptodate) {
 		set_buffer_uptodate(bh);
 	} else {
-		if (!buffer_eopnotsupp(bh) && printk_ratelimit()) {
+		if (printk_ratelimit()) {
 			printk(KERN_WARNING "lost page write due to "
 					"I/O error on %s\n",
 				       bdevname(bh->b_bdev, b));
@@ -2200,21 +2200,10 @@
 			bh->b_end_io = btrfs_end_buffer_write_sync;
 		}
 
-		if (i == last_barrier && do_barriers && device->barriers) {
-			ret = submit_bh(WRITE_BARRIER, bh);
-			if (ret == -EOPNOTSUPP) {
-				printk("btrfs: disabling barriers on dev %s\n",
-				       device->name);
-				set_buffer_uptodate(bh);
-				device->barriers = 0;
-				/* one reference for submit_bh */
-				get_bh(bh);
-				lock_buffer(bh);
-				ret = submit_bh(WRITE_SYNC, bh);
-			}
-		} else {
+		if (i == last_barrier && do_barriers)
+			ret = submit_bh(WRITE_FLUSH_FUA, bh);
+		else
 			ret = submit_bh(WRITE_SYNC, bh);
-		}
 
 		if (ret)
 			errors++;
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 32d0940..0b81ecd 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1695,8 +1695,7 @@
 static void btrfs_issue_discard(struct block_device *bdev,
 				u64 start, u64 len)
 {
-	blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL,
-			BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+	blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL, 0);
 }
 
 static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 1776dbd..144f8a5 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -815,6 +815,7 @@
 	.unlocked_ioctl	 = btrfs_control_ioctl,
 	.compat_ioctl = btrfs_control_ioctl,
 	.owner	 = THIS_MODULE,
+	.llseek = noop_llseek,
 };
 
 static struct miscdevice btrfs_misc = {
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index dd318ff..e25e46a 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -398,7 +398,6 @@
 		device->work.func = pending_bios_fn;
 		memcpy(device->uuid, disk_super->dev_item.uuid,
 		       BTRFS_UUID_SIZE);
-		device->barriers = 1;
 		spin_lock_init(&device->io_lock);
 		device->name = kstrdup(path, GFP_NOFS);
 		if (!device->name) {
@@ -462,7 +461,6 @@
 		device->devid = orig_dev->devid;
 		device->work.func = pending_bios_fn;
 		memcpy(device->uuid, orig_dev->uuid, sizeof(device->uuid));
-		device->barriers = 1;
 		spin_lock_init(&device->io_lock);
 		INIT_LIST_HEAD(&device->dev_list);
 		INIT_LIST_HEAD(&device->dev_alloc_list);
@@ -1489,7 +1487,6 @@
 	trans = btrfs_start_transaction(root, 0);
 	lock_chunks(root);
 
-	device->barriers = 1;
 	device->writeable = 1;
 	device->work.func = pending_bios_fn;
 	generate_random_uuid(device->uuid);
@@ -3084,7 +3081,6 @@
 		return NULL;
 	list_add(&device->dev_list,
 		 &fs_devices->devices);
-	device->barriers = 1;
 	device->dev_root = root->fs_info->dev_root;
 	device->devid = devid;
 	device->work.func = pending_bios_fn;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 31b0fab..2b638b6 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -42,7 +42,6 @@
 	int running_pending;
 	u64 generation;
 
-	int barriers;
 	int writeable;
 	int in_fs_metadata;
 
diff --git a/fs/buffer.c b/fs/buffer.c
index 3e7dca2..7f0b9b0 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -156,7 +156,7 @@
 	if (uptodate) {
 		set_buffer_uptodate(bh);
 	} else {
-		if (!buffer_eopnotsupp(bh) && !quiet_error(bh)) {
+		if (!quiet_error(bh)) {
 			buffer_io_error(bh);
 			printk(KERN_WARNING "lost page write due to "
 					"I/O error on %s\n",
@@ -2891,7 +2891,6 @@
 
 	if (err == -EOPNOTSUPP) {
 		set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
-		set_bit(BH_Eopnotsupp, &bh->b_state);
 	}
 
 	if (unlikely (test_bit(BIO_QUIET,&bio->bi_flags)))
@@ -3031,10 +3030,6 @@
 		bh->b_end_io = end_buffer_write_sync;
 		ret = submit_bh(rw, bh);
 		wait_on_buffer(bh);
-		if (buffer_eopnotsupp(bh)) {
-			clear_buffer_eopnotsupp(bh);
-			ret = -EOPNOTSUPP;
-		}
 		if (!ret && !buffer_uptodate(bh))
 			ret = -EIO;
 	} else {
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c
index 727caed..0a1467b 100644
--- a/fs/cachefiles/daemon.c
+++ b/fs/cachefiles/daemon.c
@@ -55,6 +55,7 @@
 	.read		= cachefiles_daemon_read,
 	.write		= cachefiles_daemon_write,
 	.poll		= cachefiles_daemon_poll,
+	.llseek		= noop_llseek,
 };
 
 struct cachefiles_daemon_cmd {
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 143d393..e5b9df9 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -456,6 +456,7 @@
  */
 const struct file_operations def_chr_fops = {
 	.open = chrdev_open,
+	.llseek = noop_llseek,
 };
 
 static struct kobject *exact_match(dev_t dev, int *part, void *data)
diff --git a/fs/cifs/README b/fs/cifs/README
index 7099a52..ee68d10 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -527,6 +527,11 @@
 		SFU does).  In the future the bottom 9 bits of the
 		mode also will be emulated using queries of the security
 		descriptor (ACL).
+ mfsymlinks     Enable support for Minshall+French symlinks
+		(see http://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks)
+		This option is ignored when specified together with the
+		'sfu' option. Minshall+French symlinks are used even if
+		the server supports the CIFS Unix Extensions.
  sign           Must use packet signing (helps avoid unwanted data modification
 		by intermediate systems in the route).  Note that signing
 		does not work with lanman or plaintext authentication.
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index eb1ba49..103ab8b 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -148,7 +148,7 @@
 	seq_printf(m, "Servers:");
 
 	i = 0;
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp1, &cifs_tcp_ses_list) {
 		server = list_entry(tmp1, struct TCP_Server_Info,
 				    tcp_ses_list);
@@ -230,7 +230,7 @@
 			spin_unlock(&GlobalMid_Lock);
 		}
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	seq_putc(m, '\n');
 
 	/* BB add code to dump additional info such as TCP session info now */
@@ -270,7 +270,7 @@
 		atomic_set(&totBufAllocCount, 0);
 		atomic_set(&totSmBufAllocCount, 0);
 #endif /* CONFIG_CIFS_STATS2 */
-		read_lock(&cifs_tcp_ses_lock);
+		spin_lock(&cifs_tcp_ses_lock);
 		list_for_each(tmp1, &cifs_tcp_ses_list) {
 			server = list_entry(tmp1, struct TCP_Server_Info,
 					    tcp_ses_list);
@@ -303,7 +303,7 @@
 				}
 			}
 		}
-		read_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 	}
 
 	return count;
@@ -343,7 +343,7 @@
 		GlobalCurrentXid, GlobalMaxActiveXid);
 
 	i = 0;
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp1, &cifs_tcp_ses_list) {
 		server = list_entry(tmp1, struct TCP_Server_Info,
 				    tcp_ses_list);
@@ -397,7 +397,7 @@
 			}
 		}
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	seq_putc(m, '\n');
 	return 0;
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index aa31689..8942b28 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -34,7 +34,7 @@
 extern int traceSMB;		/* flag which enables the function below */
 void dump_smb(struct smb_hdr *, int);
 #define CIFS_INFO	0x01
-#define CIFS_RC  	0x02
+#define CIFS_RC		0x02
 #define CIFS_TIMER	0x04
 
 /*
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index d6ced7a..c68a056 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -44,8 +44,7 @@
 void cifs_dfs_release_automount_timer(void)
 {
 	BUG_ON(!list_empty(&cifs_dfs_automount_list));
-	cancel_delayed_work(&cifs_dfs_automount_task);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&cifs_dfs_automount_task);
 }
 
 /**
@@ -306,6 +305,7 @@
 	int xid, i;
 	int rc = 0;
 	struct vfsmount *mnt = ERR_PTR(-ENOENT);
+	struct tcon_link *tlink;
 
 	cFYI(1, "in %s", __func__);
 	BUG_ON(IS_ROOT(dentry));
@@ -315,14 +315,6 @@
 	dput(nd->path.dentry);
 	nd->path.dentry = dget(dentry);
 
-	cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
-	ses = cifs_sb->tcon->ses;
-
-	if (!ses) {
-		rc = -EINVAL;
-		goto out_err;
-	}
-
 	/*
 	 * The MSDFS spec states that paths in DFS referral requests and
 	 * responses must be prefixed by a single '\' character instead of
@@ -335,10 +327,20 @@
 		goto out_err;
 	}
 
-	rc = get_dfs_path(xid, ses , full_path + 1, cifs_sb->local_nls,
+	cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		goto out_err;
+	}
+	ses = tlink_tcon(tlink)->ses;
+
+	rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls,
 		&num_referrals, &referrals,
 		cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 
+	cifs_put_tlink(tlink);
+
 	for (i = 0; i < num_referrals; i++) {
 		int len;
 		dump_referral(referrals+i);
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 9e77145..525ba59 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -15,6 +15,8 @@
  *   the GNU Lesser General Public License for more details.
  *
  */
+#include <linux/radix-tree.h>
+
 #ifndef _CIFS_FS_SB_H
 #define _CIFS_FS_SB_H
 
@@ -36,23 +38,28 @@
 #define CIFS_MOUNT_NOPOSIXBRL   0x2000 /* mandatory not posix byte range lock */
 #define CIFS_MOUNT_NOSSYNC      0x4000 /* don't do slow SMBflush on every sync*/
 #define CIFS_MOUNT_FSCACHE	0x8000 /* local caching enabled */
+#define CIFS_MOUNT_MF_SYMLINKS	0x10000 /* Minshall+French Symlinks enabled */
+#define CIFS_MOUNT_MULTIUSER	0x20000 /* multiuser mount */
 
 struct cifs_sb_info {
-	struct cifsTconInfo *tcon;	/* primary mount */
-	struct list_head nested_tcon_q;
+	struct radix_tree_root tlink_tree;
+#define CIFS_TLINK_MASTER_TAG		0	/* is "master" (mount) tcon */
+	spinlock_t tlink_tree_lock;
 	struct nls_table *local_nls;
 	unsigned int rsize;
 	unsigned int wsize;
+	atomic_t active;
 	uid_t	mnt_uid;
 	gid_t	mnt_gid;
 	mode_t	mnt_file_mode;
 	mode_t	mnt_dir_mode;
-	int     mnt_cifs_flags;
+	unsigned int mnt_cifs_flags;
 	int	prepathlen;
 	char   *prepath; /* relative path under the share to mount to */
 #ifdef CONFIG_CIFS_DFS_UPCALL
 	char   *mountdata; /* mount options received at mount time */
 #endif
 	struct backing_dev_info bdi;
+	struct delayed_work prune_tlinks;
 };
 #endif				/* _CIFS_FS_SB_H */
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 85d7cf7..c9b4792 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -557,11 +557,16 @@
 {
 	struct cifs_ntsd *pntsd = NULL;
 	int xid, rc;
+	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+
+	if (IS_ERR(tlink))
+		return NULL;
 
 	xid = GetXid();
-	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+	rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
 	FreeXid(xid);
 
+	cifs_put_tlink(tlink);
 
 	cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
 	return pntsd;
@@ -574,10 +579,16 @@
 	int oplock = 0;
 	int xid, rc;
 	__u16 fid;
+	struct cifsTconInfo *tcon;
+	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 
+	if (IS_ERR(tlink))
+		return NULL;
+
+	tcon = tlink_tcon(tlink);
 	xid = GetXid();
 
-	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0,
+	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
 			 &fid, &oplock, NULL, cifs_sb->local_nls,
 			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
@@ -585,11 +596,12 @@
 		goto out;
 	}
 
-	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
+	rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
 	cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
 
-	CIFSSMBClose(xid, cifs_sb->tcon, fid);
+	CIFSSMBClose(xid, tcon, fid);
  out:
+	cifs_put_tlink(tlink);
 	FreeXid(xid);
 	return pntsd;
 }
@@ -603,7 +615,7 @@
 	struct cifsFileInfo *open_file = NULL;
 
 	if (inode)
-		open_file = find_readable_file(CIFS_I(inode));
+		open_file = find_readable_file(CIFS_I(inode), true);
 	if (!open_file)
 		return get_cifs_acl_by_path(cifs_sb, path, pacllen);
 
@@ -616,10 +628,15 @@
 		struct cifs_ntsd *pnntsd, u32 acllen)
 {
 	int xid, rc;
+	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
+
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
 
 	xid = GetXid();
-	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
+	rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 
 	cFYI(DBG2, "SetCIFSACL rc = %d", rc);
 	return rc;
@@ -631,10 +648,16 @@
 	int oplock = 0;
 	int xid, rc;
 	__u16 fid;
+	struct cifsTconInfo *tcon;
+	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+
+	tcon = tlink_tcon(tlink);
 	xid = GetXid();
 
-	rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0,
+	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
 			 &fid, &oplock, NULL, cifs_sb->local_nls,
 			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
@@ -642,12 +665,13 @@
 		goto out;
 	}
 
-	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
+	rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
 	cFYI(DBG2, "SetCIFSACL rc = %d", rc);
 
-	CIFSSMBClose(xid, cifs_sb->tcon, fid);
- out:
+	CIFSSMBClose(xid, tcon, fid);
+out:
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -661,7 +685,7 @@
 
 	cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
 
-	open_file = find_readable_file(CIFS_I(inode));
+	open_file = find_readable_file(CIFS_I(inode), true);
 	if (!open_file)
 		return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
 
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 35042d8..7ac0056 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -27,6 +27,7 @@
 #include "md5.h"
 #include "cifs_unicode.h"
 #include "cifsproto.h"
+#include "ntlmssp.h"
 #include <linux/ctype.h>
 #include <linux/random.h>
 
@@ -42,7 +43,7 @@
 		       unsigned char *p24);
 
 static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
-				    const struct mac_key *key, char *signature)
+				const struct session_key *key, char *signature)
 {
 	struct	MD5Context context;
 
@@ -78,7 +79,7 @@
 	server->sequence_number++;
 	spin_unlock(&GlobalMid_Lock);
 
-	rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key,
+	rc = cifs_calculate_signature(cifs_pdu, &server->session_key,
 				      smb_signature);
 	if (rc)
 		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
@@ -89,7 +90,7 @@
 }
 
 static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
-				const struct mac_key *key, char *signature)
+				const struct session_key *key, char *signature)
 {
 	struct  MD5Context context;
 	int i;
@@ -145,7 +146,7 @@
 	server->sequence_number++;
 	spin_unlock(&GlobalMid_Lock);
 
-	rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key,
+	rc = cifs_calc_signature2(iov, n_vec, &server->session_key,
 				      smb_signature);
 	if (rc)
 		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
@@ -156,14 +157,14 @@
 }
 
 int cifs_verify_signature(struct smb_hdr *cifs_pdu,
-			  const struct mac_key *mac_key,
+			  const struct session_key *session_key,
 			  __u32 expected_sequence_number)
 {
 	unsigned int rc;
 	char server_response_sig[8];
 	char what_we_think_sig_should_be[20];
 
-	if ((cifs_pdu == NULL) || (mac_key == NULL))
+	if (cifs_pdu == NULL || session_key == NULL)
 		return -EINVAL;
 
 	if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
@@ -192,7 +193,7 @@
 					cpu_to_le32(expected_sequence_number);
 	cifs_pdu->Signature.Sequence.Reserved = 0;
 
-	rc = cifs_calculate_signature(cifs_pdu, mac_key,
+	rc = cifs_calculate_signature(cifs_pdu, session_key,
 		what_we_think_sig_should_be);
 
 	if (rc)
@@ -209,7 +210,7 @@
 }
 
 /* We fill in key by putting in 40 byte array which was allocated by caller */
-int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
+int cifs_calculate_session_key(struct session_key *key, const char *rn,
 			   const char *password)
 {
 	char temp_key[16];
@@ -262,6 +263,148 @@
 }
 #endif /* CIFS_WEAK_PW_HASH */
 
+/* Build a proper attribute value/target info pairs blob.
+ * Fill in netbios and dns domain name and workstation name
+ * and client time (total five av pairs and + one end of fields indicator.
+ * Allocate domain name which gets freed when session struct is deallocated.
+ */
+static int
+build_avpair_blob(struct cifsSesInfo *ses, const struct nls_table *nls_cp)
+{
+	unsigned int dlen;
+	unsigned int wlen;
+	unsigned int size = 6 * sizeof(struct ntlmssp2_name);
+	__le64  curtime;
+	char *defdmname = "WORKGROUP";
+	unsigned char *blobptr;
+	struct ntlmssp2_name *attrptr;
+
+	if (!ses->domainName) {
+		ses->domainName = kstrdup(defdmname, GFP_KERNEL);
+		if (!ses->domainName)
+			return -ENOMEM;
+	}
+
+	dlen = strlen(ses->domainName);
+	wlen = strlen(ses->server->hostname);
+
+	/* The length of this blob is a size which is
+	 * six times the size of a structure which holds name/size +
+	 * two times the unicode length of a domain name +
+	 * two times the unicode length of a server name +
+	 * size of a timestamp (which is 8 bytes).
+	 */
+	ses->tilen = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8;
+	ses->tiblob = kzalloc(ses->tilen, GFP_KERNEL);
+	if (!ses->tiblob) {
+		ses->tilen = 0;
+		cERROR(1, "Challenge target info allocation failure");
+		return -ENOMEM;
+	}
+
+	blobptr = ses->tiblob;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
+	attrptr->length = cpu_to_le16(2 * dlen);
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
+
+	blobptr += 2 * dlen;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_COMPUTER_NAME);
+	attrptr->length = cpu_to_le16(2 * wlen);
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp);
+
+	blobptr += 2 * wlen;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_DOMAIN_NAME);
+	attrptr->length = cpu_to_le16(2 * dlen);
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
+
+	blobptr += 2 * dlen;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_COMPUTER_NAME);
+	attrptr->length = cpu_to_le16(2 * wlen);
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp);
+
+	blobptr += 2 * wlen;
+	attrptr = (struct ntlmssp2_name *) blobptr;
+
+	attrptr->type = cpu_to_le16(NTLMSSP_AV_TIMESTAMP);
+	attrptr->length = cpu_to_le16(sizeof(__le64));
+	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
+	curtime = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+	memcpy(blobptr, &curtime, sizeof(__le64));
+
+	return 0;
+}
+
+/* Server has provided av pairs/target info in the type 2 challenge
+ * packet and we have plucked it and stored within smb session.
+ * We parse that blob here to find netbios domain name to be used
+ * as part of ntlmv2 authentication (in Target String), if not already
+ * specified on the command line.
+ * If this function returns without any error but without fetching
+ * domain name, authentication may fail against some server but
+ * may not fail against other (those who are not very particular
+ * about target string i.e. for some, just user name might suffice.
+ */
+static int
+find_domain_name(struct cifsSesInfo *ses)
+{
+	unsigned int attrsize;
+	unsigned int type;
+	unsigned int onesize = sizeof(struct ntlmssp2_name);
+	unsigned char *blobptr;
+	unsigned char *blobend;
+	struct ntlmssp2_name *attrptr;
+
+	if (!ses->tilen || !ses->tiblob)
+		return 0;
+
+	blobptr = ses->tiblob;
+	blobend = ses->tiblob + ses->tilen;
+
+	while (blobptr + onesize < blobend) {
+		attrptr = (struct ntlmssp2_name *) blobptr;
+		type = le16_to_cpu(attrptr->type);
+		if (type == NTLMSSP_AV_EOL)
+			break;
+		blobptr += 2; /* advance attr type */
+		attrsize = le16_to_cpu(attrptr->length);
+		blobptr += 2; /* advance attr size */
+		if (blobptr + attrsize > blobend)
+			break;
+		if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
+			if (!attrsize)
+				break;
+			if (!ses->domainName) {
+				struct nls_table *default_nls;
+				ses->domainName =
+					kmalloc(attrsize + 1, GFP_KERNEL);
+				if (!ses->domainName)
+						return -ENOMEM;
+				default_nls = load_nls_default();
+				cifs_from_ucs2(ses->domainName,
+					(__le16 *)blobptr, attrsize, attrsize,
+					default_nls, false);
+				unload_nls(default_nls);
+				break;
+			}
+		}
+		blobptr += attrsize; /* advance attr  value */
+	}
+
+	return 0;
+}
+
 static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
 			    const struct nls_table *nls_cp)
 {
@@ -315,13 +458,14 @@
 calc_exit_2:
 	/* BB FIXME what about bytes 24 through 40 of the signing key?
 	   compare with the NTLM example */
-	hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
+	hmac_md5_final(ses->ntlmv2_hash, pctxt);
 
 	kfree(pctxt);
 	return rc;
 }
 
-void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
+int
+setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
 		      const struct nls_table *nls_cp)
 {
 	int rc;
@@ -333,25 +477,48 @@
 	buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
 	get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
 	buf->reserved2 = 0;
-	buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
-	buf->names[0].length = 0;
-	buf->names[1].type = 0;
-	buf->names[1].length = 0;
+
+	if (ses->server->secType == RawNTLMSSP) {
+		if (!ses->domainName) {
+			rc = find_domain_name(ses);
+			if (rc) {
+				cERROR(1, "error %d finding domain name", rc);
+				goto setup_ntlmv2_rsp_ret;
+			}
+		}
+	} else {
+		rc = build_avpair_blob(ses, nls_cp);
+		if (rc) {
+			cERROR(1, "error %d building av pair blob", rc);
+			return rc;
+		}
+	}
 
 	/* calculate buf->ntlmv2_hash */
 	rc = calc_ntlmv2_hash(ses, nls_cp);
-	if (rc)
+	if (rc) {
 		cERROR(1, "could not get v2 hash rc %d", rc);
+		goto setup_ntlmv2_rsp_ret;
+	}
 	CalcNTLMv2_response(ses, resp_buf);
 
-	/* now calculate the MAC key for NTLMv2 */
-	hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
+	/* now calculate the session key for NTLMv2 */
+	hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context);
 	hmac_md5_update(resp_buf, 16, &context);
-	hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context);
+	hmac_md5_final(ses->auth_key.data.ntlmv2.key, &context);
 
-	memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf,
+	memcpy(&ses->auth_key.data.ntlmv2.resp, resp_buf,
 	       sizeof(struct ntlmv2_resp));
-	ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);
+	ses->auth_key.len = 16 + sizeof(struct ntlmv2_resp);
+
+	return 0;
+
+setup_ntlmv2_rsp_ret:
+	kfree(ses->tiblob);
+	ses->tiblob = NULL;
+	ses->tilen = 0;
+
+	return rc;
 }
 
 void CalcNTLMv2_response(const struct cifsSesInfo *ses,
@@ -359,12 +526,15 @@
 {
 	struct HMACMD5Context context;
 	/* rest of v2 struct already generated */
-	memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
-	hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
+	memcpy(v2_session_response + 8, ses->cryptKey, 8);
+	hmac_md5_init_limK_to_64(ses->ntlmv2_hash, 16, &context);
 
 	hmac_md5_update(v2_session_response+8,
 			sizeof(struct ntlmv2_resp) - 8, &context);
 
+	if (ses->tilen)
+		hmac_md5_update(ses->tiblob, ses->tilen, &context);
+
 	hmac_md5_final(v2_session_response, &context);
 /*	cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
 }
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index b7431af..3437163 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -35,7 +35,7 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
+#include <net/ipv6.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
@@ -82,6 +82,24 @@
 extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
 
+void
+cifs_sb_active(struct super_block *sb)
+{
+	struct cifs_sb_info *server = CIFS_SB(sb);
+
+	if (atomic_inc_return(&server->active) == 1)
+		atomic_inc(&sb->s_active);
+}
+
+void
+cifs_sb_deactive(struct super_block *sb)
+{
+	struct cifs_sb_info *server = CIFS_SB(sb);
+
+	if (atomic_dec_and_test(&server->active))
+		deactivate_super(sb);
+}
+
 static int
 cifs_read_super(struct super_block *sb, void *data,
 		const char *devname, int silent)
@@ -97,6 +115,9 @@
 	if (cifs_sb == NULL)
 		return -ENOMEM;
 
+	spin_lock_init(&cifs_sb->tlink_tree_lock);
+	INIT_RADIX_TREE(&cifs_sb->tlink_tree, GFP_KERNEL);
+
 	rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
 	if (rc) {
 		kfree(cifs_sb);
@@ -136,9 +157,6 @@
 	sb->s_magic = CIFS_MAGIC_NUMBER;
 	sb->s_op = &cifs_super_ops;
 	sb->s_bdi = &cifs_sb->bdi;
-/*	if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
-	    sb->s_blocksize =
-		cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
 	sb->s_blocksize = CIFS_MAX_MSGSIZE;
 	sb->s_blocksize_bits = 14;	/* default 2**14 = CIFS_MAX_MSGSIZE */
 	inode = cifs_root_iget(sb, ROOT_I);
@@ -200,8 +218,6 @@
 		return;
 	}
 
-	lock_kernel();
-
 	rc = cifs_umount(sb, cifs_sb);
 	if (rc)
 		cERROR(1, "cifs_umount failed with return code %d", rc);
@@ -215,8 +231,6 @@
 	unload_nls(cifs_sb->local_nls);
 	bdi_destroy(&cifs_sb->bdi);
 	kfree(cifs_sb);
-
-	unlock_kernel();
 }
 
 static int
@@ -224,7 +238,7 @@
 {
 	struct super_block *sb = dentry->d_sb;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 	int rc = -EOPNOTSUPP;
 	int xid;
 
@@ -366,14 +380,36 @@
 cifs_show_options(struct seq_file *s, struct vfsmount *m)
 {
 	struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
+	struct sockaddr *srcaddr;
+	srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
 
 	seq_printf(s, ",unc=%s", tcon->treeName);
-	if (tcon->ses->userName)
+
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
+		seq_printf(s, ",multiuser");
+	else if (tcon->ses->userName)
 		seq_printf(s, ",username=%s", tcon->ses->userName);
+
 	if (tcon->ses->domainName)
 		seq_printf(s, ",domain=%s", tcon->ses->domainName);
 
+	if (srcaddr->sa_family != AF_UNSPEC) {
+		struct sockaddr_in *saddr4;
+		struct sockaddr_in6 *saddr6;
+		saddr4 = (struct sockaddr_in *)srcaddr;
+		saddr6 = (struct sockaddr_in6 *)srcaddr;
+		if (srcaddr->sa_family == AF_INET6)
+			seq_printf(s, ",srcaddr=%pI6c",
+				   &saddr6->sin6_addr);
+		else if (srcaddr->sa_family == AF_INET)
+			seq_printf(s, ",srcaddr=%pI4",
+				   &saddr4->sin_addr.s_addr);
+		else
+			seq_printf(s, ",srcaddr=BAD-AF:%i",
+				   (int)(srcaddr->sa_family));
+	}
+
 	seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
 		seq_printf(s, ",forceuid");
@@ -422,6 +458,8 @@
 		seq_printf(s, ",dynperm");
 	if (m->mnt_sb->s_flags & MS_POSIXACL)
 		seq_printf(s, ",acl");
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		seq_printf(s, ",mfsymlinks");
 
 	seq_printf(s, ",rsize=%d", cifs_sb->rsize);
 	seq_printf(s, ",wsize=%d", cifs_sb->wsize);
@@ -437,20 +475,18 @@
 	if (cifs_sb == NULL)
 		return;
 
-	tcon = cifs_sb->tcon;
-	if (tcon == NULL)
-		return;
+	tcon = cifs_sb_master_tcon(cifs_sb);
 
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
 		/* we have other mounts to same share or we have
 		   already tried to force umount this and woken up
 		   all waiting network requests, nothing to do */
-		read_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return;
 	} else if (tcon->tc_count == 1)
 		tcon->tidStatus = CifsExiting;
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
 	/* cancel_notify_requests(tcon); */
@@ -514,7 +550,9 @@
 	    int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
 	int rc;
-	struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
+	struct super_block *sb;
+
+	sb = sget(fs_type, NULL, set_anon_super, NULL);
 
 	cFYI(1, "Devname: %s flags: %d ", dev_name, flags);
 
@@ -565,9 +603,10 @@
 
 static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
 {
-	/* note that this is called by vfs setlease with the BKL held
-	   although I doubt that BKL is needed here in cifs */
+	/* note that this is called by vfs setlease with lock_flocks held
+	   to protect *lease from going away */
 	struct inode *inode = file->f_path.dentry->d_inode;
+	struct cifsFileInfo *cfile = file->private_data;
 
 	if (!(S_ISREG(inode->i_mode)))
 		return -EINVAL;
@@ -578,8 +617,8 @@
 	    ((arg == F_WRLCK) &&
 		(CIFS_I(inode)->clientCanCacheAll)))
 		return generic_setlease(file, arg, lease);
-	else if (CIFS_SB(inode->i_sb)->tcon->local_lease &&
-			!CIFS_I(inode)->clientCanCacheRead)
+	else if (tlink_tcon(cfile->tlink)->local_lease &&
+		 !CIFS_I(inode)->clientCanCacheRead)
 		/* If the server claims to support oplock on this
 		   file, then we still need to check oplock even
 		   if the local_lease mount option is set, but there
@@ -898,8 +937,8 @@
 	GlobalTotalActiveXid = 0;
 	GlobalMaxActiveXid = 0;
 	memset(Local_System_Name, 0, 15);
-	rwlock_init(&GlobalSMBSeslock);
-	rwlock_init(&cifs_tcp_ses_lock);
+	spin_lock_init(&cifs_tcp_ses_lock);
+	spin_lock_init(&cifs_file_list_lock);
 	spin_lock_init(&GlobalMid_Lock);
 
 	if (cifs_max_pending < 2) {
@@ -912,11 +951,11 @@
 
 	rc = cifs_fscache_register();
 	if (rc)
-		goto out;
+		goto out_clean_proc;
 
 	rc = cifs_init_inodecache();
 	if (rc)
-		goto out_clean_proc;
+		goto out_unreg_fscache;
 
 	rc = cifs_init_mids();
 	if (rc)
@@ -938,19 +977,19 @@
 	return 0;
 
 #ifdef CONFIG_CIFS_UPCALL
- out_unregister_filesystem:
+out_unregister_filesystem:
 	unregister_filesystem(&cifs_fs_type);
 #endif
- out_destroy_request_bufs:
+out_destroy_request_bufs:
 	cifs_destroy_request_bufs();
- out_destroy_mids:
+out_destroy_mids:
 	cifs_destroy_mids();
- out_destroy_inodecache:
+out_destroy_inodecache:
 	cifs_destroy_inodecache();
- out_clean_proc:
-	cifs_proc_clean();
+out_unreg_fscache:
 	cifs_fscache_unregister();
- out:
+out_clean_proc:
+	cifs_proc_clean();
 	return rc;
 }
 
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d82f5fb..f35795a 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -42,10 +42,8 @@
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
 /* Functions related to super block operations */
-/* extern const struct super_operations cifs_super_ops;*/
-extern void cifs_read_inode(struct inode *);
-/*extern void cifs_delete_inode(struct inode *);*/  /* BB not needed yet */
-/* extern void cifs_write_inode(struct inode *); */ /* BB not needed yet */
+extern void cifs_sb_active(struct super_block *sb);
+extern void cifs_sb_deactive(struct super_block *sb);
 
 /* Functions related to inodes */
 extern const struct inode_operations cifs_dir_inode_ops;
@@ -104,7 +102,7 @@
 extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
 			const char *symname);
 extern int	cifs_removexattr(struct dentry *, const char *);
-extern int 	cifs_setxattr(struct dentry *, const char *, const void *,
+extern int	cifs_setxattr(struct dentry *, const char *, const void *,
 			size_t, int);
 extern ssize_t	cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
@@ -114,5 +112,5 @@
 extern const struct export_operations cifs_export_ops;
 #endif /* EXPERIMENTAL */
 
-#define CIFS_VERSION   "1.65"
+#define CIFS_VERSION   "1.67"
 #endif				/* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 0cdfb8c..3365e77f 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -97,7 +97,7 @@
 	/* Netbios frames protocol not supported at this time */
 };
 
-struct mac_key {
+struct session_key {
 	unsigned int len;
 	union {
 		char ntlm[CIFS_SESS_KEY_SIZE + 16];
@@ -139,6 +139,7 @@
 		struct sockaddr_in sockAddr;
 		struct sockaddr_in6 sockAddr6;
 	} addr;
+	struct sockaddr_storage srcaddr; /* locally bind to this IP */
 	wait_queue_head_t response_q;
 	wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
 	struct list_head pending_mid_q;
@@ -178,12 +179,10 @@
 	int capabilities; /* allow selective disabling of caps by smb sess */
 	int timeAdj;  /* Adjust for difference in server time zone in sec */
 	__u16 CurrentMid;         /* multiplex id - rotating counter */
-	char cryptKey[CIFS_CRYPTO_KEY_SIZE];
 	/* 16th byte of RFC1001 workstation name is always null */
 	char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
 	__u32 sequence_number; /* needed for CIFS PDU signature */
-	struct mac_key mac_signing_key;
-	char ntlmv2_hash[16];
+	struct session_key session_key;
 	unsigned long lstrp; /* when we got last response from this server */
 	u16 dialect; /* dialect index that server chose */
 	/* extended security flavors that server supports */
@@ -191,6 +190,7 @@
 	bool	sec_mskerberos;		/* supports legacy MS Kerberos */
 	bool	sec_kerberosu2u;	/* supports U2U Kerberos */
 	bool	sec_ntlmssp;		/* supports NTLMSSP */
+	bool session_estab; /* mark when very first sess is established */
 #ifdef CONFIG_CIFS_FSCACHE
 	struct fscache_cookie   *fscache; /* client index cache cookie */
 #endif
@@ -222,6 +222,11 @@
 	char userName[MAX_USERNAME_SIZE + 1];
 	char *domainName;
 	char *password;
+	char cryptKey[CIFS_CRYPTO_KEY_SIZE];
+	struct session_key auth_key;
+	char ntlmv2_hash[16];
+	unsigned int tilen; /* length of the target info blob */
+	unsigned char *tiblob; /* target info blob in challenge response */
 	bool need_reconnect:1; /* connection reset, uid now invalid */
 };
 /* no more than one of the following three session flags may be set */
@@ -308,6 +313,44 @@
 };
 
 /*
+ * This is a refcounted and timestamped container for a tcon pointer. The
+ * container holds a tcon reference. It is considered safe to free one of
+ * these when the tl_count goes to 0. The tl_time is the time of the last
+ * "get" on the container.
+ */
+struct tcon_link {
+	unsigned long		tl_index;
+	unsigned long		tl_flags;
+#define TCON_LINK_MASTER	0
+#define TCON_LINK_PENDING	1
+#define TCON_LINK_IN_TREE	2
+	unsigned long		tl_time;
+	atomic_t		tl_count;
+	struct cifsTconInfo	*tl_tcon;
+};
+
+extern struct tcon_link *cifs_sb_tlink(struct cifs_sb_info *cifs_sb);
+
+static inline struct cifsTconInfo *
+tlink_tcon(struct tcon_link *tlink)
+{
+	return tlink->tl_tcon;
+}
+
+extern void cifs_put_tlink(struct tcon_link *tlink);
+
+static inline struct tcon_link *
+cifs_get_tlink(struct tcon_link *tlink)
+{
+	if (tlink && !IS_ERR(tlink))
+		atomic_inc(&tlink->tl_count);
+	return tlink;
+}
+
+/* This function is always expected to succeed */
+extern struct cifsTconInfo *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb);
+
+/*
  * This info hangs off the cifsFileInfo structure, pointed to by llist.
  * This is used to track byte stream locks on the file
  */
@@ -345,12 +388,11 @@
 	__u16 netfid;		/* file id from remote */
 	/* BB add lock scope info here if needed */ ;
 	/* lock scope id (0 if none) */
-	struct file *pfile; /* needed for writepage */
-	struct inode *pInode; /* needed for oplock break */
-	struct vfsmount *mnt;
+	struct dentry *dentry;
+	unsigned int f_flags;
+	struct tcon_link *tlink;
 	struct mutex lock_mutex;
 	struct list_head llist; /* list of byte range locks we have. */
-	bool closePend:1;	/* file is marked to close */
 	bool invalidHandle:1;	/* file closed via session abend */
 	bool oplock_break_cancelled:1;
 	atomic_t count;		/* reference count */
@@ -365,14 +407,7 @@
 	atomic_inc(&cifs_file->count);
 }
 
-/* Release a reference on the file private data */
-static inline void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
-{
-	if (atomic_dec_and_test(&cifs_file->count)) {
-		iput(cifs_file->pInode);
-		kfree(cifs_file);
-	}
-}
+void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
 
 /*
  * One of these for each file inode
@@ -474,16 +509,16 @@
 
 /* for pending dnotify requests */
 struct dir_notify_req {
-       struct list_head lhead;
-       __le16 Pid;
-       __le16 PidHigh;
-       __u16 Mid;
-       __u16 Tid;
-       __u16 Uid;
-       __u16 netfid;
-       __u32 filter; /* CompletionFilter (for multishot) */
-       int multishot;
-       struct file *pfile;
+	struct list_head lhead;
+	__le16 Pid;
+	__le16 PidHigh;
+	__u16 Mid;
+	__u16 Tid;
+	__u16 Uid;
+	__u16 netfid;
+	__u32 filter; /* CompletionFilter (for multishot) */
+	int multishot;
+	struct file *pfile;
 };
 
 struct dfs_info3_param {
@@ -667,7 +702,7 @@
  * the reference counters for the server, smb session, and tcon. Finally,
  * changes to the tcon->tidStatus should be done while holding this lock.
  */
-GLOBAL_EXTERN rwlock_t		cifs_tcp_ses_lock;
+GLOBAL_EXTERN spinlock_t		cifs_tcp_ses_lock;
 
 /*
  * This lock protects the cifs_file->llist and cifs_file->flist
@@ -676,7 +711,7 @@
  * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
  * the cifs_tcp_ses_lock must be grabbed first and released last.
  */
-GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
+GLOBAL_EXTERN spinlock_t	cifs_file_list_lock;
 
 /* Outstanding dir notify requests */
 GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 14d036d..b0f4b56 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -663,7 +663,6 @@
 	__le64  time;
 	__u64  client_chal; /* random */
 	__u32  reserved2;
-	struct ntlmssp2_name names[2];
 	/* array of name entries could follow ending in minimum 4 byte struct */
 } __attribute__((packed));
 
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1d60c65..e593c40 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -78,9 +78,9 @@
 extern bool is_valid_oplock_break(struct smb_hdr *smb,
 				  struct TCP_Server_Info *);
 extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
-extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
+extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *);
+extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
 #endif
 extern unsigned int smbCalcSize(struct smb_hdr *ptr);
 extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
@@ -105,12 +105,12 @@
 extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
 				      int offset);
 
-extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
-				__u16 fileHandle, struct file *file,
-				struct vfsmount *mnt, unsigned int oflags);
+extern struct cifsFileInfo *cifs_new_fileinfo(__u16 fileHandle,
+				struct file *file, struct tcon_link *tlink,
+				__u32 oplock);
 extern int cifs_posix_open(char *full_path, struct inode **pinode,
 				struct super_block *sb,
-				int mode, int oflags,
+				int mode, unsigned int f_flags,
 				__u32 *poplock, __u16 *pnetfid, int xid);
 void cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr);
 extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
@@ -362,12 +362,12 @@
 extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
 			  __u32 *);
 extern int cifs_verify_signature(struct smb_hdr *,
-				 const struct mac_key *mac_key,
+				 const struct session_key *session_key,
 				__u32 expected_sequence_number);
-extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
+extern int cifs_calculate_session_key(struct session_key *key, const char *rn,
 				 const char *pass);
 extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
-extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
+extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
 			     const struct nls_table *);
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 extern void calc_lanman_hash(const char *password, const char *cryptkey,
@@ -408,4 +408,8 @@
 extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
 			const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
+extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
+extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+		const unsigned char *path,
+		struct cifs_sb_info *cifs_sb, int xid);
 #endif			/* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 7e83b35..e98f1f3 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -91,13 +91,13 @@
 	struct list_head *tmp1;
 
 /* list all files open on tree connection and mark them invalid */
-	write_lock(&GlobalSMBSeslock);
+	spin_lock(&cifs_file_list_lock);
 	list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
 		open_file = list_entry(tmp, struct cifsFileInfo, tlist);
 		open_file->invalidHandle = true;
 		open_file->oplock_break_cancelled = true;
 	}
-	write_unlock(&GlobalSMBSeslock);
+	spin_unlock(&cifs_file_list_lock);
 	/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
 	   to this tcon */
 }
@@ -503,7 +503,7 @@
 
 		if (rsp->EncryptionKeyLength ==
 				cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
-			memcpy(server->cryptKey, rsp->EncryptionKey,
+			memcpy(ses->cryptKey, rsp->EncryptionKey,
 				CIFS_CRYPTO_KEY_SIZE);
 		} else if (server->secMode & SECMODE_PW_ENCRYPT) {
 			rc = -EIO; /* need cryptkey unless plain text */
@@ -574,7 +574,7 @@
 	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
 	server->timeAdj *= 60;
 	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
-		memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
+		memcpy(ses->cryptKey, pSMBr->u.EncryptionKey,
 		       CIFS_CRYPTO_KEY_SIZE);
 	} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
 			&& (pSMBr->EncryptionKeyLength == 0)) {
@@ -593,9 +593,9 @@
 			rc = -EIO;
 			goto neg_err_exit;
 		}
-		read_lock(&cifs_tcp_ses_lock);
+		spin_lock(&cifs_tcp_ses_lock);
 		if (server->srv_count > 1) {
-			read_unlock(&cifs_tcp_ses_lock);
+			spin_unlock(&cifs_tcp_ses_lock);
 			if (memcmp(server->server_GUID,
 				   pSMBr->u.extended_response.
 				   GUID, 16) != 0) {
@@ -605,7 +605,7 @@
 					16);
 			}
 		} else {
-			read_unlock(&cifs_tcp_ses_lock);
+			spin_unlock(&cifs_tcp_ses_lock);
 			memcpy(server->server_GUID,
 			       pSMBr->u.extended_response.GUID, 16);
 		}
@@ -620,13 +620,15 @@
 				rc = 0;
 			else
 				rc = -EINVAL;
-
-			if (server->sec_kerberos || server->sec_mskerberos)
-				server->secType = Kerberos;
-			else if (server->sec_ntlmssp)
-				server->secType = RawNTLMSSP;
-			else
-				rc = -EOPNOTSUPP;
+			if (server->secType == Kerberos) {
+				if (!server->sec_kerberos &&
+						!server->sec_mskerberos)
+					rc = -EOPNOTSUPP;
+			} else if (server->secType == RawNTLMSSP) {
+				if (!server->sec_ntlmssp)
+					rc = -EOPNOTSUPP;
+			} else
+					rc = -EOPNOTSUPP;
 		}
 	} else
 		server->capabilities &= ~CAP_EXTENDED_SECURITY;
diff --git a/fs/cifs/cn_cifs.h b/fs/cifs/cn_cifs.h
deleted file mode 100644
index ea59cca..0000000
--- a/fs/cifs/cn_cifs.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *   fs/cifs/cn_cifs.h
- *
- *   Copyright (c) International Business Machines  Corp., 2002
- *   Author(s): Steve French (sfrench@us.ibm.com)
- *
- *   This library is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU Lesser General Public License as published
- *   by the Free Software Foundation; either version 2.1 of the License, or
- *   (at your option) any later version.
- *
- *   This library is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public License
- *   along with this library; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _CN_CIFS_H
-#define _CN_CIFS_H
-#ifdef CONFIG_CIFS_UPCALL
-#include <linux/types.h>
-#include <linux/connector.h>
-
-struct cifs_upcall {
-	char signature[4]; /* CIFS */
-	enum command {
-		CIFS_GET_IP = 0x00000001,   /* get ip address for hostname */
-		CIFS_GET_SECBLOB = 0x00000002, /* get SPNEGO wrapped blob */
-	} command;
-	/* union cifs upcall data follows */
-};
-#endif /* CIFS_UPCALL */
-#endif /* _CN_CIFS_H */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 88c84a3..7e73176 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -47,7 +47,6 @@
 #include "ntlmssp.h"
 #include "nterr.h"
 #include "rfc1002pdu.h"
-#include "cn_cifs.h"
 #include "fscache.h"
 
 #define CIFS_PORT 445
@@ -100,16 +99,24 @@
 	bool noautotune:1;
 	bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
 	bool fsc:1;	/* enable fscache */
+	bool mfsymlinks:1; /* use Minshall+French Symlinks */
+	bool multiuser:1;
 	unsigned int rsize;
 	unsigned int wsize;
 	bool sockopt_tcp_nodelay:1;
 	unsigned short int port;
 	char *prepath;
+	struct sockaddr_storage srcaddr; /* allow binding to a local IP */
 	struct nls_table *local_nls;
 };
 
+/* FIXME: should these be tunable? */
+#define TLINK_ERROR_EXPIRE	(1 * HZ)
+#define TLINK_IDLE_EXPIRE	(600 * HZ)
+
 static int ipv4_connect(struct TCP_Server_Info *server);
 static int ipv6_connect(struct TCP_Server_Info *server);
+static void cifs_prune_tlinks(struct work_struct *work);
 
 /*
  * cifs tcp session reconnection
@@ -143,7 +150,7 @@
 
 	/* before reconnecting the tcp session, mark the smb session (uid)
 		and the tid bad so they are not used until reconnected */
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &server->smb_ses_list) {
 		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
 		ses->need_reconnect = true;
@@ -153,7 +160,7 @@
 			tcon->need_reconnect = true;
 		}
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	/* do not want to be sending data on a socket we are freeing */
 	mutex_lock(&server->srv_mutex);
 	if (server->ssocket) {
@@ -166,6 +173,8 @@
 		sock_release(server->ssocket);
 		server->ssocket = NULL;
 	}
+	server->sequence_number = 0;
+	server->session_estab = false;
 
 	spin_lock(&GlobalMid_Lock);
 	list_for_each(tmp, &server->pending_mid_q) {
@@ -198,7 +207,6 @@
 			spin_lock(&GlobalMid_Lock);
 			if (server->tcpStatus != CifsExiting)
 				server->tcpStatus = CifsGood;
-			server->sequence_number = 0;
 			spin_unlock(&GlobalMid_Lock);
 	/*		atomic_set(&server->inFlight,0);*/
 			wake_up(&server->response_q);
@@ -629,9 +637,9 @@
 	} /* end while !EXITING */
 
 	/* take it off the list, if it's not already */
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_del_init(&server->tcp_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	spin_lock(&GlobalMid_Lock);
 	server->tcpStatus = CifsExiting;
@@ -669,7 +677,7 @@
 	 * BB: we shouldn't have to do any of this. It shouldn't be
 	 * possible to exit from the thread with active SMB sessions
 	 */
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if (list_empty(&server->pending_mid_q)) {
 		/* loop through server session structures attached to this and
 		    mark them dead */
@@ -679,7 +687,7 @@
 			ses->status = CifsExiting;
 			ses->server = NULL;
 		}
-		read_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 	} else {
 		/* although we can not zero the server struct pointer yet,
 		since there are active requests which may depnd on them,
@@ -702,7 +710,7 @@
 			}
 		}
 		spin_unlock(&GlobalMid_Lock);
-		read_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		/* 1/8th of sec is more than enough time for them to exit */
 		msleep(125);
 	}
@@ -725,12 +733,12 @@
 	if a crazy root user tried to kill cifsd
 	kernel thread explicitly this might happen) */
 	/* BB: This shouldn't be necessary, see above */
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &server->smb_ses_list) {
 		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
 		ses->server = NULL;
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	kfree(server->hostname);
 	task_to_wake = xchg(&server->tsk, NULL);
@@ -1046,6 +1054,22 @@
 						    "long\n");
 				return 1;
 			}
+		} else if (strnicmp(data, "srcaddr", 7) == 0) {
+			vol->srcaddr.ss_family = AF_UNSPEC;
+
+			if (!value || !*value) {
+				printk(KERN_WARNING "CIFS: srcaddr value"
+				       " not specified.\n");
+				return 1;	/* needs_arg; */
+			}
+			i = cifs_convert_address((struct sockaddr *)&vol->srcaddr,
+						 value, strlen(value));
+			if (i < 0) {
+				printk(KERN_WARNING "CIFS:  Could not parse"
+				       " srcaddr: %s\n",
+				       value);
+				return 1;
+			}
 		} else if (strnicmp(data, "prefixpath", 10) == 0) {
 			if (!value || !*value) {
 				printk(KERN_WARNING
@@ -1325,6 +1349,10 @@
 				"/proc/fs/cifs/LookupCacheEnabled to 0\n");
 		} else if (strnicmp(data, "fsc", 3) == 0) {
 			vol->fsc = true;
+		} else if (strnicmp(data, "mfsymlinks", 10) == 0) {
+			vol->mfsymlinks = true;
+		} else if (strnicmp(data, "multiuser", 8) == 0) {
+			vol->multiuser = true;
 		} else
 			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
 						data);
@@ -1356,6 +1384,13 @@
 			return 1;
 		}
 	}
+
+	if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
+		cERROR(1, "Multiuser mounts currently require krb5 "
+			  "authentication!");
+		return 1;
+	}
+
 	if (vol->UNCip == NULL)
 		vol->UNCip = &vol->UNC[2];
 
@@ -1374,8 +1409,36 @@
 	return 0;
 }
 
+/** Returns true if srcaddr isn't specified and rhs isn't
+ * specified, or if srcaddr is specified and
+ * matches the IP address of the rhs argument.
+ */
 static bool
-match_address(struct TCP_Server_Info *server, struct sockaddr *addr)
+srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
+{
+	switch (srcaddr->sa_family) {
+	case AF_UNSPEC:
+		return (rhs->sa_family == AF_UNSPEC);
+	case AF_INET: {
+		struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
+		struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
+		return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
+	}
+	case AF_INET6: {
+		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
+		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
+		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
+	}
+	default:
+		WARN_ON(1);
+		return false; /* don't expect to be here */
+	}
+}
+
+
+static bool
+match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
+	      struct sockaddr *srcaddr)
 {
 	struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
 	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
@@ -1402,6 +1465,9 @@
 		break;
 	}
 
+	if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
+		return false;
+
 	return true;
 }
 
@@ -1458,29 +1524,21 @@
 {
 	struct TCP_Server_Info *server;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
-		/*
-		 * the demux thread can exit on its own while still in CifsNew
-		 * so don't accept any sockets in that state. Since the
-		 * tcpStatus never changes back to CifsNew it's safe to check
-		 * for this without a lock.
-		 */
-		if (server->tcpStatus == CifsNew)
-			continue;
-
-		if (!match_address(server, addr))
+		if (!match_address(server, addr,
+				   (struct sockaddr *)&vol->srcaddr))
 			continue;
 
 		if (!match_security(server, vol))
 			continue;
 
 		++server->srv_count;
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		cFYI(1, "Existing tcp session with server found");
 		return server;
 	}
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	return NULL;
 }
 
@@ -1489,14 +1547,14 @@
 {
 	struct task_struct *task;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if (--server->srv_count > 0) {
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return;
 	}
 
 	list_del_init(&server->tcp_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	spin_lock(&GlobalMid_Lock);
 	server->tcpStatus = CifsExiting;
@@ -1574,6 +1632,7 @@
 		volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
 	memcpy(tcp_ses->server_RFC1001_name,
 		volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
+	tcp_ses->session_estab = false;
 	tcp_ses->sequence_number = 0;
 	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
 	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
@@ -1584,6 +1643,8 @@
 	 * no need to spinlock this init of tcpStatus or srv_count
 	 */
 	tcp_ses->tcpStatus = CifsNew;
+	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
+	       sizeof(tcp_ses->srcaddr));
 	++tcp_ses->srv_count;
 
 	if (addr.ss_family == AF_INET6) {
@@ -1618,9 +1679,9 @@
 	}
 
 	/* thread spawned, put it on the list */
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	cifs_fscache_get_client_cookie(tcp_ses);
 
@@ -1642,7 +1703,7 @@
 {
 	struct cifsSesInfo *ses;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
 		switch (server->secType) {
 		case Kerberos:
@@ -1662,10 +1723,10 @@
 				continue;
 		}
 		++ses->ses_count;
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return ses;
 	}
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	return NULL;
 }
 
@@ -1676,14 +1737,14 @@
 	struct TCP_Server_Info *server = ses->server;
 
 	cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if (--ses->ses_count > 0) {
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return;
 	}
 
 	list_del_init(&ses->smb_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	if (ses->status == CifsGood) {
 		xid = GetXid();
@@ -1740,6 +1801,8 @@
 	if (ses == NULL)
 		goto get_ses_fail;
 
+	ses->tilen = 0;
+	ses->tiblob = NULL;
 	/* new SMB session uses our server ref */
 	ses->server = server;
 	if (server->addr.sockAddr6.sin6_family == AF_INET6)
@@ -1778,9 +1841,9 @@
 		goto get_ses_fail;
 
 	/* success, put it on the list */
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_add(&ses->smb_ses_list, &server->smb_ses_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	FreeXid(xid);
 	return ses;
@@ -1797,7 +1860,7 @@
 	struct list_head *tmp;
 	struct cifsTconInfo *tcon;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &ses->tcon_list) {
 		tcon = list_entry(tmp, struct cifsTconInfo, tcon_list);
 		if (tcon->tidStatus == CifsExiting)
@@ -1806,10 +1869,10 @@
 			continue;
 
 		++tcon->tc_count;
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return tcon;
 	}
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	return NULL;
 }
 
@@ -1820,14 +1883,14 @@
 	struct cifsSesInfo *ses = tcon->ses;
 
 	cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if (--tcon->tc_count > 0) {
-		write_unlock(&cifs_tcp_ses_lock);
+		spin_unlock(&cifs_tcp_ses_lock);
 		return;
 	}
 
 	list_del_init(&tcon->tcon_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	xid = GetXid();
 	CIFSSMBTDis(xid, tcon);
@@ -1900,9 +1963,9 @@
 	tcon->nocase = volume_info->nocase;
 	tcon->local_lease = volume_info->local_lease;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_add(&tcon->tcon_list, &ses->tcon_list);
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	cifs_fscache_get_super_cookie(tcon);
 
@@ -1913,6 +1976,23 @@
 	return ERR_PTR(rc);
 }
 
+void
+cifs_put_tlink(struct tcon_link *tlink)
+{
+	if (!tlink || IS_ERR(tlink))
+		return;
+
+	if (!atomic_dec_and_test(&tlink->tl_count) ||
+	    test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
+		tlink->tl_time = jiffies;
+		return;
+	}
+
+	if (!IS_ERR(tlink_tcon(tlink)))
+		cifs_put_tcon(tlink_tcon(tlink));
+	kfree(tlink);
+	return;
+}
 
 int
 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
@@ -1997,6 +2077,33 @@
 
 }
 
+static int
+bind_socket(struct TCP_Server_Info *server)
+{
+	int rc = 0;
+	if (server->srcaddr.ss_family != AF_UNSPEC) {
+		/* Bind to the specified local IP address */
+		struct socket *socket = server->ssocket;
+		rc = socket->ops->bind(socket,
+				       (struct sockaddr *) &server->srcaddr,
+				       sizeof(server->srcaddr));
+		if (rc < 0) {
+			struct sockaddr_in *saddr4;
+			struct sockaddr_in6 *saddr6;
+			saddr4 = (struct sockaddr_in *)&server->srcaddr;
+			saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
+			if (saddr6->sin6_family == AF_INET6)
+				cERROR(1, "cifs: "
+				       "Failed to bind to: %pI6c, error: %d\n",
+				       &saddr6->sin6_addr, rc);
+			else
+				cERROR(1, "cifs: "
+				       "Failed to bind to: %pI4, error: %d\n",
+				       &saddr4->sin_addr.s_addr, rc);
+		}
+	}
+	return rc;
+}
 
 static int
 ipv4_connect(struct TCP_Server_Info *server)
@@ -2022,6 +2129,10 @@
 		cifs_reclassify_socket4(socket);
 	}
 
+	rc = bind_socket(server);
+	if (rc < 0)
+		return rc;
+
 	/* user overrode default port */
 	if (server->addr.sockAddr.sin_port) {
 		rc = socket->ops->connect(socket, (struct sockaddr *)
@@ -2184,6 +2295,10 @@
 		cifs_reclassify_socket6(socket);
 	}
 
+	rc = bind_socket(server);
+	if (rc < 0)
+		return rc;
+
 	/* user overrode default port */
 	if (server->addr.sockAddr6.sin6_port) {
 		rc = socket->ops->connect(socket,
@@ -2383,6 +2498,8 @@
 static void setup_cifs_sb(struct smb_vol *pvolume_info,
 			  struct cifs_sb_info *cifs_sb)
 {
+	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
+
 	if (pvolume_info->rsize > CIFSMaxBufSize) {
 		cERROR(1, "rsize %d too large, using MaxBufSize",
 			pvolume_info->rsize);
@@ -2462,10 +2579,21 @@
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
 	if (pvolume_info->fsc)
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
+	if (pvolume_info->multiuser)
+		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
+					    CIFS_MOUNT_NO_PERM);
 	if (pvolume_info->direct_io) {
 		cFYI(1, "mounting share using direct i/o");
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
 	}
+	if (pvolume_info->mfsymlinks) {
+		if (pvolume_info->sfu_emul) {
+			cERROR(1,  "mount option mfsymlinks ignored if sfu "
+				   "mount option is used");
+		} else {
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
+		}
+	}
 
 	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
 		cERROR(1, "mount option dynperm ignored if cifsacl "
@@ -2552,6 +2680,7 @@
 	struct TCP_Server_Info *srvTcp;
 	char   *full_path;
 	char *mount_data = mount_data_global;
+	struct tcon_link *tlink;
 #ifdef CONFIG_CIFS_DFS_UPCALL
 	struct dfs_info3_param *referrals = NULL;
 	unsigned int num_referrals = 0;
@@ -2563,6 +2692,7 @@
 	pSesInfo = NULL;
 	srvTcp = NULL;
 	full_path = NULL;
+	tlink = NULL;
 
 	xid = GetXid();
 
@@ -2638,8 +2768,6 @@
 		goto remote_path_check;
 	}
 
-	cifs_sb->tcon = tcon;
-
 	/* do not care if following two calls succeed - informational */
 	if (!tcon->ipc) {
 		CIFSSMBQFSDeviceInfo(xid, tcon);
@@ -2748,6 +2876,38 @@
 #endif
 	}
 
+	if (rc)
+		goto mount_fail_check;
+
+	/* now, hang the tcon off of the superblock */
+	tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
+	if (tlink == NULL) {
+		rc = -ENOMEM;
+		goto mount_fail_check;
+	}
+
+	tlink->tl_index = pSesInfo->linux_uid;
+	tlink->tl_tcon = tcon;
+	tlink->tl_time = jiffies;
+	set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
+	set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
+
+	rc = radix_tree_preload(GFP_KERNEL);
+	if (rc == -ENOMEM) {
+		kfree(tlink);
+		goto mount_fail_check;
+	}
+
+	spin_lock(&cifs_sb->tlink_tree_lock);
+	radix_tree_insert(&cifs_sb->tlink_tree, pSesInfo->linux_uid, tlink);
+	radix_tree_tag_set(&cifs_sb->tlink_tree, pSesInfo->linux_uid,
+			   CIFS_TLINK_MASTER_TAG);
+	spin_unlock(&cifs_sb->tlink_tree_lock);
+	radix_tree_preload_end();
+
+	queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
+				TLINK_IDLE_EXPIRE);
+
 mount_fail_check:
 	/* on error free sesinfo and tcon struct if needed */
 	if (rc) {
@@ -2825,14 +2985,13 @@
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
 		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
 		    (ses->server->secType == LANMAN))
-			calc_lanman_hash(tcon->password, ses->server->cryptKey,
+			calc_lanman_hash(tcon->password, ses->cryptKey,
 					 ses->server->secMode &
 					    SECMODE_PW_ENCRYPT ? true : false,
 					 bcc_ptr);
 		else
 #endif /* CIFS_WEAK_PW_HASH */
-		SMBNTencrypt(tcon->password, ses->server->cryptKey,
-			     bcc_ptr);
+		SMBNTencrypt(tcon->password, ses->cryptKey, bcc_ptr);
 
 		bcc_ptr += CIFS_SESS_KEY_SIZE;
 		if (ses->capabilities & CAP_UNICODE) {
@@ -2934,19 +3093,39 @@
 int
 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
 {
-	int rc = 0;
+	int i, ret;
 	char *tmp;
+	struct tcon_link *tlink[8];
+	unsigned long index = 0;
 
-	if (cifs_sb->tcon)
-		cifs_put_tcon(cifs_sb->tcon);
+	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
 
-	cifs_sb->tcon = NULL;
+	do {
+		spin_lock(&cifs_sb->tlink_tree_lock);
+		ret = radix_tree_gang_lookup(&cifs_sb->tlink_tree,
+					     (void **)tlink, index,
+					     ARRAY_SIZE(tlink));
+		/* increment index for next pass */
+		if (ret > 0)
+			index = tlink[ret - 1]->tl_index + 1;
+		for (i = 0; i < ret; i++) {
+			cifs_get_tlink(tlink[i]);
+			clear_bit(TCON_LINK_IN_TREE, &tlink[i]->tl_flags);
+			radix_tree_delete(&cifs_sb->tlink_tree,
+							tlink[i]->tl_index);
+		}
+		spin_unlock(&cifs_sb->tlink_tree_lock);
+
+		for (i = 0; i < ret; i++)
+			cifs_put_tlink(tlink[i]);
+	} while (ret != 0);
+
 	tmp = cifs_sb->prepath;
 	cifs_sb->prepathlen = 0;
 	cifs_sb->prepath = NULL;
 	kfree(tmp);
 
-	return rc;
+	return 0;
 }
 
 int cifs_negotiate_protocol(unsigned int xid, struct cifsSesInfo *ses)
@@ -2997,6 +3176,15 @@
 	if (rc) {
 		cERROR(1, "Send error in SessSetup = %d", rc);
 	} else {
+		mutex_lock(&ses->server->srv_mutex);
+		if (!server->session_estab) {
+			memcpy(&server->session_key.data,
+				&ses->auth_key.data, ses->auth_key.len);
+			server->session_key.len = ses->auth_key.len;
+			ses->server->session_estab = true;
+		}
+		mutex_unlock(&server->srv_mutex);
+
 		cFYI(1, "CIFS Session Established successfully");
 		spin_lock(&GlobalMid_Lock);
 		ses->status = CifsGood;
@@ -3007,3 +3195,237 @@
 	return rc;
 }
 
+static struct cifsTconInfo *
+cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
+{
+	struct cifsTconInfo *master_tcon = cifs_sb_master_tcon(cifs_sb);
+	struct cifsSesInfo *ses;
+	struct cifsTconInfo *tcon = NULL;
+	struct smb_vol *vol_info;
+	char username[MAX_USERNAME_SIZE + 1];
+
+	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
+	if (vol_info == NULL) {
+		tcon = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	snprintf(username, MAX_USERNAME_SIZE, "krb50x%x", fsuid);
+	vol_info->username = username;
+	vol_info->local_nls = cifs_sb->local_nls;
+	vol_info->linux_uid = fsuid;
+	vol_info->cred_uid = fsuid;
+	vol_info->UNC = master_tcon->treeName;
+	vol_info->retry = master_tcon->retry;
+	vol_info->nocase = master_tcon->nocase;
+	vol_info->local_lease = master_tcon->local_lease;
+	vol_info->no_linux_ext = !master_tcon->unix_ext;
+
+	/* FIXME: allow for other secFlg settings */
+	vol_info->secFlg = CIFSSEC_MUST_KRB5;
+
+	/* get a reference for the same TCP session */
+	spin_lock(&cifs_tcp_ses_lock);
+	++master_tcon->ses->server->srv_count;
+	spin_unlock(&cifs_tcp_ses_lock);
+
+	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
+	if (IS_ERR(ses)) {
+		tcon = (struct cifsTconInfo *)ses;
+		cifs_put_tcp_session(master_tcon->ses->server);
+		goto out;
+	}
+
+	tcon = cifs_get_tcon(ses, vol_info);
+	if (IS_ERR(tcon)) {
+		cifs_put_smb_ses(ses);
+		goto out;
+	}
+
+	if (ses->capabilities & CAP_UNIX)
+		reset_cifs_unix_caps(0, tcon, NULL, vol_info);
+out:
+	kfree(vol_info);
+
+	return tcon;
+}
+
+static struct tcon_link *
+cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
+{
+	struct tcon_link *tlink;
+	unsigned int ret;
+
+	spin_lock(&cifs_sb->tlink_tree_lock);
+	ret = radix_tree_gang_lookup_tag(&cifs_sb->tlink_tree, (void **)&tlink,
+					0, 1, CIFS_TLINK_MASTER_TAG);
+	spin_unlock(&cifs_sb->tlink_tree_lock);
+
+	/* the master tcon should always be present */
+	if (ret == 0)
+		BUG();
+
+	return tlink;
+}
+
+struct cifsTconInfo *
+cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
+{
+	return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
+}
+
+static int
+cifs_sb_tcon_pending_wait(void *unused)
+{
+	schedule();
+	return signal_pending(current) ? -ERESTARTSYS : 0;
+}
+
+/*
+ * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
+ * current task.
+ *
+ * If the superblock doesn't refer to a multiuser mount, then just return
+ * the master tcon for the mount.
+ *
+ * First, search the radix tree for an existing tcon for this fsuid. If one
+ * exists, then check to see if it's pending construction. If it is then wait
+ * for construction to complete. Once it's no longer pending, check to see if
+ * it failed and either return an error or retry construction, depending on
+ * the timeout.
+ *
+ * If one doesn't exist then insert a new tcon_link struct into the tree and
+ * try to construct a new one.
+ */
+struct tcon_link *
+cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
+{
+	int ret;
+	unsigned long fsuid = (unsigned long) current_fsuid();
+	struct tcon_link *tlink, *newtlink;
+
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
+		return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
+
+	spin_lock(&cifs_sb->tlink_tree_lock);
+	tlink = radix_tree_lookup(&cifs_sb->tlink_tree, fsuid);
+	if (tlink)
+		cifs_get_tlink(tlink);
+	spin_unlock(&cifs_sb->tlink_tree_lock);
+
+	if (tlink == NULL) {
+		newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
+		if (newtlink == NULL)
+			return ERR_PTR(-ENOMEM);
+		newtlink->tl_index = fsuid;
+		newtlink->tl_tcon = ERR_PTR(-EACCES);
+		set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
+		set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
+		cifs_get_tlink(newtlink);
+
+		ret = radix_tree_preload(GFP_KERNEL);
+		if (ret != 0) {
+			kfree(newtlink);
+			return ERR_PTR(ret);
+		}
+
+		spin_lock(&cifs_sb->tlink_tree_lock);
+		/* was one inserted after previous search? */
+		tlink = radix_tree_lookup(&cifs_sb->tlink_tree, fsuid);
+		if (tlink) {
+			cifs_get_tlink(tlink);
+			spin_unlock(&cifs_sb->tlink_tree_lock);
+			radix_tree_preload_end();
+			kfree(newtlink);
+			goto wait_for_construction;
+		}
+		ret = radix_tree_insert(&cifs_sb->tlink_tree, fsuid, newtlink);
+		spin_unlock(&cifs_sb->tlink_tree_lock);
+		radix_tree_preload_end();
+		if (ret) {
+			kfree(newtlink);
+			return ERR_PTR(ret);
+		}
+		tlink = newtlink;
+	} else {
+wait_for_construction:
+		ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
+				  cifs_sb_tcon_pending_wait,
+				  TASK_INTERRUPTIBLE);
+		if (ret) {
+			cifs_put_tlink(tlink);
+			return ERR_PTR(ret);
+		}
+
+		/* if it's good, return it */
+		if (!IS_ERR(tlink->tl_tcon))
+			return tlink;
+
+		/* return error if we tried this already recently */
+		if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
+			cifs_put_tlink(tlink);
+			return ERR_PTR(-EACCES);
+		}
+
+		if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
+			goto wait_for_construction;
+	}
+
+	tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
+	clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
+	wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
+
+	if (IS_ERR(tlink->tl_tcon)) {
+		cifs_put_tlink(tlink);
+		return ERR_PTR(-EACCES);
+	}
+
+	return tlink;
+}
+
+/*
+ * periodic workqueue job that scans tcon_tree for a superblock and closes
+ * out tcons.
+ */
+static void
+cifs_prune_tlinks(struct work_struct *work)
+{
+	struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
+						    prune_tlinks.work);
+	struct tcon_link *tlink[8];
+	unsigned long now = jiffies;
+	unsigned long index = 0;
+	int i, ret;
+
+	do {
+		spin_lock(&cifs_sb->tlink_tree_lock);
+		ret = radix_tree_gang_lookup(&cifs_sb->tlink_tree,
+					     (void **)tlink, index,
+					     ARRAY_SIZE(tlink));
+		/* increment index for next pass */
+		if (ret > 0)
+			index = tlink[ret - 1]->tl_index + 1;
+		for (i = 0; i < ret; i++) {
+			if (test_bit(TCON_LINK_MASTER, &tlink[i]->tl_flags) ||
+			    atomic_read(&tlink[i]->tl_count) != 0 ||
+			    time_after(tlink[i]->tl_time + TLINK_IDLE_EXPIRE,
+				       now)) {
+				tlink[i] = NULL;
+				continue;
+			}
+			cifs_get_tlink(tlink[i]);
+			clear_bit(TCON_LINK_IN_TREE, &tlink[i]->tl_flags);
+			radix_tree_delete(&cifs_sb->tlink_tree,
+					  tlink[i]->tl_index);
+		}
+		spin_unlock(&cifs_sb->tlink_tree_lock);
+
+		for (i = 0; i < ret; i++) {
+			if (tlink[i] != NULL)
+				cifs_put_tlink(tlink[i]);
+		}
+	} while (ret != 0);
+
+	queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
+				TLINK_IDLE_EXPIRE);
+}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f9ed075..3840edd 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -54,18 +54,18 @@
 	int dfsplen;
 	char *full_path;
 	char dirsep;
-	struct cifs_sb_info *cifs_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
 	if (direntry == NULL)
 		return NULL;  /* not much we can do if dentry is freed and
 		we need to reopen the file after it was closed implicitly
 		when the server crashed */
 
-	cifs_sb = CIFS_SB(direntry->d_sb);
 	dirsep = CIFS_DIR_SEP(cifs_sb);
 	pplen = cifs_sb->prepathlen;
-	if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
-		dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
+	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
+		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
 	else
 		dfsplen = 0;
 cifs_bp_rename_retry:
@@ -117,7 +117,7 @@
 	/* BB test paths to Windows with '/' in the midst of prepath */
 
 	if (dfsplen) {
-		strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
+		strncpy(full_path, tcon->treeName, dfsplen);
 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
 			int i;
 			for (i = 0; i < dfsplen; i++) {
@@ -130,135 +130,6 @@
 	return full_path;
 }
 
-struct cifsFileInfo *
-cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
-		  struct file *file, struct vfsmount *mnt, unsigned int oflags)
-{
-	int oplock = 0;
-	struct cifsFileInfo *pCifsFile;
-	struct cifsInodeInfo *pCifsInode;
-	struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
-
-	pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
-	if (pCifsFile == NULL)
-		return pCifsFile;
-
-	if (oplockEnabled)
-		oplock = REQ_OPLOCK;
-
-	pCifsFile->netfid = fileHandle;
-	pCifsFile->pid = current->tgid;
-	pCifsFile->pInode = igrab(newinode);
-	pCifsFile->mnt = mnt;
-	pCifsFile->pfile = file;
-	pCifsFile->invalidHandle = false;
-	pCifsFile->closePend = false;
-	mutex_init(&pCifsFile->fh_mutex);
-	mutex_init(&pCifsFile->lock_mutex);
-	INIT_LIST_HEAD(&pCifsFile->llist);
-	atomic_set(&pCifsFile->count, 1);
-	INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
-
-	write_lock(&GlobalSMBSeslock);
-	list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
-	pCifsInode = CIFS_I(newinode);
-	if (pCifsInode) {
-		/* if readable file instance put first in list*/
-		if (oflags & FMODE_READ)
-			list_add(&pCifsFile->flist, &pCifsInode->openFileList);
-		else
-			list_add_tail(&pCifsFile->flist,
-				      &pCifsInode->openFileList);
-
-		if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-			pCifsInode->clientCanCacheAll = true;
-			pCifsInode->clientCanCacheRead = true;
-			cFYI(1, "Exclusive Oplock inode %p", newinode);
-		} else if ((oplock & 0xF) == OPLOCK_READ)
-				pCifsInode->clientCanCacheRead = true;
-	}
-	write_unlock(&GlobalSMBSeslock);
-
-	file->private_data = pCifsFile;
-
-	return pCifsFile;
-}
-
-int cifs_posix_open(char *full_path, struct inode **pinode,
-			struct super_block *sb, int mode, int oflags,
-			__u32 *poplock, __u16 *pnetfid, int xid)
-{
-	int rc;
-	FILE_UNIX_BASIC_INFO *presp_data;
-	__u32 posix_flags = 0;
-	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	struct cifs_fattr fattr;
-
-	cFYI(1, "posix open %s", full_path);
-
-	presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
-	if (presp_data == NULL)
-		return -ENOMEM;
-
-/* So far cifs posix extensions can only map the following flags.
-   There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
-   so far we do not seem to need them, and we can treat them as local only */
-	if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
-		(FMODE_READ | FMODE_WRITE))
-		posix_flags = SMB_O_RDWR;
-	else if (oflags & FMODE_READ)
-		posix_flags = SMB_O_RDONLY;
-	else if (oflags & FMODE_WRITE)
-		posix_flags = SMB_O_WRONLY;
-	if (oflags & O_CREAT)
-		posix_flags |= SMB_O_CREAT;
-	if (oflags & O_EXCL)
-		posix_flags |= SMB_O_EXCL;
-	if (oflags & O_TRUNC)
-		posix_flags |= SMB_O_TRUNC;
-	/* be safe and imply O_SYNC for O_DSYNC */
-	if (oflags & O_DSYNC)
-		posix_flags |= SMB_O_SYNC;
-	if (oflags & O_DIRECTORY)
-		posix_flags |= SMB_O_DIRECTORY;
-	if (oflags & O_NOFOLLOW)
-		posix_flags |= SMB_O_NOFOLLOW;
-	if (oflags & O_DIRECT)
-		posix_flags |= SMB_O_DIRECT;
-
-	mode &= ~current_umask();
-	rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
-			pnetfid, presp_data, poplock, full_path,
-			cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
-					CIFS_MOUNT_MAP_SPECIAL_CHR);
-	if (rc)
-		goto posix_open_ret;
-
-	if (presp_data->Type == cpu_to_le32(-1))
-		goto posix_open_ret; /* open ok, caller does qpathinfo */
-
-	if (!pinode)
-		goto posix_open_ret; /* caller does not need info */
-
-	cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
-
-	/* get new inode and set it up */
-	if (*pinode == NULL) {
-		cifs_fill_uniqueid(sb, &fattr);
-		*pinode = cifs_iget(sb, &fattr);
-		if (!*pinode) {
-			rc = -ENOMEM;
-			goto posix_open_ret;
-		}
-	} else {
-		cifs_fattr_to_inode(*pinode, &fattr);
-	}
-
-posix_open_ret:
-	kfree(presp_data);
-	return rc;
-}
-
 static void setup_cifs_dentry(struct cifsTconInfo *tcon,
 			      struct dentry *direntry,
 			      struct inode *newinode)
@@ -291,6 +162,7 @@
 	int desiredAccess = GENERIC_READ | GENERIC_WRITE;
 	__u16 fileHandle;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *tcon;
 	char *full_path = NULL;
 	FILE_ALL_INFO *buf = NULL;
@@ -300,7 +172,20 @@
 	xid = GetXid();
 
 	cifs_sb = CIFS_SB(inode->i_sb);
-	tcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		FreeXid(xid);
+		return PTR_ERR(tlink);
+	}
+	tcon = tlink_tcon(tlink);
+
+	if (oplockEnabled)
+		oplock = REQ_OPLOCK;
+
+	if (nd && (nd->flags & LOOKUP_OPEN))
+		oflags = nd->intent.open.file->f_flags;
+	else
+		oflags = O_RDONLY | O_CREAT;
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
@@ -308,14 +193,6 @@
 		goto cifs_create_out;
 	}
 
-	if (oplockEnabled)
-		oplock = REQ_OPLOCK;
-
-	if (nd && (nd->flags & LOOKUP_OPEN))
-		oflags = nd->intent.open.flags;
-	else
-		oflags = FMODE_READ | SMB_O_CREAT;
-
 	if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
 	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
@@ -344,9 +221,9 @@
 		/* if the file is going to stay open, then we
 		   need to set the desired access properly */
 		desiredAccess = 0;
-		if (oflags & FMODE_READ)
+		if (OPEN_FMODE(oflags) & FMODE_READ)
 			desiredAccess |= GENERIC_READ; /* is this too little? */
-		if (oflags & FMODE_WRITE)
+		if (OPEN_FMODE(oflags) & FMODE_WRITE)
 			desiredAccess |= GENERIC_WRITE;
 
 		if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
@@ -375,7 +252,7 @@
 	if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
 		create_options |= CREATE_OPTION_READONLY;
 
-	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
+	if (tcon->ses->capabilities & CAP_NT_SMBS)
 		rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
 			 desiredAccess, create_options,
 			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
@@ -467,8 +344,7 @@
 			goto cifs_create_out;
 		}
 
-		pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
-					       nd->path.mnt, oflags);
+		pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
 		if (pfile_info == NULL) {
 			fput(filp);
 			CIFSSMBClose(xid, tcon, fileHandle);
@@ -481,6 +357,7 @@
 cifs_create_out:
 	kfree(buf);
 	kfree(full_path);
+	cifs_put_tlink(tlink);
 	FreeXid(xid);
 	return rc;
 }
@@ -491,6 +368,7 @@
 	int rc = -EPERM;
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	struct inode *newinode = NULL;
@@ -503,10 +381,14 @@
 	if (!old_valid_dev(device_number))
 		return -EINVAL;
 
-	xid = GetXid();
-
 	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
@@ -606,6 +488,7 @@
 	kfree(full_path);
 	kfree(buf);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -619,6 +502,7 @@
 	__u16 fileHandle = 0;
 	bool posix_open = false;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct cifsFileInfo *cfile;
 	struct inode *newInode = NULL;
@@ -633,7 +517,12 @@
 	/* check whether path exists */
 
 	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		FreeXid(xid);
+		return (struct dentry *)tlink;
+	}
+	pTcon = tlink_tcon(tlink);
 
 	/*
 	 * Don't allow the separator character in a path component.
@@ -644,8 +533,8 @@
 		for (i = 0; i < direntry->d_name.len; i++)
 			if (direntry->d_name.name[i] == '\\') {
 				cFYI(1, "Invalid file name");
-				FreeXid(xid);
-				return ERR_PTR(-EINVAL);
+				rc = -EINVAL;
+				goto lookup_out;
 			}
 	}
 
@@ -655,7 +544,8 @@
 	 */
 	if (nd && (nd->flags & LOOKUP_EXCL)) {
 		d_instantiate(direntry, NULL);
-		return NULL;
+		rc = 0;
+		goto lookup_out;
 	}
 
 	/* can not grab the rename sem here since it would
@@ -663,8 +553,8 @@
 	in which we already have the sb rename sem */
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
-		FreeXid(xid);
-		return ERR_PTR(-ENOMEM);
+		rc = -ENOMEM;
+		goto lookup_out;
 	}
 
 	if (direntry->d_inode != NULL) {
@@ -687,11 +577,11 @@
 	if (pTcon->unix_ext) {
 		if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
 		     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
-		     (nd->intent.open.flags & O_CREAT)) {
+		     (nd->intent.open.file->f_flags & O_CREAT)) {
 			rc = cifs_posix_open(full_path, &newInode,
 					parent_dir_inode->i_sb,
 					nd->intent.open.create_mode,
-					nd->intent.open.flags, &oplock,
+					nd->intent.open.file->f_flags, &oplock,
 					&fileHandle, xid);
 			/*
 			 * The check below works around a bug in POSIX
@@ -727,9 +617,8 @@
 				goto lookup_out;
 			}
 
-			cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
-						  nd->path.mnt,
-						  nd->intent.open.flags);
+			cfile = cifs_new_fileinfo(fileHandle, filp, tlink,
+						  oplock);
 			if (cfile == NULL) {
 				fput(filp);
 				CIFSSMBClose(xid, pTcon, fileHandle);
@@ -759,6 +648,7 @@
 
 lookup_out:
 	kfree(full_path);
+	cifs_put_tlink(tlink);
 	FreeXid(xid);
 	return ERR_PTR(rc);
 }
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index de748c6..8c81e7b 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -60,34 +60,32 @@
 		FILE_READ_DATA);
 }
 
-static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
+static u32 cifs_posix_convert_flags(unsigned int flags)
 {
-	fmode_t posix_flags = 0;
+	u32 posix_flags = 0;
 
 	if ((flags & O_ACCMODE) == O_RDONLY)
-		posix_flags = FMODE_READ;
+		posix_flags = SMB_O_RDONLY;
 	else if ((flags & O_ACCMODE) == O_WRONLY)
-		posix_flags = FMODE_WRITE;
-	else if ((flags & O_ACCMODE) == O_RDWR) {
-		/* GENERIC_ALL is too much permission to request
-		   can cause unnecessary access denied on create */
-		/* return GENERIC_ALL; */
-		posix_flags = FMODE_READ | FMODE_WRITE;
-	}
-	/* can not map O_CREAT or O_EXCL or O_TRUNC flags when
-	   reopening a file.  They had their effect on the original open */
-	if (flags & O_APPEND)
-		posix_flags |= (fmode_t)O_APPEND;
+		posix_flags = SMB_O_WRONLY;
+	else if ((flags & O_ACCMODE) == O_RDWR)
+		posix_flags = SMB_O_RDWR;
+
+	if (flags & O_CREAT)
+		posix_flags |= SMB_O_CREAT;
+	if (flags & O_EXCL)
+		posix_flags |= SMB_O_EXCL;
+	if (flags & O_TRUNC)
+		posix_flags |= SMB_O_TRUNC;
+	/* be safe and imply O_SYNC for O_DSYNC */
 	if (flags & O_DSYNC)
-		posix_flags |= (fmode_t)O_DSYNC;
-	if (flags & __O_SYNC)
-		posix_flags |= (fmode_t)__O_SYNC;
+		posix_flags |= SMB_O_SYNC;
 	if (flags & O_DIRECTORY)
-		posix_flags |= (fmode_t)O_DIRECTORY;
+		posix_flags |= SMB_O_DIRECTORY;
 	if (flags & O_NOFOLLOW)
-		posix_flags |= (fmode_t)O_NOFOLLOW;
+		posix_flags |= SMB_O_NOFOLLOW;
 	if (flags & O_DIRECT)
-		posix_flags |= (fmode_t)O_DIRECT;
+		posix_flags |= SMB_O_DIRECT;
 
 	return posix_flags;
 }
@@ -106,66 +104,8 @@
 		return FILE_OPEN;
 }
 
-/* all arguments to this function must be checked for validity in caller */
-static inline int
-cifs_posix_open_inode_helper(struct inode *inode, struct file *file,
-			     struct cifsInodeInfo *pCifsInode, __u32 oplock,
-			     u16 netfid)
-{
-
-	write_lock(&GlobalSMBSeslock);
-
-	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
-	if (pCifsInode == NULL) {
-		write_unlock(&GlobalSMBSeslock);
-		return -EINVAL;
-	}
-
-	if (pCifsInode->clientCanCacheRead) {
-		/* we have the inode open somewhere else
-		   no need to discard cache data */
-		goto psx_client_can_cache;
-	}
-
-	/* BB FIXME need to fix this check to move it earlier into posix_open
-	   BB  fIX following section BB FIXME */
-
-	/* if not oplocked, invalidate inode pages if mtime or file
-	   size changed */
-/*	temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
-	if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
-			   (file->f_path.dentry->d_inode->i_size ==
-			    (loff_t)le64_to_cpu(buf->EndOfFile))) {
-		cFYI(1, "inode unchanged on server");
-	} else {
-		if (file->f_path.dentry->d_inode->i_mapping) {
-			rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
-			if (rc != 0)
-				CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
-		}
-		cFYI(1, "invalidating remote inode since open detected it "
-			 "changed");
-		invalidate_remote_inode(file->f_path.dentry->d_inode);
-	} */
-
-psx_client_can_cache:
-	if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-		pCifsInode->clientCanCacheAll = true;
-		pCifsInode->clientCanCacheRead = true;
-		cFYI(1, "Exclusive Oplock granted on inode %p",
-			 file->f_path.dentry->d_inode);
-	} else if ((oplock & 0xF) == OPLOCK_READ)
-		pCifsInode->clientCanCacheRead = true;
-
-	/* will have to change the unlock if we reenable the
-	   filemap_fdatawrite (which does not seem necessary */
-	write_unlock(&GlobalSMBSeslock);
-	return 0;
-}
-
-/* all arguments to this function must be checked for validity in caller */
 static inline int cifs_open_inode_helper(struct inode *inode,
-	struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
+	struct cifsTconInfo *pTcon, __u32 oplock, FILE_ALL_INFO *buf,
 	char *full_path, int xid)
 {
 	struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
@@ -207,16 +147,175 @@
 		rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
 					 xid, NULL);
 
-	if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+	if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
 		pCifsInode->clientCanCacheAll = true;
 		pCifsInode->clientCanCacheRead = true;
 		cFYI(1, "Exclusive Oplock granted on inode %p", inode);
-	} else if ((*oplock & 0xF) == OPLOCK_READ)
+	} else if ((oplock & 0xF) == OPLOCK_READ)
 		pCifsInode->clientCanCacheRead = true;
 
 	return rc;
 }
 
+int cifs_posix_open(char *full_path, struct inode **pinode,
+			struct super_block *sb, int mode, unsigned int f_flags,
+			__u32 *poplock, __u16 *pnetfid, int xid)
+{
+	int rc;
+	FILE_UNIX_BASIC_INFO *presp_data;
+	__u32 posix_flags = 0;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	struct cifs_fattr fattr;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
+
+	cFYI(1, "posix open %s", full_path);
+
+	presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+	if (presp_data == NULL)
+		return -ENOMEM;
+
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		goto posix_open_ret;
+	}
+
+	tcon = tlink_tcon(tlink);
+	mode &= ~current_umask();
+
+	posix_flags = cifs_posix_convert_flags(f_flags);
+	rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
+			     poplock, full_path, cifs_sb->local_nls,
+			     cifs_sb->mnt_cifs_flags &
+					CIFS_MOUNT_MAP_SPECIAL_CHR);
+	cifs_put_tlink(tlink);
+
+	if (rc)
+		goto posix_open_ret;
+
+	if (presp_data->Type == cpu_to_le32(-1))
+		goto posix_open_ret; /* open ok, caller does qpathinfo */
+
+	if (!pinode)
+		goto posix_open_ret; /* caller does not need info */
+
+	cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
+
+	/* get new inode and set it up */
+	if (*pinode == NULL) {
+		cifs_fill_uniqueid(sb, &fattr);
+		*pinode = cifs_iget(sb, &fattr);
+		if (!*pinode) {
+			rc = -ENOMEM;
+			goto posix_open_ret;
+		}
+	} else {
+		cifs_fattr_to_inode(*pinode, &fattr);
+	}
+
+posix_open_ret:
+	kfree(presp_data);
+	return rc;
+}
+
+struct cifsFileInfo *
+cifs_new_fileinfo(__u16 fileHandle, struct file *file,
+		  struct tcon_link *tlink, __u32 oplock)
+{
+	struct dentry *dentry = file->f_path.dentry;
+	struct inode *inode = dentry->d_inode;
+	struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
+	struct cifsFileInfo *pCifsFile;
+
+	pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+	if (pCifsFile == NULL)
+		return pCifsFile;
+
+	pCifsFile->netfid = fileHandle;
+	pCifsFile->pid = current->tgid;
+	pCifsFile->uid = current_fsuid();
+	pCifsFile->dentry = dget(dentry);
+	pCifsFile->f_flags = file->f_flags;
+	pCifsFile->invalidHandle = false;
+	pCifsFile->tlink = cifs_get_tlink(tlink);
+	mutex_init(&pCifsFile->fh_mutex);
+	mutex_init(&pCifsFile->lock_mutex);
+	INIT_LIST_HEAD(&pCifsFile->llist);
+	atomic_set(&pCifsFile->count, 1);
+	INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
+
+	spin_lock(&cifs_file_list_lock);
+	list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList));
+	/* if readable file instance put first in list*/
+	if (file->f_mode & FMODE_READ)
+		list_add(&pCifsFile->flist, &pCifsInode->openFileList);
+	else
+		list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList);
+	spin_unlock(&cifs_file_list_lock);
+
+	if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+		pCifsInode->clientCanCacheAll = true;
+		pCifsInode->clientCanCacheRead = true;
+		cFYI(1, "Exclusive Oplock inode %p", inode);
+	} else if ((oplock & 0xF) == OPLOCK_READ)
+		pCifsInode->clientCanCacheRead = true;
+
+	file->private_data = pCifsFile;
+	return pCifsFile;
+}
+
+/*
+ * Release a reference on the file private data. This may involve closing
+ * the filehandle out on the server.
+ */
+void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
+{
+	struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink);
+	struct cifsInodeInfo *cifsi = CIFS_I(cifs_file->dentry->d_inode);
+	struct cifsLockInfo *li, *tmp;
+
+	spin_lock(&cifs_file_list_lock);
+	if (!atomic_dec_and_test(&cifs_file->count)) {
+		spin_unlock(&cifs_file_list_lock);
+		return;
+	}
+
+	/* remove it from the lists */
+	list_del(&cifs_file->flist);
+	list_del(&cifs_file->tlist);
+
+	if (list_empty(&cifsi->openFileList)) {
+		cFYI(1, "closing last open instance for inode %p",
+			cifs_file->dentry->d_inode);
+		cifsi->clientCanCacheRead = false;
+		cifsi->clientCanCacheAll  = false;
+	}
+	spin_unlock(&cifs_file_list_lock);
+
+	if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
+		int xid, rc;
+
+		xid = GetXid();
+		rc = CIFSSMBClose(xid, tcon, cifs_file->netfid);
+		FreeXid(xid);
+	}
+
+	/* Delete any outstanding lock records. We'll lose them when the file
+	 * is closed anyway.
+	 */
+	mutex_lock(&cifs_file->lock_mutex);
+	list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) {
+		list_del(&li->llist);
+		kfree(li);
+	}
+	mutex_unlock(&cifs_file->lock_mutex);
+
+	cifs_put_tlink(cifs_file->tlink);
+	dput(cifs_file->dentry);
+	kfree(cifs_file);
+}
+
 int cifs_open(struct inode *inode, struct file *file)
 {
 	int rc = -EACCES;
@@ -224,6 +323,7 @@
 	__u32 oplock;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *tcon;
+	struct tcon_link *tlink;
 	struct cifsFileInfo *pCifsFile = NULL;
 	struct cifsInodeInfo *pCifsInode;
 	char *full_path = NULL;
@@ -235,7 +335,12 @@
 	xid = GetXid();
 
 	cifs_sb = CIFS_SB(inode->i_sb);
-	tcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		FreeXid(xid);
+		return PTR_ERR(tlink);
+	}
+	tcon = tlink_tcon(tlink);
 
 	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
 
@@ -257,27 +362,15 @@
 	    (tcon->ses->capabilities & CAP_UNIX) &&
 	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
-		oflags |= SMB_O_CREAT;
 		/* can not refresh inode info since size could be stale */
 		rc = cifs_posix_open(full_path, &inode, inode->i_sb,
 				cifs_sb->mnt_file_mode /* ignored */,
-				oflags, &oplock, &netfid, xid);
+				file->f_flags, &oplock, &netfid, xid);
 		if (rc == 0) {
 			cFYI(1, "posix open succeeded");
-			/* no need for special case handling of setting mode
-			   on read only files needed here */
 
-			rc = cifs_posix_open_inode_helper(inode, file,
-					pCifsInode, oplock, netfid);
-			if (rc != 0) {
-				CIFSSMBClose(xid, tcon, netfid);
-				goto out;
-			}
-
-			pCifsFile = cifs_new_fileinfo(inode, netfid, file,
-							file->f_path.mnt,
-							oflags);
+			pCifsFile = cifs_new_fileinfo(netfid, file, tlink,
+						      oplock);
 			if (pCifsFile == NULL) {
 				CIFSSMBClose(xid, tcon, netfid);
 				rc = -ENOMEM;
@@ -345,7 +438,7 @@
 		goto out;
 	}
 
-	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
+	if (tcon->ses->capabilities & CAP_NT_SMBS)
 		rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
 			 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
 			 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
@@ -365,12 +458,11 @@
 		goto out;
 	}
 
-	rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid);
+	rc = cifs_open_inode_helper(inode, tcon, oplock, buf, full_path, xid);
 	if (rc != 0)
 		goto out;
 
-	pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
-					file->f_flags);
+	pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
 	if (pCifsFile == NULL) {
 		rc = -ENOMEM;
 		goto out;
@@ -402,6 +494,7 @@
 	kfree(buf);
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -416,14 +509,13 @@
 	return rc;
 }
 
-static int cifs_reopen_file(struct file *file, bool can_flush)
+static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
 {
 	int rc = -EACCES;
 	int xid;
 	__u32 oplock;
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *tcon;
-	struct cifsFileInfo *pCifsFile;
 	struct cifsInodeInfo *pCifsInode;
 	struct inode *inode;
 	char *full_path = NULL;
@@ -431,11 +523,6 @@
 	int disposition = FILE_OPEN;
 	__u16 netfid;
 
-	if (file->private_data)
-		pCifsFile = file->private_data;
-	else
-		return -EBADF;
-
 	xid = GetXid();
 	mutex_lock(&pCifsFile->fh_mutex);
 	if (!pCifsFile->invalidHandle) {
@@ -445,39 +532,24 @@
 		return rc;
 	}
 
-	if (file->f_path.dentry == NULL) {
-		cERROR(1, "no valid name if dentry freed");
-		dump_stack();
-		rc = -EBADF;
-		goto reopen_error_exit;
-	}
-
-	inode = file->f_path.dentry->d_inode;
-	if (inode == NULL) {
-		cERROR(1, "inode not valid");
-		dump_stack();
-		rc = -EBADF;
-		goto reopen_error_exit;
-	}
-
+	inode = pCifsFile->dentry->d_inode;
 	cifs_sb = CIFS_SB(inode->i_sb);
-	tcon = cifs_sb->tcon;
+	tcon = tlink_tcon(pCifsFile->tlink);
 
 /* can not grab rename sem here because various ops, including
    those that already have the rename sem can end up causing writepage
    to get called and if the server was down that means we end up here,
    and we can never tell if the caller already has the rename_sem */
-	full_path = build_path_from_dentry(file->f_path.dentry);
+	full_path = build_path_from_dentry(pCifsFile->dentry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-reopen_error_exit:
 		mutex_unlock(&pCifsFile->fh_mutex);
 		FreeXid(xid);
 		return rc;
 	}
 
 	cFYI(1, "inode = 0x%p file flags 0x%x for %s",
-		 inode, file->f_flags, full_path);
+		 inode, pCifsFile->f_flags, full_path);
 
 	if (oplockEnabled)
 		oplock = REQ_OPLOCK;
@@ -487,8 +559,14 @@
 	if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
 	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-		int oflags = (int) cifs_posix_convert_flags(file->f_flags);
-		/* can not refresh inode info since size could be stale */
+
+		/*
+		 * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
+		 * original open. Must mask them off for a reopen.
+		 */
+		unsigned int oflags = pCifsFile->f_flags &
+						~(O_CREAT | O_EXCL | O_TRUNC);
+
 		rc = cifs_posix_open(full_path, NULL, inode->i_sb,
 				cifs_sb->mnt_file_mode /* ignored */,
 				oflags, &oplock, &netfid, xid);
@@ -500,7 +578,7 @@
 		   in the reconnect path it is important to retry hard */
 	}
 
-	desiredAccess = cifs_convert_flags(file->f_flags);
+	desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
 
 	/* Can not refresh inode by passing in file_info buf to be returned
 	   by SMBOpen and then calling get_inode_info with returned buf
@@ -516,49 +594,50 @@
 		mutex_unlock(&pCifsFile->fh_mutex);
 		cFYI(1, "cifs_open returned 0x%x", rc);
 		cFYI(1, "oplock: %d", oplock);
-	} else {
-reopen_success:
-		pCifsFile->netfid = netfid;
-		pCifsFile->invalidHandle = false;
-		mutex_unlock(&pCifsFile->fh_mutex);
-		pCifsInode = CIFS_I(inode);
-		if (pCifsInode) {
-			if (can_flush) {
-				rc = filemap_write_and_wait(inode->i_mapping);
-				if (rc != 0)
-					CIFS_I(inode)->write_behind_rc = rc;
-			/* temporarily disable caching while we
-			   go to server to get inode info */
-				pCifsInode->clientCanCacheAll = false;
-				pCifsInode->clientCanCacheRead = false;
-				if (tcon->unix_ext)
-					rc = cifs_get_inode_info_unix(&inode,
-						full_path, inode->i_sb, xid);
-				else
-					rc = cifs_get_inode_info(&inode,
-						full_path, NULL, inode->i_sb,
-						xid, NULL);
-			} /* else we are writing out data to server already
-			     and could deadlock if we tried to flush data, and
-			     since we do not know if we have data that would
-			     invalidate the current end of file on the server
-			     we can not go to the server to get the new inod
-			     info */
-			if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-				pCifsInode->clientCanCacheAll = true;
-				pCifsInode->clientCanCacheRead = true;
-				cFYI(1, "Exclusive Oplock granted on inode %p",
-					 file->f_path.dentry->d_inode);
-			} else if ((oplock & 0xF) == OPLOCK_READ) {
-				pCifsInode->clientCanCacheRead = true;
-				pCifsInode->clientCanCacheAll = false;
-			} else {
-				pCifsInode->clientCanCacheRead = false;
-				pCifsInode->clientCanCacheAll = false;
-			}
-			cifs_relock_file(pCifsFile);
-		}
+		goto reopen_error_exit;
 	}
+
+reopen_success:
+	pCifsFile->netfid = netfid;
+	pCifsFile->invalidHandle = false;
+	mutex_unlock(&pCifsFile->fh_mutex);
+	pCifsInode = CIFS_I(inode);
+
+	if (can_flush) {
+		rc = filemap_write_and_wait(inode->i_mapping);
+		if (rc != 0)
+			CIFS_I(inode)->write_behind_rc = rc;
+
+		pCifsInode->clientCanCacheAll = false;
+		pCifsInode->clientCanCacheRead = false;
+		if (tcon->unix_ext)
+			rc = cifs_get_inode_info_unix(&inode,
+				full_path, inode->i_sb, xid);
+		else
+			rc = cifs_get_inode_info(&inode,
+				full_path, NULL, inode->i_sb,
+				xid, NULL);
+	} /* else we are writing out data to server already
+	     and could deadlock if we tried to flush data, and
+	     since we do not know if we have data that would
+	     invalidate the current end of file on the server
+	     we can not go to the server to get the new inod
+	     info */
+	if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+		pCifsInode->clientCanCacheAll = true;
+		pCifsInode->clientCanCacheRead = true;
+		cFYI(1, "Exclusive Oplock granted on inode %p",
+			 pCifsFile->dentry->d_inode);
+	} else if ((oplock & 0xF) == OPLOCK_READ) {
+		pCifsInode->clientCanCacheRead = true;
+		pCifsInode->clientCanCacheAll = false;
+	} else {
+		pCifsInode->clientCanCacheRead = false;
+		pCifsInode->clientCanCacheAll = false;
+	}
+	cifs_relock_file(pCifsFile);
+
+reopen_error_exit:
 	kfree(full_path);
 	FreeXid(xid);
 	return rc;
@@ -566,79 +645,11 @@
 
 int cifs_close(struct inode *inode, struct file *file)
 {
-	int rc = 0;
-	int xid, timeout;
-	struct cifs_sb_info *cifs_sb;
-	struct cifsTconInfo *pTcon;
-	struct cifsFileInfo *pSMBFile = file->private_data;
+	cifsFileInfo_put(file->private_data);
+	file->private_data = NULL;
 
-	xid = GetXid();
-
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
-	if (pSMBFile) {
-		struct cifsLockInfo *li, *tmp;
-		write_lock(&GlobalSMBSeslock);
-		pSMBFile->closePend = true;
-		if (pTcon) {
-			/* no sense reconnecting to close a file that is
-			   already closed */
-			if (!pTcon->need_reconnect) {
-				write_unlock(&GlobalSMBSeslock);
-				timeout = 2;
-				while ((atomic_read(&pSMBFile->count) != 1)
-					&& (timeout <= 2048)) {
-					/* Give write a better chance to get to
-					server ahead of the close.  We do not
-					want to add a wait_q here as it would
-					increase the memory utilization as
-					the struct would be in each open file,
-					but this should give enough time to
-					clear the socket */
-					cFYI(DBG2, "close delay, write pending");
-					msleep(timeout);
-					timeout *= 4;
-				}
-				if (!pTcon->need_reconnect &&
-				    !pSMBFile->invalidHandle)
-					rc = CIFSSMBClose(xid, pTcon,
-						  pSMBFile->netfid);
-			} else
-				write_unlock(&GlobalSMBSeslock);
-		} else
-			write_unlock(&GlobalSMBSeslock);
-
-		/* Delete any outstanding lock records.
-		   We'll lose them when the file is closed anyway. */
-		mutex_lock(&pSMBFile->lock_mutex);
-		list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
-			list_del(&li->llist);
-			kfree(li);
-		}
-		mutex_unlock(&pSMBFile->lock_mutex);
-
-		write_lock(&GlobalSMBSeslock);
-		list_del(&pSMBFile->flist);
-		list_del(&pSMBFile->tlist);
-		write_unlock(&GlobalSMBSeslock);
-		cifsFileInfo_put(file->private_data);
-		file->private_data = NULL;
-	} else
-		rc = -EBADF;
-
-	read_lock(&GlobalSMBSeslock);
-	if (list_empty(&(CIFS_I(inode)->openFileList))) {
-		cFYI(1, "closing last open instance for inode %p", inode);
-		/* if the file is not open we do not know if we can cache info
-		   on this inode, much less write behind and read ahead */
-		CIFS_I(inode)->clientCanCacheRead = false;
-		CIFS_I(inode)->clientCanCacheAll  = false;
-	}
-	read_unlock(&GlobalSMBSeslock);
-	if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
-		rc = CIFS_I(inode)->write_behind_rc;
-	FreeXid(xid);
-	return rc;
+	/* return code from the ->release op is always ignored */
+	return 0;
 }
 
 int cifs_closedir(struct inode *inode, struct file *file)
@@ -653,25 +664,21 @@
 	xid = GetXid();
 
 	if (pCFileStruct) {
-		struct cifsTconInfo *pTcon;
-		struct cifs_sb_info *cifs_sb =
-			CIFS_SB(file->f_path.dentry->d_sb);
-
-		pTcon = cifs_sb->tcon;
+		struct cifsTconInfo *pTcon = tlink_tcon(pCFileStruct->tlink);
 
 		cFYI(1, "Freeing private data in close dir");
-		write_lock(&GlobalSMBSeslock);
+		spin_lock(&cifs_file_list_lock);
 		if (!pCFileStruct->srch_inf.endOfSearch &&
 		    !pCFileStruct->invalidHandle) {
 			pCFileStruct->invalidHandle = true;
-			write_unlock(&GlobalSMBSeslock);
+			spin_unlock(&cifs_file_list_lock);
 			rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
 			cFYI(1, "Closing uncompleted readdir with rc %d",
 				 rc);
 			/* not much we can do if it fails anyway, ignore rc */
 			rc = 0;
 		} else
-			write_unlock(&GlobalSMBSeslock);
+			spin_unlock(&cifs_file_list_lock);
 		ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
 		if (ptmp) {
 			cFYI(1, "closedir free smb buf in srch struct");
@@ -681,6 +688,7 @@
 			else
 				cifs_buf_release(ptmp);
 		}
+		cifs_put_tlink(pCFileStruct->tlink);
 		kfree(file->private_data);
 		file->private_data = NULL;
 	}
@@ -767,7 +775,7 @@
 		cFYI(1, "Unknown type of lock");
 
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	tcon = cifs_sb->tcon;
+	tcon = tlink_tcon(((struct cifsFileInfo *)file->private_data)->tlink);
 
 	if (file->private_data == NULL) {
 		rc = -EBADF;
@@ -960,14 +968,14 @@
 
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
 
-	pTcon = cifs_sb->tcon;
-
 	/* cFYI(1, " write %d bytes to offset %lld of %s", write_size,
 	   *poffset, file->f_path.dentry->d_name.name); */
 
 	if (file->private_data == NULL)
 		return -EBADF;
+
 	open_file = file->private_data;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	rc = generic_write_checks(file, poffset, &write_size, 0);
 	if (rc)
@@ -988,19 +996,12 @@
 			   we blocked so return what we managed to write */
 				return total_written;
 			}
-			if (open_file->closePend) {
-				FreeXid(xid);
-				if (total_written)
-					return total_written;
-				else
-					return -EBADF;
-			}
 			if (open_file->invalidHandle) {
 				/* we could deadlock if we called
 				   filemap_fdatawait from here so tell
 				   reopen_file not to flush data to server
 				   now */
-				rc = cifs_reopen_file(file, false);
+				rc = cifs_reopen_file(open_file, false);
 				if (rc != 0)
 					break;
 			}
@@ -1048,8 +1049,9 @@
 	return total_written;
 }
 
-static ssize_t cifs_write(struct file *file, const char *write_data,
-			  size_t write_size, loff_t *poffset)
+static ssize_t cifs_write(struct cifsFileInfo *open_file,
+			  const char *write_data, size_t write_size,
+			  loff_t *poffset)
 {
 	int rc = 0;
 	unsigned int bytes_written = 0;
@@ -1057,19 +1059,15 @@
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 	int xid, long_op;
-	struct cifsFileInfo *open_file;
-	struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
+	struct dentry *dentry = open_file->dentry;
+	struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
 
-	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-
-	pTcon = cifs_sb->tcon;
+	cifs_sb = CIFS_SB(dentry->d_sb);
 
 	cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
-	   *poffset, file->f_path.dentry->d_name.name);
+	   *poffset, dentry->d_name.name);
 
-	if (file->private_data == NULL)
-		return -EBADF;
-	open_file = file->private_data;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	xid = GetXid();
 
@@ -1078,28 +1076,12 @@
 	     total_written += bytes_written) {
 		rc = -EAGAIN;
 		while (rc == -EAGAIN) {
-			if (file->private_data == NULL) {
-				/* file has been closed on us */
-				FreeXid(xid);
-			/* if we have gotten here we have written some data
-			   and blocked, and the file has been freed on us
-			   while we blocked so return what we managed to
-			   write */
-				return total_written;
-			}
-			if (open_file->closePend) {
-				FreeXid(xid);
-				if (total_written)
-					return total_written;
-				else
-					return -EBADF;
-			}
 			if (open_file->invalidHandle) {
 				/* we could deadlock if we called
 				   filemap_fdatawait from here so tell
 				   reopen_file not to flush data to
 				   server now */
-				rc = cifs_reopen_file(file, false);
+				rc = cifs_reopen_file(open_file, false);
 				if (rc != 0)
 					break;
 			}
@@ -1146,43 +1128,41 @@
 
 	cifs_stats_bytes_written(pTcon, total_written);
 
-	/* since the write may have blocked check these pointers again */
-	if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {
-/*BB We could make this contingent on superblock ATIME flag too */
-/*		file->f_path.dentry->d_inode->i_ctime =
-		file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/
-		if (total_written > 0) {
-			spin_lock(&file->f_path.dentry->d_inode->i_lock);
-			if (*poffset > file->f_path.dentry->d_inode->i_size)
-				i_size_write(file->f_path.dentry->d_inode,
-					     *poffset);
-			spin_unlock(&file->f_path.dentry->d_inode->i_lock);
-		}
-		mark_inode_dirty_sync(file->f_path.dentry->d_inode);
+	if (total_written > 0) {
+		spin_lock(&dentry->d_inode->i_lock);
+		if (*poffset > dentry->d_inode->i_size)
+			i_size_write(dentry->d_inode, *poffset);
+		spin_unlock(&dentry->d_inode->i_lock);
 	}
+	mark_inode_dirty_sync(dentry->d_inode);
 	FreeXid(xid);
 	return total_written;
 }
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
+struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
+					bool fsuid_only)
 {
 	struct cifsFileInfo *open_file = NULL;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
 
-	read_lock(&GlobalSMBSeslock);
+	/* only filter by fsuid on multiuser mounts */
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
+		fsuid_only = false;
+
+	spin_lock(&cifs_file_list_lock);
 	/* we could simply get the first_list_entry since write-only entries
 	   are always at the end of the list but since the first entry might
 	   have a close pending, we go through the whole list */
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
-		if (open_file->closePend)
+		if (fsuid_only && open_file->uid != current_fsuid())
 			continue;
-		if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
-		    (open_file->pfile->f_flags & O_RDONLY))) {
+		if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
 			if (!open_file->invalidHandle) {
 				/* found a good file */
 				/* lock it so it will not be closed on us */
 				cifsFileInfo_get(open_file);
-				read_unlock(&GlobalSMBSeslock);
+				spin_unlock(&cifs_file_list_lock);
 				return open_file;
 			} /* else might as well continue, and look for
 			     another, or simply have the caller reopen it
@@ -1190,14 +1170,16 @@
 		} else /* write only file */
 			break; /* write only files are last so must be done */
 	}
-	read_unlock(&GlobalSMBSeslock);
+	spin_unlock(&cifs_file_list_lock);
 	return NULL;
 }
 #endif
 
-struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
+struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
+					bool fsuid_only)
 {
 	struct cifsFileInfo *open_file;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
 	bool any_available = false;
 	int rc;
 
@@ -1211,53 +1193,39 @@
 		return NULL;
 	}
 
-	read_lock(&GlobalSMBSeslock);
+	/* only filter by fsuid on multiuser mounts */
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
+		fsuid_only = false;
+
+	spin_lock(&cifs_file_list_lock);
 refind_writable:
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
-		if (open_file->closePend ||
-		    (!any_available && open_file->pid != current->tgid))
+		if (!any_available && open_file->pid != current->tgid)
 			continue;
-
-		if (open_file->pfile &&
-		    ((open_file->pfile->f_flags & O_RDWR) ||
-		     (open_file->pfile->f_flags & O_WRONLY))) {
+		if (fsuid_only && open_file->uid != current_fsuid())
+			continue;
+		if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
 			cifsFileInfo_get(open_file);
 
 			if (!open_file->invalidHandle) {
 				/* found a good writable file */
-				read_unlock(&GlobalSMBSeslock);
+				spin_unlock(&cifs_file_list_lock);
 				return open_file;
 			}
 
-			read_unlock(&GlobalSMBSeslock);
-			/* Had to unlock since following call can block */
-			rc = cifs_reopen_file(open_file->pfile, false);
-			if (!rc) {
-				if (!open_file->closePend)
-					return open_file;
-				else { /* start over in case this was deleted */
-				       /* since the list could be modified */
-					read_lock(&GlobalSMBSeslock);
-					cifsFileInfo_put(open_file);
-					goto refind_writable;
-				}
-			}
+			spin_unlock(&cifs_file_list_lock);
 
-			/* if it fails, try another handle if possible -
-			(we can not do this if closePending since
-			loop could be modified - in which case we
-			have to start at the beginning of the list
-			again. Note that it would be bad
-			to hold up writepages here (rather than
-			in caller) with continuous retries */
+			/* Had to unlock since following call can block */
+			rc = cifs_reopen_file(open_file, false);
+			if (!rc)
+				return open_file;
+
+			/* if it fails, try another handle if possible */
 			cFYI(1, "wp failed on reopen file");
-			read_lock(&GlobalSMBSeslock);
-			/* can not use this handle, no write
-			   pending on this one after all */
 			cifsFileInfo_put(open_file);
 
-			if (open_file->closePend) /* list could have changed */
-				goto refind_writable;
+			spin_lock(&cifs_file_list_lock);
+
 			/* else we simply continue to the next entry. Thus
 			   we do not loop on reopen errors.  If we
 			   can not reopen the file, for example if we
@@ -1272,7 +1240,7 @@
 		any_available = true;
 		goto refind_writable;
 	}
-	read_unlock(&GlobalSMBSeslock);
+	spin_unlock(&cifs_file_list_lock);
 	return NULL;
 }
 
@@ -1284,7 +1252,6 @@
 	int rc = -EFAULT;
 	int bytes_written = 0;
 	struct cifs_sb_info *cifs_sb;
-	struct cifsTconInfo *pTcon;
 	struct inode *inode;
 	struct cifsFileInfo *open_file;
 
@@ -1293,7 +1260,6 @@
 
 	inode = page->mapping->host;
 	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
 
 	offset += (loff_t)from;
 	write_data = kmap(page);
@@ -1314,10 +1280,10 @@
 	if (mapping->host->i_size - offset < (loff_t)to)
 		to = (unsigned)(mapping->host->i_size - offset);
 
-	open_file = find_writable_file(CIFS_I(mapping->host));
+	open_file = find_writable_file(CIFS_I(mapping->host), false);
 	if (open_file) {
-		bytes_written = cifs_write(open_file->pfile, write_data,
-					   to-from, &offset);
+		bytes_written = cifs_write(open_file, write_data,
+					   to - from, &offset);
 		cifsFileInfo_put(open_file);
 		/* Does mm or vfs already set times? */
 		inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
@@ -1352,6 +1318,7 @@
 	int nr_pages;
 	__u64 offset = 0;
 	struct cifsFileInfo *open_file;
+	struct cifsTconInfo *tcon;
 	struct cifsInodeInfo *cifsi = CIFS_I(mapping->host);
 	struct page *page;
 	struct pagevec pvec;
@@ -1359,6 +1326,15 @@
 	int scanned = 0;
 	int xid, long_op;
 
+	/*
+	 * BB: Is this meaningful for a non-block-device file system?
+	 * If it is, we should test it again after we do I/O
+	 */
+	if (wbc->nonblocking && bdi_write_congested(bdi)) {
+		wbc->encountered_congestion = 1;
+		return 0;
+	}
+
 	cifs_sb = CIFS_SB(mapping->host->i_sb);
 
 	/*
@@ -1368,27 +1344,29 @@
 	if (cifs_sb->wsize < PAGE_CACHE_SIZE)
 		return generic_writepages(mapping, wbc);
 
-	if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
-		if (cifs_sb->tcon->ses->server->secMode &
-				(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-			if (!experimEnabled)
-				return generic_writepages(mapping, wbc);
-
 	iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
 	if (iov == NULL)
 		return generic_writepages(mapping, wbc);
 
-
 	/*
-	 * BB: Is this meaningful for a non-block-device file system?
-	 * If it is, we should test it again after we do I/O
+	 * if there's no open file, then this is likely to fail too,
+	 * but it'll at least handle the return. Maybe it should be
+	 * a BUG() instead?
 	 */
-	if (wbc->nonblocking && bdi_write_congested(bdi)) {
-		wbc->encountered_congestion = 1;
+	open_file = find_writable_file(CIFS_I(mapping->host), false);
+	if (!open_file) {
 		kfree(iov);
-		return 0;
+		return generic_writepages(mapping, wbc);
 	}
 
+	tcon = tlink_tcon(open_file->tlink);
+	if (!experimEnabled && tcon->ses->server->secMode &
+			(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
+		cifsFileInfo_put(open_file);
+		return generic_writepages(mapping, wbc);
+	}
+	cifsFileInfo_put(open_file);
+
 	xid = GetXid();
 
 	pagevec_init(&pvec, 0);
@@ -1492,38 +1470,34 @@
 				break;
 		}
 		if (n_iov) {
-			/* Search for a writable handle every time we call
-			 * CIFSSMBWrite2.  We can't rely on the last handle
-			 * we used to still be valid
-			 */
-			open_file = find_writable_file(CIFS_I(mapping->host));
+			open_file = find_writable_file(CIFS_I(mapping->host),
+							false);
 			if (!open_file) {
 				cERROR(1, "No writable handles for inode");
 				rc = -EBADF;
 			} else {
 				long_op = cifs_write_timeout(cifsi, offset);
-				rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
-						   open_file->netfid,
+				rc = CIFSSMBWrite2(xid, tcon, open_file->netfid,
 						   bytes_to_write, offset,
 						   &bytes_written, iov, n_iov,
 						   long_op);
 				cifsFileInfo_put(open_file);
 				cifs_update_eof(cifsi, offset, bytes_written);
-
-				if (rc || bytes_written < bytes_to_write) {
-					cERROR(1, "Write2 ret %d, wrote %d",
-						  rc, bytes_written);
-					/* BB what if continued retry is
-					   requested via mount flags? */
-					if (rc == -ENOSPC)
-						set_bit(AS_ENOSPC, &mapping->flags);
-					else
-						set_bit(AS_EIO, &mapping->flags);
-				} else {
-					cifs_stats_bytes_written(cifs_sb->tcon,
-								 bytes_written);
-				}
 			}
+
+			if (rc || bytes_written < bytes_to_write) {
+				cERROR(1, "Write2 ret %d, wrote %d",
+					  rc, bytes_written);
+				/* BB what if continued retry is
+				   requested via mount flags? */
+				if (rc == -ENOSPC)
+					set_bit(AS_ENOSPC, &mapping->flags);
+				else
+					set_bit(AS_EIO, &mapping->flags);
+			} else {
+				cifs_stats_bytes_written(tcon, bytes_written);
+			}
+
 			for (i = 0; i < n_iov; i++) {
 				page = pvec.pages[first + i];
 				/* Should we also set page error on
@@ -1624,7 +1598,8 @@
 		/* BB check if anything else missing out of ppw
 		   such as updating last write time */
 		page_data = kmap(page);
-		rc = cifs_write(file, page_data + offset, copied, &pos);
+		rc = cifs_write(file->private_data, page_data + offset,
+				copied, &pos);
 		/* if (rc < 0) should we set writebehind rc? */
 		kunmap(page);
 
@@ -1665,7 +1640,7 @@
 	if (rc == 0) {
 		rc = CIFS_I(inode)->write_behind_rc;
 		CIFS_I(inode)->write_behind_rc = 0;
-		tcon = CIFS_SB(inode->i_sb)->tcon;
+		tcon = tlink_tcon(smbfile->tlink);
 		if (!rc && tcon && smbfile &&
 		   !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
 			rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
@@ -1750,7 +1725,6 @@
 
 	xid = GetXid();
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	pTcon = cifs_sb->tcon;
 
 	if (file->private_data == NULL) {
 		rc = -EBADF;
@@ -1758,6 +1732,7 @@
 		return rc;
 	}
 	open_file = file->private_data;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 		cFYI(1, "attempting read on write only file instance");
@@ -1771,9 +1746,8 @@
 		smb_read_data = NULL;
 		while (rc == -EAGAIN) {
 			int buf_type = CIFS_NO_BUFFER;
-			if ((open_file->invalidHandle) &&
-			    (!open_file->closePend)) {
-				rc = cifs_reopen_file(file, true);
+			if (open_file->invalidHandle) {
+				rc = cifs_reopen_file(open_file, true);
 				if (rc != 0)
 					break;
 			}
@@ -1831,7 +1805,6 @@
 
 	xid = GetXid();
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	pTcon = cifs_sb->tcon;
 
 	if (file->private_data == NULL) {
 		rc = -EBADF;
@@ -1839,6 +1812,7 @@
 		return rc;
 	}
 	open_file = file->private_data;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 		cFYI(1, "attempting read on write only file instance");
@@ -1857,9 +1831,8 @@
 		}
 		rc = -EAGAIN;
 		while (rc == -EAGAIN) {
-			if ((open_file->invalidHandle) &&
-			    (!open_file->closePend)) {
-				rc = cifs_reopen_file(file, true);
+			if (open_file->invalidHandle) {
+				rc = cifs_reopen_file(open_file, true);
 				if (rc != 0)
 					break;
 			}
@@ -1974,7 +1947,7 @@
 	}
 	open_file = file->private_data;
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	pTcon = cifs_sb->tcon;
+	pTcon = tlink_tcon(open_file->tlink);
 
 	/*
 	 * Reads as many pages as possible from fscache. Returns -ENOBUFS
@@ -2022,9 +1995,8 @@
 				read_size, contig_pages);
 		rc = -EAGAIN;
 		while (rc == -EAGAIN) {
-			if ((open_file->invalidHandle) &&
-			    (!open_file->closePend)) {
-				rc = cifs_reopen_file(file, true);
+			if (open_file->invalidHandle) {
+				rc = cifs_reopen_file(open_file, true);
 				if (rc != 0)
 					break;
 			}
@@ -2173,18 +2145,14 @@
 {
 	struct cifsFileInfo *open_file;
 
-	read_lock(&GlobalSMBSeslock);
+	spin_lock(&cifs_file_list_lock);
 	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
-		if (open_file->closePend)
-			continue;
-		if (open_file->pfile &&
-		    ((open_file->pfile->f_flags & O_RDWR) ||
-		     (open_file->pfile->f_flags & O_WRONLY))) {
-			read_unlock(&GlobalSMBSeslock);
+		if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
+			spin_unlock(&cifs_file_list_lock);
 			return 1;
 		}
 	}
-	read_unlock(&GlobalSMBSeslock);
+	spin_unlock(&cifs_file_list_lock);
 	return 0;
 }
 
@@ -2310,9 +2278,8 @@
 {
 	struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
 						  oplock_break);
-	struct inode *inode = cfile->pInode;
+	struct inode *inode = cfile->dentry->d_inode;
 	struct cifsInodeInfo *cinode = CIFS_I(inode);
-	struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->mnt->mnt_sb);
 	int rc, waitrc = 0;
 
 	if (inode && S_ISREG(inode->i_mode)) {
@@ -2338,9 +2305,9 @@
 	 * not bother sending an oplock release if session to server still is
 	 * disconnected since oplock already released by the server
 	 */
-	if (!cfile->closePend && !cfile->oplock_break_cancelled) {
-		rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0,
-				 LOCKING_ANDX_OPLOCK_RELEASE, false);
+	if (!cfile->oplock_break_cancelled) {
+		rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0,
+				 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false);
 		cFYI(1, "Oplock release rc = %d", rc);
 	}
 
@@ -2349,22 +2316,22 @@
 	 * finished grabbing reference for us.  Make sure it's done by
 	 * waiting for GlobalSMSSeslock.
 	 */
-	write_lock(&GlobalSMBSeslock);
-	write_unlock(&GlobalSMBSeslock);
+	spin_lock(&cifs_file_list_lock);
+	spin_unlock(&cifs_file_list_lock);
 
 	cifs_oplock_break_put(cfile);
 }
 
 void cifs_oplock_break_get(struct cifsFileInfo *cfile)
 {
-	mntget(cfile->mnt);
+	cifs_sb_active(cfile->dentry->d_sb);
 	cifsFileInfo_get(cfile);
 }
 
 void cifs_oplock_break_put(struct cifsFileInfo *cfile)
 {
-	mntput(cfile->mnt);
 	cifsFileInfo_put(cfile);
+	cifs_sb_deactive(cfile->dentry->d_sb);
 }
 
 const struct address_space_operations cifs_addr_ops = {
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 9f3f5c4..a2ad94e 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -62,15 +62,15 @@
 {
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
 	if (cifsi->fscache)
 		return;
 
-	cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
-				&cifs_fscache_inode_object_def,
-				cifsi);
-	cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)",
-			cifs_sb->tcon->fscache, cifsi->fscache);
+	cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
+				&cifs_fscache_inode_object_def, cifsi);
+	cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache,
+				cifsi->fscache);
 }
 
 void cifs_fscache_release_inode_cookie(struct inode *inode)
@@ -117,7 +117,8 @@
 		/* retire the current fscache cache and get a new one */
 		fscache_relinquish_cookie(cifsi->fscache, 1);
 
-		cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
+		cifsi->fscache = fscache_acquire_cookie(
+					cifs_sb_master_tcon(cifs_sb)->fscache,
 					&cifs_fscache_inode_object_def,
 					cifsi);
 		cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p",
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 53cce8c..9497930 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -52,7 +52,7 @@
 
 
 		/* check if server can support readpages */
-		if (cifs_sb->tcon->ses->server->maxBuf <
+		if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
 				PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
 			inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
 		else
@@ -288,8 +288,8 @@
 	struct cifs_fattr fattr;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
 	struct cifsFileInfo *cfile = filp->private_data;
+	struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink);
 
 	xid = GetXid();
 	rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -313,15 +313,21 @@
 	FILE_UNIX_BASIC_INFO find_data;
 	struct cifs_fattr fattr;
 	struct cifsTconInfo *tcon;
+	struct tcon_link *tlink;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
-	tcon = cifs_sb->tcon;
 	cFYI(1, "Getting info on %s", full_path);
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
 	/* could have done a find first instead but this returns more info */
 	rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
 				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
+	cifs_put_tlink(tlink);
 
 	if (!rc) {
 		cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
@@ -332,6 +338,13 @@
 		return rc;
 	}
 
+	/* check for Minshall+French symlinks */
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
+		int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+		if (tmprc)
+			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
+	}
+
 	if (*pinode == NULL) {
 		/* get new inode */
 		cifs_fill_uniqueid(sb, &fattr);
@@ -353,7 +366,8 @@
 	int rc;
 	int oplock = 0;
 	__u16 netfid;
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
 	char buf[24];
 	unsigned int bytes_read;
 	char *pbuf;
@@ -372,7 +386,12 @@
 		return -EINVAL;	 /* EOPNOTSUPP? */
 	}
 
-	rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
+	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ,
 			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
 			 cifs_sb->local_nls,
 			 cifs_sb->mnt_cifs_flags &
@@ -380,7 +399,7 @@
 	if (rc == 0) {
 		int buf_type = CIFS_NO_BUFFER;
 			/* Read header */
-		rc = CIFSSMBRead(xid, pTcon, netfid,
+		rc = CIFSSMBRead(xid, tcon, netfid,
 				 24 /* length */, 0 /* offset */,
 				 &bytes_read, &pbuf, &buf_type);
 		if ((rc == 0) && (bytes_read >= 8)) {
@@ -422,8 +441,9 @@
 			fattr->cf_dtype = DT_REG;
 			rc = -EOPNOTSUPP; /* or some unknown SFU type */
 		}
-		CIFSSMBClose(xid, pTcon, netfid);
+		CIFSSMBClose(xid, tcon, netfid);
 	}
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -441,11 +461,19 @@
 	ssize_t rc;
 	char ea_value[4];
 	__u32 mode;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
 
-	rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
+	rc = CIFSSMBQAllEAs(xid, tcon, path, "SETFILEBITS",
 			    ea_value, 4 /* size of buf */, cifs_sb->local_nls,
 			    cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
+	cifs_put_tlink(tlink);
 	if (rc < 0)
 		return (int)rc;
 	else if (rc > 3) {
@@ -468,6 +496,8 @@
 cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
 		       struct cifs_sb_info *cifs_sb, bool adjust_tz)
 {
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
+
 	memset(fattr, 0, sizeof(*fattr));
 	fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
 	if (info->DeletePending)
@@ -482,8 +512,8 @@
 	fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
 
 	if (adjust_tz) {
-		fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
-		fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
+		fattr->cf_ctime.tv_sec += tcon->ses->server->timeAdj;
+		fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj;
 	}
 
 	fattr->cf_eof = le64_to_cpu(info->EndOfFile);
@@ -515,8 +545,8 @@
 	struct cifs_fattr fattr;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
 	struct cifsFileInfo *cfile = filp->private_data;
+	struct cifsTconInfo *tcon = tlink_tcon(cfile->tlink);
 
 	xid = GetXid();
 	rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
@@ -554,26 +584,33 @@
 {
 	int rc = 0, tmprc;
 	struct cifsTconInfo *pTcon;
+	struct tcon_link *tlink;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 	char *buf = NULL;
 	bool adjustTZ = false;
 	struct cifs_fattr fattr;
 
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
 	cFYI(1, "Getting info on %s", full_path);
 
 	if ((pfindData == NULL) && (*pinode != NULL)) {
 		if (CIFS_I(*pinode)->clientCanCacheRead) {
 			cFYI(1, "No need to revalidate cached inode sizes");
-			return rc;
+			goto cgii_exit;
 		}
 	}
 
 	/* if file info not passed in then get it from server */
 	if (pfindData == NULL) {
 		buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
+		if (buf == NULL) {
+			rc = -ENOMEM;
+			goto cgii_exit;
+		}
 		pfindData = (FILE_ALL_INFO *)buf;
 
 		/* could do find first instead but this returns more info */
@@ -661,6 +698,13 @@
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
 		cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
 
+	/* check for Minshall+French symlinks */
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
+		tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+		if (tmprc)
+			cFYI(1, "CIFSCheckMFSymlink: %d", tmprc);
+	}
+
 	if (!*pinode) {
 		*pinode = cifs_iget(sb, &fattr);
 		if (!*pinode)
@@ -671,6 +715,7 @@
 
 cgii_exit:
 	kfree(buf);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -683,6 +728,7 @@
 	int pplen = cifs_sb->prepathlen;
 	int dfsplen;
 	char *full_path = NULL;
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
 	/* if no prefix path, simply set path to the root of share to "" */
 	if (pplen == 0) {
@@ -692,8 +738,8 @@
 		return full_path;
 	}
 
-	if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
-		dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
+	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
+		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
 	else
 		dfsplen = 0;
 
@@ -702,7 +748,7 @@
 		return full_path;
 
 	if (dfsplen) {
-		strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
+		strncpy(full_path, tcon->treeName, dfsplen);
 		/* switch slash direction in prepath depending on whether
 		 * windows or posix style path names
 		 */
@@ -818,18 +864,18 @@
 struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
 {
 	int xid;
-	struct cifs_sb_info *cifs_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 	struct inode *inode = NULL;
 	long rc;
 	char *full_path;
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
-	cifs_sb = CIFS_SB(sb);
 	full_path = cifs_build_path_to_root(cifs_sb);
 	if (full_path == NULL)
 		return ERR_PTR(-ENOMEM);
 
 	xid = GetXid();
-	if (cifs_sb->tcon->unix_ext)
+	if (tcon->unix_ext)
 		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
 	else
 		rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
@@ -840,10 +886,10 @@
 
 #ifdef CONFIG_CIFS_FSCACHE
 	/* populate tcon->resource_id */
-	cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid;
+	tcon->resource_id = CIFS_I(inode)->uniqueid;
 #endif
 
-	if (rc && cifs_sb->tcon->ipc) {
+	if (rc && tcon->ipc) {
 		cFYI(1, "ipc connection - fake read inode");
 		inode->i_mode |= S_IFDIR;
 		inode->i_nlink = 2;
@@ -879,7 +925,8 @@
 	struct cifsFileInfo *open_file;
 	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink = NULL;
+	struct cifsTconInfo *pTcon;
 	FILE_BASIC_INFO	info_buf;
 
 	if (attrs == NULL)
@@ -918,13 +965,22 @@
 	/*
 	 * If the file is already open for write, just use that fileid
 	 */
-	open_file = find_writable_file(cifsInode);
+	open_file = find_writable_file(cifsInode, true);
 	if (open_file) {
 		netfid = open_file->netfid;
 		netpid = open_file->pid;
+		pTcon = tlink_tcon(open_file->tlink);
 		goto set_via_filehandle;
 	}
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		tlink = NULL;
+		goto out;
+	}
+	pTcon = tlink_tcon(tlink);
+
 	/*
 	 * NT4 apparently returns success on this call, but it doesn't
 	 * really work.
@@ -968,6 +1024,8 @@
 	else
 		cifsFileInfo_put(open_file);
 out:
+	if (tlink != NULL)
+		cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -985,10 +1043,16 @@
 	struct inode *inode = dentry->d_inode;
 	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
 	__u32 dosattr, origattr;
 	FILE_BASIC_INFO *info_buf = NULL;
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
 	rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
 			 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
 			 &netfid, &oplock, NULL, cifs_sb->local_nls,
@@ -1057,6 +1121,7 @@
 	CIFSSMBClose(xid, tcon, netfid);
 out:
 	kfree(info_buf);
+	cifs_put_tlink(tlink);
 	return rc;
 
 	/*
@@ -1096,12 +1161,18 @@
 	struct cifsInodeInfo *cifs_inode;
 	struct super_block *sb = dir->i_sb;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *tcon;
 	struct iattr *attrs = NULL;
 	__u32 dosattr = 0, origattr = 0;
 
 	cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
+
 	xid = GetXid();
 
 	/* Unlink can be called from rename so we can not take the
@@ -1109,8 +1180,7 @@
 	full_path = build_path_from_dentry(dentry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto unlink_out;
 	}
 
 	if ((tcon->ses->capabilities & CAP_UNIX) &&
@@ -1176,10 +1246,11 @@
 	dir->i_ctime = dir->i_mtime = current_fs_time(sb);
 	cifs_inode = CIFS_I(dir);
 	CIFS_I(dir)->time = 0;	/* force revalidate of dir as well */
-
+unlink_out:
 	kfree(full_path);
 	kfree(attrs);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -1188,6 +1259,7 @@
 	int rc = 0, tmprc;
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	struct inode *newinode = NULL;
@@ -1195,16 +1267,18 @@
 
 	cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode);
 
-	xid = GetXid();
-
 	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto mkdir_out;
 	}
 
 	if ((pTcon->ses->capabilities & CAP_UNIX) &&
@@ -1362,6 +1436,7 @@
 mkdir_out:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -1370,6 +1445,7 @@
 	int rc = 0;
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	struct cifsInodeInfo *cifsInode;
@@ -1378,18 +1454,23 @@
 
 	xid = GetXid();
 
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
-
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto rmdir_exit;
 	}
 
+	cifs_sb = CIFS_SB(inode->i_sb);
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		goto rmdir_exit;
+	}
+	pTcon = tlink_tcon(tlink);
+
 	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
 			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+	cifs_put_tlink(tlink);
 
 	if (!rc) {
 		drop_nlink(inode);
@@ -1410,6 +1491,7 @@
 	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
 		current_fs_time(inode->i_sb);
 
+rmdir_exit:
 	kfree(full_path);
 	FreeXid(xid);
 	return rc;
@@ -1420,10 +1502,16 @@
 		struct dentry *to_dentry, const char *toPath)
 {
 	struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *pTcon;
 	__u16 srcfid;
 	int oplock, rc;
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
 	/* try path-based rename first */
 	rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
 			   cifs_sb->mnt_cifs_flags &
@@ -1435,11 +1523,11 @@
 	 * rename by filehandle to various Windows servers.
 	 */
 	if (rc == 0 || rc != -ETXTBSY)
-		return rc;
+		goto do_rename_exit;
 
 	/* open-file renames don't work across directories */
 	if (to_dentry->d_parent != from_dentry->d_parent)
-		return rc;
+		goto do_rename_exit;
 
 	/* open the file to be renamed -- we need DELETE perms */
 	rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
@@ -1455,7 +1543,8 @@
 
 		CIFSSMBClose(xid, pTcon, srcfid);
 	}
-
+do_rename_exit:
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -1465,13 +1554,17 @@
 	char *fromName = NULL;
 	char *toName = NULL;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *tcon;
 	FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
 	FILE_UNIX_BASIC_INFO *info_buf_target;
 	int xid, rc, tmprc;
 
 	cifs_sb = CIFS_SB(source_dir->i_sb);
-	tcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	tcon = tlink_tcon(tlink);
 
 	xid = GetXid();
 
@@ -1547,6 +1640,7 @@
 	kfree(fromName);
 	kfree(toName);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -1599,11 +1693,12 @@
 {
 	int rc = 0;
 	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
 
 	if (!cifs_inode_needs_reval(inode))
 		goto check_inval;
 
-	if (CIFS_SB(inode->i_sb)->tcon->unix_ext)
+	if (tlink_tcon(cfile->tlink)->unix_ext)
 		rc = cifs_get_file_info_unix(filp);
 	else
 		rc = cifs_get_file_info(filp);
@@ -1644,7 +1739,7 @@
 		 "jiffies %ld", full_path, inode, inode->i_count.counter,
 		 dentry, dentry->d_time, jiffies);
 
-	if (CIFS_SB(sb)->tcon->unix_ext)
+	if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
 		rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
 	else
 		rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
@@ -1660,13 +1755,29 @@
 }
 
 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
-	struct kstat *stat)
+		 struct kstat *stat)
 {
+	struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
+	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 	int err = cifs_revalidate_dentry(dentry);
+
 	if (!err) {
 		generic_fillattr(dentry->d_inode, stat);
 		stat->blksize = CIFS_MAX_MSGSIZE;
 		stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
+
+		/*
+		 * If on a multiuser mount without unix extensions, and the
+		 * admin hasn't overridden them, set the ownership to the
+		 * fsuid/fsgid of the current process.
+		 */
+		if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
+		    !tcon->unix_ext) {
+			if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
+				stat->uid = current_fsuid();
+			if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
+				stat->gid = current_fsgid();
+		}
 	}
 	return err;
 }
@@ -1708,7 +1819,8 @@
 	struct cifsFileInfo *open_file;
 	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink = NULL;
+	struct cifsTconInfo *pTcon = NULL;
 
 	/*
 	 * To avoid spurious oplock breaks from server, in the case of
@@ -1719,10 +1831,11 @@
 	 * writebehind data than the SMB timeout for the SetPathInfo
 	 * request would allow
 	 */
-	open_file = find_writable_file(cifsInode);
+	open_file = find_writable_file(cifsInode, true);
 	if (open_file) {
 		__u16 nfid = open_file->netfid;
 		__u32 npid = open_file->pid;
+		pTcon = tlink_tcon(open_file->tlink);
 		rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
 					npid, false);
 		cifsFileInfo_put(open_file);
@@ -1737,6 +1850,13 @@
 		rc = -EINVAL;
 
 	if (rc != 0) {
+		if (pTcon == NULL) {
+			tlink = cifs_sb_tlink(cifs_sb);
+			if (IS_ERR(tlink))
+				return PTR_ERR(tlink);
+			pTcon = tlink_tcon(tlink);
+		}
+
 		/* Set file size by pathname rather than by handle
 		   either because no valid, writeable file handle for
 		   it was found or because there was an error setting
@@ -1766,6 +1886,8 @@
 				CIFSSMBClose(xid, pTcon, netfid);
 			}
 		}
+		if (tlink)
+			cifs_put_tlink(tlink);
 	}
 
 	if (rc == 0) {
@@ -1786,7 +1908,8 @@
 	struct inode *inode = direntry->d_inode;
 	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *pTcon;
 	struct cifs_unix_set_info_args *args = NULL;
 	struct cifsFileInfo *open_file;
 
@@ -1873,17 +1996,25 @@
 		args->ctime = NO_CHANGE_64;
 
 	args->device = 0;
-	open_file = find_writable_file(cifsInode);
+	open_file = find_writable_file(cifsInode, true);
 	if (open_file) {
 		u16 nfid = open_file->netfid;
 		u32 npid = open_file->pid;
+		pTcon = tlink_tcon(open_file->tlink);
 		rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
 		cifsFileInfo_put(open_file);
 	} else {
+		tlink = cifs_sb_tlink(cifs_sb);
+		if (IS_ERR(tlink)) {
+			rc = PTR_ERR(tlink);
+			goto out;
+		}
+		pTcon = tlink_tcon(tlink);
 		rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
 				    cifs_sb->local_nls,
 				    cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
+		cifs_put_tlink(tlink);
 	}
 
 	if (rc)
@@ -2064,7 +2195,7 @@
 {
 	struct inode *inode = direntry->d_inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *pTcon = cifs_sb->tcon;
+	struct cifsTconInfo *pTcon = cifs_sb_master_tcon(cifs_sb);
 
 	if (pTcon->unix_ext)
 		return cifs_setattr_unix(direntry, attrs);
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 9d38a71..077bf75 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -37,11 +37,11 @@
 	int xid;
 	struct cifs_sb_info *cifs_sb;
 #ifdef CONFIG_CIFS_POSIX
+	struct cifsFileInfo *pSMBFile = filep->private_data;
+	struct cifsTconInfo *tcon = tlink_tcon(pSMBFile->tlink);
 	__u64	ExtAttrBits = 0;
 	__u64	ExtAttrMask = 0;
-	__u64   caps;
-	struct cifsTconInfo *tcon;
-	struct cifsFileInfo *pSMBFile = filep->private_data;
+	__u64   caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
 #endif /* CONFIG_CIFS_POSIX */
 
 	xid = GetXid();
@@ -50,17 +50,6 @@
 
 	cifs_sb = CIFS_SB(inode->i_sb);
 
-#ifdef CONFIG_CIFS_POSIX
-	tcon = cifs_sb->tcon;
-	if (tcon)
-		caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
-	else {
-		rc = -EIO;
-		FreeXid(xid);
-		return -EIO;
-	}
-#endif /* CONFIG_CIFS_POSIX */
-
 	switch (command) {
 		case CIFS_IOC_CHECKUMOUNT:
 			cFYI(1, "User unmount attempted");
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 473ca80..85cdbf8 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -28,6 +28,296 @@
 #include "cifsproto.h"
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
+#include "md5.h"
+
+#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
+#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
+#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
+#define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
+#define CIFS_MF_SYMLINK_FILE_SIZE \
+	(CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
+
+#define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
+#define CIFS_MF_SYMLINK_MD5_FORMAT \
+	"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
+#define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) \
+	md5_hash[0],  md5_hash[1],  md5_hash[2],  md5_hash[3], \
+	md5_hash[4],  md5_hash[5],  md5_hash[6],  md5_hash[7], \
+	md5_hash[8],  md5_hash[9],  md5_hash[10], md5_hash[11],\
+	md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15]
+
+static int
+CIFSParseMFSymlink(const u8 *buf,
+		   unsigned int buf_len,
+		   unsigned int *_link_len,
+		   char **_link_str)
+{
+	int rc;
+	unsigned int link_len;
+	const char *md5_str1;
+	const char *link_str;
+	struct MD5Context md5_ctx;
+	u8 md5_hash[16];
+	char md5_str2[34];
+
+	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EINVAL;
+
+	md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
+	link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
+
+	rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
+	if (rc != 1)
+		return -EINVAL;
+
+	cifs_MD5_init(&md5_ctx);
+	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len);
+	cifs_MD5_final(md5_hash, &md5_ctx);
+
+	snprintf(md5_str2, sizeof(md5_str2),
+		 CIFS_MF_SYMLINK_MD5_FORMAT,
+		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+	if (strncmp(md5_str1, md5_str2, 17) != 0)
+		return -EINVAL;
+
+	if (_link_str) {
+		*_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
+		if (!*_link_str)
+			return -ENOMEM;
+	}
+
+	*_link_len = link_len;
+	return 0;
+}
+
+static int
+CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
+{
+	unsigned int link_len;
+	unsigned int ofs;
+	struct MD5Context md5_ctx;
+	u8 md5_hash[16];
+
+	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EINVAL;
+
+	link_len = strlen(link_str);
+
+	if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
+		return -ENAMETOOLONG;
+
+	cifs_MD5_init(&md5_ctx);
+	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len);
+	cifs_MD5_final(md5_hash, &md5_ctx);
+
+	snprintf(buf, buf_len,
+		 CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
+		 link_len,
+		 CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
+
+	ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
+	memcpy(buf + ofs, link_str, link_len);
+
+	ofs += link_len;
+	if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+		buf[ofs] = '\n';
+		ofs++;
+	}
+
+	while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
+		buf[ofs] = ' ';
+		ofs++;
+	}
+
+	return 0;
+}
+
+static int
+CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
+		    const char *fromName, const char *toName,
+		    const struct nls_table *nls_codepage, int remap)
+{
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	u8 *buf;
+	unsigned int bytes_written = 0;
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
+			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
+			 nls_codepage, remap);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSSMBWrite(xid, tcon, netfid,
+			  CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			  0 /* offset */,
+			  &bytes_written, buf, NULL, 0);
+	CIFSSMBClose(xid, tcon, netfid);
+	kfree(buf);
+	if (rc != 0)
+		return rc;
+
+	if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
+		return -EIO;
+
+	return 0;
+}
+
+static int
+CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
+		   const unsigned char *searchName, char **symlinkinfo,
+		   const struct nls_table *nls_codepage, int remap)
+{
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	u8 *buf;
+	char *pbuf;
+	unsigned int bytes_read = 0;
+	int buf_type = CIFS_NO_BUFFER;
+	unsigned int link_len = 0;
+	FILE_ALL_INFO file_info;
+
+	rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
+			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
+			 nls_codepage, remap);
+	if (rc != 0)
+		return rc;
+
+	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+		CIFSSMBClose(xid, tcon, netfid);
+		/* it's not a symlink */
+		return -EINVAL;
+	}
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	pbuf = buf;
+
+	rc = CIFSSMBRead(xid, tcon, netfid,
+			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			 0 /* offset */,
+			 &bytes_read, &pbuf, &buf_type);
+	CIFSSMBClose(xid, tcon, netfid);
+	if (rc != 0) {
+		kfree(buf);
+		return rc;
+	}
+
+	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo);
+	kfree(buf);
+	if (rc != 0)
+		return rc;
+
+	return 0;
+}
+
+bool
+CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
+{
+	if (!(fattr->cf_mode & S_IFREG))
+		/* it's not a symlink */
+		return false;
+
+	if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
+		/* it's not a symlink */
+		return false;
+
+	return true;
+}
+
+int
+CIFSCheckMFSymlink(struct cifs_fattr *fattr,
+		   const unsigned char *path,
+		   struct cifs_sb_info *cifs_sb, int xid)
+{
+	int rc;
+	int oplock = 0;
+	__u16 netfid = 0;
+	struct tcon_link *tlink;
+	struct cifsTconInfo *pTcon;
+	u8 *buf;
+	char *pbuf;
+	unsigned int bytes_read = 0;
+	int buf_type = CIFS_NO_BUFFER;
+	unsigned int link_len = 0;
+	FILE_ALL_INFO file_info;
+
+	if (!CIFSCouldBeMFSymlink(fattr))
+		/* it's not a symlink */
+		return 0;
+
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
+			 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
+			 cifs_sb->local_nls,
+			 cifs_sb->mnt_cifs_flags &
+				CIFS_MOUNT_MAP_SPECIAL_CHR);
+	if (rc != 0)
+		goto out;
+
+	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+		CIFSSMBClose(xid, pTcon, netfid);
+		/* it's not a symlink */
+		goto out;
+	}
+
+	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
+	if (!buf) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	pbuf = buf;
+
+	rc = CIFSSMBRead(xid, pTcon, netfid,
+			 CIFS_MF_SYMLINK_FILE_SIZE /* length */,
+			 0 /* offset */,
+			 &bytes_read, &pbuf, &buf_type);
+	CIFSSMBClose(xid, pTcon, netfid);
+	if (rc != 0) {
+		kfree(buf);
+		goto out;
+	}
+
+	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL);
+	kfree(buf);
+	if (rc == -EINVAL) {
+		/* it's not a symlink */
+		rc = 0;
+		goto out;
+	}
+
+	if (rc != 0)
+		goto out;
+
+	/* it is a symlink */
+	fattr->cf_eof = link_len;
+	fattr->cf_mode &= ~S_IFMT;
+	fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
+	fattr->cf_dtype = DT_LNK;
+out:
+	cifs_put_tlink(tlink);
+	return rc;
+}
 
 int
 cifs_hardlink(struct dentry *old_file, struct inode *inode,
@@ -37,18 +327,18 @@
 	int xid;
 	char *fromName = NULL;
 	char *toName = NULL;
-	struct cifs_sb_info *cifs_sb_target;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct cifsInodeInfo *cifsInode;
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
 	xid = GetXid();
 
-	cifs_sb_target = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb_target->tcon;
-
-/* No need to check for cross device links since server will do that
-   BB note DFS case in future though (when we may have to check) */
-
 	fromName = build_path_from_dentry(old_file);
 	toName = build_path_from_dentry(direntry);
 	if ((fromName == NULL) || (toName == NULL)) {
@@ -56,16 +346,15 @@
 		goto cifs_hl_exit;
 	}
 
-/*	if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
 	if (pTcon->unix_ext)
 		rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
-					    cifs_sb_target->local_nls,
-					    cifs_sb_target->mnt_cifs_flags &
+					    cifs_sb->local_nls,
+					    cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 	else {
 		rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
-					cifs_sb_target->local_nls,
-					cifs_sb_target->mnt_cifs_flags &
+					cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 		if ((rc == -EIO) || (rc == -EINVAL))
 			rc = -EOPNOTSUPP;
@@ -101,6 +390,7 @@
 	kfree(fromName);
 	kfree(toName);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -113,10 +403,19 @@
 	char *full_path = NULL;
 	char *target_path = NULL;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-	struct cifsTconInfo *tcon = cifs_sb->tcon;
+	struct tcon_link *tlink = NULL;
+	struct cifsTconInfo *tcon;
 
 	xid = GetXid();
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		tlink = NULL;
+		goto out;
+	}
+	tcon = tlink_tcon(tlink);
+
 	/*
 	 * For now, we just handle symlinks with unix extensions enabled.
 	 * Eventually we should handle NTFS reparse points, and MacOS
@@ -130,7 +429,8 @@
 	 * but there doesn't seem to be any harm in allowing the client to
 	 * read them.
 	 */
-	if (!(tcon->ses->capabilities & CAP_UNIX)) {
+	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+	    && !(tcon->ses->capabilities & CAP_UNIX)) {
 		rc = -EACCES;
 		goto out;
 	}
@@ -141,8 +441,21 @@
 
 	cFYI(1, "Full path: %s inode = 0x%p", full_path, inode);
 
-	rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
-				     cifs_sb->local_nls);
+	rc = -EACCES;
+	/*
+	 * First try Minshall+French Symlinks, if configured
+	 * and fallback to UNIX Extensions Symlinks.
+	 */
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path,
+					cifs_sb->local_nls,
+					cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
+
+	if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX))
+		rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
+					     cifs_sb->local_nls);
+
 	kfree(full_path);
 out:
 	if (rc != 0) {
@@ -151,6 +464,8 @@
 	}
 
 	FreeXid(xid);
+	if (tlink)
+		cifs_put_tlink(tlink);
 	nd_set_link(nd, target_path);
 	return NULL;
 }
@@ -160,29 +475,37 @@
 {
 	int rc = -EOPNOTSUPP;
 	int xid;
-	struct cifs_sb_info *cifs_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	char *full_path = NULL;
 	struct inode *newinode = NULL;
 
 	xid = GetXid();
 
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink)) {
+		rc = PTR_ERR(tlink);
+		goto symlink_exit;
+	}
+	pTcon = tlink_tcon(tlink);
 
 	full_path = build_path_from_dentry(direntry);
-
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto symlink_exit;
 	}
 
 	cFYI(1, "Full path: %s", full_path);
 	cFYI(1, "symname is %s", symname);
 
 	/* BB what if DFS and this volume is on different share? BB */
-	if (pTcon->unix_ext)
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
+		rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname,
+					 cifs_sb->local_nls,
+					 cifs_sb->mnt_cifs_flags &
+						CIFS_MOUNT_MAP_SPECIAL_CHR);
+	else if (pTcon->unix_ext)
 		rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
 					   cifs_sb->local_nls);
 	/* else
@@ -208,8 +531,9 @@
 			d_instantiate(direntry, newinode);
 		}
 	}
-
+symlink_exit:
 	kfree(full_path);
+	cifs_put_tlink(tlink);
 	FreeXid(xid);
 	return rc;
 }
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 3ccadc1..1c681f6 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -347,7 +347,7 @@
 				if (current_fsuid() != treeCon->ses->linux_uid) {
 					cFYI(1, "Multiuser mode and UID "
 						 "did not match tcon uid");
-					read_lock(&cifs_tcp_ses_lock);
+					spin_lock(&cifs_tcp_ses_lock);
 					list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
 						ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
 						if (ses->linux_uid == current_fsuid()) {
@@ -361,7 +361,7 @@
 							}
 						}
 					}
-					read_unlock(&cifs_tcp_ses_lock);
+					spin_unlock(&cifs_tcp_ses_lock);
 				}
 			}
 		}
@@ -551,7 +551,7 @@
 		return false;
 
 	/* look up tcon based on tid & uid */
-	read_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &srv->smb_ses_list) {
 		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
 		list_for_each(tmp1, &ses->tcon_list) {
@@ -560,25 +560,15 @@
 				continue;
 
 			cifs_stats_inc(&tcon->num_oplock_brks);
-			read_lock(&GlobalSMBSeslock);
+			spin_lock(&cifs_file_list_lock);
 			list_for_each(tmp2, &tcon->openFileList) {
 				netfile = list_entry(tmp2, struct cifsFileInfo,
 						     tlist);
 				if (pSMB->Fid != netfile->netfid)
 					continue;
 
-				/*
-				 * don't do anything if file is about to be
-				 * closed anyway.
-				 */
-				if (netfile->closePend) {
-					read_unlock(&GlobalSMBSeslock);
-					read_unlock(&cifs_tcp_ses_lock);
-					return true;
-				}
-
 				cFYI(1, "file id match, oplock break");
-				pCifsInode = CIFS_I(netfile->pInode);
+				pCifsInode = CIFS_I(netfile->dentry->d_inode);
 				pCifsInode->clientCanCacheAll = false;
 				if (pSMB->OplockLevel == 0)
 					pCifsInode->clientCanCacheRead = false;
@@ -594,17 +584,17 @@
 					cifs_oplock_break_get(netfile);
 				netfile->oplock_break_cancelled = false;
 
-				read_unlock(&GlobalSMBSeslock);
-				read_unlock(&cifs_tcp_ses_lock);
+				spin_unlock(&cifs_file_list_lock);
+				spin_unlock(&cifs_tcp_ses_lock);
 				return true;
 			}
-			read_unlock(&GlobalSMBSeslock);
-			read_unlock(&cifs_tcp_ses_lock);
+			spin_unlock(&cifs_file_list_lock);
+			spin_unlock(&cifs_tcp_ses_lock);
 			cFYI(1, "No matching file for oplock break");
 			return true;
 		}
 	}
-	read_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 	cFYI(1, "Can not process oplock break for non-existent connection");
 	return true;
 }
@@ -729,6 +719,6 @@
 			   "properly. Hardlinks will not be recognized on this "
 			   "mount. Consider mounting with the \"noserverino\" "
 			   "option to silence this message.",
-			   cifs_sb->tcon->treeName);
+			   cifs_sb_master_tcon(cifs_sb)->treeName);
 	}
 }
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 49c9a4e..5d52e4a 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -61,6 +61,21 @@
 #define NTLMSSP_NEGOTIATE_KEY_XCH   0x40000000
 #define NTLMSSP_NEGOTIATE_56        0x80000000
 
+/* Define AV Pair Field IDs */
+enum av_field_type {
+	NTLMSSP_AV_EOL = 0,
+	NTLMSSP_AV_NB_COMPUTER_NAME,
+	NTLMSSP_AV_NB_DOMAIN_NAME,
+	NTLMSSP_AV_DNS_COMPUTER_NAME,
+	NTLMSSP_AV_DNS_DOMAIN_NAME,
+	NTLMSSP_AV_DNS_TREE_NAME,
+	NTLMSSP_AV_FLAGS,
+	NTLMSSP_AV_TIMESTAMP,
+	NTLMSSP_AV_RESTRICTION,
+	NTLMSSP_AV_TARGET_NAME,
+	NTLMSSP_AV_CHANNEL_BINDINGS
+};
+
 /* Although typedefs are not commonly used for structure definitions */
 /* in the Linux kernel, in this particular case they are useful      */
 /* to more closely match the standards document for NTLMSSP from     */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index d5e591f..ef7bb7b 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -102,7 +102,7 @@
 		return NULL;
 	}
 
-	if (CIFS_SB(sb)->tcon->nocase)
+	if (cifs_sb_master_tcon(CIFS_SB(sb))->nocase)
 		dentry->d_op = &cifs_ci_dentry_ops;
 	else
 		dentry->d_op = &cifs_dentry_ops;
@@ -171,7 +171,7 @@
 cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
 		       struct cifs_sb_info *cifs_sb)
 {
-	int offset = cifs_sb->tcon->ses->server->timeAdj;
+	int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj;
 
 	memset(fattr, 0, sizeof(*fattr));
 	fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
@@ -199,7 +199,7 @@
 	int len;
 	int oplock = 0;
 	int rc;
-	struct cifsTconInfo *ptcon = cifs_sb->tcon;
+	struct cifsTconInfo *ptcon = cifs_sb_tcon(cifs_sb);
 	char *tmpbuffer;
 
 	rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
@@ -223,34 +223,35 @@
 static int initiate_cifs_search(const int xid, struct file *file)
 {
 	int rc = 0;
-	char *full_path;
+	char *full_path = NULL;
 	struct cifsFileInfo *cifsFile;
-	struct cifs_sb_info *cifs_sb;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 
-	if (file->private_data == NULL) {
-		file->private_data =
-			kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
-	}
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
 
 	if (file->private_data == NULL)
-		return -ENOMEM;
+		file->private_data =
+			kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+	if (file->private_data == NULL) {
+		rc = -ENOMEM;
+		goto error_exit;
+	}
+
 	cifsFile = file->private_data;
 	cifsFile->invalidHandle = true;
 	cifsFile->srch_inf.endOfSearch = false;
-
-	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	if (cifs_sb == NULL)
-		return -EINVAL;
-
-	pTcon = cifs_sb->tcon;
-	if (pTcon == NULL)
-		return -EINVAL;
+	cifsFile->tlink = cifs_get_tlink(tlink);
 
 	full_path = build_path_from_dentry(file->f_path.dentry);
-
-	if (full_path == NULL)
-		return -ENOMEM;
+	if (full_path == NULL) {
+		rc = -ENOMEM;
+		goto error_exit;
+	}
 
 	cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos);
 
@@ -283,7 +284,9 @@
 		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
 		goto ffirst_retry;
 	}
+error_exit:
 	kfree(full_path);
+	cifs_put_tlink(tlink);
 	return rc;
 }
 
@@ -525,14 +528,14 @@
 	   (index_to_find < first_entry_in_buffer)) {
 		/* close and restart search */
 		cFYI(1, "search backing up - close and restart search");
-		write_lock(&GlobalSMBSeslock);
+		spin_lock(&cifs_file_list_lock);
 		if (!cifsFile->srch_inf.endOfSearch &&
 		    !cifsFile->invalidHandle) {
 			cifsFile->invalidHandle = true;
-			write_unlock(&GlobalSMBSeslock);
+			spin_unlock(&cifs_file_list_lock);
 			CIFSFindClose(xid, pTcon, cifsFile->netfid);
 		} else
-			write_unlock(&GlobalSMBSeslock);
+			spin_unlock(&cifs_file_list_lock);
 		if (cifsFile->srch_inf.ntwrk_buf_start) {
 			cFYI(1, "freeing SMB ff cache buf on search rewind");
 			if (cifsFile->srch_inf.smallBuf)
@@ -738,6 +741,15 @@
 		cifs_autodisable_serverino(cifs_sb);
 	}
 
+	if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
+	    CIFSCouldBeMFSymlink(&fattr))
+		/*
+		 * trying to get the type and mode can be slow,
+		 * so just call those regular files for now, and mark
+		 * for reval
+		 */
+		fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
+
 	ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
 	tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
 
@@ -777,9 +789,17 @@
 	xid = GetXid();
 
 	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
-	pTcon = cifs_sb->tcon;
-	if (pTcon == NULL)
-		return -EINVAL;
+
+	/*
+	 * Ensure FindFirst doesn't fail before doing filldir() for '.' and
+	 * '..'. Otherwise we won't be able to notify VFS in case of failure.
+	 */
+	if (file->private_data == NULL) {
+		rc = initiate_cifs_search(xid, file);
+		cFYI(1, "initiate cifs search rc %d", rc);
+		if (rc)
+			goto rddir2_exit;
+	}
 
 	switch ((int) file->f_pos) {
 	case 0:
@@ -805,14 +825,6 @@
 			if after then keep searching till find it */
 
 		if (file->private_data == NULL) {
-			rc = initiate_cifs_search(xid, file);
-			cFYI(1, "initiate cifs search rc %d", rc);
-			if (rc) {
-				FreeXid(xid);
-				return rc;
-			}
-		}
-		if (file->private_data == NULL) {
 			rc = -EINVAL;
 			FreeXid(xid);
 			return rc;
@@ -829,6 +841,7 @@
 			CIFSFindClose(xid, pTcon, cifsFile->netfid);
 		} */
 
+		pTcon = tlink_tcon(cifsFile->tlink);
 		rc = find_cifs_entry(xid, pTcon, file,
 				&current_entry, &num_to_fill);
 		if (rc) {
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 0a57cb7..2a11efd 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -80,7 +80,7 @@
 	if (max_vcs < 2)
 		max_vcs = 0xFFFF;
 
-	write_lock(&cifs_tcp_ses_lock);
+	spin_lock(&cifs_tcp_ses_lock);
 	if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
 			goto get_vc_num_exit;  /* vcnum will be zero */
 	for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
@@ -112,7 +112,7 @@
 		vcnum = i;
 	ses->vcnum = vcnum;
 get_vc_num_exit:
-	write_unlock(&cifs_tcp_ses_lock);
+	spin_unlock(&cifs_tcp_ses_lock);
 
 	return cpu_to_le16(vcnum);
 }
@@ -383,6 +383,9 @@
 static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
 				    struct cifsSesInfo *ses)
 {
+	unsigned int tioffset; /* challenge message target info area */
+	unsigned int tilen; /* challenge message target info area length  */
+
 	CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
 
 	if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
@@ -399,12 +402,25 @@
 		return -EINVAL;
 	}
 
-	memcpy(ses->server->cryptKey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
+	memcpy(ses->cryptKey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
 	/* BB we could decode pblob->NegotiateFlags; some may be useful */
 	/* In particular we can examine sign flags */
 	/* BB spec says that if AvId field of MsvAvTimestamp is populated then
 		we must set the MIC field of the AUTHENTICATE_MESSAGE */
 
+	tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
+	tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
+	ses->tilen = tilen;
+	if (ses->tilen) {
+		ses->tiblob = kmalloc(tilen, GFP_KERNEL);
+		if (!ses->tiblob) {
+			cERROR(1, "Challenge target info allocation failure");
+			ses->tilen = 0;
+			return -ENOMEM;
+		}
+		memcpy(ses->tiblob,  bcc_ptr + tioffset, ses->tilen);
+	}
+
 	return 0;
 }
 
@@ -425,7 +441,7 @@
 	/* BB is NTLMV2 session security format easier to use here? */
 	flags = NTLMSSP_NEGOTIATE_56 |	NTLMSSP_REQUEST_TARGET |
 		NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
-		NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
+		NTLMSSP_NEGOTIATE_NTLM;
 	if (ses->server->secMode &
 	   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -448,13 +464,16 @@
    maximum possible size is fixed and small, making this approach cleaner.
    This function returns the length of the data in the blob */
 static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
+					u16 *buflen,
 				   struct cifsSesInfo *ses,
-				   const struct nls_table *nls_cp, bool first)
+				   const struct nls_table *nls_cp)
 {
+	int rc;
+	unsigned int size;
 	AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
 	__u32 flags;
 	unsigned char *tmp;
-	char ntlm_session_key[CIFS_SESS_KEY_SIZE];
+	struct ntlmv2_resp ntlmv2_response = {};
 
 	memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
 	sec_blob->MessageType = NtLmAuthenticate;
@@ -462,7 +481,7 @@
 	flags = NTLMSSP_NEGOTIATE_56 |
 		NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
 		NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
-		NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
+		NTLMSSP_NEGOTIATE_NTLM;
 	if (ses->server->secMode &
 	   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		flags |= NTLMSSP_NEGOTIATE_SIGN;
@@ -477,19 +496,26 @@
 	sec_blob->LmChallengeResponse.Length = 0;
 	sec_blob->LmChallengeResponse.MaximumLength = 0;
 
-	/* calculate session key,  BB what about adding similar ntlmv2 path? */
-	SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
-	if (first)
-		cifs_calculate_mac_key(&ses->server->mac_signing_key,
-				       ntlm_session_key, ses->password);
-
-	memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
 	sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
-	sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE);
-	sec_blob->NtChallengeResponse.MaximumLength =
-				cpu_to_le16(CIFS_SESS_KEY_SIZE);
+	rc = setup_ntlmv2_rsp(ses, (char *)&ntlmv2_response, nls_cp);
+	if (rc) {
+		cERROR(1, "Error %d during NTLMSSP authentication", rc);
+		goto setup_ntlmv2_ret;
+	}
+	size =  sizeof(struct ntlmv2_resp);
+	memcpy(tmp, (char *)&ntlmv2_response, size);
+	tmp += size;
+	if (ses->tilen > 0) {
+		memcpy(tmp, ses->tiblob, ses->tilen);
+		tmp += ses->tilen;
+	}
 
-	tmp += CIFS_SESS_KEY_SIZE;
+	sec_blob->NtChallengeResponse.Length = cpu_to_le16(size + ses->tilen);
+	sec_blob->NtChallengeResponse.MaximumLength =
+				cpu_to_le16(size + ses->tilen);
+	kfree(ses->tiblob);
+	ses->tiblob = NULL;
+	ses->tilen = 0;
 
 	if (ses->domainName == NULL) {
 		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
@@ -501,7 +527,6 @@
 		len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
 				    MAX_USERNAME_SIZE, nls_cp);
 		len *= 2; /* unicode is 2 bytes each */
-		len += 2; /* trailing null */
 		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
 		sec_blob->DomainName.Length = cpu_to_le16(len);
 		sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
@@ -518,7 +543,6 @@
 		len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
 				    MAX_USERNAME_SIZE, nls_cp);
 		len *= 2; /* unicode is 2 bytes each */
-		len += 2; /* trailing null */
 		sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
 		sec_blob->UserName.Length = cpu_to_le16(len);
 		sec_blob->UserName.MaximumLength = cpu_to_le16(len);
@@ -533,7 +557,10 @@
 	sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
 	sec_blob->SessionKey.Length = 0;
 	sec_blob->SessionKey.MaximumLength = 0;
-	return tmp - pbuffer;
+
+setup_ntlmv2_ret:
+	*buflen = tmp - pbuffer;
+	return rc;
 }
 
 
@@ -545,19 +572,6 @@
 
 	return;
 }
-
-static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,
-				  struct cifsSesInfo *ses,
-				  const struct nls_table *nls, bool first_time)
-{
-	int bloblen;
-
-	bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls,
-					  first_time);
-	pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
-
-	return bloblen;
-}
 #endif
 
 int
@@ -579,15 +593,12 @@
 	int bytes_remaining;
 	struct key *spnego_key = NULL;
 	__le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
-	bool first_time;
+	u16 blob_len;
+	char *ntlmsspblob = NULL;
 
 	if (ses == NULL)
 		return -EINVAL;
 
-	read_lock(&cifs_tcp_ses_lock);
-	first_time = is_first_ses_reconnect(ses);
-	read_unlock(&cifs_tcp_ses_lock);
-
 	type = ses->server->secType;
 
 	cFYI(1, "sess setup type %d", type);
@@ -658,7 +669,7 @@
 		/* BB calculate hash with password */
 		/* and copy into bcc */
 
-		calc_lanman_hash(ses->password, ses->server->cryptKey,
+		calc_lanman_hash(ses->password, ses->cryptKey,
 				 ses->server->secMode & SECMODE_PW_ENCRYPT ?
 					true : false, lnm_session_key);
 
@@ -685,15 +696,11 @@
 			cpu_to_le16(CIFS_SESS_KEY_SIZE);
 
 		/* calculate session key */
-		SMBNTencrypt(ses->password, ses->server->cryptKey,
-			     ntlm_session_key);
+		SMBNTencrypt(ses->password, ses->cryptKey, ntlm_session_key);
 
-		if (first_time) /* should this be moved into common code
-				  with similar ntlmv2 path? */
-			cifs_calculate_mac_key(&ses->server->mac_signing_key,
-				ntlm_session_key, ses->password);
+		cifs_calculate_session_key(&ses->auth_key,
+					ntlm_session_key, ses->password);
 		/* copy session key */
-
 		memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
 		bcc_ptr += CIFS_SESS_KEY_SIZE;
 		memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
@@ -725,16 +732,31 @@
 		pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
 		/*	cpu_to_le16(LM2_SESS_KEY_SIZE); */
 
-		pSMB->req_no_secext.CaseSensitivePasswordLength =
-			cpu_to_le16(sizeof(struct ntlmv2_resp));
-
 		/* calculate session key */
-		setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
-		/* FIXME: calculate MAC key */
+		rc = setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
+		if (rc) {
+			cERROR(1, "Error %d during NTLMv2 authentication", rc);
+			kfree(v2_sess_key);
+			goto ssetup_exit;
+		}
 		memcpy(bcc_ptr, (char *)v2_sess_key,
-		       sizeof(struct ntlmv2_resp));
+				sizeof(struct ntlmv2_resp));
 		bcc_ptr += sizeof(struct ntlmv2_resp);
 		kfree(v2_sess_key);
+		/* set case sensitive password length after tilen may get
+		 * assigned, tilen is 0 otherwise.
+		 */
+		pSMB->req_no_secext.CaseSensitivePasswordLength =
+			cpu_to_le16(sizeof(struct ntlmv2_resp) + ses->tilen);
+		if (ses->tilen > 0) {
+			memcpy(bcc_ptr, ses->tiblob, ses->tilen);
+			bcc_ptr += ses->tilen;
+			/* we never did allocate ses->domainName to free */
+			kfree(ses->tiblob);
+			ses->tiblob = NULL;
+			ses->tilen = 0;
+		}
+
 		if (ses->capabilities & CAP_UNICODE) {
 			if (iov[0].iov_len % 2) {
 				*bcc_ptr = 0;
@@ -765,17 +787,14 @@
 		}
 		/* bail out if key is too long */
 		if (msg->sesskey_len >
-		    sizeof(ses->server->mac_signing_key.data.krb5)) {
+		    sizeof(ses->auth_key.data.krb5)) {
 			cERROR(1, "Kerberos signing key too long (%u bytes)",
 				msg->sesskey_len);
 			rc = -EOVERFLOW;
 			goto ssetup_exit;
 		}
-		if (first_time) {
-			ses->server->mac_signing_key.len = msg->sesskey_len;
-			memcpy(ses->server->mac_signing_key.data.krb5,
-				msg->data, msg->sesskey_len);
-		}
+		ses->auth_key.len = msg->sesskey_len;
+		memcpy(ses->auth_key.data.krb5, msg->data, msg->sesskey_len);
 		pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
 		capabilities |= CAP_EXTENDED_SECURITY;
 		pSMB->req.Capabilities = cpu_to_le32(capabilities);
@@ -815,12 +834,30 @@
 			if (phase == NtLmNegotiate) {
 				setup_ntlmssp_neg_req(pSMB, ses);
 				iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
+				iov[1].iov_base = &pSMB->req.SecurityBlob[0];
 			} else if (phase == NtLmAuthenticate) {
-				int blob_len;
-				blob_len = setup_ntlmssp_auth_req(pSMB, ses,
-								  nls_cp,
-								  first_time);
+				/* 5 is an empirical value, large enought to
+				 * hold authenticate message, max 10 of
+				 * av paris, doamin,user,workstation mames,
+				 * flags etc..
+				 */
+				ntlmsspblob = kmalloc(
+					5*sizeof(struct _AUTHENTICATE_MESSAGE),
+					GFP_KERNEL);
+				if (!ntlmsspblob) {
+					cERROR(1, "Can't allocate NTLMSSP");
+					rc = -ENOMEM;
+					goto ssetup_exit;
+				}
+
+				rc = build_ntlmssp_auth_blob(ntlmsspblob,
+							&blob_len, ses, nls_cp);
+				if (rc)
+					goto ssetup_exit;
 				iov[1].iov_len = blob_len;
+				iov[1].iov_base = ntlmsspblob;
+				pSMB->req.SecurityBlobLength =
+					cpu_to_le16(blob_len);
 				/* Make sure that we tell the server that we
 				   are using the uid that it just gave us back
 				   on the response (challenge) */
@@ -830,7 +867,6 @@
 				rc = -ENOSYS;
 				goto ssetup_exit;
 			}
-			iov[1].iov_base = &pSMB->req.SecurityBlob[0];
 			/* unicode strings must be word aligned */
 			if ((iov[0].iov_len + iov[1].iov_len) % 2) {
 				*bcc_ptr = 0;
@@ -895,7 +931,6 @@
 	bcc_ptr = pByteArea(smb_buf);
 
 	if (smb_buf->WordCount == 4) {
-		__u16 blob_len;
 		blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
 		if (blob_len > bytes_remaining) {
 			cERROR(1, "bad security blob length %d", blob_len);
@@ -931,6 +966,8 @@
 		key_put(spnego_key);
 	}
 	kfree(str_area);
+	kfree(ntlmsspblob);
+	ntlmsspblob = NULL;
 	if (resp_buf_type == CIFS_SMALL_BUFFER) {
 		cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base);
 		cifs_small_buf_release(iov[0].iov_base);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 82f78c4..a66c91e 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -543,7 +543,7 @@
 		    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
 					     SECMODE_SIGN_ENABLED))) {
 			rc = cifs_verify_signature(midQ->resp_buf,
-						&ses->server->mac_signing_key,
+						&ses->server->session_key,
 						midQ->sequence_number+1);
 			if (rc) {
 				cERROR(1, "Unexpected SMB signature");
@@ -731,7 +731,7 @@
 		    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
 					     SECMODE_SIGN_ENABLED))) {
 			rc = cifs_verify_signature(out_buf,
-						&ses->server->mac_signing_key,
+						&ses->server->session_key,
 						midQ->sequence_number+1);
 			if (rc) {
 				cERROR(1, "Unexpected SMB signature");
@@ -981,7 +981,7 @@
 	    (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
 				     SECMODE_SIGN_ENABLED))) {
 		rc = cifs_verify_signature(out_buf,
-					   &ses->server->mac_signing_key,
+					   &ses->server->session_key,
 					   midQ->sequence_number+1);
 		if (rc) {
 			cERROR(1, "Unexpected SMB signature");
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index a150920..a264b74 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -47,9 +47,10 @@
 #ifdef CONFIG_CIFS_XATTR
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct super_block *sb;
-	char *full_path;
+	char *full_path = NULL;
 
 	if (direntry == NULL)
 		return -EIO;
@@ -58,16 +59,19 @@
 	sb = direntry->d_inode->i_sb;
 	if (sb == NULL)
 		return -EIO;
-	xid = GetXid();
 
 	cifs_sb = CIFS_SB(sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto remove_ea_exit;
 	}
 	if (ea_name == NULL) {
 		cFYI(1, "Null xattr names not supported");
@@ -91,6 +95,7 @@
 remove_ea_exit:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 #endif
 	return rc;
 }
@@ -102,6 +107,7 @@
 #ifdef CONFIG_CIFS_XATTR
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct super_block *sb;
 	char *full_path;
@@ -113,16 +119,19 @@
 	sb = direntry->d_inode->i_sb;
 	if (sb == NULL)
 		return -EIO;
-	xid = GetXid();
 
 	cifs_sb = CIFS_SB(sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto set_ea_exit;
 	}
 	/* return dos attributes as pseudo xattr */
 	/* return alt name if available as pseudo attr */
@@ -132,9 +141,8 @@
 		returns as xattrs */
 	if (value_size > MAX_EA_VALUE_SIZE) {
 		cFYI(1, "size of EA value too large");
-		kfree(full_path);
-		FreeXid(xid);
-		return -EOPNOTSUPP;
+		rc = -EOPNOTSUPP;
+		goto set_ea_exit;
 	}
 
 	if (ea_name == NULL) {
@@ -198,6 +206,7 @@
 set_ea_exit:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 #endif
 	return rc;
 }
@@ -209,6 +218,7 @@
 #ifdef CONFIG_CIFS_XATTR
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct super_block *sb;
 	char *full_path;
@@ -221,16 +231,18 @@
 	if (sb == NULL)
 		return -EIO;
 
-	xid = GetXid();
-
 	cifs_sb = CIFS_SB(sb);
-	pTcon = cifs_sb->tcon;
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
+	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto get_ea_exit;
 	}
 	/* return dos attributes as pseudo xattr */
 	/* return alt name if available as pseudo attr */
@@ -323,6 +335,7 @@
 get_ea_exit:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 #endif
 	return rc;
 }
@@ -333,6 +346,7 @@
 #ifdef CONFIG_CIFS_XATTR
 	int xid;
 	struct cifs_sb_info *cifs_sb;
+	struct tcon_link *tlink;
 	struct cifsTconInfo *pTcon;
 	struct super_block *sb;
 	char *full_path;
@@ -346,18 +360,20 @@
 		return -EIO;
 
 	cifs_sb = CIFS_SB(sb);
-	pTcon = cifs_sb->tcon;
-
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
 		return -EOPNOTSUPP;
 
+	tlink = cifs_sb_tlink(cifs_sb);
+	if (IS_ERR(tlink))
+		return PTR_ERR(tlink);
+	pTcon = tlink_tcon(tlink);
+
 	xid = GetXid();
 
 	full_path = build_path_from_dentry(direntry);
 	if (full_path == NULL) {
 		rc = -ENOMEM;
-		FreeXid(xid);
-		return rc;
+		goto list_ea_exit;
 	}
 	/* return dos attributes as pseudo xattr */
 	/* return alt name if available as pseudo attr */
@@ -370,8 +386,10 @@
 				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 
+list_ea_exit:
 	kfree(full_path);
 	FreeXid(xid);
+	cifs_put_tlink(tlink);
 #endif
 	return rc;
 }
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 6526e6f..bfe8179 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -148,6 +148,8 @@
 	int error;
 	int idx;
 
+	lock_kernel();
+
 	idx = get_device_index((struct coda_mount_data *) data);
 
 	/* Ignore errors in data, for backward compatibility */
@@ -159,11 +161,13 @@
 	vc = &coda_comms[idx];
 	if (!vc->vc_inuse) {
 		printk("coda_read_super: No pseudo device\n");
+		unlock_kernel();
 		return -EINVAL;
 	}
 
         if ( vc->vc_sb ) {
 		printk("coda_read_super: Device already mounted\n");
+		unlock_kernel();
 		return -EBUSY;
 	}
 
@@ -202,7 +206,8 @@
 	sb->s_root = d_alloc_root(root);
 	if (!sb->s_root)
 		goto error;
-        return 0;
+	unlock_kernel();
+	return 0;
 
  error:
 	bdi_destroy(&vc->bdi);
@@ -212,6 +217,7 @@
 	if (vc)
 		vc->vc_sb = NULL;
 
+	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index ca25d96..028a9a0 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -39,6 +39,7 @@
 const struct file_operations coda_ioctl_operations = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= coda_pioctl,
+	.llseek		= noop_llseek,
 };
 
 /* the coda pioctl inode ops */
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 116af75..fdc2f3e 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -346,6 +346,7 @@
 	.unlocked_ioctl	= coda_psdev_ioctl,
 	.open		= coda_psdev_open,
 	.release	= coda_psdev_release,
+	.llseek		= noop_llseek,
 };
 
 static int init_coda_psdev(void)
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 03e59aa..d0ad09d 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -599,69 +599,6 @@
 #define HIDPGETCONNLIST	_IOR('H', 210, int)
 #define HIDPGETCONNINFO	_IOR('H', 211, int)
 
-#ifdef CONFIG_BLOCK
-struct raw32_config_request
-{
-        compat_int_t    raw_minor;
-        __u64   block_major;
-        __u64   block_minor;
-} __attribute__((packed));
-
-static int get_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req)
-{
-        int ret;
-
-        if (!access_ok(VERIFY_READ, user_req, sizeof(struct raw32_config_request)))
-                return -EFAULT;
-
-        ret = __get_user(req->raw_minor, &user_req->raw_minor);
-        ret |= __get_user(req->block_major, &user_req->block_major);
-        ret |= __get_user(req->block_minor, &user_req->block_minor);
-
-        return ret ? -EFAULT : 0;
-}
-
-static int set_raw32_request(struct raw_config_request *req, struct raw32_config_request __user *user_req)
-{
-	int ret;
-
-        if (!access_ok(VERIFY_WRITE, user_req, sizeof(struct raw32_config_request)))
-                return -EFAULT;
-
-        ret = __put_user(req->raw_minor, &user_req->raw_minor);
-        ret |= __put_user(req->block_major, &user_req->block_major);
-        ret |= __put_user(req->block_minor, &user_req->block_minor);
-
-        return ret ? -EFAULT : 0;
-}
-
-static int raw_ioctl(unsigned fd, unsigned cmd,
-		struct raw32_config_request __user *user_req)
-{
-        int ret;
-
-        switch (cmd) {
-        case RAW_SETBIND:
-	default: {	/* RAW_GETBIND */
-                struct raw_config_request req;
-                mm_segment_t oldfs = get_fs();
-
-                if ((ret = get_raw32_request(&req, user_req)))
-                        return ret;
-
-                set_fs(KERNEL_DS);
-                ret = sys_ioctl(fd,cmd,(unsigned long)&req);
-                set_fs(oldfs);
-
-                if ((!ret) && (cmd == RAW_GETBIND)) {
-                        ret = set_raw32_request(&req, user_req);
-                }
-                break;
-        }
-        }
-        return ret;
-}
-#endif /* CONFIG_BLOCK */
 
 struct serial_struct32 {
         compat_int_t    type;
@@ -1262,9 +1199,6 @@
 COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
 COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
 COMPATIBLE_IOCTL(OSS_GETVERSION)
-/* Raw devices */
-COMPATIBLE_IOCTL(RAW_SETBIND)
-COMPATIBLE_IOCTL(RAW_GETBIND)
 /* SMB ioctls which do not need any translations */
 COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
 /* Watchdog */
@@ -1523,10 +1457,6 @@
 	case MTIOCGET32:
 	case MTIOCPOS32:
 		return mt_ioctl_trans(fd, cmd, argp);
-	/* Raw devices */
-	case RAW_SETBIND:
-	case RAW_GETBIND:
-		return raw_ioctl(fd, cmd, argp);
 #endif
 	/* One SMB ioctl needs translations. */
 #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 0210898..89d394d 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -43,6 +43,7 @@
 	.read =		default_read_file,
 	.write =	default_write_file,
 	.open =		default_open,
+	.llseek =	noop_llseek,
 };
 
 static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
@@ -454,6 +455,7 @@
 	.read =		read_file_bool,
 	.write =	write_file_bool,
 	.open =		default_open,
+	.llseek =	default_llseek,
 };
 
 /**
@@ -498,6 +500,7 @@
 static const struct file_operations fops_blob = {
 	.read =		read_file_blob,
 	.open =		default_open,
+	.llseek =	default_llseek,
 };
 
 /**
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index c6cf251..6b42ba8 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -643,7 +643,8 @@
 static const struct file_operations waiters_fops = {
 	.owner   = THIS_MODULE,
 	.open    = waiters_open,
-	.read    = waiters_read
+	.read    = waiters_read,
+	.llseek  = default_llseek,
 };
 
 void dlm_delete_debug_file(struct dlm_ls *ls)
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 031dbe3..64e5f3e 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -1846,6 +1846,9 @@
 	struct dlm_lkb *gr;
 
 	list_for_each_entry(gr, head, lkb_statequeue) {
+		/* skip self when sending basts to convertqueue */
+		if (gr == lkb)
+			continue;
 		if (gr->lkb_bastfn && modes_require_bast(gr, lkb)) {
 			queue_bast(r, gr, lkb->lkb_rqmode);
 			gr->lkb_highbast = lkb->lkb_rqmode;
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
index d45c02d..30d8b85 100644
--- a/fs/dlm/plock.c
+++ b/fs/dlm/plock.c
@@ -412,7 +412,8 @@
 	.read    = dev_read,
 	.write   = dev_write,
 	.poll    = dev_poll,
-	.owner   = THIS_MODULE
+	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice plock_dev_misc = {
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index b627285..66d6c16 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -1009,6 +1009,7 @@
 	.write   = device_write,
 	.poll    = device_poll,
 	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static const struct file_operations ctl_device_fops = {
@@ -1017,6 +1018,7 @@
 	.read    = device_read,
 	.write   = device_write,
 	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice ctl_device = {
@@ -1029,6 +1031,7 @@
 	.open    = monitor_device_open,
 	.release = monitor_device_close,
 	.owner   = THIS_MODULE,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice monitor_device = {
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 622c9514..91da029 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -31,7 +31,6 @@
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/fs_stack.h>
-#include <linux/smp_lock.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -284,11 +283,9 @@
 	int rc = 0;
 	struct file *lower_file = NULL;
 
-	lock_kernel();
 	lower_file = ecryptfs_file_to_lower(file);
 	if (lower_file->f_op && lower_file->f_op->fasync)
 		rc = lower_file->f_op->fasync(fd, lower_file, flag);
-	unlock_kernel();
 	return rc;
 }
 
@@ -332,6 +329,7 @@
 	.fsync = ecryptfs_fsync,
 	.fasync = ecryptfs_fasync,
 	.splice_read = generic_file_splice_read,
+	.llseek = default_llseek,
 };
 
 const struct file_operations ecryptfs_main_fops = {
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 00208c3..940a82e 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -482,6 +482,7 @@
 	.read    = ecryptfs_miscdev_read,
 	.write   = ecryptfs_miscdev_write,
 	.release = ecryptfs_miscdev_release,
+	.llseek  = noop_llseek,
 };
 
 static struct miscdevice ecryptfs_miscdev = {
diff --git a/fs/eventfd.c b/fs/eventfd.c
index 6bd3f76..e0194b3 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -293,6 +293,7 @@
 	.poll		= eventfd_poll,
 	.read		= eventfd_read,
 	.write		= eventfd_write,
+	.llseek		= noop_llseek,
 };
 
 /**
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 3817149..256bb7b 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -674,7 +674,8 @@
 /* File callbacks that implement the eventpoll file behaviour */
 static const struct file_operations eventpoll_fops = {
 	.release	= ep_eventpoll_release,
-	.poll		= ep_eventpoll_poll
+	.poll		= ep_eventpoll_poll,
+	.llseek		= noop_llseek,
 };
 
 /* Fast test to see if the file is an evenpoll file */
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 1ec6026..85df87d 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -747,15 +747,16 @@
 	__le32 features;
 	int err;
 
+	err = -ENOMEM;
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
-		return -ENOMEM;
+		goto failed_unlock;
 
 	sbi->s_blockgroup_lock =
 		kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
 	if (!sbi->s_blockgroup_lock) {
 		kfree(sbi);
-		return -ENOMEM;
+		goto failed_unlock;
 	}
 	sb->s_fs_info = sbi;
 	sbi->s_sb_block = sb_block;
@@ -1107,6 +1108,7 @@
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
 	kfree(sbi);
+failed_unlock:
 	return ret;
 }
 
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index d7e9f74..09b13bb 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -90,7 +90,6 @@
 	 * storage
 	 */
 	if (needs_barrier)
-		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL,
-				BLKDEV_IFL_WAIT);
+		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 	return ret;
 }
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index a367dd0..3777680 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -411,9 +411,6 @@
 	int i, err;
 
 	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
-
-	lock_kernel();
-
 	ext3_xattr_put_super(sb);
 	err = journal_destroy(sbi->s_journal);
 	sbi->s_journal = NULL;
@@ -462,8 +459,6 @@
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
 	kfree(sbi);
-
-	unlock_kernel();
 }
 
 static struct kmem_cache *ext3_inode_cachep;
@@ -1627,8 +1622,6 @@
 	sbi->s_resgid = EXT3_DEF_RESGID;
 	sbi->s_sb_block = sb_block;
 
-	unlock_kernel();
-
 	blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
 	if (!blocksize) {
 		ext3_msg(sb, KERN_ERR, "error: unable to set blocksize");
@@ -2025,7 +2018,6 @@
 		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
 		"writeback");
 
-	lock_kernel();
 	return 0;
 
 cantfind_ext3:
@@ -2055,7 +2047,6 @@
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
 	kfree(sbi);
-	lock_kernel();
 	return ret;
 }
 
@@ -2538,8 +2529,6 @@
 	int i;
 #endif
 
-	lock_kernel();
-
 	/* Store the original options */
 	lock_super(sb);
 	old_sb_flags = sb->s_flags;
@@ -2648,7 +2637,6 @@
 			kfree(old_opts.s_qf_names[i]);
 #endif
 	unlock_super(sb);
-	unlock_kernel();
 
 	if (enable_quota)
 		dquot_resume(sb, -1);
@@ -2669,7 +2657,6 @@
 	}
 #endif
 	unlock_super(sb);
-	unlock_kernel();
 	return err;
 }
 
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
index 592adf2..3f3ff5e 100644
--- a/fs/ext4/fsync.c
+++ b/fs/ext4/fsync.c
@@ -128,10 +128,9 @@
 		    (journal->j_fs_dev != journal->j_dev) &&
 		    (journal->j_flags & JBD2_BARRIER))
 			blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL,
-					NULL, BLKDEV_IFL_WAIT);
+					NULL);
 		ret = jbd2_log_wait_commit(journal, commit_tid);
 	} else if (journal->j_flags & JBD2_BARRIER)
-		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
+		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 	return ret;
 }
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 4b4ad4b..19aa0d4 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2566,7 +2566,7 @@
 	discard_block = block + ext4_group_first_block_no(sb, block_group);
 	trace_ext4_discard_blocks(sb,
 			(unsigned long long) discard_block, count);
-	ret = sb_issue_discard(sb, discard_block, count);
+	ret = sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
 	if (ret == EOPNOTSUPP) {
 		ext4_warning(sb, "discard not supported, disabling");
 		clear_opt(EXT4_SB(sb)->s_mount_opt, DISCARD);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 7f47c36..8ecc1e5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/parser.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/exportfs.h>
 #include <linux/vfs.h>
@@ -708,7 +707,6 @@
 	destroy_workqueue(sbi->dio_unwritten_wq);
 
 	lock_super(sb);
-	lock_kernel();
 	if (sb->s_dirt)
 		ext4_commit_super(sb, 1);
 
@@ -775,7 +773,6 @@
 	 * Now that we are completely done shutting down the
 	 * superblock, we need to actually destroy the kobject.
 	 */
-	unlock_kernel();
 	unlock_super(sb);
 	kobject_put(&sbi->s_kobj);
 	wait_for_completion(&sbi->s_kobj_unregister);
@@ -2588,8 +2585,6 @@
 		sbi->s_sectors_written_start =
 			part_stat_read(sb->s_bdev->bd_part, sectors[1]);
 
-	unlock_kernel();
-
 	/* Cleanup superblock name */
 	for (cp = sb->s_id; (cp = strchr(cp, '/'));)
 		*cp = '!';
@@ -3164,7 +3159,6 @@
 	if (es->s_error_count)
 		mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
 
-	lock_kernel();
 	kfree(orig_data);
 	return 0;
 
@@ -3211,7 +3205,6 @@
 	sb->s_fs_info = NULL;
 	kfree(sbi->s_blockgroup_lock);
 	kfree(sbi);
-	lock_kernel();
 out_free_orig:
 	kfree(orig_data);
 	return ret;
@@ -3720,8 +3713,6 @@
 #endif
 	char *orig_data = kstrdup(data, GFP_KERNEL);
 
-	lock_kernel();
-
 	/* Store the original options */
 	lock_super(sb);
 	old_sb_flags = sb->s_flags;
@@ -3856,7 +3847,6 @@
 			kfree(old_opts.s_qf_names[i]);
 #endif
 	unlock_super(sb);
-	unlock_kernel();
 	if (enable_quota)
 		dquot_resume(sb, -1);
 
@@ -3882,7 +3872,6 @@
 	}
 #endif
 	unlock_super(sb);
-	unlock_kernel();
 	kfree(orig_data);
 	return err;
 }
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 81184d3..b47d2c9 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -577,7 +577,8 @@
 
 				sb_issue_discard(sb,
 					fat_clus_to_blknr(sbi, first_cl),
-					nr_clus * sbi->sec_per_clus);
+					nr_clus * sbi->sec_per_clus,
+					GFP_NOFS, 0);
 
 				first_cl = cluster;
 			}
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 8300580..ad6998a 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/time.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
@@ -489,8 +488,6 @@
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
-	lock_kernel();
-
 	if (sb->s_dirt)
 		fat_write_super(sb);
 
@@ -504,8 +501,6 @@
 
 	sb->s_fs_info = NULL;
 	kfree(sbi);
-
-	unlock_kernel();
 }
 
 static struct kmem_cache *fat_inode_cachep;
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 1736f23..970e682 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -255,10 +255,7 @@
 
 	for (i = 0; i < nr_bhs; i++) {
 		wait_on_buffer(bhs[i]);
-		if (buffer_eopnotsupp(bhs[i])) {
-			clear_buffer_eopnotsupp(bhs[i]);
-			err = -EOPNOTSUPP;
-		} else if (!err && !buffer_uptodate(bhs[i]))
+		if (!err && !buffer_uptodate(bhs[i]))
 			err = -EIO;
 	}
 	return err;
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index bbc94ae..bbca5c1 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -662,12 +662,16 @@
 {
 	int res;
 
+	lock_super(sb);
 	res = fat_fill_super(sb, data, silent, &msdos_dir_inode_operations, 0);
-	if (res)
+	if (res) {
+		unlock_super(sb);
 		return res;
+	}
 
 	sb->s_flags |= MS_NOATIME;
 	sb->s_root->d_op = &msdos_dentry_operations;
+	unlock_super(sb);
 	return 0;
 }
 
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 6fcc7e7..6f0f6c9 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -1055,15 +1055,19 @@
 {
 	int res;
 
+	lock_super(sb);
 	res = fat_fill_super(sb, data, silent, &vfat_dir_inode_operations, 1);
-	if (res)
+	if (res) {
+		unlock_super(sb);
 		return res;
+	}
 
 	if (MSDOS_SB(sb)->options.name_check != 's')
 		sb->s_root->d_op = &vfat_ci_dentry_ops;
 	else
 		sb->s_root->d_op = &vfat_dentry_ops;
 
+	unlock_super(sb);
 	return 0;
 }
 
diff --git a/fs/fifo.c b/fs/fifo.c
index 5d6606f..4e303c2 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -151,4 +151,5 @@
  */
 const struct file_operations def_fifo_fops = {
 	.open		= fifo_open,	/* will set read_ or write_pipefifo_fops */
+	.llseek		= noop_llseek,
 };
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 0ec7bb2..6c5131d 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -36,7 +36,6 @@
 #include <linux/highmem.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 #include "vxfs.h"
 #include "vxfs_dir.h"
@@ -212,16 +211,12 @@
 	if (dp->d_name.len > VXFS_NAMELEN)
 		return ERR_PTR(-ENAMETOOLONG);
 				 
-	lock_kernel();
 	ino = vxfs_inode_by_name(dip, dp);
 	if (ino) {
 		ip = vxfs_iget(dip->i_sb, ino);
-		if (IS_ERR(ip)) {
-			unlock_kernel();
+		if (IS_ERR(ip))
 			return ERR_CAST(ip);
-		}
 	}
-	unlock_kernel();
 	d_add(dp, ip);
 	return NULL;
 }
@@ -248,8 +243,6 @@
 	u_long			page, npages, block, pblocks, nblocks, offset;
 	loff_t			pos;
 
-	lock_kernel();
-
 	switch ((long)fp->f_pos) {
 	case 0:
 		if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
@@ -265,10 +258,8 @@
 
 	pos = fp->f_pos - 2;
 	
-	if (pos > VXFS_DIRROUND(ip->i_size)) {
-		unlock_kernel();
+	if (pos > VXFS_DIRROUND(ip->i_size))
 		return 0;
-	}
 
 	npages = dir_pages(ip);
 	nblocks = dir_blocks(ip);
@@ -327,6 +318,5 @@
 done:
 	fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
 out:
-	unlock_kernel();
 	return 0;
 }
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index dc0c041..71b0148 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -38,7 +38,6 @@
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/stat.h>
 #include <linux/vfs.h>
 #include <linux/mount.h>
@@ -81,16 +80,12 @@
 {
 	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
 
-	lock_kernel();
-
 	vxfs_put_fake_inode(infp->vsi_fship);
 	vxfs_put_fake_inode(infp->vsi_ilist);
 	vxfs_put_fake_inode(infp->vsi_stilist);
 
 	brelse(infp->vsi_bp);
 	kfree(infp);
-
-	unlock_kernel();
 }
 
 /**
@@ -148,7 +143,7 @@
  *   The superblock on success, else %NULL.
  *
  * Locking:
- *   We are under the bkl and @sbp->s_lock.
+ *   We are under @sbp->s_lock.
  */
 static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 {
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 3773fd6..7367e17 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -179,23 +179,27 @@
 static const struct file_operations fuse_ctl_abort_ops = {
 	.open = nonseekable_open,
 	.write = fuse_conn_abort_write,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations fuse_ctl_waiting_ops = {
 	.open = nonseekable_open,
 	.read = fuse_conn_waiting_read,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations fuse_conn_max_background_ops = {
 	.open = nonseekable_open,
 	.read = fuse_conn_max_background_read,
 	.write = fuse_conn_max_background_write,
+	.llseek = no_llseek,
 };
 
 static const struct file_operations fuse_conn_congestion_threshold_ops = {
 	.open = nonseekable_open,
 	.read = fuse_conn_congestion_threshold_read,
 	.write = fuse_conn_congestion_threshold_write,
+	.llseek = no_llseek,
 };
 
 static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index e1f8171..3e87cce 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -182,6 +182,7 @@
 	.unlocked_ioctl		= cuse_file_ioctl,
 	.compat_ioctl		= cuse_file_compat_ioctl,
 	.poll			= fuse_file_poll,
+	.llseek		= noop_llseek,
 };
 
 
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 237ee6a..aa99647 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -622,6 +622,8 @@
  * cluster; until we do, disable leases (by just returning -EINVAL),
  * unless the administrator has requested purely local locking.
  *
+ * Locking: called under lock_flocks
+ *
  * Returns: errno
  */
 
@@ -773,6 +775,7 @@
 	.fsync		= gfs2_fsync,
 	.lock		= gfs2_lock,
 	.flock		= gfs2_flock,
+	.llseek		= default_llseek,
 };
 
 #endif /* CONFIG_GFS2_FS_LOCKING_DLM */
@@ -799,5 +802,6 @@
 	.open		= gfs2_open,
 	.release	= gfs2_close,
 	.fsync		= gfs2_fsync,
+	.llseek		= default_llseek,
 };
 
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index ac750bd..eb01f35 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -592,22 +592,13 @@
 	lh->lh_hash = cpu_to_be32(hash);
 
 	bh->b_end_io = end_buffer_write_sync;
-	if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
-		goto skip_barrier;
 	get_bh(bh);
-	submit_bh(WRITE_BARRIER | REQ_META, bh);
-	wait_on_buffer(bh);
-	if (buffer_eopnotsupp(bh)) {
-		clear_buffer_eopnotsupp(bh);
-		set_buffer_uptodate(bh);
-		fs_info(sdp, "barrier sync failed - disabling barriers\n");
-		set_bit(SDF_NOBARRIERS, &sdp->sd_flags);
-		lock_buffer(bh);
-skip_barrier:
-		get_bh(bh);
+	if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
 		submit_bh(WRITE_SYNC | REQ_META, bh);
-		wait_on_buffer(bh);
-	}
+	else
+		submit_bh(WRITE_FLUSH_FUA | REQ_META, bh);
+	wait_on_buffer(bh);
+
 	if (!buffer_uptodate(bh))
 		gfs2_io_error_bh(sdp, bh);
 	brelse(bh);
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index d7eb1e2..ebef7ab 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -144,7 +144,7 @@
 
 	error = -ENOMEM;
 	gfs_recovery_wq = alloc_workqueue("gfs_recovery",
-					  WQ_RESCUER | WQ_FREEZEABLE, 0);
+					  WQ_MEM_RECLAIM | WQ_FREEZEABLE, 0);
 	if (!gfs_recovery_wq)
 		goto fail_wq;
 
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index fb67f593..bef3ab6 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -866,8 +866,7 @@
 				if ((start + nr_sects) != blk) {
 					rv = blkdev_issue_discard(bdev, start,
 							    nr_sects, GFP_NOFS,
-							    BLKDEV_IFL_WAIT |
-							    BLKDEV_IFL_BARRIER);
+							    0);
 					if (rv)
 						goto fail;
 					nr_sects = 0;
@@ -881,8 +880,7 @@
 		}
 	}
 	if (nr_sects) {
-		rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS,
-					 BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+		rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, 0);
 		if (rv)
 			goto fail;
 	}
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 34235d4..3325416 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -20,7 +20,6 @@
 #include <linux/parser.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 
 #include "hfs_fs.h"
@@ -79,15 +78,11 @@
  */
 static void hfs_put_super(struct super_block *sb)
 {
-	lock_kernel();
-
 	if (sb->s_dirt)
 		hfs_write_super(sb);
 	hfs_mdb_close(sb);
 	/* release the MDB's resources */
 	hfs_mdb_put(sb);
-
-	unlock_kernel();
 }
 
 /*
@@ -385,6 +380,7 @@
 	sbi = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
+
 	sb->s_fs_info = sbi;
 	INIT_HLIST_HEAD(&sbi->rsrc_inodes);
 
diff --git a/fs/hpfs/Kconfig b/fs/hpfs/Kconfig
index 56bd15c..63b6f56 100644
--- a/fs/hpfs/Kconfig
+++ b/fs/hpfs/Kconfig
@@ -1,6 +1,7 @@
 config HPFS_FS
 	tristate "OS/2 HPFS file system support"
 	depends on BLOCK
+	depends on BKL # nontrivial to fix
 	help
 	  OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
 	  is the file system used for organizing files on OS/2 hard disk
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 2607010..c969a1a 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -477,11 +477,15 @@
 
 	int o;
 
+	lock_kernel();
+
 	save_mount_options(s, options);
 
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-	if (!sbi)
+	if (!sbi) {
+		unlock_kernel();
 		return -ENOMEM;
+	}
 	s->s_fs_info = sbi;
 
 	sbi->sb_bmp_dir = NULL;
@@ -666,6 +670,7 @@
 			root->i_blocks = 5;
 		hpfs_brelse4(&qbh);
 	}
+	unlock_kernel();
 	return 0;
 
 bail4:	brelse(bh2);
@@ -677,6 +682,7 @@
 	kfree(sbi->sb_cp_table);
 	s->s_fs_info = NULL;
 	kfree(sbi);
+	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 7b02772..4e2a45e 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -598,6 +598,7 @@
 	.readdir	= hppfs_readdir,
 	.open		= hppfs_dir_open,
 	.fsync		= hppfs_fsync,
+	.llseek		= default_llseek,
 };
 
 static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 6e5bd42..113eba3 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -674,6 +674,7 @@
 	.mmap			= hugetlbfs_file_mmap,
 	.fsync			= noop_fsync,
 	.get_unmapped_area	= hugetlb_get_unmapped_area,
+	.llseek		= default_llseek,
 };
 
 static const struct inode_operations hugetlbfs_dir_inode_operations = {
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index e0aca9a..0542b6e 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -10,7 +10,6 @@
  *
  *  isofs directory handling functions
  */
-#include <linux/smp_lock.h>
 #include <linux/gfp.h>
 #include "isofs.h"
 
@@ -255,18 +254,19 @@
 	char *tmpname;
 	struct iso_directory_record *tmpde;
 	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
 
 	tmpname = (char *)__get_free_page(GFP_KERNEL);
 	if (tmpname == NULL)
 		return -ENOMEM;
 
-	lock_kernel();
+	mutex_lock(&sbi->s_mutex);
 	tmpde = (struct iso_directory_record *) (tmpname+1024);
 
 	result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
 
 	free_page((unsigned long) tmpname);
-	unlock_kernel();
+	mutex_unlock(&sbi->s_mutex);
 	return result;
 }
 
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 5a44811..09ff41a 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/nls.h>
 #include <linux/ctype.h>
-#include <linux/smp_lock.h>
 #include <linux/statfs.h>
 #include <linux/cdrom.h>
 #include <linux/parser.h>
@@ -44,11 +43,7 @@
 	struct isofs_sb_info *sbi = ISOFS_SB(sb);
 
 #ifdef CONFIG_JOLIET
-	lock_kernel();
-
 	unload_nls(sbi->s_nls_iocharset);
-
-	unlock_kernel();
 #endif
 
 	kfree(sbi);
@@ -823,6 +818,7 @@
 	sbi->s_utf8 = opt.utf8;
 	sbi->s_nocompress = opt.nocompress;
 	sbi->s_overriderockperm = opt.overriderockperm;
+	mutex_init(&sbi->s_mutex);
 	/*
 	 * It would be incredibly stupid to allow people to mark every file
 	 * on the disk as suid, so we merely allow them to set the default
@@ -977,8 +973,6 @@
 	int section, rv, error;
 	struct iso_inode_info *ei = ISOFS_I(inode);
 
-	lock_kernel();
-
 	error = -EIO;
 	rv = 0;
 	if (iblock < 0 || iblock != iblock_s) {
@@ -1054,7 +1048,6 @@
 
 	error = 0;
 abort:
-	unlock_kernel();
 	return rv != 0 ? rv : error;
 }
 
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 7d33de8..2882dc0 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -55,6 +55,7 @@
 	gid_t s_gid;
 	uid_t s_uid;
 	struct nls_table *s_nls_iocharset; /* Native language support table */
+	struct mutex s_mutex; /* replaces BKL, please remove if possible */
 };
 
 #define ISOFS_INVALID_MODE ((mode_t) -1)
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index ab438be..0d23abf 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -6,7 +6,6 @@
  *  (C) 1991  Linus Torvalds - minix filesystem
  */
 
-#include <linux/smp_lock.h>
 #include <linux/gfp.h>
 #include "isofs.h"
 
@@ -168,6 +167,7 @@
 	int found;
 	unsigned long uninitialized_var(block);
 	unsigned long uninitialized_var(offset);
+	struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
 	struct inode *inode;
 	struct page *page;
 
@@ -177,7 +177,7 @@
 	if (!page)
 		return ERR_PTR(-ENOMEM);
 
-	lock_kernel();
+	mutex_lock(&sbi->s_mutex);
 	found = isofs_find_entry(dir, dentry,
 				&block, &offset,
 				page_address(page),
@@ -188,10 +188,10 @@
 	if (found) {
 		inode = isofs_iget(dir->i_sb, block, offset);
 		if (IS_ERR(inode)) {
-			unlock_kernel();
+			mutex_unlock(&sbi->s_mutex);
 			return ERR_CAST(inode);
 		}
 	}
-	unlock_kernel();
+	mutex_unlock(&sbi->s_mutex);
 	return d_splice_alias(inode, dentry);
 }
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 96a685c..f9cd04d 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -8,7 +8,6 @@
 
 #include <linux/slab.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 #include "isofs.h"
 #include "rock.h"
@@ -661,6 +660,7 @@
 {
 	struct inode *inode = page->mapping->host;
 	struct iso_inode_info *ei = ISOFS_I(inode);
+	struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
 	char *link = kmap(page);
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	struct buffer_head *bh;
@@ -673,12 +673,12 @@
 	struct rock_state rs;
 	int ret;
 
-	if (!ISOFS_SB(inode->i_sb)->s_rock)
+	if (!sbi->s_rock)
 		goto error;
 
 	init_rock_state(&rs, inode);
 	block = ei->i_iget5_block;
-	lock_kernel();
+	mutex_lock(&sbi->s_mutex);
 	bh = sb_bread(inode->i_sb, block);
 	if (!bh)
 		goto out_noread;
@@ -748,7 +748,7 @@
 		goto fail;
 	brelse(bh);
 	*rpnt = '\0';
-	unlock_kernel();
+	mutex_unlock(&sbi->s_mutex);
 	SetPageUptodate(page);
 	kunmap(page);
 	unlock_page(page);
@@ -765,7 +765,7 @@
 	printk("symlink spans iso9660 blocks\n");
 fail:
 	brelse(bh);
-	unlock_kernel();
+	mutex_unlock(&sbi->s_mutex);
 error:
 	SetPageError(page);
 	kunmap(page);
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 95d8c11..85a6883 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -137,34 +137,10 @@
 	JBUFFER_TRACE(descriptor, "write commit block");
 	set_buffer_dirty(bh);
 
-	if (journal->j_flags & JFS_BARRIER) {
-		ret = __sync_dirty_buffer(bh, WRITE_SYNC | WRITE_BARRIER);
-
-		/*
-		 * Is it possible for another commit to fail at roughly
-		 * the same time as this one?  If so, we don't want to
-		 * trust the barrier flag in the super, but instead want
-		 * to remember if we sent a barrier request
-		 */
-		if (ret == -EOPNOTSUPP) {
-			char b[BDEVNAME_SIZE];
-
-			printk(KERN_WARNING
-				"JBD: barrier-based sync failed on %s - "
-				"disabling barriers\n",
-				bdevname(journal->j_dev, b));
-			spin_lock(&journal->j_state_lock);
-			journal->j_flags &= ~JFS_BARRIER;
-			spin_unlock(&journal->j_state_lock);
-
-			/* And try again, without the barrier */
-			set_buffer_uptodate(bh);
-			set_buffer_dirty(bh);
-			ret = sync_dirty_buffer(bh);
-		}
-	} else {
+	if (journal->j_flags & JFS_BARRIER)
+		ret = __sync_dirty_buffer(bh, WRITE_SYNC | WRITE_FLUSH_FUA);
+	else
 		ret = sync_dirty_buffer(bh);
-	}
 
 	put_bh(bh);		/* One for getblk() */
 	journal_put_journal_head(descriptor);
@@ -318,7 +294,7 @@
 	int first_tag = 0;
 	int tag_flag;
 	int i;
-	int write_op = WRITE;
+	int write_op = WRITE_SYNC;
 
 	/*
 	 * First job: lock down the current transaction and wait for
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 5247e7f..6571a05 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -532,8 +532,7 @@
 	 */
 	if ((journal->j_fs_dev != journal->j_dev) &&
 	    (journal->j_flags & JBD2_BARRIER))
-		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
+		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
 	if (!(journal->j_flags & JBD2_ABORT))
 		jbd2_journal_update_superblock(journal, 1);
 	return 0;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 7c068c1..bc6be8b 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -134,25 +134,11 @@
 
 	if (journal->j_flags & JBD2_BARRIER &&
 	    !JBD2_HAS_INCOMPAT_FEATURE(journal,
-				       JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
-		ret = submit_bh(WRITE_SYNC_PLUG | WRITE_BARRIER, bh);
-		if (ret == -EOPNOTSUPP) {
-			printk(KERN_WARNING
-			       "JBD2: Disabling barriers on %s, "
-			       "not supported by device\n", journal->j_devname);
-			write_lock(&journal->j_state_lock);
-			journal->j_flags &= ~JBD2_BARRIER;
-			write_unlock(&journal->j_state_lock);
-
-			/* And try again, without the barrier */
-			lock_buffer(bh);
-			set_buffer_uptodate(bh);
-			clear_buffer_dirty(bh);
-			ret = submit_bh(WRITE_SYNC_PLUG, bh);
-		}
-	} else {
+				       JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT))
+		ret = submit_bh(WRITE_SYNC_PLUG | WRITE_FLUSH_FUA, bh);
+	else
 		ret = submit_bh(WRITE_SYNC_PLUG, bh);
-	}
+
 	*cbh = bh;
 	return ret;
 }
@@ -166,29 +152,8 @@
 {
 	int ret = 0;
 
-retry:
 	clear_buffer_dirty(bh);
 	wait_on_buffer(bh);
-	if (buffer_eopnotsupp(bh) && (journal->j_flags & JBD2_BARRIER)) {
-		printk(KERN_WARNING
-		       "JBD2: %s: disabling barries on %s - not supported "
-		       "by device\n", __func__, journal->j_devname);
-		write_lock(&journal->j_state_lock);
-		journal->j_flags &= ~JBD2_BARRIER;
-		write_unlock(&journal->j_state_lock);
-
-		lock_buffer(bh);
-		clear_buffer_dirty(bh);
-		set_buffer_uptodate(bh);
-		bh->b_end_io = journal_end_buffer_io_sync;
-
-		ret = submit_bh(WRITE_SYNC_PLUG, bh);
-		if (ret) {
-			unlock_buffer(bh);
-			return ret;
-		}
-		goto retry;
-	}
 
 	if (unlikely(!buffer_uptodate(bh)))
 		ret = -EIO;
@@ -360,7 +325,7 @@
 	int tag_bytes = journal_tag_bytes(journal);
 	struct buffer_head *cbh = NULL; /* For transactional checksums */
 	__u32 crc32_sum = ~0;
-	int write_op = WRITE;
+	int write_op = WRITE_SYNC;
 
 	/*
 	 * First job: lock down the current transaction and wait for
@@ -701,29 +666,6 @@
 		}
 	}
 
-	/* 
-	 * If the journal is not located on the file system device,
-	 * then we must flush the file system device before we issue
-	 * the commit record
-	 */
-	if (commit_transaction->t_flushed_data_blocks &&
-	    (journal->j_fs_dev != journal->j_dev) &&
-	    (journal->j_flags & JBD2_BARRIER))
-		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
-
-	/* Done it all: now write the commit record asynchronously. */
-	if (JBD2_HAS_INCOMPAT_FEATURE(journal,
-				      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
-		err = journal_submit_commit_record(journal, commit_transaction,
-						 &cbh, crc32_sum);
-		if (err)
-			__jbd2_journal_abort_hard(journal);
-		if (journal->j_flags & JBD2_BARRIER)
-			blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL,
-				BLKDEV_IFL_WAIT);
-	}
-
 	err = journal_finish_inode_data_buffers(journal, commit_transaction);
 	if (err) {
 		printk(KERN_WARNING
@@ -734,6 +676,25 @@
 		err = 0;
 	}
 
+	/* 
+	 * If the journal is not located on the file system device,
+	 * then we must flush the file system device before we issue
+	 * the commit record
+	 */
+	if (commit_transaction->t_flushed_data_blocks &&
+	    (journal->j_fs_dev != journal->j_dev) &&
+	    (journal->j_flags & JBD2_BARRIER))
+		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
+
+	/* Done it all: now write the commit record asynchronously. */
+	if (JBD2_HAS_INCOMPAT_FEATURE(journal,
+				      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
+		err = journal_submit_commit_record(journal, commit_transaction,
+						 &cbh, crc32_sum);
+		if (err)
+			__jbd2_journal_abort_hard(journal);
+	}
+
 	/* Lo and behold: we have just managed to send a transaction to
            the log.  Before we can commit it, wait for the IO so far to
            complete.  Control buffers being written are on the
@@ -845,6 +806,11 @@
 	}
 	if (!err && !is_journal_aborted(journal))
 		err = journal_wait_on_commit_record(journal, cbh);
+	if (JBD2_HAS_INCOMPAT_FEATURE(journal,
+				      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) &&
+	    journal->j_flags & JBD2_BARRIER) {
+		blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL);
+	}
 
 	if (err)
 		jbd2_journal_abort(journal, err);
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 6b2964a..d9beb06 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -21,7 +21,6 @@
 #include <linux/vmalloc.h>
 #include <linux/vfs.h>
 #include <linux/crc32.h>
-#include <linux/smp_lock.h>
 #include "nodelist.h"
 
 static int jffs2_flash_setup(struct jffs2_sb_info *c);
@@ -391,7 +390,6 @@
 	   This also catches the case where it was stopped and this
 	   is just a remount to restart it.
 	   Flush the writebuffer, if neccecary, else we loose it */
-	lock_kernel();
 	if (!(sb->s_flags & MS_RDONLY)) {
 		jffs2_stop_garbage_collect_thread(c);
 		mutex_lock(&c->alloc_sem);
@@ -403,8 +401,6 @@
 		jffs2_start_garbage_collect_thread(c);
 
 	*flags |= MS_NOATIME;
-
-	unlock_kernel();
 	return 0;
 }
 
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 662bba0..d1ae5df 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/fs.h>
@@ -146,6 +145,7 @@
 static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct jffs2_sb_info *c;
+	int ret;
 
 	D1(printk(KERN_DEBUG "jffs2_get_sb_mtd():"
 		  " New superblock for device %d (\"%s\")\n",
@@ -175,7 +175,8 @@
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
 	sb->s_flags |= MS_POSIXACL;
 #endif
-	return jffs2_do_fill_super(sb, data, silent);
+	ret = jffs2_do_fill_super(sb, data, silent);
+	return ret;
 }
 
 static int jffs2_get_sb(struct file_system_type *fs_type,
@@ -192,8 +193,6 @@
 
 	D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
 
-	lock_kernel();
-
 	if (sb->s_dirt)
 		jffs2_write_super(sb);
 
@@ -215,8 +214,6 @@
 	if (c->mtd->sync)
 		c->mtd->sync(c->mtd);
 
-	unlock_kernel();
-
 	D1(printk(KERN_DEBUG "jffs2_put_super returning\n"));
 }
 
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index ec8c3e4..68eee2b 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -33,7 +33,6 @@
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <linux/seq_file.h>
-#include <linux/smp_lock.h>
 
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
@@ -176,8 +175,6 @@
 
 	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
 
-	lock_kernel();
-
 	rc = jfs_umount(sb);
 	if (rc)
 		jfs_err("jfs_umount failed with return code %d", rc);
@@ -188,8 +185,6 @@
 	iput(sbi->direct_inode);
 
 	kfree(sbi);
-
-	unlock_kernel();
 }
 
 enum {
@@ -369,19 +364,16 @@
 	if (!parse_options(data, sb, &newLVSize, &flag)) {
 		return -EINVAL;
 	}
-	lock_kernel();
+
 	if (newLVSize) {
 		if (sb->s_flags & MS_RDONLY) {
 			printk(KERN_ERR
 		  "JFS: resize requires volume to be mounted read-write\n");
-			unlock_kernel();
 			return -EROFS;
 		}
 		rc = jfs_extendfs(sb, newLVSize, 0);
-		if (rc) {
-			unlock_kernel();
+		if (rc)
 			return rc;
-		}
 	}
 
 	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
@@ -397,36 +389,30 @@
 		/* mark the fs r/w for quota activity */
 		sb->s_flags &= ~MS_RDONLY;
 
-		unlock_kernel();
 		dquot_resume(sb, -1);
 		return ret;
 	}
 	if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY)) {
 		rc = dquot_suspend(sb, -1);
 		if (rc < 0) {
-			unlock_kernel();
 			return rc;
 		}
 		rc = jfs_umount_rw(sb);
 		JFS_SBI(sb)->flag = flag;
-		unlock_kernel();
 		return rc;
 	}
 	if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY))
 		if (!(sb->s_flags & MS_RDONLY)) {
 			rc = jfs_umount_rw(sb);
-			if (rc) {
-				unlock_kernel();
+			if (rc)
 				return rc;
-			}
+
 			JFS_SBI(sb)->flag = flag;
 			ret = jfs_mount_rw(sb, 1);
-			unlock_kernel();
 			return ret;
 		}
 	JFS_SBI(sb)->flag = flag;
 
-	unlock_kernel();
 	return 0;
 }
 
@@ -446,6 +432,7 @@
 	sbi = kzalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
+
 	sb->s_fs_info = sbi;
 	sbi->sb = sb;
 	sbi->uid = sbi->gid = sbi->umask = -1;
diff --git a/fs/locks.c b/fs/locks.c
index ab24d49..8b2b6ad 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -143,6 +143,22 @@
 static LIST_HEAD(file_lock_list);
 static LIST_HEAD(blocked_list);
 
+/*
+ * Protects the two list heads above, plus the inode->i_flock list
+ * FIXME: should use a spinlock, once lockd and ceph are ready.
+ */
+void lock_flocks(void)
+{
+	lock_kernel();
+}
+EXPORT_SYMBOL_GPL(lock_flocks);
+
+void unlock_flocks(void)
+{
+	unlock_kernel();
+}
+EXPORT_SYMBOL_GPL(unlock_flocks);
+
 static struct kmem_cache *filelock_cache __read_mostly;
 
 /* Allocate an empty lock structure. */
@@ -511,9 +527,9 @@
  */
 static void locks_delete_block(struct file_lock *waiter)
 {
-	lock_kernel();
+	lock_flocks();
 	__locks_delete_block(waiter);
-	unlock_kernel();
+	unlock_flocks();
 }
 
 /* Insert waiter into blocker's block list.
@@ -644,7 +660,7 @@
 {
 	struct file_lock *cfl;
 
-	lock_kernel();
+	lock_flocks();
 	for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
 		if (!IS_POSIX(cfl))
 			continue;
@@ -657,7 +673,7 @@
 			fl->fl_pid = pid_vnr(cfl->fl_nspid);
 	} else
 		fl->fl_type = F_UNLCK;
-	unlock_kernel();
+	unlock_flocks();
 	return;
 }
 EXPORT_SYMBOL(posix_test_lock);
@@ -730,18 +746,16 @@
 	int error = 0;
 	int found = 0;
 
-	lock_kernel();
+	if (!(request->fl_flags & FL_ACCESS) && (request->fl_type != F_UNLCK)) {
+		new_fl = locks_alloc_lock();
+		if (!new_fl)
+			return -ENOMEM;
+	}
+
+	lock_flocks();
 	if (request->fl_flags & FL_ACCESS)
 		goto find_conflict;
 
-	if (request->fl_type != F_UNLCK) {
-		error = -ENOMEM;
-		new_fl = locks_alloc_lock();
-		if (new_fl == NULL)
-			goto out;
-		error = 0;
-	}
-
 	for_each_lock(inode, before) {
 		struct file_lock *fl = *before;
 		if (IS_POSIX(fl))
@@ -767,8 +781,11 @@
 	 * If a higher-priority process was blocked on the old file lock,
 	 * give it the opportunity to lock the file.
 	 */
-	if (found)
+	if (found) {
+		unlock_flocks();
 		cond_resched();
+		lock_flocks();
+	}
 
 find_conflict:
 	for_each_lock(inode, before) {
@@ -794,7 +811,7 @@
 	error = 0;
 
 out:
-	unlock_kernel();
+	unlock_flocks();
 	if (new_fl)
 		locks_free_lock(new_fl);
 	return error;
@@ -823,7 +840,7 @@
 		new_fl2 = locks_alloc_lock();
 	}
 
-	lock_kernel();
+	lock_flocks();
 	if (request->fl_type != F_UNLCK) {
 		for_each_lock(inode, before) {
 			fl = *before;
@@ -991,7 +1008,7 @@
 		locks_wake_up_blocks(left);
 	}
  out:
-	unlock_kernel();
+	unlock_flocks();
 	/*
 	 * Free any unused locks.
 	 */
@@ -1066,14 +1083,14 @@
 	/*
 	 * Search the lock list for this inode for any POSIX locks.
 	 */
-	lock_kernel();
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (!IS_POSIX(fl))
 			continue;
 		if (fl->fl_owner != owner)
 			break;
 	}
-	unlock_kernel();
+	unlock_flocks();
 	return fl ? -EAGAIN : 0;
 }
 
@@ -1186,7 +1203,7 @@
 
 	new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK);
 
-	lock_kernel();
+	lock_flocks();
 
 	time_out_leases(inode);
 
@@ -1247,8 +1264,10 @@
 			break_time++;
 	}
 	locks_insert_block(flock, new_fl);
+	unlock_flocks();
 	error = wait_event_interruptible_timeout(new_fl->fl_wait,
 						!new_fl->fl_next, break_time);
+	lock_flocks();
 	__locks_delete_block(new_fl);
 	if (error >= 0) {
 		if (error == 0)
@@ -1263,7 +1282,7 @@
 	}
 
 out:
-	unlock_kernel();
+	unlock_flocks();
 	if (!IS_ERR(new_fl))
 		locks_free_lock(new_fl);
 	return error;
@@ -1319,7 +1338,7 @@
 	struct file_lock *fl;
 	int type = F_UNLCK;
 
-	lock_kernel();
+	lock_flocks();
 	time_out_leases(filp->f_path.dentry->d_inode);
 	for (fl = filp->f_path.dentry->d_inode->i_flock; fl && IS_LEASE(fl);
 			fl = fl->fl_next) {
@@ -1328,7 +1347,7 @@
 			break;
 		}
 	}
-	unlock_kernel();
+	unlock_flocks();
 	return type;
 }
 
@@ -1341,7 +1360,7 @@
  *	The (input) flp->fl_lmops->fl_break function is required
  *	by break_lease().
  *
- *	Called with kernel lock held.
+ *	Called with file_lock_lock held.
  */
 int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
 {
@@ -1436,7 +1455,15 @@
 }
 EXPORT_SYMBOL(generic_setlease);
 
- /**
+static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
+{
+	if (filp->f_op && filp->f_op->setlease)
+		return filp->f_op->setlease(filp, arg, lease);
+	else
+		return generic_setlease(filp, arg, lease);
+}
+
+/**
  *	vfs_setlease        -       sets a lease on an open file
  *	@filp: file pointer
  *	@arg: type of lease to obtain
@@ -1467,12 +1494,9 @@
 {
 	int error;
 
-	lock_kernel();
-	if (filp->f_op && filp->f_op->setlease)
-		error = filp->f_op->setlease(filp, arg, lease);
-	else
-		error = generic_setlease(filp, arg, lease);
-	unlock_kernel();
+	lock_flocks();
+	error = __vfs_setlease(filp, arg, lease);
+	unlock_flocks();
 
 	return error;
 }
@@ -1499,9 +1523,9 @@
 	if (error)
 		return error;
 
-	lock_kernel();
+	lock_flocks();
 
-	error = vfs_setlease(filp, arg, &flp);
+	error = __vfs_setlease(filp, arg, &flp);
 	if (error || arg == F_UNLCK)
 		goto out_unlock;
 
@@ -1516,7 +1540,7 @@
 
 	error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
 out_unlock:
-	unlock_kernel();
+	unlock_flocks();
 	return error;
 }
 
@@ -2020,7 +2044,7 @@
 			fl.fl_ops->fl_release_private(&fl);
 	}
 
-	lock_kernel();
+	lock_flocks();
 	before = &inode->i_flock;
 
 	while ((fl = *before) != NULL) {
@@ -2038,7 +2062,7 @@
  		}
 		before = &fl->fl_next;
 	}
-	unlock_kernel();
+	unlock_flocks();
 }
 
 /**
@@ -2053,12 +2077,12 @@
 {
 	int status = 0;
 
-	lock_kernel();
+	lock_flocks();
 	if (waiter->fl_next)
 		__locks_delete_block(waiter);
 	else
 		status = -ENOENT;
-	unlock_kernel();
+	unlock_flocks();
 	return status;
 }
 
@@ -2172,7 +2196,7 @@
 
 static void *locks_start(struct seq_file *f, loff_t *pos)
 {
-	lock_kernel();
+	lock_flocks();
 	f->private = (void *)1;
 	return seq_list_start(&file_lock_list, *pos);
 }
@@ -2184,7 +2208,7 @@
 
 static void locks_stop(struct seq_file *f, void *v)
 {
-	unlock_kernel();
+	unlock_flocks();
 }
 
 static const struct seq_operations locks_seq_operations = {
@@ -2231,7 +2255,7 @@
 {
 	struct file_lock *fl;
 	int result = 1;
-	lock_kernel();
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (IS_POSIX(fl)) {
 			if (fl->fl_type == F_RDLCK)
@@ -2248,7 +2272,7 @@
 		result = 0;
 		break;
 	}
-	unlock_kernel();
+	unlock_flocks();
 	return result;
 }
 
@@ -2271,7 +2295,7 @@
 {
 	struct file_lock *fl;
 	int result = 1;
-	lock_kernel();
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (IS_POSIX(fl)) {
 			if ((fl->fl_end < start) || (fl->fl_start > (start + len)))
@@ -2286,7 +2310,7 @@
 		result = 0;
 		break;
 	}
-	unlock_kernel();
+	unlock_flocks();
 	return result;
 }
 
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 9777eb5..1eb4e89 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -827,4 +827,5 @@
 	.unlocked_ioctl	= logfs_ioctl,
 	.readdir	= logfs_readdir,
 	.read		= generic_read_dir,
+	.llseek		= default_llseek,
 };
diff --git a/fs/namespace.c b/fs/namespace.c
index a72eaab..7ca5182 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1744,9 +1744,7 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	lock_kernel();
 	mnt = do_kern_mount(type, flags, name, data);
-	unlock_kernel();
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
 
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 9578cbe..aac8832e 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -95,6 +95,34 @@
 };
 
 
+#define ncp_namespace(i)	(NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
+
+static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
+{
+#ifdef CONFIG_NCPFS_SMALLDOS
+	int ns = ncp_namespace(i);
+
+	if ((ns == NW_NS_DOS)
+#ifdef CONFIG_NCPFS_OS2_NS
+		|| ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
+#endif /* CONFIG_NCPFS_OS2_NS */
+	   )
+		return 0;
+#endif /* CONFIG_NCPFS_SMALLDOS */
+	return 1;
+}
+
+#define ncp_preserve_case(i)	(ncp_namespace(i) != NW_NS_DOS)
+
+static inline int ncp_case_sensitive(struct dentry *dentry)
+{
+#ifdef CONFIG_NCPFS_NFS_NS
+	return ncp_namespace(dentry->d_inode) == NW_NS_NFS;
+#else
+	return 0;
+#endif /* CONFIG_NCPFS_NFS_NS */
+}
+
 /*
  * Note: leave the hash unchanged if the directory
  * is case-sensitive.
@@ -102,13 +130,12 @@
 static int 
 ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
 {
-	struct nls_table *t;
-	unsigned long hash;
-	int i;
+	if (!ncp_case_sensitive(dentry)) {
+		struct nls_table *t;
+		unsigned long hash;
+		int i;
 
-	t = NCP_IO_TABLE(dentry);
-
-	if (!ncp_case_sensitive(dentry->d_inode)) {
+		t = NCP_IO_TABLE(dentry);
 		hash = init_name_hash();
 		for (i=0; i<this->len ; i++)
 			hash = partial_name_hash(ncp_tolower(t, this->name[i]),
@@ -124,7 +151,7 @@
 	if (a->len != b->len)
 		return 1;
 
-	if (ncp_case_sensitive(dentry->d_inode))
+	if (ncp_case_sensitive(dentry))
 		return strncmp(a->name, b->name, a->len);
 
 	return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
@@ -266,7 +293,7 @@
 
 
 static int
-__ncp_lookup_validate(struct dentry *dentry)
+ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
 {
 	struct ncp_server *server;
 	struct dentry *parent;
@@ -283,9 +310,6 @@
 
 	server = NCP_SERVER(dir);
 
-	if (!ncp_conn_valid(server))
-		goto finished;
-
 	/*
 	 * Inspired by smbfs:
 	 * The default validation is based on dentry age:
@@ -304,8 +328,11 @@
 	if (ncp_is_server_root(dir)) {
 		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 				 dentry->d_name.len, 1);
-		if (!res)
+		if (!res) {
 			res = ncp_lookup_volume(server, __name, &(finfo.i));
+			if (!res)
+				ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
+		}
 	} else {
 		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 				 dentry->d_name.len, !ncp_preserve_case(dir));
@@ -320,13 +347,17 @@
 	 * what we remember, it's not valid any more.
 	 */
 	if (!res) {
-		if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) {
+		struct inode *inode = dentry->d_inode;
+
+		mutex_lock(&inode->i_mutex);
+		if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
 			ncp_new_dentry(dentry);
 			val=1;
 		} else
 			DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
 
-		ncp_update_inode2(dentry->d_inode, &finfo);
+		ncp_update_inode2(inode, &finfo);
+		mutex_unlock(&inode->i_mutex);
 	}
 
 finished:
@@ -335,16 +366,6 @@
 	return val;
 }
 
-static int
-ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
-{
-	int res;
-	lock_kernel();
-	res = __ncp_lookup_validate(dentry);
-	unlock_kernel();
-	return res;
-}
-
 static struct dentry *
 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
 {
@@ -411,8 +432,6 @@
 	int result, mtime_valid = 0;
 	time_t mtime = 0;
 
-	lock_kernel();
-
 	ctl.page  = NULL;
 	ctl.cache = NULL;
 
@@ -421,6 +440,7 @@
 		(int) filp->f_pos);
 
 	result = -EIO;
+	/* Do not generate '.' and '..' when server is dead. */
 	if (!ncp_conn_valid(server))
 		goto out;
 
@@ -532,6 +552,12 @@
 	ctl.head.end = ctl.fpos - 1;
 	ctl.head.eof = ctl.valid;
 finished:
+	if (ctl.page) {
+		kunmap(ctl.page);
+		SetPageUptodate(ctl.page);
+		unlock_page(ctl.page);
+		page_cache_release(ctl.page);
+	}
 	if (page) {
 		cache->head = ctl.head;
 		kunmap(page);
@@ -539,23 +565,17 @@
 		unlock_page(page);
 		page_cache_release(page);
 	}
-	if (ctl.page) {
-		kunmap(ctl.page);
-		SetPageUptodate(ctl.page);
-		unlock_page(ctl.page);
-		page_cache_release(ctl.page);
-	}
 out:
-	unlock_kernel();
 	return result;
 }
 
 static int
 ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-		struct ncp_cache_control *ctrl, struct ncp_entry_info *entry)
+		struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
+		int inval_childs)
 {
 	struct dentry *newdent, *dentry = filp->f_path.dentry;
-	struct inode *newino, *inode = dentry->d_inode;
+	struct inode *dir = dentry->d_inode;
 	struct ncp_cache_control ctl = *ctrl;
 	struct qstr qname;
 	int valid = 0;
@@ -564,9 +584,9 @@
 	__u8 __name[NCP_MAXPATHLEN + 1];
 
 	qname.len = sizeof(__name);
-	if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len,
+	if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
 			entry->i.entryName, entry->i.nameLen,
-			!ncp_preserve_entry_case(inode, entry->i.NSCreator)))
+			!ncp_preserve_entry_case(dir, entry->i.NSCreator)))
 		return 1; /* I'm not sure */
 
 	qname.name = __name;
@@ -584,22 +604,64 @@
 			goto end_advance;
 	} else {
 		hashed = 1;
-		memcpy((char *) newdent->d_name.name, qname.name,
-							newdent->d_name.len);
+
+		/* If case sensitivity changed for this volume, all entries below this one
+		   should be thrown away.  This entry itself is not affected, as its case
+		   sensitivity is controlled by its own parent. */
+		if (inval_childs)
+			shrink_dcache_parent(newdent);
+
+		/*
+		 * It is not as dangerous as it looks.  NetWare's OS2 namespace is
+		 * case preserving yet case insensitive.  So we update dentry's name
+		 * as received from server.  We found dentry via d_lookup with our
+		 * hash, so we know that hash does not change, and so replacing name
+		 * should be reasonably safe.
+		 */
+		if (qname.len == newdent->d_name.len &&
+		    memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) {
+			struct inode *inode = newdent->d_inode;
+
+			/*
+			 * Inside ncpfs all uses of d_name are either for debugging,
+			 * or on functions which acquire inode mutex (mknod, creat,
+			 * lookup).  So grab i_mutex here, to be sure.  d_path
+			 * uses dcache_lock when generating path, so we should too.
+			 * And finally d_compare is protected by dentry's d_lock, so
+			 * here we go.
+			 */
+			if (inode)
+				mutex_lock(&inode->i_mutex);
+			spin_lock(&dcache_lock);
+			spin_lock(&newdent->d_lock);
+			memcpy((char *) newdent->d_name.name, qname.name,
+								newdent->d_name.len);
+			spin_unlock(&newdent->d_lock);
+			spin_unlock(&dcache_lock);
+			if (inode)
+				mutex_unlock(&inode->i_mutex);
+		}
 	}
 
 	if (!newdent->d_inode) {
+		struct inode *inode;
+
 		entry->opened = 0;
-		entry->ino = iunique(inode->i_sb, 2);
-		newino = ncp_iget(inode->i_sb, entry);
-		if (newino) {
+		entry->ino = iunique(dir->i_sb, 2);
+		inode = ncp_iget(dir->i_sb, entry);
+		if (inode) {
 			newdent->d_op = &ncp_dentry_operations;
-			d_instantiate(newdent, newino);
+			d_instantiate(newdent, inode);
 			if (!hashed)
 				d_rehash(newdent);
 		}
-	} else
-		ncp_update_inode2(newdent->d_inode, entry);
+	} else {
+		struct inode *inode = newdent->d_inode;
+
+		mutex_lock(&inode->i_mutex);
+		ncp_update_inode2(inode, entry);
+		mutex_unlock(&inode->i_mutex);
+	}
 
 	if (newdent->d_inode) {
 		ino = newdent->d_inode->i_ino;
@@ -617,7 +679,7 @@
 		ctl.cache = NULL;
 		ctl.idx  -= NCP_DIRCACHE_SIZE;
 		ctl.ofs  += 1;
-		ctl.page  = grab_cache_page(&inode->i_data, ctl.ofs);
+		ctl.page  = grab_cache_page(&dir->i_data, ctl.ofs);
 		if (ctl.page)
 			ctl.cache = kmap(ctl.page);
 	}
@@ -633,7 +695,7 @@
 		if (!ino)
 			ino = find_inode_number(dentry, &qname);
 		if (!ino)
-			ino = iunique(inode->i_sb, 2);
+			ino = iunique(dir->i_sb, 2);
 		ctl.filled = filldir(dirent, qname.name, qname.len,
 				     filp->f_pos, ino, DT_UNKNOWN);
 		if (!ctl.filled)
@@ -660,6 +722,7 @@
 			(unsigned long) filp->f_pos);
 
 	for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
+		int inval_dentry;
 
 		if (ncp_get_volume_info_with_number(server, i, &info) != 0)
 			return;
@@ -675,8 +738,9 @@
 				info.volume_name);
 			continue;
 		}
+		inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
 		entry.volume = entry.i.volNumber;
-		if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
+		if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
 			return;
 	}
 }
@@ -739,7 +803,7 @@
 			rpl += onerpl;
 			rpls -= onerpl;
 			entry.volume = entry.i.volNumber;
-			if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
+			if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
 				break;
 		}
 	} while (more);
@@ -775,17 +839,19 @@
 		if (dent) {
 			struct inode* ino = dent->d_inode;
 			if (ino) {
+				ncp_update_known_namespace(server, volNumber, NULL);
 				NCP_FINFO(ino)->volNumber = volNumber;
 				NCP_FINFO(ino)->dirEntNum = dirEntNum;
 				NCP_FINFO(ino)->DosDirNum = DosDirNum;
+				result = 0;
 			} else {
 				DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
 			}
 		} else {
 			DPRINTK("ncpfs: sb->s_root == NULL!\n");
 		}
-	}
-	result = 0;
+	} else
+		result = 0;
 
 out:
 	return result;
@@ -799,7 +865,6 @@
 	int error, res, len;
 	__u8 __name[NCP_MAXPATHLEN + 1];
 
-	lock_kernel();
 	error = -EIO;
 	if (!ncp_conn_valid(server))
 		goto finished;
@@ -813,6 +878,8 @@
 				 dentry->d_name.len, 1);
 		if (!res)
 			res = ncp_lookup_volume(server, __name, &(finfo.i));
+			if (!res)
+				ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
 	} else {
 		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 				 dentry->d_name.len, !ncp_preserve_case(dir));
@@ -846,7 +913,6 @@
 
 finished:
 	PPRINTK("ncp_lookup: result=%d\n", error);
-	unlock_kernel();
 	return ERR_PTR(error);
 }
 
@@ -887,11 +953,6 @@
 	PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name, mode);
 
-	error = -EIO;
-	lock_kernel();
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	ncp_age_dentry(server, dentry);
 	len = sizeof(__name);
 	error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -917,6 +978,8 @@
 		if (result) {
 			if (result == 0x87)
 				error = -ENAMETOOLONG;
+			else if (result < 0)
+				error = result;
 			DPRINTK("ncp_create: %s/%s failed\n",
 				dentry->d_parent->d_name.name, dentry->d_name.name);
 			goto out;
@@ -935,7 +998,6 @@
 
 	error = ncp_instantiate(dir, dentry, &finfo);
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -955,11 +1017,6 @@
 	DPRINTK("ncp_mkdir: making %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	error = -EIO;
-	lock_kernel();
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	ncp_age_dentry(server, dentry);
 	len = sizeof(__name);
 	error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -967,12 +1024,11 @@
 	if (error)
 		goto out;
 
-	error = -EACCES;
-	if (ncp_open_create_file_or_subdir(server, dir, __name,
+	error = ncp_open_create_file_or_subdir(server, dir, __name,
 					   OC_MODE_CREATE, aDIR,
 					   cpu_to_le16(0xffff),
-					   &finfo) == 0)
-	{
+					   &finfo);
+	if (error == 0) {
 		if (ncp_is_nfs_extras(server, finfo.volume)) {
 			mode |= S_IFDIR;
 			finfo.i.nfs.mode = mode;
@@ -983,9 +1039,10 @@
 				goto out;
 		}
 		error = ncp_instantiate(dir, dentry, &finfo);
+	} else if (error > 0) {
+		error = -EACCES;
 	}
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -998,11 +1055,6 @@
 	DPRINTK("ncp_rmdir: removing %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	error = -EIO;
-	lock_kernel();
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	error = -EBUSY;
 	if (!d_unhashed(dentry))
 		goto out;
@@ -1036,11 +1088,10 @@
 			error = -ENOENT;
 			break;
 		default:
-			error = -EACCES;
+			error = result < 0 ? result : -EACCES;
 			break;
        	}
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -1050,15 +1101,10 @@
 	struct ncp_server *server;
 	int error;
 
-	lock_kernel();
 	server = NCP_SERVER(dir);
 	DPRINTK("ncp_unlink: unlinking %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 	
-	error = -EIO;
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	/*
 	 * Check whether to close the file ...
 	 */
@@ -1097,12 +1143,9 @@
 			error = -ENOENT;
 			break;
 		default:
-			error = -EACCES;
+			error = error < 0 ? error : -EACCES;
 			break;
 	}
-		
-out:
-	unlock_kernel();
 	return error;
 }
 
@@ -1118,11 +1161,6 @@
 		old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
 		new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
 
-	error = -EIO;
-	lock_kernel();
-	if (!ncp_conn_valid(server))
-		goto out;
-
 	ncp_age_dentry(server, old_dentry);
 	ncp_age_dentry(server, new_dentry);
 
@@ -1161,11 +1199,10 @@
 			error = -ENOENT;
 			break;
 		default:
-			error = -EACCES;
+			error = error < 0 ? error : -EACCES;
 			break;
 	}
 out:
-	unlock_kernel();
 	return error;
 }
 
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 3639cc5..6c754f7 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -113,9 +113,6 @@
 	DPRINTK("ncp_file_read: enter %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	if (!ncp_conn_valid(NCP_SERVER(inode)))
-		return -EIO;
-
 	pos = *ppos;
 
 	if ((ssize_t) count < 0) {
@@ -192,13 +189,11 @@
 
 	DPRINTK("ncp_file_write: enter %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
-	if (!ncp_conn_valid(NCP_SERVER(inode)))
-		return -EIO;
 	if ((ssize_t) count < 0)
 		return -EINVAL;
 	pos = *ppos;
 	if (file->f_flags & O_APPEND) {
-		pos = inode->i_size;
+		pos = i_size_read(inode);
 	}
 
 	if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
@@ -264,8 +259,11 @@
 
 	*ppos = pos;
 
-	if (pos > inode->i_size) {
-		inode->i_size = pos;
+	if (pos > i_size_read(inode)) {
+		mutex_lock(&inode->i_mutex);
+		if (pos > i_size_read(inode))
+			i_size_write(inode, pos);
+		mutex_unlock(&inode->i_mutex);
 	}
 	DPRINTK("ncp_file_write: exit %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -281,18 +279,9 @@
 	return 0;
 }
 
-static loff_t ncp_remote_llseek(struct file *file, loff_t offset, int origin)
-{
-	loff_t ret;
-	lock_kernel();
-	ret = generic_file_llseek_unlocked(file, offset, origin);
-	unlock_kernel();
-	return ret;
-}
-
 const struct file_operations ncp_file_operations =
 {
-	.llseek 	= ncp_remote_llseek,
+	.llseek		= generic_file_llseek,
 	.read		= ncp_file_read,
 	.write		= ncp_file_write,
 	.unlocked_ioctl	= ncp_ioctl,
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index b4de38c..985fabb 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -139,7 +139,7 @@
 		inode->i_mode = nwi->nfs.mode;
 	}
 
-	inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
+	inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
 
 	inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
 	inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
@@ -158,18 +158,21 @@
 		inode->i_mode = server->m.dir_mode;
 		/* for directories dataStreamSize seems to be some
 		   Object ID ??? */
-		inode->i_size = NCP_BLOCK_SIZE;
+		i_size_write(inode, NCP_BLOCK_SIZE);
 	} else {
+		u32 size;
+
 		inode->i_mode = server->m.file_mode;
-		inode->i_size = le32_to_cpu(nwi->dataStreamSize);
+		size = le32_to_cpu(nwi->dataStreamSize);
+		i_size_write(inode, size);
 #ifdef CONFIG_NCPFS_EXTRAS
 		if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
 		 && (nwi->attributes & aSHARED)) {
 			switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
 				case aHIDDEN:
 					if (server->m.flags & NCP_MOUNT_SYMLINKS) {
-						if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
-						 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+						if (/* (size >= NCP_MIN_SYMLINK_SIZE)
+						 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
 							inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
 							NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
 							break;
@@ -208,7 +211,7 @@
 }
 
 /*
- * Fill in the inode based on the ncp_entry_info structure.
+ * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
  */
 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 {
@@ -254,6 +257,7 @@
 	if (inode) {
 		atomic_set(&NCP_FINFO(inode)->opened, info->opened);
 
+		inode->i_mapping->backing_dev_info = sb->s_bdi;
 		inode->i_ino = info->ino;
 		ncp_set_attr(inode, info);
 		if (S_ISREG(inode->i_mode)) {
@@ -299,10 +303,12 @@
 
 static void ncp_stop_tasks(struct ncp_server *server) {
 	struct sock* sk = server->ncp_sock->sk;
-		
+
+	lock_sock(sk);
 	sk->sk_error_report = server->error_report;
 	sk->sk_data_ready   = server->data_ready;
 	sk->sk_write_space  = server->write_space;
+	release_sock(sk);
 	del_timer_sync(&server->timeout_tm);
 	flush_scheduled_work();
 }
@@ -565,10 +571,12 @@
 /*	server->conn_status = 0;	*/
 /*	server->root_dentry = NULL;	*/
 /*	server->root_setuped = 0;	*/
+	mutex_init(&server->root_setup_lock);
 #ifdef CONFIG_NCPFS_PACKET_SIGNING
 /*	server->sign_wanted = 0;	*/
 /*	server->sign_active = 0;	*/
 #endif
+	init_rwsem(&server->auth_rwsem);
 	server->auth.auth_type = NCP_AUTH_NONE;
 /*	server->auth.object_name_len = 0;	*/
 /*	server->auth.object_name = NULL;	*/
@@ -593,16 +601,12 @@
 	server->nls_io = load_nls_default();
 #endif /* CONFIG_NCPFS_NLS */
 
-	server->dentry_ttl = 0;	/* no caching */
+	atomic_set(&server->dentry_ttl, 0);	/* no caching */
 
 	INIT_LIST_HEAD(&server->tx.requests);
 	mutex_init(&server->rcv.creq_mutex);
 	server->tx.creq		= NULL;
 	server->rcv.creq	= NULL;
-	server->data_ready	= sock->sk->sk_data_ready;
-	server->write_space	= sock->sk->sk_write_space;
-	server->error_report	= sock->sk->sk_error_report;
-	sock->sk->sk_user_data	= server;
 
 	init_timer(&server->timeout_tm);
 #undef NCP_PACKET_SIZE
@@ -619,6 +623,11 @@
 	if (server->rxbuf == NULL)
 		goto out_txbuf;
 
+	lock_sock(sock->sk);
+	server->data_ready	= sock->sk->sk_data_ready;
+	server->write_space	= sock->sk->sk_write_space;
+	server->error_report	= sock->sk->sk_error_report;
+	sock->sk->sk_user_data	= server;
 	sock->sk->sk_data_ready	  = ncp_tcp_data_ready;
 	sock->sk->sk_error_report = ncp_tcp_error_report;
 	if (sock->type == SOCK_STREAM) {
@@ -634,6 +643,7 @@
 		server->timeout_tm.data = (unsigned long)server;
 		server->timeout_tm.function = ncpdgram_timeout_call;
 	}
+	release_sock(sock->sk);
 
 	ncp_lock_server(server);
 	error = ncp_connect(server);
@@ -658,8 +668,10 @@
 				goto out_disconnect;
 			}
 		}
+		ncp_lock_server(server);
 		if (options & 2)
 			server->sign_wanted = 1;
+		ncp_unlock_server(server);
 	}
 	else 
 #endif	/* CONFIG_NCPFS_PACKET_SIGNING */
@@ -720,6 +732,9 @@
 	unload_nls(server->nls_io);
 	unload_nls(server->nls_vol);
 #endif
+	mutex_destroy(&server->rcv.creq_mutex);
+	mutex_destroy(&server->root_setup_lock);
+	mutex_destroy(&server->mutex);
 out_fput2:
 	if (server->info_filp)
 		fput(server->info_filp);
@@ -743,8 +758,6 @@
 {
 	struct ncp_server *server = NCP_SBP(sb);
 
-	lock_kernel();
-
 	ncp_lock_server(server);
 	ncp_disconnect(server);
 	ncp_unlock_server(server);
@@ -756,6 +769,9 @@
 	unload_nls(server->nls_vol);
 	unload_nls(server->nls_io);
 #endif /* CONFIG_NCPFS_NLS */
+	mutex_destroy(&server->rcv.creq_mutex);
+	mutex_destroy(&server->root_setup_lock);
+	mutex_destroy(&server->mutex);
 
 	if (server->info_filp)
 		fput(server->info_filp);
@@ -771,8 +787,6 @@
 	vfree(server->packet);
 	sb->s_fs_info = NULL;
 	kfree(server);
-
-	unlock_kernel();
 }
 
 static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -851,10 +865,8 @@
 
 	result = -EIO;
 
-	lock_kernel();	
-
 	server = NCP_SERVER(inode);
-	if ((!server) || !ncp_conn_valid(server))
+	if (!server)	/* How this could happen? */
 		goto out;
 
 	/* ageing the dentry to force validation */
@@ -981,8 +993,6 @@
 		result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
 				      inode, info_mask, &info);
 		if (result != 0) {
-			result = -EACCES;
-
 			if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
 				/* NetWare seems not to allow this. I
 				   do not know why. So, just tell the
@@ -1005,7 +1015,8 @@
 	mark_inode_dirty(inode);
 
 out:
-	unlock_kernel();
+	if (result > 0)
+		result = -EACCES;
 	return result;
 }
 
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 84a8cfc..c2a1f9a 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -35,16 +35,11 @@
 #define NCP_PACKET_SIZE_INTERNAL 65536
 
 static int
-ncp_get_fs_info(struct ncp_server * server, struct file *file,
+ncp_get_fs_info(struct ncp_server * server, struct inode *inode,
 		struct ncp_fs_info __user *arg)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
 	struct ncp_fs_info info;
 
-	if (file_permission(file, MAY_WRITE) != 0
-	    && current_uid() != server->m.mounted_uid)
-		return -EACCES;
-
 	if (copy_from_user(&info, arg, sizeof(info)))
 		return -EFAULT;
 
@@ -65,16 +60,11 @@
 }
 
 static int
-ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
+ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode,
 		   struct ncp_fs_info_v2 __user * arg)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
 	struct ncp_fs_info_v2 info2;
 
-	if (file_permission(file, MAY_WRITE) != 0
-	    && current_uid() != server->m.mounted_uid)
-		return -EACCES;
-
 	if (copy_from_user(&info2, arg, sizeof(info2)))
 		return -EFAULT;
 
@@ -136,16 +126,11 @@
 #define NCP_IOC_SETPRIVATEDATA_32	_IOR('n', 10, struct compat_ncp_privatedata_ioctl)
 
 static int
-ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
+ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode,
 		   struct compat_ncp_fs_info_v2 __user * arg)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
 	struct compat_ncp_fs_info_v2 info2;
 
-	if (file_permission(file, MAY_WRITE) != 0
-	    && current_uid() != server->m.mounted_uid)
-		return -EACCES;
-
 	if (copy_from_user(&info2, arg, sizeof(info2)))
 		return -EFAULT;
 
@@ -182,11 +167,8 @@
 	struct nls_table *iocharset;
 	struct nls_table *oldset_io;
 	struct nls_table *oldset_cp;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-	if (server->root_setuped)
-		return -EBUSY;
+	int utf8;
+	int err;
 
 	if (copy_from_user(&user, arg, sizeof(user)))
 		return -EFAULT;
@@ -206,28 +188,40 @@
 	user.iocharset[NCP_IOCSNAME_LEN] = 0;
 	if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
 		iocharset = load_nls_default();
-		NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+		utf8 = 0;
 	} else if (!strcmp(user.iocharset, "utf8")) {
 		iocharset = load_nls_default();
-		NCP_SET_FLAG(server, NCP_FLAG_UTF8);
+		utf8 = 1;
 	} else {
 		iocharset = load_nls(user.iocharset);
 		if (!iocharset) {
 			unload_nls(codepage);
 			return -EBADRQC;
 		}
-		NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+		utf8 = 0;
 	}
 
-	oldset_cp = server->nls_vol;
-	server->nls_vol = codepage;
-	oldset_io = server->nls_io;
-	server->nls_io = iocharset;
-
+	mutex_lock(&server->root_setup_lock);
+	if (server->root_setuped) {
+		oldset_cp = codepage;
+		oldset_io = iocharset;
+		err = -EBUSY;
+	} else {
+		if (utf8)
+			NCP_SET_FLAG(server, NCP_FLAG_UTF8);
+		else
+			NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+		oldset_cp = server->nls_vol;
+		server->nls_vol = codepage;
+		oldset_io = server->nls_io;
+		server->nls_io = iocharset;
+		err = 0;
+	}
+	mutex_unlock(&server->root_setup_lock);
 	unload_nls(oldset_cp);
 	unload_nls(oldset_io);
 
-	return 0;
+	return err;
 }
 
 static int
@@ -237,6 +231,7 @@
 	int len;
 
 	memset(&user, 0, sizeof(user));
+	mutex_lock(&server->root_setup_lock);
 	if (server->nls_vol && server->nls_vol->charset) {
 		len = strlen(server->nls_vol->charset);
 		if (len > NCP_IOCSNAME_LEN)
@@ -254,6 +249,7 @@
 		strncpy(user.iocharset,	server->nls_io->charset, len);
 		user.iocharset[len] = 0;
 	}
+	mutex_unlock(&server->root_setup_lock);
 
 	if (copy_to_user(arg, &user, sizeof(user)))
 		return -EFAULT;
@@ -261,25 +257,19 @@
 }
 #endif /* CONFIG_NCPFS_NLS */
 
-static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg)
 {
-	struct inode *inode = filp->f_dentry->d_inode;
 	struct ncp_server *server = NCP_SERVER(inode);
 	int result;
 	struct ncp_ioctl_request request;
 	char* bouncebuffer;
 	void __user *argp = (void __user *)arg;
-	uid_t uid = current_uid();
 
 	switch (cmd) {
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_NCPREQUEST_32:
 #endif
 	case NCP_IOC_NCPREQUEST:
-		if (file_permission(filp, MAY_WRITE) != 0
-		    && uid != server->m.mounted_uid)
-			return -EACCES;
-
 #ifdef CONFIG_COMPAT
 		if (cmd == NCP_IOC_NCPREQUEST_32) {
 			struct compat_ncp_ioctl_request request32;
@@ -314,7 +304,7 @@
 		server->current_size = request.size;
 		memcpy(server->packet, bouncebuffer, request.size);
 
-		result = ncp_request2(server, request.function, 
+		result = ncp_request2(server, request.function,
 			bouncebuffer, NCP_PACKET_SIZE_INTERNAL);
 		if (result < 0)
 			result = -EIO;
@@ -331,69 +321,69 @@
 
 	case NCP_IOC_CONN_LOGGED_IN:
 
-		if (!capable(CAP_SYS_ADMIN))
-			return -EACCES;
 		if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
 			return -EINVAL;
+		mutex_lock(&server->root_setup_lock);
 		if (server->root_setuped)
-			return -EBUSY;
-		server->root_setuped = 1;
-		return ncp_conn_logged_in(inode->i_sb);
+			result = -EBUSY;
+		else {
+			result = ncp_conn_logged_in(inode->i_sb);
+			if (result == 0)
+				server->root_setuped = 1;
+		}
+		mutex_unlock(&server->root_setup_lock);
+		return result;
 
 	case NCP_IOC_GET_FS_INFO:
-		return ncp_get_fs_info(server, filp, argp);
+		return ncp_get_fs_info(server, inode, argp);
 
 	case NCP_IOC_GET_FS_INFO_V2:
-		return ncp_get_fs_info_v2(server, filp, argp);
+		return ncp_get_fs_info_v2(server, inode, argp);
 
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_GET_FS_INFO_V2_32:
-		return ncp_get_compat_fs_info_v2(server, filp, argp);
+		return ncp_get_compat_fs_info_v2(server, inode, argp);
 #endif
 	/* we have too many combinations of CONFIG_COMPAT,
 	 * CONFIG_64BIT and CONFIG_UID16, so just handle
 	 * any of the possible ioctls */
 	case NCP_IOC_GETMOUNTUID16:
-	case NCP_IOC_GETMOUNTUID32:
-	case NCP_IOC_GETMOUNTUID64:
-		if (file_permission(filp, MAY_READ) != 0
-			&& uid != server->m.mounted_uid)
-			return -EACCES;
-
-		if (cmd == NCP_IOC_GETMOUNTUID16) {
+		{
 			u16 uid;
+
 			SET_UID(uid, server->m.mounted_uid);
 			if (put_user(uid, (u16 __user *)argp))
 				return -EFAULT;
-		} else if (cmd == NCP_IOC_GETMOUNTUID32) {
-			if (put_user(server->m.mounted_uid,
-						(u32 __user *)argp))
-				return -EFAULT;
-		} else {
-			if (put_user(server->m.mounted_uid,
-						(u64 __user *)argp))
-				return -EFAULT;
+			return 0;
 		}
+	case NCP_IOC_GETMOUNTUID32:
+		if (put_user(server->m.mounted_uid,
+			     (u32 __user *)argp))
+			return -EFAULT;
+		return 0;
+	case NCP_IOC_GETMOUNTUID64:
+		if (put_user(server->m.mounted_uid,
+			     (u64 __user *)argp))
+			return -EFAULT;
 		return 0;
 
 	case NCP_IOC_GETROOT:
 		{
 			struct ncp_setroot_ioctl sr;
 
-			if (file_permission(filp, MAY_READ) != 0
-			    && uid != server->m.mounted_uid)
-				return -EACCES;
-
+			result = -EACCES;
+			mutex_lock(&server->root_setup_lock);
 			if (server->m.mounted_vol[0]) {
 				struct dentry* dentry = inode->i_sb->s_root;
 
 				if (dentry) {
 					struct inode* s_inode = dentry->d_inode;
-				
+
 					if (s_inode) {
 						sr.volNumber = NCP_FINFO(s_inode)->volNumber;
 						sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum;
 						sr.namespace = server->name_space[sr.volNumber];
+						result = 0;
 					} else
 						DPRINTK("ncpfs: s_root->d_inode==NULL\n");
 				} else
@@ -402,10 +392,12 @@
 				sr.volNumber = -1;
 				sr.namespace = 0;
 				sr.dirEntNum = 0;
+				result = 0;
 			}
-			if (copy_to_user(argp, &sr, sizeof(sr)))
-				return -EFAULT;
-			return 0;
+			mutex_unlock(&server->root_setup_lock);
+			if (!result && copy_to_user(argp, &sr, sizeof(sr)))
+				result = -EFAULT;
+			return result;
 		}
 
 	case NCP_IOC_SETROOT:
@@ -416,103 +408,114 @@
 			__le32 dosde;
 			struct dentry* dentry;
 
-			if (!capable(CAP_SYS_ADMIN))
-			{
-				return -EACCES;
-			}
-			if (server->root_setuped) return -EBUSY;
 			if (copy_from_user(&sr, argp, sizeof(sr)))
 				return -EFAULT;
-			if (sr.volNumber < 0) {
-				server->m.mounted_vol[0] = 0;
-				vnum = NCP_NUMBER_OF_VOLUMES;
-				de = 0;
-				dosde = 0;
-			} else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
-				return -EINVAL;
-			} else if (ncp_mount_subdir(server, sr.volNumber,
-						sr.namespace, sr.dirEntNum,
-						&vnum, &de, &dosde)) {
-				return -ENOENT;
-			}
-			
-			dentry = inode->i_sb->s_root;
-			server->root_setuped = 1;
-			if (dentry) {
-				struct inode* s_inode = dentry->d_inode;
-				
-				if (s_inode) {
-					NCP_FINFO(s_inode)->volNumber = vnum;
-					NCP_FINFO(s_inode)->dirEntNum = de;
-					NCP_FINFO(s_inode)->DosDirNum = dosde;
+			mutex_lock(&server->root_setup_lock);
+			if (server->root_setuped)
+				result = -EBUSY;
+			else {
+				if (sr.volNumber < 0) {
+					server->m.mounted_vol[0] = 0;
+					vnum = NCP_NUMBER_OF_VOLUMES;
+					de = 0;
+					dosde = 0;
+					result = 0;
+				} else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
+					result = -EINVAL;
+				} else if (ncp_mount_subdir(server, sr.volNumber,
+							sr.namespace, sr.dirEntNum,
+							&vnum, &de, &dosde)) {
+					result = -ENOENT;
 				} else
-					DPRINTK("ncpfs: s_root->d_inode==NULL\n");
-			} else
-				DPRINTK("ncpfs: s_root==NULL\n");
+					result = 0;
 
+				if (result == 0) {
+					dentry = inode->i_sb->s_root;
+					if (dentry) {
+						struct inode* s_inode = dentry->d_inode;
+
+						if (s_inode) {
+							NCP_FINFO(s_inode)->volNumber = vnum;
+							NCP_FINFO(s_inode)->dirEntNum = de;
+							NCP_FINFO(s_inode)->DosDirNum = dosde;
+							server->root_setuped = 1;
+						} else {
+							DPRINTK("ncpfs: s_root->d_inode==NULL\n");
+							result = -EIO;
+						}
+					} else {
+						DPRINTK("ncpfs: s_root==NULL\n");
+						result = -EIO;
+					}
+				}
+				result = 0;
+			}
+			mutex_unlock(&server->root_setup_lock);
+
+			return result;
+		}
+
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
+	case NCP_IOC_SIGN_INIT:
+		{
+			struct ncp_sign_init sign;
+
+			if (argp)
+				if (copy_from_user(&sign, argp, sizeof(sign)))
+					return -EFAULT;
+			ncp_lock_server(server);
+			mutex_lock(&server->rcv.creq_mutex);
+			if (argp) {
+				if (server->sign_wanted) {
+					memcpy(server->sign_root,sign.sign_root,8);
+					memcpy(server->sign_last,sign.sign_last,16);
+					server->sign_active = 1;
+				}
+				/* ignore when signatures not wanted */
+			} else {
+				server->sign_active = 0;
+			}
+			mutex_unlock(&server->rcv.creq_mutex);
+			ncp_unlock_server(server);
 			return 0;
 		}
 
-#ifdef CONFIG_NCPFS_PACKET_SIGNING	
-	case NCP_IOC_SIGN_INIT:
-		if (file_permission(filp, MAY_WRITE) != 0
-		    && uid != server->m.mounted_uid)
-			return -EACCES;
-
-		if (argp) {
-			if (server->sign_wanted)
-			{
-				struct ncp_sign_init sign;
-
-				if (copy_from_user(&sign, argp, sizeof(sign)))
-					return -EFAULT;
-				memcpy(server->sign_root,sign.sign_root,8);
-				memcpy(server->sign_last,sign.sign_last,16);
-				server->sign_active = 1;
-			}
-			/* ignore when signatures not wanted */
-		} else {
-			server->sign_active = 0;
-		}
-		return 0;		
-		
         case NCP_IOC_SIGN_WANTED:
-		if (file_permission(filp, MAY_READ) != 0
-		    && uid != server->m.mounted_uid)
-			return -EACCES;
-		
-                if (put_user(server->sign_wanted, (int __user *)argp))
-			return -EFAULT;
-                return 0;
+		{
+			int state;
+
+			ncp_lock_server(server);
+			state = server->sign_wanted;
+			ncp_unlock_server(server);
+			if (put_user(state, (int __user *)argp))
+				return -EFAULT;
+			return 0;
+		}
 
 	case NCP_IOC_SET_SIGN_WANTED:
 		{
 			int newstate;
 
-			if (file_permission(filp, MAY_WRITE) != 0
-			    && uid != server->m.mounted_uid)
-				return -EACCES;
-
 			/* get only low 8 bits... */
 			if (get_user(newstate, (unsigned char __user *)argp))
 				return -EFAULT;
+			result = 0;
+			ncp_lock_server(server);
 			if (server->sign_active) {
 				/* cannot turn signatures OFF when active */
-				if (!newstate) return -EINVAL;
+				if (!newstate)
+					result = -EINVAL;
 			} else {
 				server->sign_wanted = newstate != 0;
 			}
-			return 0;
+			ncp_unlock_server(server);
+			return result;
 		}
 
 #endif /* CONFIG_NCPFS_PACKET_SIGNING */
 
 #ifdef CONFIG_NCPFS_IOCTL_LOCKING
 	case NCP_IOC_LOCKUNLOCK:
-		if (file_permission(filp, MAY_WRITE) != 0
-		    && uid != server->m.mounted_uid)
-			return -EACCES;
-
 		{
 			struct ncp_lock_ioctl	 rqdata;
 
@@ -541,16 +544,13 @@
 			{
 				return result;
 			}
-			result = -EIO;
-			if (!ncp_conn_valid(server))
-				goto outrel;
 			result = -EISDIR;
 			if (!S_ISREG(inode->i_mode))
 				goto outrel;
 			if (rqdata.cmd == NCP_LOCK_CLEAR)
 			{
 				result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
-							NCP_FINFO(inode)->file_handle, 
+							NCP_FINFO(inode)->file_handle,
 							rqdata.offset,
 							rqdata.length);
 				if (result > 0) result = 0;	/* no such lock */
@@ -573,7 +573,7 @@
 							rqdata.timeout);
 				if (result > 0) result = -EAGAIN;
 			}
-outrel:			
+outrel:
 			ncp_inode_close(inode);
 			return result;
 		}
@@ -581,60 +581,62 @@
 
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_GETOBJECTNAME_32:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct compat_ncp_objectname_ioctl user;
 			size_t outl;
 
 			if (copy_from_user(&user, argp, sizeof(user)))
 				return -EFAULT;
+			down_read(&server->auth_rwsem);
 			user.auth_type = server->auth.auth_type;
 			outl = user.object_name_len;
 			user.object_name_len = server->auth.object_name_len;
 			if (outl > user.object_name_len)
 				outl = user.object_name_len;
+			result = 0;
 			if (outl) {
 				if (copy_to_user(compat_ptr(user.object_name),
 						 server->auth.object_name,
-						 outl)) return -EFAULT;
+						 outl))
+					result = -EFAULT;
 			}
-			if (copy_to_user(argp, &user, sizeof(user)))
-				return -EFAULT;
-			return 0;
+			up_read(&server->auth_rwsem);
+			if (!result && copy_to_user(argp, &user, sizeof(user)))
+				result = -EFAULT;
+			return result;
 		}
 #endif
 
 	case NCP_IOC_GETOBJECTNAME:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct ncp_objectname_ioctl user;
 			size_t outl;
 
 			if (copy_from_user(&user, argp, sizeof(user)))
 				return -EFAULT;
+			down_read(&server->auth_rwsem);
 			user.auth_type = server->auth.auth_type;
 			outl = user.object_name_len;
 			user.object_name_len = server->auth.object_name_len;
 			if (outl > user.object_name_len)
 				outl = user.object_name_len;
+			result = 0;
 			if (outl) {
 				if (copy_to_user(user.object_name,
 						 server->auth.object_name,
-						 outl)) return -EFAULT;
+						 outl))
+					result = -EFAULT;
 			}
-			if (copy_to_user(argp, &user, sizeof(user)))
-				return -EFAULT;
-			return 0;
+			up_read(&server->auth_rwsem);
+			if (!result && copy_to_user(argp, &user, sizeof(user)))
+				result = -EFAULT;
+			return result;
 		}
 
 #ifdef CONFIG_COMPAT
 	case NCP_IOC_SETOBJECTNAME_32:
 #endif
 	case NCP_IOC_SETOBJECTNAME:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct ncp_objectname_ioctl user;
 			void* newname;
@@ -666,9 +668,7 @@
 			} else {
 				newname = NULL;
 			}
-			/* enter critical section */
-			/* maybe that kfree can sleep so do that this way */
-			/* it is at least more SMP friendly (in future...) */
+			down_write(&server->auth_rwsem);
 			oldname = server->auth.object_name;
 			oldnamelen = server->auth.object_name_len;
 			oldprivate = server->priv.data;
@@ -678,7 +678,7 @@
 			server->auth.object_name = newname;
 			server->priv.len = 0;
 			server->priv.data = NULL;
-			/* leave critical section */
+			up_write(&server->auth_rwsem);
 			kfree(oldprivate);
 			kfree(oldname);
 			return 0;
@@ -688,8 +688,6 @@
 	case NCP_IOC_GETPRIVATEDATA_32:
 #endif
 	case NCP_IOC_GETPRIVATEDATA:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct ncp_privatedata_ioctl user;
 			size_t outl;
@@ -706,14 +704,20 @@
 			if (copy_from_user(&user, argp, sizeof(user)))
 				return -EFAULT;
 
+			down_read(&server->auth_rwsem);
 			outl = user.len;
 			user.len = server->priv.len;
 			if (outl > user.len) outl = user.len;
+			result = 0;
 			if (outl) {
 				if (copy_to_user(user.data,
 						 server->priv.data,
-						 outl)) return -EFAULT;
+						 outl))
+					result = -EFAULT;
 			}
+			up_read(&server->auth_rwsem);
+			if (result)
+				return result;
 #ifdef CONFIG_COMPAT
 			if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
 				struct compat_ncp_privatedata_ioctl user32;
@@ -733,8 +737,6 @@
 	case NCP_IOC_SETPRIVATEDATA_32:
 #endif
 	case NCP_IOC_SETPRIVATEDATA:
-		if (uid != server->m.mounted_uid)
-			return -EACCES;
 		{
 			struct ncp_privatedata_ioctl user;
 			void* new;
@@ -762,12 +764,12 @@
 			} else {
 				new = NULL;
 			}
-			/* enter critical section */
+			down_write(&server->auth_rwsem);
 			old = server->priv.data;
 			oldlen = server->priv.len;
 			server->priv.len = user.len;
 			server->priv.data = new;
-			/* leave critical section */
+			up_write(&server->auth_rwsem);
 			kfree(old);
 			return 0;
 		}
@@ -775,17 +777,13 @@
 #ifdef CONFIG_NCPFS_NLS
 	case NCP_IOC_SETCHARSETS:
 		return ncp_set_charsets(server, argp);
-		
+
 	case NCP_IOC_GETCHARSETS:
 		return ncp_get_charsets(server, argp);
 
 #endif /* CONFIG_NCPFS_NLS */
 
 	case NCP_IOC_SETDENTRYTTL:
-		if (file_permission(filp, MAY_WRITE) != 0 &&
-		    uid != server->m.mounted_uid)
-			return -EACCES;
-
 		{
 			u_int32_t user;
 
@@ -795,13 +793,13 @@
 			if (user > 20000)
 				return -EINVAL;
 			user = (user * HZ) / 1000;
-			server->dentry_ttl = user;
+			atomic_set(&server->dentry_ttl, user);
 			return 0;
 		}
-		
+
 	case NCP_IOC_GETDENTRYTTL:
 		{
-			u_int32_t user = (server->dentry_ttl * 1000) / HZ;
+			u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ;
 			if (copy_to_user(argp, &user, sizeof(user)))
 				return -EFAULT;
 			return 0;
@@ -811,59 +809,103 @@
 	return -EINVAL;
 }
 
-static int ncp_ioctl_need_write(unsigned int cmd)
-{
-	switch (cmd) {
-	case NCP_IOC_GET_FS_INFO:
-	case NCP_IOC_GET_FS_INFO_V2:
-	case NCP_IOC_NCPREQUEST:
-	case NCP_IOC_SETDENTRYTTL:
-	case NCP_IOC_SIGN_INIT:
-	case NCP_IOC_LOCKUNLOCK:
-	case NCP_IOC_SET_SIGN_WANTED:
-		return 1;
-	case NCP_IOC_GETOBJECTNAME:
-	case NCP_IOC_SETOBJECTNAME:
-	case NCP_IOC_GETPRIVATEDATA:
-	case NCP_IOC_SETPRIVATEDATA:
-	case NCP_IOC_SETCHARSETS:
-	case NCP_IOC_GETCHARSETS:
-	case NCP_IOC_CONN_LOGGED_IN:
-	case NCP_IOC_GETDENTRYTTL:
-	case NCP_IOC_GETMOUNTUID2:
-	case NCP_IOC_SIGN_WANTED:
-	case NCP_IOC_GETROOT:
-	case NCP_IOC_SETROOT:
-		return 0;
-	default:
-		/* unknown IOCTL command, assume write */
-		return 1;
-	}
-}
-
 long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct ncp_server *server = NCP_SERVER(inode);
+	uid_t uid = current_uid();
+	int need_drop_write = 0;
 	long ret;
 
-	lock_kernel();
-	if (ncp_ioctl_need_write(cmd)) {
-		/*
-		 * inside the ioctl(), any failures which
-		 * are because of file_permission() are
-		 * -EACCESS, so it seems consistent to keep
-		 *  that here.
-		 */
-		if (mnt_want_write(filp->f_path.mnt)) {
+	switch (cmd) {
+	case NCP_IOC_SETCHARSETS:
+	case NCP_IOC_CONN_LOGGED_IN:
+	case NCP_IOC_SETROOT:
+		if (!capable(CAP_SYS_ADMIN)) {
 			ret = -EACCES;
 			goto out;
 		}
+		break;
 	}
-	ret = __ncp_ioctl(filp, cmd, arg);
-	if (ncp_ioctl_need_write(cmd))
+	if (server->m.mounted_uid != uid) {
+		switch (cmd) {
+		/*
+		 * Only mount owner can issue these ioctls.  Information
+		 * necessary to authenticate to other NDS servers are
+		 * stored here.
+		 */
+		case NCP_IOC_GETOBJECTNAME:
+		case NCP_IOC_SETOBJECTNAME:
+		case NCP_IOC_GETPRIVATEDATA:
+		case NCP_IOC_SETPRIVATEDATA:
+#ifdef CONFIG_COMPAT
+		case NCP_IOC_GETOBJECTNAME_32:
+		case NCP_IOC_SETOBJECTNAME_32:
+		case NCP_IOC_GETPRIVATEDATA_32:
+		case NCP_IOC_SETPRIVATEDATA_32:
+#endif
+			ret = -EACCES;
+			goto out;
+		/*
+		 * These require write access on the inode if user id
+		 * does not match.  Note that they do not write to the
+		 * file...  But old code did mnt_want_write, so I keep
+		 * it as is.  Of course not for mountpoint owner, as
+		 * that breaks read-only mounts altogether as ncpmount
+		 * needs working NCP_IOC_NCPREQUEST and
+		 * NCP_IOC_GET_FS_INFO.  Some of these codes (setdentryttl,
+		 * signinit, setsignwanted) should be probably restricted
+		 * to owner only, or even more to CAP_SYS_ADMIN).
+		 */
+		case NCP_IOC_GET_FS_INFO:
+		case NCP_IOC_GET_FS_INFO_V2:
+		case NCP_IOC_NCPREQUEST:
+		case NCP_IOC_SETDENTRYTTL:
+		case NCP_IOC_SIGN_INIT:
+		case NCP_IOC_LOCKUNLOCK:
+		case NCP_IOC_SET_SIGN_WANTED:
+#ifdef CONFIG_COMPAT
+		case NCP_IOC_GET_FS_INFO_V2_32:
+		case NCP_IOC_NCPREQUEST_32:
+#endif
+			ret = mnt_want_write_file(filp);
+			if (ret)
+				goto out;
+			need_drop_write = 1;
+			ret = inode_permission(inode, MAY_WRITE);
+			if (ret)
+				goto outDropWrite;
+			break;
+		/*
+		 * Read access required.
+		 */
+		case NCP_IOC_GETMOUNTUID16:
+		case NCP_IOC_GETMOUNTUID32:
+		case NCP_IOC_GETMOUNTUID64:
+		case NCP_IOC_GETROOT:
+		case NCP_IOC_SIGN_WANTED:
+			ret = inode_permission(inode, MAY_READ);
+			if (ret)
+				goto out;
+			break;
+		/*
+		 * Anybody can read these.
+		 */
+		case NCP_IOC_GETCHARSETS:
+		case NCP_IOC_GETDENTRYTTL:
+		default:
+		/* Three codes below are protected by CAP_SYS_ADMIN above. */
+		case NCP_IOC_SETCHARSETS:
+		case NCP_IOC_CONN_LOGGED_IN:
+		case NCP_IOC_SETROOT:
+			break;
+		}
+	}
+	ret = __ncp_ioctl(inode, cmd, arg);
+outDropWrite:
+	if (need_drop_write)
 		mnt_drop_write(filp->f_path.mnt);
-
 out:
-	unlock_kernel();
 	return ret;
 }
 
@@ -872,10 +914,8 @@
 {
 	long ret;
 
-	lock_kernel();
 	arg = (unsigned long) compat_ptr(arg);
 	ret = ncp_ioctl(file, cmd, arg);
-	unlock_kernel();
 	return ret;
 }
 #endif
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index 0ec6237..a95615a 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -107,17 +107,17 @@
 	return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
 }
 
-static inline u8 BVAL(void *data)
+static inline u8 BVAL(const void *data)
 {
-	return *(u8 *)data;
+	return *(const u8 *)data;
 }
 
 static u8 ncp_reply_byte(struct ncp_server *server, int offset)
 {
-	return *(u8 *)ncp_reply_data(server, offset);
+	return *(const u8 *)ncp_reply_data(server, offset);
 }
 
-static inline u16 WVAL_LH(void *data)
+static inline u16 WVAL_LH(const void *data)
 {
 	return get_unaligned_le16(data);
 }
@@ -134,7 +134,7 @@
 	return get_unaligned_be16(ncp_reply_data(server, offset));
 }
 
-static inline u32 DVAL_LH(void *data)
+static inline u32 DVAL_LH(const void *data)
 {
 	return get_unaligned_le32(data);
 }
@@ -349,9 +349,9 @@
 	return result;
 }
 
-void ncp_extract_file_info(void *structure, struct nw_info_struct *target)
+void ncp_extract_file_info(const void *structure, struct nw_info_struct *target)
 {
-	__u8 *name_len;
+	const __u8 *name_len;
 	const int info_struct_size = offsetof(struct nw_info_struct, nameLen);
 
 	memcpy(target, structure, info_struct_size);
@@ -364,7 +364,7 @@
 }
 
 #ifdef CONFIG_NCPFS_NFS_NS
-static inline void ncp_extract_nfs_info(unsigned char *structure,
+static inline void ncp_extract_nfs_info(const unsigned char *structure,
 				 struct nw_nfs_info *target)
 {
 	target->mode = DVAL_LH(structure);
@@ -417,7 +417,7 @@
  * Returns information for a (one-component) name relative to
  * the specified directory.
  */
-int ncp_obtain_info(struct ncp_server *server, struct inode *dir, char *path,
+int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path,
 			struct nw_info_struct *target)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
@@ -452,16 +452,16 @@
 #ifdef CONFIG_NCPFS_NFS_NS
 static int
 ncp_obtain_DOS_dir_base(struct ncp_server *server,
-		__u8 volnum, __le32 dirent,
-		char *path, /* At most 1 component */
+		__u8 ns, __u8 volnum, __le32 dirent,
+		const char *path, /* At most 1 component */
 		__le32 *DOS_dir_base)
 {
 	int result;
 
 	ncp_init_request(server);
 	ncp_add_byte(server, 6); /* subfunction */
-	ncp_add_byte(server, server->name_space[volnum]);
-	ncp_add_byte(server, server->name_space[volnum]);
+	ncp_add_byte(server, ns);
+	ncp_add_byte(server, ns);
 	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
 	ncp_add_dword(server, RIM_DIRECTORY);
 	ncp_add_handle_path(server, volnum, dirent, 1, path);
@@ -523,10 +523,27 @@
 #endif	/* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
 }
 
+int
+ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns)
+{
+	int ns = ncp_get_known_namespace(server, volume);
+
+	if (ret_ns)
+		*ret_ns = ns;
+
+	DPRINTK("lookup_vol: namespace[%d] = %d\n",
+		volume, server->name_space[volume]);
+
+	if (server->name_space[volume] == ns)
+		return 0;
+	server->name_space[volume] = ns;
+	return 1;
+}
+
 static int
 ncp_ObtainSpecificDirBase(struct ncp_server *server,
 		__u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
-		char *path, /* At most 1 component */
+		const char *path, /* At most 1 component */
 		__le32 *dirEntNum, __le32 *DosDirNum)
 {
 	int result;
@@ -560,14 +577,13 @@
 {
 	int dstNS;
 	int result;
-	
-	dstNS = ncp_get_known_namespace(server, volNumber);
+
+	ncp_update_known_namespace(server, volNumber, &dstNS);
 	if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, 
 				      dirEntNum, NULL, newDirEnt, newDosEnt)) != 0)
 	{
 		return result;
 	}
-	server->name_space[volNumber] = dstNS;
 	*volume = volNumber;
 	server->m.mounted_vol[1] = 0;
 	server->m.mounted_vol[0] = 'X';
@@ -575,11 +591,10 @@
 }
 
 int 
-ncp_get_volume_root(struct ncp_server *server, const char *volname,
-		    __u32* volume, __le32* dirent, __le32* dosdirent)
+ncp_get_volume_root(struct ncp_server *server,
+		    const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent)
 {
 	int result;
-	__u8 volnum;
 
 	DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname);
 
@@ -601,21 +616,14 @@
 		return result;
 	}
 	*dirent = *dosdirent = ncp_reply_dword(server, 4);
-	volnum = ncp_reply_byte(server, 8);
+	*volume = ncp_reply_byte(server, 8);
 	ncp_unlock_server(server);
-	*volume = volnum;
-
-	server->name_space[volnum] = ncp_get_known_namespace(server, volnum);
-
-	DPRINTK("lookup_vol: namespace[%d] = %d\n",
-		volnum, server->name_space[volnum]);
-
 	return 0;
 }
 
 int
-ncp_lookup_volume(struct ncp_server *server, const char *volname,
-		  struct nw_info_struct *target)
+ncp_lookup_volume(struct ncp_server *server,
+		  const char *volname, struct nw_info_struct *target)
 {
 	int result;
 
@@ -625,6 +633,7 @@
 	if (result) {
 		return result;
 	}
+	ncp_update_known_namespace(server, target->volNumber, NULL);
 	target->nameLen = strlen(volname);
 	memcpy(target->entryName, volname, target->nameLen+1);
 	target->attributes = aDIR;
@@ -676,8 +685,8 @@
 {
 	int result = 0;
 
+	ncp_init_request(server);
 	if (server->name_space[volnum] == NW_NS_NFS) {
-		ncp_init_request(server);
 		ncp_add_byte(server, 25);	/* subfunction */
 		ncp_add_byte(server, server->name_space[volnum]);
 		ncp_add_byte(server, NW_NS_NFS);
@@ -690,8 +699,8 @@
 		ncp_add_dword_lh(server, 1);	/* nlinks */
 		ncp_add_dword_lh(server, rdev);
 		result = ncp_request(server, 87);
-		ncp_unlock_server(server);
 	}
+	ncp_unlock_server(server);
 	return result;
 }
 #endif
@@ -700,7 +709,7 @@
 static int
 ncp_DeleteNSEntry(struct ncp_server *server,
 		  __u8 have_dir_base, __u8 volnum, __le32 dirent,
-		  char* name, __u8 ns, __le16 attr)
+		  const char* name, __u8 ns, __le16 attr)
 {
 	int result;
 
@@ -734,23 +743,25 @@
 
 int
 ncp_del_file_or_subdir(struct ncp_server *server,
-		       struct inode *dir, char *name)
+		       struct inode *dir, const char *name)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
 	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
+	int name_space;
 
+	name_space = server->name_space[volnum];
 #ifdef CONFIG_NCPFS_NFS_NS
-	if (server->name_space[volnum]==NW_NS_NFS)
+	if (name_space == NW_NS_NFS)
  	{
  		int result;
  
- 		result=ncp_obtain_DOS_dir_base(server, volnum, dirent, name, &dirent);
+		result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent);
  		if (result) return result;
- 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
+		name = NULL;
+		name_space = NW_NS_DOS;
  	}
- 	else
 #endif	/* CONFIG_NCPFS_NFS_NS */
- 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, server->name_space[volnum], cpu_to_le16(0x8006));
+	return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006));
 }
 
 static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
@@ -765,7 +776,7 @@
 /* If both dir and name are NULL, then in target there's already a
    looked-up entry that wants to be opened. */
 int ncp_open_create_file_or_subdir(struct ncp_server *server,
-				   struct inode *dir, char *name,
+				   struct inode *dir, const char *name,
 				   int open_create_mode,
 				   __le32 create_attributes,
 				   __le16 desired_acc_rights,
@@ -890,8 +901,8 @@
 
 static int
 ncp_RenameNSEntry(struct ncp_server *server,
-		  struct inode *old_dir, char *old_name, __le16 old_type,
-		  struct inode *new_dir, char *new_name)
+		  struct inode *old_dir, const char *old_name, __le16 old_type,
+		  struct inode *new_dir, const char *new_name)
 {
 	int result = -EINVAL;
 
@@ -929,8 +940,8 @@
 }
 
 int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
-				struct inode *old_dir, char *old_name,
-				struct inode *new_dir, char *new_name)
+				struct inode *old_dir, const char *old_name,
+				struct inode *new_dir, const char *new_name)
 {
         int result;
         __le16 old_type = cpu_to_le16(0x06);
@@ -958,7 +969,7 @@
 ncp_read_kernel(struct ncp_server *server, const char *file_id,
 	     __u32 offset, __u16 to_read, char *target, int *bytes_read)
 {
-	char *source;
+	const char *source;
 	int result;
 
 	ncp_init_request(server);
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 2441d1a..3c57eca 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -65,10 +65,11 @@
 	atomic_dec(&NCP_FINFO(inode)->opened);
 }
 
-void ncp_extract_file_info(void* src, struct nw_info_struct* target);
-int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
+void ncp_extract_file_info(const void* src, struct nw_info_struct* target);
+int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *,
 		struct nw_info_struct *target);
 int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
+int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns);
 int ncp_get_volume_root(struct ncp_server *server, const char *volname,
 			__u32 *volume, __le32 *dirent, __le32 *dosdirent);
 int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *);
@@ -80,8 +81,8 @@
 			__u32 mode, __u32 rdev);
 
 int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
-int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *);
-int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, char *,
+int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *);
+int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *,
 				int, __le32, __le16, struct ncp_entry_info *);
 
 int ncp_initialize_search(struct ncp_server *, struct inode *,
@@ -93,7 +94,7 @@
 			   char** rbuf, size_t* rsize);
 
 int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
-			      struct inode *, char *, struct inode *, char *);
+			      struct inode *, const char *, struct inode *, const char *);
 
 
 int
@@ -170,13 +171,13 @@
 #endif /* CONFIG_NCPFS_NLS */
 
 #define NCP_GET_AGE(dentry)	(jiffies - (dentry)->d_time)
-#define NCP_MAX_AGE(server)	((server)->dentry_ttl)
+#define NCP_MAX_AGE(server)	atomic_read(&(server)->dentry_ttl)
 #define NCP_TEST_AGE(server,dentry)	(NCP_GET_AGE(dentry) < NCP_MAX_AGE(server))
 
 static inline void
 ncp_age_dentry(struct ncp_server* server, struct dentry* dentry)
 {
-	dentry->d_time = jiffies - server->dentry_ttl;
+	dentry->d_time = jiffies - NCP_MAX_AGE(server);
 }
 
 static inline void
diff --git a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c
index 7c0b5c2..d8b2d7e 100644
--- a/fs/ncpfs/ncpsign_kernel.c
+++ b/fs/ncpfs/ncpsign_kernel.c
@@ -15,21 +15,21 @@
 
 /* i386: 32-bit, little endian, handles mis-alignment */
 #ifdef __i386__
-#define GET_LE32(p) (*(int *)(p))
+#define GET_LE32(p) (*(const int *)(p))
 #define PUT_LE32(p,v) { *(int *)(p)=v; }
 #else
 /* from include/ncplib.h */
-#define BVAL(buf,pos) (((__u8 *)(buf))[pos])
+#define BVAL(buf,pos) (((const __u8 *)(buf))[pos])
 #define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
-#define BSET(buf,pos,val) (BVAL(buf,pos) = (val))
+#define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val))
 
 static inline __u16
-WVAL_LH(__u8 * buf, int pos)
+WVAL_LH(const __u8 * buf, int pos)
 {
 	return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8;
 }
 static inline __u32
-DVAL_LH(__u8 * buf, int pos)
+DVAL_LH(const __u8 * buf, int pos)
 {
 	return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16;
 }
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
index c7ff6c7..668bd26 100644
--- a/fs/ncpfs/sock.c
+++ b/fs/ncpfs/sock.c
@@ -746,7 +746,6 @@
 		return -EIO;
 	}
 	if (!ncp_conn_valid(server)) {
-		printk(KERN_ERR "ncpfs: Connection invalid!\n");
 		return -EIO;
 	}
 	{
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index f7e13db..b950415 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -1,6 +1,7 @@
 config NFS_FS
 	tristate "NFS client support"
 	depends on INET && FILE_LOCKING
+	depends on BKL # fix as soon as lockd is done
 	select LOCKD
 	select SUNRPC
 	select NFS_ACL_SUPPORT if NFS_V3_ACL
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index b9c3c43..232a7ee 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -71,20 +71,20 @@
 	if (inode->i_flock == NULL)
 		goto out;
 
-	/* Protect inode->i_flock using the BKL */
-	lock_kernel();
+	/* Protect inode->i_flock using the file locks lock */
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
 			continue;
 		if (nfs_file_open_context(fl->fl_file) != ctx)
 			continue;
-		unlock_kernel();
+		unlock_flocks();
 		status = nfs4_lock_delegation_recall(state, fl);
 		if (status < 0)
 			goto out;
-		lock_kernel();
+		lock_flocks();
 	}
-	unlock_kernel();
+	unlock_flocks();
 out:
 	return status;
 }
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 3e2f19b..96524c5 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -40,7 +40,7 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/fs.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
 #include <linux/kthread.h>
@@ -970,13 +970,13 @@
 	/* Guard against delegation returns and new lock/unlock calls */
 	down_write(&nfsi->rwsem);
 	/* Protect inode->i_flock using the BKL */
-	lock_kernel();
+	lock_flocks();
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
 		if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
 			continue;
 		if (nfs_file_open_context(fl->fl_file)->state != state)
 			continue;
-		unlock_kernel();
+		unlock_flocks();
 		status = ops->recover_lock(state, fl);
 		switch (status) {
 			case 0:
@@ -1003,9 +1003,9 @@
 				/* kill_proc(fl->fl_pid, SIGLOST, 1); */
 				status = 0;
 		}
-		lock_kernel();
+		lock_flocks();
 	}
-	unlock_kernel();
+	unlock_flocks();
 out:
 	up_write(&nfsi->rwsem);
 	return status;
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index 4264377..7cf4dda 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -2,6 +2,7 @@
 	tristate "NFS server support"
 	depends on INET
 	depends on FILE_LOCKING
+	depends on BKL # fix as soon as lockd is done
 	select LOCKD
 	select SUNRPC
 	select EXPORTFS
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index cf0d2ff..a7292fc 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -33,7 +33,7 @@
 */
 
 #include <linux/file.h>
-#include <linux/smp_lock.h>
+#include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/namei.h>
 #include <linux/swap.h>
@@ -3895,7 +3895,7 @@
 	struct inode *inode = filp->fi_inode;
 	int status = 0;
 
-	lock_kernel();
+	lock_flocks();
 	for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
 		if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
 			status = 1;
@@ -3903,7 +3903,7 @@
 		}
 	}
 out:
-	unlock_kernel();
+	unlock_flocks();
 	return status;
 }
 
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index b53b1d0..06fa87e 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -137,6 +137,7 @@
 	.write		= nfsctl_transaction_write,
 	.read		= nfsctl_transaction_read,
 	.release	= simple_transaction_release,
+	.llseek		= default_llseek,
 };
 
 static int exports_open(struct inode *inode, struct file *file)
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index f90a33d..0442ee3 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -22,7 +22,6 @@
 
 #include <linux/fs.h>
 #include <linux/wait.h>
-#include <linux/smp_lock.h>	/* lock_kernel(), unlock_kernel() */
 #include <linux/slab.h>
 #include <linux/capability.h>	/* capable() */
 #include <linux/uaccess.h>	/* copy_from_user(), copy_to_user() */
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 9222633..f3b7520 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -45,7 +45,6 @@
 #include <linux/parser.h>
 #include <linux/random.h>
 #include <linux/crc32.h>
-#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
 #include <linux/kobject.h>
@@ -178,17 +177,9 @@
 
  retry:
 	set_buffer_dirty(nilfs->ns_sbh[0]);
-
 	if (nilfs_test_opt(sbi, BARRIER)) {
 		err = __sync_dirty_buffer(nilfs->ns_sbh[0],
-					  WRITE_SYNC | WRITE_BARRIER);
-		if (err == -EOPNOTSUPP) {
-			nilfs_warning(sbi->s_super, __func__,
-				      "barrier-based sync failed. "
-				      "disabling barriers\n");
-			nilfs_clear_opt(sbi, BARRIER);
-			goto retry;
-		}
+					  WRITE_SYNC | WRITE_FLUSH_FUA);
 	} else {
 		err = sync_dirty_buffer(nilfs->ns_sbh[0]);
 	}
@@ -342,8 +333,6 @@
 	struct nilfs_sb_info *sbi = NILFS_SB(sb);
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 
-	lock_kernel();
-
 	nilfs_detach_segment_constructor(sbi);
 
 	if (!(sb->s_flags & MS_RDONLY)) {
@@ -361,8 +350,6 @@
 	sbi->s_super = NULL;
 	sb->s_fs_info = NULL;
 	nilfs_put_sbinfo(sbi);
-
-	unlock_kernel();
 }
 
 static int nilfs_sync_fs(struct super_block *sb, int wait)
@@ -949,8 +936,6 @@
 	struct nilfs_mount_options old_opts;
 	int was_snapshot, err;
 
-	lock_kernel();
-
 	down_write(&nilfs->ns_super_sem);
 	old_sb_flags = sb->s_flags;
 	old_opts.mount_opt = sbi->s_mount_opt;
@@ -1024,7 +1009,6 @@
 	}
  out:
 	up_write(&nilfs->ns_super_sem);
-	unlock_kernel();
 	return 0;
 
  restore_opts:
@@ -1032,7 +1016,6 @@
 	sbi->s_mount_opt = old_opts.mount_opt;
 	sbi->s_snapshot_cno = old_opts.snapshot_cno;
 	up_write(&nilfs->ns_super_sem);
-	unlock_kernel();
 	return err;
 }
 
@@ -1205,7 +1188,6 @@
 	put_nilfs(nilfs);
  failed:
 	close_bdev_exclusive(sd.bdev, mode);
-
 	return err;
 
  cancel_new:
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index ba7c10c..d277151 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -775,9 +775,7 @@
 			ret = blkdev_issue_discard(nilfs->ns_bdev,
 						   start * sects_per_block,
 						   nblocks * sects_per_block,
-						   GFP_NOFS,
-						   BLKDEV_IFL_WAIT |
-						   BLKDEV_IFL_BARRIER);
+						   GFP_NOFS, 0);
 			if (ret < 0)
 				return ret;
 			nblocks = 0;
@@ -787,8 +785,7 @@
 		ret = blkdev_issue_discard(nilfs->ns_bdev,
 					   start * sects_per_block,
 					   nblocks * sects_per_block,
-					   GFP_NOFS,
-					  BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+					   GFP_NOFS, 0);
 	return ret;
 }
 
diff --git a/fs/no-block.c b/fs/no-block.c
index d269a93..6e40e42 100644
--- a/fs/no-block.c
+++ b/fs/no-block.c
@@ -19,4 +19,5 @@
 
 const struct file_operations def_blk_fops = {
 	.open		= no_blkdev_open,
+	.llseek		= noop_llseek,
 };
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 5ed8e58..bbcb98e 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -433,6 +433,7 @@
 	.release	= fanotify_release,
 	.unlocked_ioctl	= fanotify_ioctl,
 	.compat_ioctl	= fanotify_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static void fanotify_free_mark(struct fsnotify_mark *fsn_mark)
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index bf7f6d7..24edc11 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -344,6 +344,7 @@
 	.release	= inotify_release,
 	.unlocked_ioctl	= inotify_ioctl,
 	.compat_ioctl	= inotify_ioctl,
+	.llseek		= noop_llseek,
 };
 
 
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 5128061..19c5180 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -30,7 +30,6 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/moduleparam.h>
-#include <linux/smp_lock.h>
 #include <linux/bitmap.h>
 
 #include "sysctl.h"
@@ -445,7 +444,6 @@
 
 	ntfs_debug("Entering with remount options string: %s", opt);
 
-	lock_kernel();
 #ifndef NTFS_RW
 	/* For read-only compiled driver, enforce read-only flag. */
 	*flags |= MS_RDONLY;
@@ -469,18 +467,15 @@
 		if (NVolErrors(vol)) {
 			ntfs_error(sb, "Volume has errors and is read-only%s",
 					es);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (vol->vol_flags & VOLUME_IS_DIRTY) {
 			ntfs_error(sb, "Volume is dirty and read-only%s", es);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (vol->vol_flags & VOLUME_MODIFIED_BY_CHKDSK) {
 			ntfs_error(sb, "Volume has been modified by chkdsk "
 					"and is read-only%s", es);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) {
@@ -488,13 +483,11 @@
 					"(0x%x) and is read-only%s",
 					(unsigned)le16_to_cpu(vol->vol_flags),
 					es);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (ntfs_set_volume_flags(vol, VOLUME_IS_DIRTY)) {
 			ntfs_error(sb, "Failed to set dirty bit in volume "
 					"information flags%s", es);
-			unlock_kernel();
 			return -EROFS;
 		}
 #if 0
@@ -514,21 +507,18 @@
 			ntfs_error(sb, "Failed to empty journal $LogFile%s",
 					es);
 			NVolSetErrors(vol);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (!ntfs_mark_quotas_out_of_date(vol)) {
 			ntfs_error(sb, "Failed to mark quotas out of date%s",
 					es);
 			NVolSetErrors(vol);
-			unlock_kernel();
 			return -EROFS;
 		}
 		if (!ntfs_stamp_usnjrnl(vol)) {
 			ntfs_error(sb, "Failed to stamp transation log "
 					"($UsnJrnl)%s", es);
 			NVolSetErrors(vol);
-			unlock_kernel();
 			return -EROFS;
 		}
 	} else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
@@ -544,11 +534,9 @@
 
 	// TODO: Deal with *flags.
 
-	if (!parse_options(vol, opt)) {
-		unlock_kernel();
+	if (!parse_options(vol, opt))
 		return -EINVAL;
-	}
-	unlock_kernel();
+
 	ntfs_debug("Done.");
 	return 0;
 }
@@ -2261,8 +2249,6 @@
 
 	ntfs_debug("Entering.");
 
-	lock_kernel();
-
 #ifdef NTFS_RW
 	/*
 	 * Commit all inodes while they are still open in case some of them
@@ -2433,8 +2419,6 @@
 
 	sb->s_fs_info = NULL;
 	kfree(vol);
-
-	unlock_kernel();
 }
 
 /**
@@ -2772,8 +2756,6 @@
 	init_rwsem(&vol->mftbmp_lock);
 	init_rwsem(&vol->lcnbmp_lock);
 
-	unlock_kernel();
-
 	/* By default, enable sparse support. */
 	NVolSetSparseEnabled(vol);
 
@@ -2940,7 +2922,6 @@
 		}
 		mutex_unlock(&ntfs_lock);
 		sb->s_export_op = &ntfs_export_ops;
-		lock_kernel();
 		lockdep_on();
 		return 0;
 	}
@@ -3057,7 +3038,6 @@
 	}
 	/* Errors at this stage are irrelevant. */
 err_out_now:
-	lock_kernel();
 	sb->s_fs_info = NULL;
 	kfree(vol);
 	ntfs_debug("Failed, returning -EINVAL.");
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c
index c2903b8..a7ebd9d 100644
--- a/fs/ocfs2/dlmfs/dlmfs.c
+++ b/fs/ocfs2/dlmfs/dlmfs.c
@@ -612,6 +612,7 @@
 	.poll		= dlmfs_file_poll,
 	.read		= dlmfs_file_read,
 	.write		= dlmfs_file_write,
+	.llseek		= default_llseek,
 };
 
 static const struct inode_operations dlmfs_dir_inode_operations = {
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 9e8cc43..1ca6867 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -187,8 +187,7 @@
 		 * platter
 		 */
 		if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER)
-			blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL,
-					   NULL, BLKDEV_IFL_WAIT);
+			blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 		goto bail;
 	}
 
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
index 2dc57bc..252e7c8 100644
--- a/fs/ocfs2/stack_user.c
+++ b/fs/ocfs2/stack_user.c
@@ -22,7 +22,6 @@
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/reboot.h>
 #include <asm/uaccess.h>
 
@@ -612,12 +611,10 @@
 		return -ENOMEM;
 	p->op_this_node = -1;
 
-	lock_kernel();
 	mutex_lock(&ocfs2_control_lock);
 	file->private_data = p;
 	list_add(&p->op_list, &ocfs2_control_private_list);
 	mutex_unlock(&ocfs2_control_lock);
-	unlock_kernel();
 
 	return 0;
 }
@@ -628,6 +625,7 @@
 	.read    = ocfs2_control_read,
 	.write   = ocfs2_control_write,
 	.owner   = THIS_MODULE,
+	.llseek  = default_llseek,
 };
 
 static struct miscdevice ocfs2_control_device = {
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index a8a0ca4..56f0cb3 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -630,8 +630,6 @@
 	struct ocfs2_super *osb = OCFS2_SB(sb);
 	u32 tmp;
 
-	lock_kernel();
-
 	if (!ocfs2_parse_options(sb, data, &parsed_options, 1) ||
 	    !ocfs2_check_set_options(sb, &parsed_options)) {
 		ret = -EINVAL;
@@ -739,7 +737,6 @@
 							MS_POSIXACL : 0);
 	}
 out:
-	unlock_kernel();
 	return ret;
 }
 
@@ -1696,13 +1693,9 @@
 {
 	mlog_entry("(0x%p)\n", sb);
 
-	lock_kernel();
-
 	ocfs2_sync_blockdev(sb);
 	ocfs2_dismount_volume(sb, 0);
 
-	unlock_kernel();
-
 	mlog_exit_void();
 }
 
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 79fbf3f..b81bfc0 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -352,6 +352,7 @@
 {
 	struct hd_struct *p = dev_to_part(dev);
 	free_part_stats(p);
+	free_part_info(p);
 	kfree(p);
 }
 
@@ -364,17 +365,25 @@
 static void delete_partition_rcu_cb(struct rcu_head *head)
 {
 	struct hd_struct *part = container_of(head, struct hd_struct, rcu_head);
+	struct gendisk *disk = part_to_disk(part);
+	struct request_queue *q = disk->queue;
+	unsigned long flags;
 
 	part->start_sect = 0;
 	part->nr_sects = 0;
 	part_stat_set_all(part, 0);
 	put_device(part_to_dev(part));
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	elv_quiesce_end(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 void delete_partition(struct gendisk *disk, int partno)
 {
 	struct disk_part_tbl *ptbl = disk->part_tbl;
 	struct hd_struct *part;
+	struct request_queue *q = disk->queue;
 
 	if (partno >= ptbl->len)
 		return;
@@ -389,6 +398,10 @@
 	kobject_put(part->holder_dir);
 	device_del(part_to_dev(part));
 
+	spin_lock_irq(q->queue_lock);
+	elv_quiesce_start(q);
+	spin_unlock_irq(q->queue_lock);
+
 	call_rcu(&part->rcu_head, delete_partition_rcu_cb);
 }
 
@@ -401,7 +414,8 @@
 		   whole_disk_show, NULL);
 
 struct hd_struct *add_partition(struct gendisk *disk, int partno,
-				sector_t start, sector_t len, int flags)
+				sector_t start, sector_t len, int flags,
+				struct partition_meta_info *info)
 {
 	struct hd_struct *p;
 	dev_t devt = MKDEV(0, 0);
@@ -438,6 +452,14 @@
 	p->partno = partno;
 	p->policy = get_disk_ro(disk);
 
+	if (info) {
+		struct partition_meta_info *pinfo = alloc_part_info(disk);
+		if (!pinfo)
+			goto out_free_stats;
+		memcpy(pinfo, info, sizeof(*info));
+		p->info = pinfo;
+	}
+
 	dname = dev_name(ddev);
 	if (isdigit(dname[strlen(dname) - 1]))
 		dev_set_name(pdev, "%sp%d", dname, partno);
@@ -451,7 +473,7 @@
 
 	err = blk_alloc_devt(p, &devt);
 	if (err)
-		goto out_free_stats;
+		goto out_free_info;
 	pdev->devt = devt;
 
 	/* delay uevent until 'holders' subdir is created */
@@ -481,6 +503,8 @@
 
 	return p;
 
+out_free_info:
+	free_part_info(p);
 out_free_stats:
 	free_part_stats(p);
 out_free:
@@ -513,14 +537,14 @@
 
 	if (device_add(ddev))
 		return;
-#ifndef CONFIG_SYSFS_DEPRECATED
-	err = sysfs_create_link(block_depr, &ddev->kobj,
-				kobject_name(&ddev->kobj));
-	if (err) {
-		device_del(ddev);
-		return;
+	if (!sysfs_deprecated) {
+		err = sysfs_create_link(block_depr, &ddev->kobj,
+					kobject_name(&ddev->kobj));
+		if (err) {
+			device_del(ddev);
+			return;
+		}
 	}
-#endif
 	disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
 	disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
 
@@ -642,6 +666,7 @@
 	/* add partitions */
 	for (p = 1; p < state->limit; p++) {
 		sector_t size, from;
+		struct partition_meta_info *info = NULL;
 
 		size = state->parts[p].size;
 		if (!size)
@@ -675,8 +700,12 @@
 				size = get_capacity(disk) - from;
 			}
 		}
+
+		if (state->parts[p].has_info)
+			info = &state->parts[p].info;
 		part = add_partition(disk, p, from, size,
-				     state->parts[p].flags);
+				     state->parts[p].flags,
+				     &state->parts[p].info);
 		if (IS_ERR(part)) {
 			printk(KERN_ERR " %s: p%d could not be added: %ld\n",
 			       disk->disk_name, p, -PTR_ERR(part));
@@ -737,8 +766,7 @@
 	kobject_put(disk->part0.holder_dir);
 	kobject_put(disk->slave_dir);
 	disk->driverfs_dev = NULL;
-#ifndef CONFIG_SYSFS_DEPRECATED
-	sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
-#endif
+	if (!sysfs_deprecated)
+		sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
 	device_del(disk_to_dev(disk));
 }
diff --git a/fs/partitions/check.h b/fs/partitions/check.h
index 8e4e103..d68bf4d 100644
--- a/fs/partitions/check.h
+++ b/fs/partitions/check.h
@@ -1,5 +1,6 @@
 #include <linux/pagemap.h>
 #include <linux/blkdev.h>
+#include <linux/genhd.h>
 
 /*
  * add_gd_partition adds a partitions details to the devices partition
@@ -12,6 +13,8 @@
 		sector_t from;
 		sector_t size;
 		int flags;
+		bool has_info;
+		struct partition_meta_info info;
 	} parts[DISK_MAX_PARTS];
 	int next;
 	int limit;
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c
index dbb44d4..ac0ccb5 100644
--- a/fs/partitions/efi.c
+++ b/fs/partitions/efi.c
@@ -94,6 +94,7 @@
  *
  ************************************************************/
 #include <linux/crc32.h>
+#include <linux/ctype.h>
 #include <linux/math64.h>
 #include <linux/slab.h>
 #include "check.h"
@@ -604,6 +605,7 @@
 	gpt_entry *ptes = NULL;
 	u32 i;
 	unsigned ssz = bdev_logical_block_size(state->bdev) / 512;
+	u8 unparsed_guid[37];
 
 	if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) {
 		kfree(gpt);
@@ -614,6 +616,9 @@
 	pr_debug("GUID Partition Table is valid!  Yea!\n");
 
 	for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) {
+		struct partition_meta_info *info;
+		unsigned label_count = 0;
+		unsigned label_max;
 		u64 start = le64_to_cpu(ptes[i].starting_lba);
 		u64 size = le64_to_cpu(ptes[i].ending_lba) -
 			   le64_to_cpu(ptes[i].starting_lba) + 1ULL;
@@ -627,6 +632,26 @@
 		if (!efi_guidcmp(ptes[i].partition_type_guid,
 				 PARTITION_LINUX_RAID_GUID))
 			state->parts[i + 1].flags = ADDPART_FLAG_RAID;
+
+		info = &state->parts[i + 1].info;
+		/* Instead of doing a manual swap to big endian, reuse the
+		 * common ASCII hex format as the interim.
+		 */
+		efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid);
+		part_pack_uuid(unparsed_guid, info->uuid);
+
+		/* Naively convert UTF16-LE to 7 bits. */
+		label_max = min(sizeof(info->volname) - 1,
+				sizeof(ptes[i].partition_name));
+		info->volname[label_max] = 0;
+		while (label_count < label_max) {
+			u8 c = ptes[i].partition_name[label_count] & 0xff;
+			if (c && !isprint(c))
+				c = '!';
+			info->volname[label_count] = c;
+			label_count++;
+		}
+		state->parts[i + 1].has_info = true;
 	}
 	kfree(ptes);
 	kfree(gpt);
diff --git a/fs/pipe.c b/fs/pipe.c
index 279eef9..37eb1eb 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -382,7 +382,7 @@
 			error = ops->confirm(pipe, buf);
 			if (error) {
 				if (!ret)
-					error = ret;
+					ret = error;
 				break;
 			}
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 8e4adda..dc5d5f5 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1151,6 +1151,7 @@
 static const struct file_operations proc_oom_score_adj_operations = {
 	.read		= oom_score_adj_read,
 	.write		= oom_score_adj_write,
+	.llseek		= default_llseek,
 };
 
 #ifdef CONFIG_AUDITSYSCALL
@@ -2039,11 +2040,13 @@
 static const struct file_operations proc_fdinfo_file_operations = {
 	.open           = nonseekable_open,
 	.read		= proc_fdinfo_read,
+	.llseek		= no_llseek,
 };
 
 static const struct file_operations proc_fd_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_readfd,
+	.llseek		= default_llseek,
 };
 
 /*
@@ -2112,6 +2115,7 @@
 static const struct file_operations proc_fdinfo_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_readfdinfo,
+	.llseek		= default_llseek,
 };
 
 /*
@@ -2343,6 +2347,7 @@
 static const struct file_operations proc_attr_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_attr_dir_readdir,
+	.llseek		= default_llseek,
 };
 
 static struct dentry *proc_attr_dir_lookup(struct inode *dir,
@@ -2751,6 +2756,7 @@
 static const struct file_operations proc_tgid_base_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_tgid_base_readdir,
+	.llseek		= default_llseek,
 };
 
 static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
@@ -3088,6 +3094,7 @@
 static const struct file_operations proc_tid_base_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_tid_base_readdir,
+	.llseek		= default_llseek,
 };
 
 static const struct inode_operations proc_tid_base_inode_operations = {
@@ -3324,4 +3331,5 @@
 static const struct file_operations proc_task_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_task_readdir,
+	.llseek		= default_llseek,
 };
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 5be436e..2fc5255 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -364,6 +364,7 @@
 static const struct file_operations proc_sys_file_operations = {
 	.read		= proc_sys_read,
 	.write		= proc_sys_write,
+	.llseek		= default_llseek,
 };
 
 static const struct file_operations proc_sys_dir_file_operations = {
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index 83adcc8..dc44f94 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -12,7 +12,10 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/console.h>
 #include <linux/seq_file.h>
+#include <linux/fdtable.h>
 #include <linux/bitops.h>
 
 /*
@@ -137,6 +140,160 @@
 };
 
 /*
+ * The device ID of file descriptor 0 of the current reading
+ * task if a character device...
+ */
+static dev_t current_dev;
+
+/*
+ * This is the handler for /proc/tty/consoles
+ */
+static int show_console_dev(struct seq_file *m, void *v)
+{
+	const struct tty_driver *driver;
+	struct console *con;
+	int index, len;
+	char flags[10];
+	dev_t dev;
+
+	if (v == SEQ_START_TOKEN)
+		return 0;
+	con = (struct console *)v;
+	if (!con)
+		return 0;
+	driver = con->device(con, &index);
+	if (!driver)
+		return 0;
+	dev = MKDEV(driver->major, driver->minor_start) + index;
+
+	index = 0;
+	if (con->flags & CON_ENABLED)
+		flags[index++] = 'E';
+	if (con->flags & CON_CONSDEV)
+		flags[index++] = 'C';
+	if (con->flags & CON_BOOT)
+		flags[index++] = 'B';
+	if (con->flags & CON_PRINTBUFFER)
+		flags[index++] = 'p';
+	if (con->flags & CON_BRL)
+		flags[index++] = 'b';
+	if (con->flags & CON_ANYTIME)
+		flags[index++] = 'a';
+	if (current_dev == dev)
+		flags[index++] = '*';
+	flags[index] = 0;
+
+	seq_printf(m, "%s%d%n", con->name, con->index, &len);
+	len = 21 - len;
+	if (len < 1)
+		len = 1;
+	seq_printf(m, "%*c", len, ' ');
+	seq_printf(m, "%c%c%c (%s)%n", con->read ? 'R' : '-',
+			con->write ? 'W' : '-', con->unblank ? 'U' : '-',
+			flags, &len);
+	len = 13 - len;
+	if (len < 1)
+		len = 1;
+	seq_printf(m, "%*c%4d:%d\n", len, ' ', MAJOR(dev), MINOR(dev));
+
+	return 0;
+}
+
+/* iterator for consoles */
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	struct console *con;
+	loff_t off = 0;
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	acquire_console_sem();
+	for (con = console_drivers; con; con = con->next) {
+		if (!con->device)
+			continue;
+		if (++off == *pos)
+			break;
+	}
+	release_console_sem();
+
+	return con;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct console *con;
+
+	acquire_console_sem();
+	if (v == SEQ_START_TOKEN)
+		con = console_drivers;
+	else
+		con = ((struct console *)v)->next;
+	for (; con; con = con->next) {
+		if (!con->device)
+			continue;
+		++*pos;
+		break;
+	}
+	release_console_sem();
+
+	return con;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+static const struct seq_operations tty_consoles_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_console_dev
+};
+
+/*
+ * Used for open /proc/tty/consoles. Before this detect
+ * the device ID of file descriptor 0 of the current
+ * reading task if a character device...
+ */
+static int tty_consoles_open(struct inode *inode, struct file *file)
+{
+	struct files_struct *curfiles;
+
+	current_dev = 0;
+	curfiles = get_files_struct(current);
+	if (curfiles) {
+		const struct file *curfp;
+		spin_lock(&curfiles->file_lock);
+		curfp = fcheck_files(curfiles, 0);
+		if (curfp && curfp->private_data) {
+			const struct inode *inode;
+			dget(curfp->f_dentry);
+			inode = curfp->f_dentry->d_inode;
+			if (S_ISCHR(inode->i_mode)) {
+				struct tty_struct *tty;
+				tty = (struct tty_struct *)curfp->private_data;
+				if (tty && tty->magic == TTY_MAGIC) {
+					tty = tty_pair_get_tty(tty);
+					current_dev = tty_devnum(tty);
+				}
+			}
+			dput(curfp->f_dentry);
+		}
+		spin_unlock(&curfiles->file_lock);
+		put_files_struct(curfiles);
+	}
+	return seq_open(file, &tty_consoles_op);
+}
+
+static const struct file_operations proc_tty_consoles_operations = {
+	.open		= tty_consoles_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>
  */
@@ -186,4 +343,5 @@
 	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);
+	proc_create("tty/consoles", 0, NULL, &proc_tty_consoles_operations);
 }
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 4258384..93d99b3 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -179,6 +179,7 @@
 static const struct file_operations proc_root_operations = {
 	.read		 = generic_read_dir,
 	.readdir	 = proc_root_readdir,
+	.llseek		= default_llseek,
 };
 
 /*
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 1dbca4e8..871e25e 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -539,6 +539,7 @@
 
 const struct file_operations proc_clear_refs_operations = {
 	.write		= clear_refs_write,
+	.llseek		= noop_llseek,
 };
 
 struct pagemapread {
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 6e8fc62..7b03294 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -11,7 +11,6 @@
  * 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support.
  */
 
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include "qnx4.h"
 
@@ -29,8 +28,6 @@
 	QNX4DEBUG((KERN_INFO "qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
 	QNX4DEBUG((KERN_INFO "filp->f_pos         = %ld\n", (long) filp->f_pos));
 
-	lock_kernel();
-
 	while (filp->f_pos < inode->i_size) {
 		blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_BITS );
 		bh = sb_bread(inode->i_sb, blknum);
@@ -71,7 +68,6 @@
 		brelse(bh);
 	}
 out:
-	unlock_kernel();
 	return 0;
 }
 
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 1682972..01bad30 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/highuid.h>
-#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
@@ -157,8 +156,6 @@
 	struct super_block *sb = dentry->d_sb;
 	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
-	lock_kernel();
-
 	buf->f_type    = sb->s_magic;
 	buf->f_bsize   = sb->s_blocksize;
 	buf->f_blocks  = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size) * 8;
@@ -168,8 +165,6 @@
 	buf->f_fsid.val[0] = (u32)id;
 	buf->f_fsid.val[1] = (u32)(id >> 32);
 
-	unlock_kernel();
-
 	return 0;
 }
 
@@ -283,7 +278,6 @@
  		goto outi;
 
 	brelse(bh);
-
 	return 0;
 
       outi:
diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c
index 58703eb..275327b 100644
--- a/fs/qnx4/namei.c
+++ b/fs/qnx4/namei.c
@@ -12,7 +12,6 @@
  * 04-07-1998 by Frank Denis : first step for rmdir/unlink.
  */
 
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include "qnx4.h"
 
@@ -109,7 +108,6 @@
 	int len = dentry->d_name.len;
 	struct inode *foundinode = NULL;
 
-	lock_kernel();
 	if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino)))
 		goto out;
 	/* The entry is linked, let's get the real info */
@@ -123,13 +121,11 @@
 
 	foundinode = qnx4_iget(dir->i_sb, ino);
 	if (IS_ERR(foundinode)) {
-		unlock_kernel();
 		QNX4DEBUG((KERN_ERR "qnx4: lookup->iget -> error %ld\n",
 			   PTR_ERR(foundinode)));
 		return ERR_CAST(foundinode);
 	}
 out:
-	unlock_kernel();
 	d_add(dentry, foundinode);
 
 	return NULL;
diff --git a/fs/read_write.c b/fs/read_write.c
index 74e3658..e757ef2 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -124,7 +124,7 @@
 {
 	loff_t retval;
 
-	lock_kernel();
+	mutex_lock(&file->f_dentry->d_inode->i_mutex);
 	switch (origin) {
 		case SEEK_END:
 			offset += i_size_read(file->f_path.dentry->d_inode);
@@ -145,7 +145,7 @@
 		retval = offset;
 	}
 out:
-	unlock_kernel();
+	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
 	return retval;
 }
 EXPORT_SYMBOL(default_llseek);
@@ -156,7 +156,6 @@
 
 	fn = no_llseek;
 	if (file->f_mode & FMODE_LSEEK) {
-		fn = default_llseek;
 		if (file->f_op && file->f_op->llseek)
 			fn = file->f_op->llseek;
 	}
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 6846371..91f080c 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -152,8 +152,7 @@
 	barrier_done = reiserfs_commit_for_inode(inode);
 	reiserfs_write_unlock(inode->i_sb);
 	if (barrier_done != 1 && reiserfs_barrier_flush(inode->i_sb))
-		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL, 
-			BLKDEV_IFL_WAIT);
+		blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 	if (barrier_done < 0)
 		return barrier_done;
 	return (err < 0) ? -EIO : 0;
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 812e2c0..076c8b19 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -138,13 +138,6 @@
 	return 0;
 }
 
-static void disable_barrier(struct super_block *s)
-{
-	REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_BARRIER_FLUSH);
-	printk("reiserfs: disabling flush barriers on %s\n",
-	       reiserfs_bdevname(s));
-}
-
 static struct reiserfs_bitmap_node *allocate_bitmap_node(struct super_block
 							 *sb)
 {
@@ -677,30 +670,6 @@
 	submit_bh(WRITE, bh);
 }
 
-static int submit_barrier_buffer(struct buffer_head *bh)
-{
-	get_bh(bh);
-	bh->b_end_io = reiserfs_end_ordered_io;
-	clear_buffer_dirty(bh);
-	if (!buffer_uptodate(bh))
-		BUG();
-	return submit_bh(WRITE_BARRIER, bh);
-}
-
-static void check_barrier_completion(struct super_block *s,
-				     struct buffer_head *bh)
-{
-	if (buffer_eopnotsupp(bh)) {
-		clear_buffer_eopnotsupp(bh);
-		disable_barrier(s);
-		set_buffer_uptodate(bh);
-		set_buffer_dirty(bh);
-		reiserfs_write_unlock(s);
-		sync_dirty_buffer(bh);
-		reiserfs_write_lock(s);
-	}
-}
-
 #define CHUNK_SIZE 32
 struct buffer_chunk {
 	struct buffer_head *bh[CHUNK_SIZE];
@@ -1009,7 +978,6 @@
 	struct buffer_head *tbh = NULL;
 	unsigned int trans_id = jl->j_trans_id;
 	struct reiserfs_journal *journal = SB_JOURNAL(s);
-	int barrier = 0;
 	int retval = 0;
 	int write_len;
 
@@ -1094,24 +1062,6 @@
 	}
 	atomic_dec(&journal->j_async_throttle);
 
-	/* We're skipping the commit if there's an error */
-	if (retval || reiserfs_is_journal_aborted(journal))
-		barrier = 0;
-
-	/* wait on everything written so far before writing the commit
-	 * if we are in barrier mode, send the commit down now
-	 */
-	barrier = reiserfs_barrier_flush(s);
-	if (barrier) {
-		int ret;
-		lock_buffer(jl->j_commit_bh);
-		ret = submit_barrier_buffer(jl->j_commit_bh);
-		if (ret == -EOPNOTSUPP) {
-			set_buffer_uptodate(jl->j_commit_bh);
-			disable_barrier(s);
-			barrier = 0;
-		}
-	}
 	for (i = 0; i < (jl->j_len + 1); i++) {
 		bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) +
 		    (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s);
@@ -1143,27 +1093,22 @@
 
 	BUG_ON(atomic_read(&(jl->j_commit_left)) != 1);
 
-	if (!barrier) {
-		/* If there was a write error in the journal - we can't commit
-		 * this transaction - it will be invalid and, if successful,
-		 * will just end up propagating the write error out to
-		 * the file system. */
-		if (likely(!retval && !reiserfs_is_journal_aborted (journal))) {
-			if (buffer_dirty(jl->j_commit_bh))
-				BUG();
-			mark_buffer_dirty(jl->j_commit_bh) ;
-			reiserfs_write_unlock(s);
-			sync_dirty_buffer(jl->j_commit_bh) ;
-			reiserfs_write_lock(s);
-		}
-	} else {
+	/* If there was a write error in the journal - we can't commit
+	 * this transaction - it will be invalid and, if successful,
+	 * will just end up propagating the write error out to
+	 * the file system. */
+	if (likely(!retval && !reiserfs_is_journal_aborted (journal))) {
+		if (buffer_dirty(jl->j_commit_bh))
+			BUG();
+		mark_buffer_dirty(jl->j_commit_bh) ;
 		reiserfs_write_unlock(s);
-		wait_on_buffer(jl->j_commit_bh);
+		if (reiserfs_barrier_flush(s))
+			__sync_dirty_buffer(jl->j_commit_bh, WRITE_FLUSH_FUA);
+		else
+			sync_dirty_buffer(jl->j_commit_bh);
 		reiserfs_write_lock(s);
 	}
 
-	check_barrier_completion(s, jl->j_commit_bh);
-
 	/* If there was a write error in the journal - we can't commit this
 	 * transaction - it will be invalid and, if successful, will just end
 	 * up propagating the write error out to the filesystem. */
@@ -1319,26 +1264,15 @@
 		jh->j_first_unflushed_offset = cpu_to_le32(offset);
 		jh->j_mount_id = cpu_to_le32(journal->j_mount_id);
 
-		if (reiserfs_barrier_flush(sb)) {
-			int ret;
-			lock_buffer(journal->j_header_bh);
-			ret = submit_barrier_buffer(journal->j_header_bh);
-			if (ret == -EOPNOTSUPP) {
-				set_buffer_uptodate(journal->j_header_bh);
-				disable_barrier(sb);
-				goto sync;
-			}
-			reiserfs_write_unlock(sb);
-			wait_on_buffer(journal->j_header_bh);
-			reiserfs_write_lock(sb);
-			check_barrier_completion(sb, journal->j_header_bh);
-		} else {
-		      sync:
-			set_buffer_dirty(journal->j_header_bh);
-			reiserfs_write_unlock(sb);
+		set_buffer_dirty(journal->j_header_bh);
+		reiserfs_write_unlock(sb);
+
+		if (reiserfs_barrier_flush(sb))
+			__sync_dirty_buffer(journal->j_header_bh, WRITE_FLUSH_FUA);
+		else
 			sync_dirty_buffer(journal->j_header_bh);
-			reiserfs_write_lock(sb);
-		}
+
+		reiserfs_write_lock(sb);
 		if (!buffer_uptodate(journal->j_header_bh)) {
 			reiserfs_warning(sb, "journal-837",
 					 "IO error during journal replay");
diff --git a/fs/romfs/super.c b/fs/romfs/super.c
index 42d2135..2685805 100644
--- a/fs/romfs/super.c
+++ b/fs/romfs/super.c
@@ -282,6 +282,7 @@
 static const struct file_operations romfs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= romfs_readdir,
+	.llseek		= default_llseek,
 };
 
 static const struct inode_operations romfs_dir_inode_operations = {
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 1c5a6ad..7404730 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -206,6 +206,7 @@
 	.release	= signalfd_release,
 	.poll		= signalfd_poll,
 	.read		= signalfd_read,
+	.llseek		= noop_llseek,
 };
 
 SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
diff --git a/fs/smbfs/Kconfig b/fs/smbfs/Kconfig
index e668127..2bc24a8 100644
--- a/fs/smbfs/Kconfig
+++ b/fs/smbfs/Kconfig
@@ -1,5 +1,6 @@
 config SMB_FS
 	tristate "SMB file system support (OBSOLETE, please use CIFS)"
+	depends on BKL # probably unfixable
 	depends on INET
 	select NLS
 	help
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 450c919..8fc5e50 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -501,6 +501,8 @@
 	void *mem;
 	static int warn_count;
 
+	lock_kernel();
+
 	if (warn_count < 5) {
 		warn_count++;
 		printk(KERN_EMERG "smbfs is deprecated and will be removed"
@@ -621,6 +623,7 @@
 
 	smb_new_dentry(sb->s_root);
 
+	unlock_kernel();
 	return 0;
 
 out_no_root:
@@ -643,9 +646,11 @@
 out_no_data:
 	printk(KERN_ERR "smb_fill_super: missing data argument\n");
 out_fail:
+	unlock_kernel();
 	return -EINVAL;
 out_no_server:
 	printk(KERN_ERR "smb_fill_super: cannot allocate struct smb_sb_info\n");
+	unlock_kernel();
 	return -ENOMEM;
 }
 
diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c
index 12b933a..0dc340a 100644
--- a/fs/squashfs/dir.c
+++ b/fs/squashfs/dir.c
@@ -230,5 +230,6 @@
 
 const struct file_operations squashfs_dir_ops = {
 	.read = generic_read_dir,
-	.readdir = squashfs_readdir
+	.readdir = squashfs_readdir,
+	.llseek = default_llseek,
 };
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 88b4f86..07a4f11 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -30,7 +30,6 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
@@ -354,8 +353,6 @@
 
 static void squashfs_put_super(struct super_block *sb)
 {
-	lock_kernel();
-
 	if (sb->s_fs_info) {
 		struct squashfs_sb_info *sbi = sb->s_fs_info;
 		squashfs_cache_delete(sbi->block_cache);
@@ -370,8 +367,6 @@
 		kfree(sb->s_fs_info);
 		sb->s_fs_info = NULL;
 	}
-
-	unlock_kernel();
 }
 
 
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 4e321f7..a475983 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -179,30 +179,14 @@
 	struct bin_buffer *bb = file->private_data;
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 
-	if (!bb->vm_ops || !bb->vm_ops->open)
+	if (!bb->vm_ops)
 		return;
 
 	if (!sysfs_get_active(attr_sd))
 		return;
 
-	bb->vm_ops->open(vma);
-
-	sysfs_put_active(attr_sd);
-}
-
-static void bin_vma_close(struct vm_area_struct *vma)
-{
-	struct file *file = vma->vm_file;
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-
-	if (!bb->vm_ops || !bb->vm_ops->close)
-		return;
-
-	if (!sysfs_get_active(attr_sd))
-		return;
-
-	bb->vm_ops->close(vma);
+	if (bb->vm_ops->open)
+		bb->vm_ops->open(vma);
 
 	sysfs_put_active(attr_sd);
 }
@@ -214,13 +198,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	int ret;
 
-	if (!bb->vm_ops || !bb->vm_ops->fault)
+	if (!bb->vm_ops)
 		return VM_FAULT_SIGBUS;
 
 	if (!sysfs_get_active(attr_sd))
 		return VM_FAULT_SIGBUS;
 
-	ret = bb->vm_ops->fault(vma, vmf);
+	ret = VM_FAULT_SIGBUS;
+	if (bb->vm_ops->fault)
+		ret = bb->vm_ops->fault(vma, vmf);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -236,13 +222,12 @@
 	if (!bb->vm_ops)
 		return VM_FAULT_SIGBUS;
 
-	if (!bb->vm_ops->page_mkwrite)
-		return 0;
-
 	if (!sysfs_get_active(attr_sd))
 		return VM_FAULT_SIGBUS;
 
-	ret = bb->vm_ops->page_mkwrite(vma, vmf);
+	ret = 0;
+	if (bb->vm_ops->page_mkwrite)
+		ret = bb->vm_ops->page_mkwrite(vma, vmf);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -256,13 +241,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	int ret;
 
-	if (!bb->vm_ops || !bb->vm_ops->access)
+	if (!bb->vm_ops)
 		return -EINVAL;
 
 	if (!sysfs_get_active(attr_sd))
 		return -EINVAL;
 
-	ret = bb->vm_ops->access(vma, addr, buf, len, write);
+	ret = -EINVAL;
+	if (bb->vm_ops->access)
+		ret = bb->vm_ops->access(vma, addr, buf, len, write);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -276,13 +263,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	int ret;
 
-	if (!bb->vm_ops || !bb->vm_ops->set_policy)
+	if (!bb->vm_ops)
 		return 0;
 
 	if (!sysfs_get_active(attr_sd))
 		return -EINVAL;
 
-	ret = bb->vm_ops->set_policy(vma, new);
+	ret = 0;
+	if (bb->vm_ops->set_policy)
+		ret = bb->vm_ops->set_policy(vma, new);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -296,13 +285,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	struct mempolicy *pol;
 
-	if (!bb->vm_ops || !bb->vm_ops->get_policy)
+	if (!bb->vm_ops)
 		return vma->vm_policy;
 
 	if (!sysfs_get_active(attr_sd))
 		return vma->vm_policy;
 
-	pol = bb->vm_ops->get_policy(vma, addr);
+	pol = vma->vm_policy;
+	if (bb->vm_ops->get_policy)
+		pol = bb->vm_ops->get_policy(vma, addr);
 
 	sysfs_put_active(attr_sd);
 	return pol;
@@ -316,13 +307,15 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	int ret;
 
-	if (!bb->vm_ops || !bb->vm_ops->migrate)
+	if (!bb->vm_ops)
 		return 0;
 
 	if (!sysfs_get_active(attr_sd))
 		return 0;
 
-	ret = bb->vm_ops->migrate(vma, from, to, flags);
+	ret = 0;
+	if (bb->vm_ops->migrate)
+		ret = bb->vm_ops->migrate(vma, from, to, flags);
 
 	sysfs_put_active(attr_sd);
 	return ret;
@@ -331,7 +324,6 @@
 
 static const struct vm_operations_struct bin_vm_ops = {
 	.open		= bin_vma_open,
-	.close		= bin_vma_close,
 	.fault		= bin_fault,
 	.page_mkwrite	= bin_page_mkwrite,
 	.access		= bin_access,
@@ -377,6 +369,14 @@
 	if (bb->mmapped && bb->vm_ops != vma->vm_ops)
 		goto out_put;
 
+	/*
+	 * It is not possible to successfully wrap close.
+	 * So error if someone is trying to use close.
+	 */
+	rc = -EINVAL;
+	if (vma->vm_ops && vma->vm_ops->close)
+		goto out_put;
+
 	rc = 0;
 	bb->mmapped = 1;
 	bb->vm_ops = vma->vm_ops;
diff --git a/fs/timerfd.c b/fs/timerfd.c
index b86ab8e..8c4fc14 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -144,6 +144,7 @@
 	.release	= timerfd_release,
 	.poll		= timerfd_poll,
 	.read		= timerfd_read,
+	.llseek		= noop_llseek,
 };
 
 static struct file *timerfd_fget(int fd)
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 37fa7ed..02429d8 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -63,7 +63,9 @@
 	struct ubifs_lp_stats lst;
 
 	dbg_cmt("start");
-	if (c->ro_media) {
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+
+	if (c->ro_error) {
 		err = -EROFS;
 		goto out_up;
 	}
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index c2a68ba..0bee4db 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2239,6 +2239,162 @@
 	return err;
 }
 
+/**
+ * dbg_check_data_nodes_order - check that list of data nodes is sorted.
+ * @c: UBIFS file-system description object
+ * @head: the list of nodes ('struct ubifs_scan_node' objects)
+ *
+ * This function returns zero if the list of data nodes is sorted correctly,
+ * and %-EINVAL if not.
+ */
+int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
+{
+	struct list_head *cur;
+	struct ubifs_scan_node *sa, *sb;
+
+	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+		return 0;
+
+	for (cur = head->next; cur->next != head; cur = cur->next) {
+		ino_t inuma, inumb;
+		uint32_t blka, blkb;
+
+		cond_resched();
+		sa = container_of(cur, struct ubifs_scan_node, list);
+		sb = container_of(cur->next, struct ubifs_scan_node, list);
+
+		if (sa->type != UBIFS_DATA_NODE) {
+			ubifs_err("bad node type %d", sa->type);
+			dbg_dump_node(c, sa->node);
+			return -EINVAL;
+		}
+		if (sb->type != UBIFS_DATA_NODE) {
+			ubifs_err("bad node type %d", sb->type);
+			dbg_dump_node(c, sb->node);
+			return -EINVAL;
+		}
+
+		inuma = key_inum(c, &sa->key);
+		inumb = key_inum(c, &sb->key);
+
+		if (inuma < inumb)
+			continue;
+		if (inuma > inumb) {
+			ubifs_err("larger inum %lu goes before inum %lu",
+				  (unsigned long)inuma, (unsigned long)inumb);
+			goto error_dump;
+		}
+
+		blka = key_block(c, &sa->key);
+		blkb = key_block(c, &sb->key);
+
+		if (blka > blkb) {
+			ubifs_err("larger block %u goes before %u", blka, blkb);
+			goto error_dump;
+		}
+		if (blka == blkb) {
+			ubifs_err("two data nodes for the same block");
+			goto error_dump;
+		}
+	}
+
+	return 0;
+
+error_dump:
+	dbg_dump_node(c, sa->node);
+	dbg_dump_node(c, sb->node);
+	return -EINVAL;
+}
+
+/**
+ * dbg_check_nondata_nodes_order - check that list of data nodes is sorted.
+ * @c: UBIFS file-system description object
+ * @head: the list of nodes ('struct ubifs_scan_node' objects)
+ *
+ * This function returns zero if the list of non-data nodes is sorted correctly,
+ * and %-EINVAL if not.
+ */
+int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
+{
+	struct list_head *cur;
+	struct ubifs_scan_node *sa, *sb;
+
+	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+		return 0;
+
+	for (cur = head->next; cur->next != head; cur = cur->next) {
+		ino_t inuma, inumb;
+		uint32_t hasha, hashb;
+
+		cond_resched();
+		sa = container_of(cur, struct ubifs_scan_node, list);
+		sb = container_of(cur->next, struct ubifs_scan_node, list);
+
+		if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
+		    sa->type != UBIFS_XENT_NODE) {
+			ubifs_err("bad node type %d", sa->type);
+			dbg_dump_node(c, sa->node);
+			return -EINVAL;
+		}
+		if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
+		    sa->type != UBIFS_XENT_NODE) {
+			ubifs_err("bad node type %d", sb->type);
+			dbg_dump_node(c, sb->node);
+			return -EINVAL;
+		}
+
+		if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
+			ubifs_err("non-inode node goes before inode node");
+			goto error_dump;
+		}
+
+		if (sa->type == UBIFS_INO_NODE && sb->type != UBIFS_INO_NODE)
+			continue;
+
+		if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
+			/* Inode nodes are sorted in descending size order */
+			if (sa->len < sb->len) {
+				ubifs_err("smaller inode node goes first");
+				goto error_dump;
+			}
+			continue;
+		}
+
+		/*
+		 * This is either a dentry or xentry, which should be sorted in
+		 * ascending (parent ino, hash) order.
+		 */
+		inuma = key_inum(c, &sa->key);
+		inumb = key_inum(c, &sb->key);
+
+		if (inuma < inumb)
+			continue;
+		if (inuma > inumb) {
+			ubifs_err("larger inum %lu goes before inum %lu",
+				  (unsigned long)inuma, (unsigned long)inumb);
+			goto error_dump;
+		}
+
+		hasha = key_block(c, &sa->key);
+		hashb = key_block(c, &sb->key);
+
+		if (hasha > hashb) {
+			ubifs_err("larger hash %u goes before %u", hasha, hashb);
+			goto error_dump;
+		}
+	}
+
+	return 0;
+
+error_dump:
+	ubifs_msg("dumping first node");
+	dbg_dump_node(c, sa->node);
+	ubifs_msg("dumping second node");
+	dbg_dump_node(c, sb->node);
+	return -EINVAL;
+	return 0;
+}
+
 static int invocation_cnt;
 
 int dbg_force_in_the_gaps(void)
@@ -2625,6 +2781,7 @@
 	.open = open_debugfs_file,
 	.write = write_debugfs_file,
 	.owner = THIS_MODULE,
+	.llseek = default_llseek,
 };
 
 /**
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 29d9601..69ebe47 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -324,6 +324,8 @@
 			int row, int col);
 int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
 			 loff_t size);
+int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
+int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
 
 /* Force the use of in-the-gaps method for testing */
 
@@ -465,6 +467,8 @@
 #define dbg_check_lprops(c)                        0
 #define dbg_check_lpt_nodes(c, cnode, row, col)    0
 #define dbg_check_inode_size(c, inode, size)       0
+#define dbg_check_data_nodes_order(c, head)        0
+#define dbg_check_nondata_nodes_order(c, head)     0
 #define dbg_force_in_the_gaps_enabled              0
 #define dbg_force_in_the_gaps()                    0
 #define dbg_failure_mode                           0
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 03ae894..d77db7e 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -433,8 +433,9 @@
 	struct page *page;
 
 	ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
-	if (unlikely(c->ro_media))
+	if (unlikely(c->ro_error))
 		return -EROFS;
 
 	/* Try out the fast-path part first */
@@ -1439,9 +1440,9 @@
 
 	dbg_gen("ino %lu, pg %lu, i_size %lld",	inode->i_ino, page->index,
 		i_size_read(inode));
-	ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY));
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
-	if (unlikely(c->ro_media))
+	if (unlikely(c->ro_error))
 		return VM_FAULT_SIGBUS; /* -EROFS */
 
 	/*
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 918d158..151f108 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -125,10 +125,16 @@
 	struct ubifs_scan_node *sa, *sb;
 
 	cond_resched();
+	if (a == b)
+		return 0;
+
 	sa = list_entry(a, struct ubifs_scan_node, list);
 	sb = list_entry(b, struct ubifs_scan_node, list);
+
 	ubifs_assert(key_type(c, &sa->key) == UBIFS_DATA_KEY);
 	ubifs_assert(key_type(c, &sb->key) == UBIFS_DATA_KEY);
+	ubifs_assert(sa->type == UBIFS_DATA_NODE);
+	ubifs_assert(sb->type == UBIFS_DATA_NODE);
 
 	inuma = key_inum(c, &sa->key);
 	inumb = key_inum(c, &sb->key);
@@ -157,28 +163,40 @@
  */
 int nondata_nodes_cmp(void *priv, struct list_head *a, struct list_head *b)
 {
-	int typea, typeb;
 	ino_t inuma, inumb;
 	struct ubifs_info *c = priv;
 	struct ubifs_scan_node *sa, *sb;
 
 	cond_resched();
+	if (a == b)
+		return 0;
+
 	sa = list_entry(a, struct ubifs_scan_node, list);
 	sb = list_entry(b, struct ubifs_scan_node, list);
-	typea = key_type(c, &sa->key);
-	typeb = key_type(c, &sb->key);
-	ubifs_assert(typea != UBIFS_DATA_KEY && typeb != UBIFS_DATA_KEY);
+
+	ubifs_assert(key_type(c, &sa->key) != UBIFS_DATA_KEY &&
+		     key_type(c, &sb->key) != UBIFS_DATA_KEY);
+	ubifs_assert(sa->type != UBIFS_DATA_NODE &&
+		     sb->type != UBIFS_DATA_NODE);
 
 	/* Inodes go before directory entries */
-	if (typea == UBIFS_INO_KEY) {
-		if (typeb == UBIFS_INO_KEY)
+	if (sa->type == UBIFS_INO_NODE) {
+		if (sb->type == UBIFS_INO_NODE)
 			return sb->len - sa->len;
 		return -1;
 	}
-	if (typeb == UBIFS_INO_KEY)
+	if (sb->type == UBIFS_INO_NODE)
 		return 1;
 
-	ubifs_assert(typea == UBIFS_DENT_KEY && typeb == UBIFS_DENT_KEY);
+	ubifs_assert(key_type(c, &sa->key) == UBIFS_DENT_KEY ||
+		     key_type(c, &sa->key) == UBIFS_XENT_KEY);
+	ubifs_assert(key_type(c, &sb->key) == UBIFS_DENT_KEY ||
+		     key_type(c, &sb->key) == UBIFS_XENT_KEY);
+	ubifs_assert(sa->type == UBIFS_DENT_NODE ||
+		     sa->type == UBIFS_XENT_NODE);
+	ubifs_assert(sb->type == UBIFS_DENT_NODE ||
+		     sb->type == UBIFS_XENT_NODE);
+
 	inuma = key_inum(c, &sa->key);
 	inumb = key_inum(c, &sb->key);
 
@@ -224,17 +242,33 @@
 static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 		      struct list_head *nondata, int *min)
 {
+	int err;
 	struct ubifs_scan_node *snod, *tmp;
 
 	*min = INT_MAX;
 
 	/* Separate data nodes and non-data nodes */
 	list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
-		int err;
+		ubifs_assert(snod->type == UBIFS_INO_NODE  ||
+			     snod->type == UBIFS_DATA_NODE ||
+			     snod->type == UBIFS_DENT_NODE ||
+			     snod->type == UBIFS_XENT_NODE ||
+			     snod->type == UBIFS_TRUN_NODE);
 
-		ubifs_assert(snod->type != UBIFS_IDX_NODE);
-		ubifs_assert(snod->type != UBIFS_REF_NODE);
-		ubifs_assert(snod->type != UBIFS_CS_NODE);
+		if (snod->type != UBIFS_INO_NODE  &&
+		    snod->type != UBIFS_DATA_NODE &&
+		    snod->type != UBIFS_DENT_NODE &&
+		    snod->type != UBIFS_XENT_NODE) {
+			/* Probably truncation node, zap it */
+			list_del(&snod->list);
+			kfree(snod);
+			continue;
+		}
+
+		ubifs_assert(key_type(c, &snod->key) == UBIFS_DATA_KEY ||
+			     key_type(c, &snod->key) == UBIFS_INO_KEY  ||
+			     key_type(c, &snod->key) == UBIFS_DENT_KEY ||
+			     key_type(c, &snod->key) == UBIFS_XENT_KEY);
 
 		err = ubifs_tnc_has_node(c, &snod->key, 0, sleb->lnum,
 					 snod->offs, 0);
@@ -258,6 +292,13 @@
 	/* Sort data and non-data nodes */
 	list_sort(c, &sleb->nodes, &data_nodes_cmp);
 	list_sort(c, nondata, &nondata_nodes_cmp);
+
+	err = dbg_check_data_nodes_order(c, &sleb->nodes);
+	if (err)
+		return err;
+	err = dbg_check_nondata_nodes_order(c, nondata);
+	if (err)
+		return err;
 	return 0;
 }
 
@@ -575,13 +616,14 @@
 	struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
 
 	ubifs_assert_cmt_locked(c);
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
 	if (ubifs_gc_should_commit(c))
 		return -EAGAIN;
 
 	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
 
-	if (c->ro_media) {
+	if (c->ro_error) {
 		ret = -EROFS;
 		goto out_unlock;
 	}
@@ -677,14 +719,12 @@
 
 		ret = ubifs_garbage_collect_leb(c, &lp);
 		if (ret < 0) {
-			if (ret == -EAGAIN || ret == -ENOSPC) {
+			if (ret == -EAGAIN) {
 				/*
-				 * These codes are not errors, so we have to
-				 * return the LEB to lprops. But if the
-				 * 'ubifs_return_leb()' function fails, its
-				 * failure code is propagated to the caller
-				 * instead of the original '-EAGAIN' or
-				 * '-ENOSPC'.
+				 * This is not error, so we have to return the
+				 * LEB to lprops. But if 'ubifs_return_leb()'
+				 * fails, its failure code is propagated to the
+				 * caller instead of the original '-EAGAIN'.
 				 */
 				err = ubifs_return_leb(c, lp.lnum);
 				if (err)
@@ -774,8 +814,8 @@
 out:
 	ubifs_assert(ret < 0);
 	ubifs_assert(ret != -ENOSPC && ret != -EAGAIN);
-	ubifs_ro_mode(c, ret);
 	ubifs_wbuf_sync_nolock(wbuf);
+	ubifs_ro_mode(c, ret);
 	mutex_unlock(&wbuf->io_mutex);
 	ubifs_return_leb(c, lp.lnum);
 	return ret;
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index bcf5a16..d821731 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -61,8 +61,8 @@
  */
 void ubifs_ro_mode(struct ubifs_info *c, int err)
 {
-	if (!c->ro_media) {
-		c->ro_media = 1;
+	if (!c->ro_error) {
+		c->ro_error = 1;
 		c->no_chk_data_crc = 0;
 		c->vfs_sb->s_flags |= MS_RDONLY;
 		ubifs_warn("switched to read-only mode, error %d", err);
@@ -356,11 +356,11 @@
 
 	dbg_io("LEB %d:%d, %d bytes, jhead %s",
 	       wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));
-	ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
 	ubifs_assert(!(wbuf->avail & 7));
 	ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
-	if (c->ro_media)
+	if (c->ro_error)
 		return -EROFS;
 
 	ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail);
@@ -440,11 +440,12 @@
 {
 	int err, i;
 
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 	if (!c->need_wbuf_sync)
 		return 0;
 	c->need_wbuf_sync = 0;
 
-	if (c->ro_media) {
+	if (c->ro_error) {
 		err = -EROFS;
 		goto out_timers;
 	}
@@ -519,6 +520,7 @@
 	ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
 	ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
 	ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
 	if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
 		err = -ENOSPC;
@@ -527,7 +529,7 @@
 
 	cancel_wbuf_timer_nolock(wbuf);
 
-	if (c->ro_media)
+	if (c->ro_error)
 		return -EROFS;
 
 	if (aligned_len <= wbuf->avail) {
@@ -663,8 +665,9 @@
 	       buf_len);
 	ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
 	ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 
-	if (c->ro_media)
+	if (c->ro_error)
 		return -EROFS;
 
 	ubifs_prepare_node(c, buf, len, 1);
@@ -815,7 +818,8 @@
 	return 0;
 
 out:
-	ubifs_err("bad node at LEB %d:%d", lnum, offs);
+	ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs,
+		  ubi_is_mapped(c->ubi, lnum));
 	dbg_dump_node(c, buf);
 	dbg_dump_stack();
 	return -EINVAL;
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index d321bae..914f1bd 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -122,11 +122,12 @@
 	 * better to try to allocate space at the ends of eraseblocks. This is
 	 * what the squeeze parameter does.
 	 */
+	ubifs_assert(!c->ro_media && !c->ro_mount);
 	squeeze = (jhead == BASEHD);
 again:
 	mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
 
-	if (c->ro_media) {
+	if (c->ro_error) {
 		err = -EROFS;
 		goto out_unlock;
 	}
diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
index 0f530c6..92a8491 100644
--- a/fs/ubifs/key.h
+++ b/fs/ubifs/key.h
@@ -306,6 +306,20 @@
 }
 
 /**
+ * invalid_key_init - initialize invalid node key.
+ * @c: UBIFS file-system description object
+ * @key: key to initialize
+ *
+ * This is a helper function which marks a @key object as invalid.
+ */
+static inline void invalid_key_init(const struct ubifs_info *c,
+				    union ubifs_key *key)
+{
+	key->u32[0] = 0xDEADBEAF;
+	key->u32[1] = UBIFS_INVALID_KEY;
+}
+
+/**
  * key_type - get key type.
  * @c: UBIFS file-system description object
  * @key: key to get type of
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index c345e12..4d0cb12 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -159,7 +159,7 @@
 		jhead = &c->jheads[bud->jhead];
 		list_add_tail(&bud->list, &jhead->buds_list);
 	} else
-		ubifs_assert(c->replaying && (c->vfs_sb->s_flags & MS_RDONLY));
+		ubifs_assert(c->replaying && c->ro_mount);
 
 	/*
 	 * Note, although this is a new bud, we anyway account this space now,
@@ -223,8 +223,8 @@
 	}
 
 	mutex_lock(&c->log_mutex);
-
-	if (c->ro_media) {
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error) {
 		err = -EROFS;
 		goto out_unlock;
 	}
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 0084a33..72775d3 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -1363,6 +1363,7 @@
 		goto out;
 	for (i = 0; i < c->lsave_cnt; i++) {
 		int lnum = c->lsave[i];
+		struct ubifs_lprops *lprops;
 
 		/*
 		 * Due to automatic resizing, the values in the lsave table
@@ -1370,7 +1371,11 @@
 		 */
 		if (lnum >= c->leb_cnt)
 			continue;
-		ubifs_lpt_lookup(c, lnum);
+		lprops = ubifs_lpt_lookup(c, lnum);
+		if (IS_ERR(lprops)) {
+			err = PTR_ERR(lprops);
+			goto out;
+		}
 	}
 out:
 	vfree(buf);
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index d12535b..5c90dec 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -705,6 +705,9 @@
 	struct ubifs_pnode *pnode;
 
 	pnode = pnode_lookup(c, 0);
+	if (IS_ERR(pnode))
+		return PTR_ERR(pnode);
+
 	while (pnode) {
 		do_make_pnode_dirty(c, pnode);
 		pnode = next_pnode_to_dirty(c, pnode);
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c
index 28beaee..21f47af 100644
--- a/fs/ubifs/master.c
+++ b/fs/ubifs/master.c
@@ -361,7 +361,8 @@
 {
 	int err, lnum, offs, len;
 
-	if (c->ro_media)
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
 		return -EROFS;
 
 	lnum = UBIFS_MST_LNUM;
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h
index 4fa81d8..c3de04d 100644
--- a/fs/ubifs/misc.h
+++ b/fs/ubifs/misc.h
@@ -132,7 +132,8 @@
 {
 	int err;
 
-	if (c->ro_media)
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
 		return -EROFS;
 	err = ubi_leb_unmap(c->ubi, lnum);
 	if (err) {
@@ -159,7 +160,8 @@
 {
 	int err;
 
-	if (c->ro_media)
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
 		return -EROFS;
 	err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
 	if (err) {
@@ -186,7 +188,8 @@
 {
 	int err;
 
-	if (c->ro_media)
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
 		return -EROFS;
 	err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
 	if (err) {
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index daae9e1..77e9b87 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -292,7 +292,7 @@
 
 	memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);
 
-	if ((c->vfs_sb->s_flags & MS_RDONLY)) {
+	if (c->ro_mount) {
 		/* Read-only mode. Keep a copy for switching to rw mode */
 		c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL);
 		if (!c->rcvrd_mst_node) {
@@ -469,7 +469,7 @@
 		endpt = snod->offs + snod->len;
 	}
 
-	if ((c->vfs_sb->s_flags & MS_RDONLY) && !c->remounting_rw) {
+	if (c->ro_mount && !c->remounting_rw) {
 		/* Add to recovery list */
 		struct ubifs_unclean_leb *ucleb;
 
@@ -772,7 +772,8 @@
  * @sbuf: LEB-sized buffer to use
  *
  * This function does a scan of a LEB, but caters for errors that might have
- * been caused by the unclean unmount from which we are attempting to recover.
+ * been caused by unclean reboots from which we are attempting to recover
+ * (assume that only the last log LEB can be corrupted by an unclean reboot).
  *
  * This function returns %0 on success and a negative error code on failure.
  */
@@ -883,7 +884,7 @@
 {
 	int err;
 
-	ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY) || c->remounting_rw);
+	ubifs_assert(!c->ro_mount || c->remounting_rw);
 
 	dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
 	err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
@@ -1461,7 +1462,7 @@
 			}
 		}
 		if (e->exists && e->i_size < e->d_size) {
-			if (!e->inode && (c->vfs_sb->s_flags & MS_RDONLY)) {
+			if (!e->inode && c->ro_mount) {
 				/* Fix the inode size and pin it in memory */
 				struct inode *inode;
 
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 5c2d6d7..eed0fcf 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -627,8 +627,7 @@
 	ubifs_assert(sleb->endpt - offs >= used);
 	ubifs_assert(sleb->endpt % c->min_io_size == 0);
 
-	if (sleb->endpt + c->min_io_size <= c->leb_size &&
-	    !(c->vfs_sb->s_flags & MS_RDONLY))
+	if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount)
 		err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
 					     sleb->endpt, UBI_SHORTTERM);
 
@@ -840,6 +839,11 @@
 	if (IS_ERR(sleb)) {
 		if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
 			return PTR_ERR(sleb);
+		/*
+		 * Note, the below function will recover this log LEB only if
+		 * it is the last, because unclean reboots can possibly corrupt
+		 * only the tail of the log.
+		 */
 		sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
 		if (IS_ERR(sleb))
 			return PTR_ERR(sleb);
@@ -851,7 +855,6 @@
 	}
 
 	node = sleb->buf;
-
 	snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
 	if (c->cs_sqnum == 0) {
 		/*
@@ -898,7 +901,6 @@
 	}
 
 	list_for_each_entry(snod, &sleb->nodes, list) {
-
 		cond_resched();
 
 		if (snod->sqnum >= SQNUM_WATERMARK) {
@@ -1011,7 +1013,6 @@
 int ubifs_replay_journal(struct ubifs_info *c)
 {
 	int err, i, lnum, offs, free;
-	void *sbuf = NULL;
 
 	BUILD_BUG_ON(UBIFS_TRUN_KEY > 5);
 
@@ -1026,14 +1027,8 @@
 		return -EINVAL;
 	}
 
-	sbuf = vmalloc(c->leb_size);
-	if (!sbuf)
-		return -ENOMEM;
-
 	dbg_mnt("start replaying the journal");
-
 	c->replaying = 1;
-
 	lnum = c->ltail_lnum = c->lhead_lnum;
 	offs = c->lhead_offs;
 
@@ -1046,7 +1041,7 @@
 			lnum = UBIFS_LOG_LNUM;
 			offs = 0;
 		}
-		err = replay_log_leb(c, lnum, offs, sbuf);
+		err = replay_log_leb(c, lnum, offs, c->sbuf);
 		if (err == 1)
 			/* We hit the end of the log */
 			break;
@@ -1079,7 +1074,6 @@
 out:
 	destroy_replay_tree(c);
 	destroy_bud_list(c);
-	vfree(sbuf);
 	c->replaying = 0;
 	return err;
 }
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index 96cb62c..bf31b47 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -542,11 +542,8 @@
 	 * due to the unavailability of time-travelling equipment.
 	 */
 	if (c->fmt_version > UBIFS_FORMAT_VERSION) {
-		struct super_block *sb = c->vfs_sb;
-		int mounting_ro = sb->s_flags & MS_RDONLY;
-
-		ubifs_assert(!c->ro_media || mounting_ro);
-		if (!mounting_ro ||
+		ubifs_assert(!c->ro_media || c->ro_mount);
+		if (!c->ro_mount ||
 		    c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
 			ubifs_err("on-flash format version is w%d/r%d, but "
 				  "software only supports up to version "
@@ -624,7 +621,7 @@
 	c->old_leb_cnt = c->leb_cnt;
 	if (c->leb_cnt < c->vi.size && c->leb_cnt < c->max_leb_cnt) {
 		c->leb_cnt = min_t(int, c->max_leb_cnt, c->vi.size);
-		if (c->vfs_sb->s_flags & MS_RDONLY)
+		if (c->ro_mount)
 			dbg_mnt("Auto resizing (ro) from %d LEBs to %d LEBs",
 				c->old_leb_cnt,	c->leb_cnt);
 		else {
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index 96c5253..3e1ee57 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -197,7 +197,7 @@
 	struct ubifs_ino_node *ino = buf;
 	struct ubifs_scan_node *snod;
 
-	snod = kzalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
+	snod = kmalloc(sizeof(struct ubifs_scan_node), GFP_NOFS);
 	if (!snod)
 		return -ENOMEM;
 
@@ -212,13 +212,15 @@
 	case UBIFS_DENT_NODE:
 	case UBIFS_XENT_NODE:
 	case UBIFS_DATA_NODE:
-	case UBIFS_TRUN_NODE:
 		/*
 		 * The key is in the same place in all keyed
 		 * nodes.
 		 */
 		key_read(c, &ino->key, &snod->key);
 		break;
+	default:
+		invalid_key_init(c, &snod->key);
+		break;
 	}
 	list_add_tail(&snod->list, &sleb->nodes);
 	sleb->nodes_cnt += 1;
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c
index 0b20111..46961c0 100644
--- a/fs/ubifs/shrinker.c
+++ b/fs/ubifs/shrinker.c
@@ -250,7 +250,7 @@
 			dirty_zn_cnt = atomic_long_read(&c->dirty_zn_cnt);
 
 			if (!dirty_zn_cnt || c->cmt_state == COMMIT_BROKEN ||
-			    c->ro_media) {
+			    c->ro_mount || c->ro_error) {
 				mutex_unlock(&c->umount_mutex);
 				continue;
 			}
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index cd5900b..9a47c9f 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1137,11 +1137,11 @@
  */
 static int mount_ubifs(struct ubifs_info *c)
 {
-	struct super_block *sb = c->vfs_sb;
-	int err, mounted_read_only = (sb->s_flags & MS_RDONLY);
+	int err;
 	long long x;
 	size_t sz;
 
+	c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY);
 	err = init_constants_early(c);
 	if (err)
 		return err;
@@ -1154,7 +1154,7 @@
 	if (err)
 		goto out_free;
 
-	if (c->empty && (mounted_read_only || c->ro_media)) {
+	if (c->empty && (c->ro_mount || c->ro_media)) {
 		/*
 		 * This UBI volume is empty, and read-only, or the file system
 		 * is mounted read-only - we cannot format it.
@@ -1165,7 +1165,7 @@
 		goto out_free;
 	}
 
-	if (c->ro_media && !mounted_read_only) {
+	if (c->ro_media && !c->ro_mount) {
 		ubifs_err("cannot mount read-write - read-only media");
 		err = -EROFS;
 		goto out_free;
@@ -1185,7 +1185,7 @@
 	if (!c->sbuf)
 		goto out_free;
 
-	if (!mounted_read_only) {
+	if (!c->ro_mount) {
 		c->ileb_buf = vmalloc(c->leb_size);
 		if (!c->ileb_buf)
 			goto out_free;
@@ -1228,7 +1228,7 @@
 	}
 
 	sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
-	if (!mounted_read_only) {
+	if (!c->ro_mount) {
 		err = alloc_wbufs(c);
 		if (err)
 			goto out_cbuf;
@@ -1254,12 +1254,12 @@
 	if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
 		ubifs_msg("recovery needed");
 		c->need_recovery = 1;
-		if (!mounted_read_only) {
+		if (!c->ro_mount) {
 			err = ubifs_recover_inl_heads(c, c->sbuf);
 			if (err)
 				goto out_master;
 		}
-	} else if (!mounted_read_only) {
+	} else if (!c->ro_mount) {
 		/*
 		 * Set the "dirty" flag so that if we reboot uncleanly we
 		 * will notice this immediately on the next mount.
@@ -1270,7 +1270,7 @@
 			goto out_master;
 	}
 
-	err = ubifs_lpt_init(c, 1, !mounted_read_only);
+	err = ubifs_lpt_init(c, 1, !c->ro_mount);
 	if (err)
 		goto out_lpt;
 
@@ -1285,11 +1285,11 @@
 	/* Calculate 'min_idx_lebs' after journal replay */
 	c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
 
-	err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only);
+	err = ubifs_mount_orphans(c, c->need_recovery, c->ro_mount);
 	if (err)
 		goto out_orphans;
 
-	if (!mounted_read_only) {
+	if (!c->ro_mount) {
 		int lnum;
 
 		err = check_free_space(c);
@@ -1351,7 +1351,7 @@
 	spin_unlock(&ubifs_infos_lock);
 
 	if (c->need_recovery) {
-		if (mounted_read_only)
+		if (c->ro_mount)
 			ubifs_msg("recovery deferred");
 		else {
 			c->need_recovery = 0;
@@ -1378,7 +1378,7 @@
 
 	ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
 		  c->vi.ubi_num, c->vi.vol_id, c->vi.name);
-	if (mounted_read_only)
+	if (c->ro_mount)
 		ubifs_msg("mounted read-only");
 	x = (long long)c->main_lebs * c->leb_size;
 	ubifs_msg("file system size:   %lld bytes (%lld KiB, %lld MiB, %d "
@@ -1640,7 +1640,7 @@
 	}
 
 	dbg_gen("re-mounted read-write");
-	c->vfs_sb->s_flags &= ~MS_RDONLY;
+	c->ro_mount = 0;
 	c->remounting_rw = 0;
 	c->always_chk_crc = 0;
 	err = dbg_check_space_info(c);
@@ -1676,7 +1676,7 @@
 	int i, err;
 
 	ubifs_assert(!c->need_recovery);
-	ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
+	ubifs_assert(!c->ro_mount);
 
 	mutex_lock(&c->umount_mutex);
 	if (c->bgt) {
@@ -1686,10 +1686,8 @@
 
 	dbg_save_space_info(c);
 
-	for (i = 0; i < c->jhead_cnt; i++) {
+	for (i = 0; i < c->jhead_cnt; i++)
 		ubifs_wbuf_sync(&c->jheads[i].wbuf);
-		hrtimer_cancel(&c->jheads[i].wbuf.timer);
-	}
 
 	c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
 	c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
@@ -1704,6 +1702,7 @@
 	vfree(c->ileb_buf);
 	c->ileb_buf = NULL;
 	ubifs_lpt_free(c, 1);
+	c->ro_mount = 1;
 	err = dbg_check_space_info(c);
 	if (err)
 		ubifs_ro_mode(c, err);
@@ -1735,7 +1734,7 @@
 	 * the mutex is locked.
 	 */
 	mutex_lock(&c->umount_mutex);
-	if (!(c->vfs_sb->s_flags & MS_RDONLY)) {
+	if (!c->ro_mount) {
 		/*
 		 * First of all kill the background thread to make sure it does
 		 * not interfere with un-mounting and freeing resources.
@@ -1745,23 +1744,22 @@
 			c->bgt = NULL;
 		}
 
-		/* Synchronize write-buffers */
-		if (c->jheads)
+		/*
+		 * On fatal errors c->ro_error is set to 1, in which case we do
+		 * not write the master node.
+		 */
+		if (!c->ro_error) {
+			int err;
+
+			/* Synchronize write-buffers */
 			for (i = 0; i < c->jhead_cnt; i++)
 				ubifs_wbuf_sync(&c->jheads[i].wbuf);
 
-		/*
-		 * On fatal errors c->ro_media is set to 1, in which case we do
-		 * not write the master node.
-		 */
-		if (!c->ro_media) {
 			/*
 			 * We are being cleanly unmounted which means the
 			 * orphans were killed - indicate this in the master
 			 * node. Also save the reserved GC LEB number.
 			 */
-			int err;
-
 			c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
 			c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
 			c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
@@ -1774,6 +1772,10 @@
 				 */
 				ubifs_err("failed to write master node, "
 					  "error %d", err);
+		} else {
+			for (i = 0; i < c->jhead_cnt; i++)
+				/* Make sure write-buffer timers are canceled */
+				hrtimer_cancel(&c->jheads[i].wbuf.timer);
 		}
 	}
 
@@ -1797,17 +1799,21 @@
 		return err;
 	}
 
-	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
+	if (c->ro_mount && !(*flags & MS_RDONLY)) {
+		if (c->ro_error) {
+			ubifs_msg("cannot re-mount R/W due to prior errors");
+			return -EROFS;
+		}
 		if (c->ro_media) {
-			ubifs_msg("cannot re-mount due to prior errors");
+			ubifs_msg("cannot re-mount R/W - UBI volume is R/O");
 			return -EROFS;
 		}
 		err = ubifs_remount_rw(c);
 		if (err)
 			return err;
-	} else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) {
-		if (c->ro_media) {
-			ubifs_msg("cannot re-mount due to prior errors");
+	} else if (!c->ro_mount && (*flags & MS_RDONLY)) {
+		if (c->ro_error) {
+			ubifs_msg("cannot re-mount R/O due to prior errors");
 			return -EROFS;
 		}
 		ubifs_remount_ro(c);
@@ -2049,8 +2055,8 @@
 	 */
 	ubi = open_ubi(name, UBI_READONLY);
 	if (IS_ERR(ubi)) {
-		ubifs_err("cannot open \"%s\", error %d",
-			  name, (int)PTR_ERR(ubi));
+		dbg_err("cannot open \"%s\", error %d",
+			name, (int)PTR_ERR(ubi));
 		return PTR_ERR(ubi);
 	}
 	ubi_get_volume_info(ubi, &vi);
@@ -2064,9 +2070,11 @@
 	}
 
 	if (sb->s_root) {
+		struct ubifs_info *c1 = sb->s_fs_info;
+
 		/* A new mount point for already mounted UBIFS */
 		dbg_gen("this ubi volume is already mounted");
-		if ((flags ^ sb->s_flags) & MS_RDONLY) {
+		if (!!(flags & MS_RDONLY) != c1->ro_mount) {
 			err = -EBUSY;
 			goto out_deact;
 		}
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 2194915..ad9cf01 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -1177,6 +1177,7 @@
 	unsigned long time = get_seconds();
 
 	dbg_tnc("search key %s", DBGKEY(key));
+	ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);
 
 	znode = c->zroot.znode;
 	if (unlikely(!znode)) {
@@ -2966,7 +2967,7 @@
  *
  * This function searches an indexing node by its first key @key and its
  * address @lnum:@offs. It looks up the indexing tree by pulling all indexing
- * nodes it traverses to TNC. This function is called fro indexing nodes which
+ * nodes it traverses to TNC. This function is called for indexing nodes which
  * were found on the media by scanning, for example when garbage-collecting or
  * when doing in-the-gaps commit. This means that the indexing node which is
  * looked for does not have to have exactly the same leftmost key @key, because
@@ -2988,6 +2989,8 @@
 	struct ubifs_znode *znode, *zn;
 	int n, nn;
 
+	ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);
+
 	/*
 	 * The arguments have probably been read off flash, so don't assume
 	 * they are valid.
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 0c9876b..381d6b2 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -119,8 +119,12 @@
  * in TNC. However, when replaying, it is handy to introduce fake "truncation"
  * keys for truncation nodes because the code becomes simpler. So we define
  * %UBIFS_TRUN_KEY type.
+ *
+ * But otherwise, out of the journal reply scope, the truncation keys are
+ * invalid.
  */
-#define UBIFS_TRUN_KEY UBIFS_KEY_TYPES_CNT
+#define UBIFS_TRUN_KEY    UBIFS_KEY_TYPES_CNT
+#define UBIFS_INVALID_KEY UBIFS_KEY_TYPES_CNT
 
 /*
  * How much a directory entry/extended attribute entry adds to the parent/host
@@ -1028,6 +1032,8 @@
  * @max_leb_cnt: maximum count of logical eraseblocks
  * @old_leb_cnt: count of logical eraseblocks before re-size
  * @ro_media: the underlying UBI volume is read-only
+ * @ro_mount: the file-system was mounted as read-only
+ * @ro_error: UBIFS switched to R/O mode because an error happened
  *
  * @dirty_pg_cnt: number of dirty pages (not used)
  * @dirty_zn_cnt: number of dirty znodes
@@ -1168,11 +1174,14 @@
  * @replay_sqnum: sequence number of node currently being replayed
  * @need_recovery: file-system needs recovery
  * @replaying: set to %1 during journal replay
- * @unclean_leb_list: LEBs to recover when mounting ro to rw
- * @rcvrd_mst_node: recovered master node to write when mounting ro to rw
+ * @unclean_leb_list: LEBs to recover when re-mounting R/O mounted FS to R/W
+ *                    mode
+ * @rcvrd_mst_node: recovered master node to write when re-mounting R/O mounted
+ *                  FS to R/W mode
  * @size_tree: inode size information for recovery
- * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY)
- * @always_chk_crc: always check CRCs (while mounting and remounting rw)
+ * @remounting_rw: set while re-mounting from R/O mode to R/W mode
+ * @always_chk_crc: always check CRCs (while mounting and remounting to R/W
+ *                  mode)
  * @mount_opts: UBIFS-specific mount options
  *
  * @dbg: debugging-related information
@@ -1268,7 +1277,9 @@
 	int leb_cnt;
 	int max_leb_cnt;
 	int old_leb_cnt;
-	int ro_media;
+	unsigned int ro_media:1;
+	unsigned int ro_mount:1;
+	unsigned int ro_error:1;
 
 	atomic_long_t dirty_pg_cnt;
 	atomic_long_t dirty_zn_cnt;
diff --git a/fs/udf/Kconfig b/fs/udf/Kconfig
index 0e0e99b..f8def3c 100644
--- a/fs/udf/Kconfig
+++ b/fs/udf/Kconfig
@@ -1,5 +1,6 @@
 config UDF_FS
 	tristate "UDF file system support"
+	depends on BKL # needs serious work to remove
 	select CRC_ITU_T
 	help
 	  This is the new file system used on some CD-ROMs and DVDs. Say Y if
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 65412d8..76f3d6d 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1880,6 +1880,8 @@
 	struct kernel_lb_addr rootdir, fileset;
 	struct udf_sb_info *sbi;
 
+	lock_kernel();
+
 	uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
 	uopt.uid = -1;
 	uopt.gid = -1;
@@ -1888,8 +1890,10 @@
 	uopt.dmode = UDF_INVALID_MODE;
 
 	sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL);
-	if (!sbi)
+	if (!sbi) {
+		unlock_kernel();
 		return -ENOMEM;
+	}
 
 	sb->s_fs_info = sbi;
 
@@ -2035,6 +2039,7 @@
 		goto error_out;
 	}
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
+	unlock_kernel();
 	return 0;
 
 error_out:
@@ -2055,6 +2060,7 @@
 	kfree(sbi);
 	sb->s_fs_info = NULL;
 
+	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/ufs/Kconfig b/fs/ufs/Kconfig
index e4f10a4..30c8f22 100644
--- a/fs/ufs/Kconfig
+++ b/fs/ufs/Kconfig
@@ -1,6 +1,7 @@
 config UFS_FS
 	tristate "UFS file system support (read only)"
 	depends on BLOCK
+	depends on BKL # probably fixable
 	help
 	  BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
 	  OpenBSD and NeXTstep) use a file system called UFS. Some System V
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index d510c1b..6b9be90 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -696,6 +696,8 @@
 	unsigned maxsymlen;
 	int ret = -EINVAL;
 
+	lock_kernel();
+
 	uspi = NULL;
 	ubh = NULL;
 	flags = 0;
@@ -1163,6 +1165,7 @@
 			goto failed;
 
 	UFSD("EXIT\n");
+	unlock_kernel();
 	return 0;
 
 dalloc_failed:
@@ -1174,10 +1177,12 @@
 	kfree(sbi);
 	sb->s_fs_info = NULL;
 	UFSD("EXIT (FAILED)\n");
+	unlock_kernel();
 	return ret;
 
 failed_nomem:
 	UFSD("EXIT (NOMEM)\n");
+	unlock_kernel();
 	return -ENOMEM;
 }
 
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 286e36e..ba53128 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -188,8 +188,8 @@
 	atomic_set(&bp->b_hold, 1);
 	init_completion(&bp->b_iowait);
 	INIT_LIST_HEAD(&bp->b_list);
-	INIT_LIST_HEAD(&bp->b_hash_list);
-	init_MUTEX_LOCKED(&bp->b_sema); /* held, no waiters */
+	RB_CLEAR_NODE(&bp->b_rbnode);
+	sema_init(&bp->b_sema, 0); /* held, no waiters */
 	XB_SET_OWNER(bp);
 	bp->b_target = target;
 	bp->b_file_offset = range_base;
@@ -262,8 +262,6 @@
 {
 	trace_xfs_buf_free(bp, _RET_IP_);
 
-	ASSERT(list_empty(&bp->b_hash_list));
-
 	if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) {
 		uint		i;
 
@@ -422,8 +420,10 @@
 {
 	xfs_off_t		range_base;
 	size_t			range_length;
-	xfs_bufhash_t		*hash;
-	xfs_buf_t		*bp, *n;
+	struct xfs_perag	*pag;
+	struct rb_node		**rbp;
+	struct rb_node		*parent;
+	xfs_buf_t		*bp;
 
 	range_base = (ioff << BBSHIFT);
 	range_length = (isize << BBSHIFT);
@@ -432,14 +432,37 @@
 	ASSERT(!(range_length < (1 << btp->bt_sshift)));
 	ASSERT(!(range_base & (xfs_off_t)btp->bt_smask));
 
-	hash = &btp->bt_hash[hash_long((unsigned long)ioff, btp->bt_hashshift)];
+	/* get tree root */
+	pag = xfs_perag_get(btp->bt_mount,
+				xfs_daddr_to_agno(btp->bt_mount, ioff));
 
-	spin_lock(&hash->bh_lock);
+	/* walk tree */
+	spin_lock(&pag->pag_buf_lock);
+	rbp = &pag->pag_buf_tree.rb_node;
+	parent = NULL;
+	bp = NULL;
+	while (*rbp) {
+		parent = *rbp;
+		bp = rb_entry(parent, struct xfs_buf, b_rbnode);
 
-	list_for_each_entry_safe(bp, n, &hash->bh_list, b_hash_list) {
-		ASSERT(btp == bp->b_target);
-		if (bp->b_file_offset == range_base &&
-		    bp->b_buffer_length == range_length) {
+		if (range_base < bp->b_file_offset)
+			rbp = &(*rbp)->rb_left;
+		else if (range_base > bp->b_file_offset)
+			rbp = &(*rbp)->rb_right;
+		else {
+			/*
+			 * found a block offset match. If the range doesn't
+			 * match, the only way this is allowed is if the buffer
+			 * in the cache is stale and the transaction that made
+			 * it stale has not yet committed. i.e. we are
+			 * reallocating a busy extent. Skip this buffer and
+			 * continue searching to the right for an exact match.
+			 */
+			if (bp->b_buffer_length != range_length) {
+				ASSERT(bp->b_flags & XBF_STALE);
+				rbp = &(*rbp)->rb_right;
+				continue;
+			}
 			atomic_inc(&bp->b_hold);
 			goto found;
 		}
@@ -449,17 +472,21 @@
 	if (new_bp) {
 		_xfs_buf_initialize(new_bp, btp, range_base,
 				range_length, flags);
-		new_bp->b_hash = hash;
-		list_add(&new_bp->b_hash_list, &hash->bh_list);
+		rb_link_node(&new_bp->b_rbnode, parent, rbp);
+		rb_insert_color(&new_bp->b_rbnode, &pag->pag_buf_tree);
+		/* the buffer keeps the perag reference until it is freed */
+		new_bp->b_pag = pag;
+		spin_unlock(&pag->pag_buf_lock);
 	} else {
 		XFS_STATS_INC(xb_miss_locked);
+		spin_unlock(&pag->pag_buf_lock);
+		xfs_perag_put(pag);
 	}
-
-	spin_unlock(&hash->bh_lock);
 	return new_bp;
 
 found:
-	spin_unlock(&hash->bh_lock);
+	spin_unlock(&pag->pag_buf_lock);
+	xfs_perag_put(pag);
 
 	/* Attempt to get the semaphore without sleeping,
 	 * if this does not work then we need to drop the
@@ -625,8 +652,7 @@
 xfs_buf_readahead(
 	xfs_buftarg_t		*target,
 	xfs_off_t		ioff,
-	size_t			isize,
-	xfs_buf_flags_t		flags)
+	size_t			isize)
 {
 	struct backing_dev_info *bdi;
 
@@ -634,8 +660,42 @@
 	if (bdi_read_congested(bdi))
 		return;
 
-	flags |= (XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD);
-	xfs_buf_read(target, ioff, isize, flags);
+	xfs_buf_read(target, ioff, isize,
+		     XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD|XBF_DONT_BLOCK);
+}
+
+/*
+ * Read an uncached buffer from disk. Allocates and returns a locked
+ * buffer containing the disk contents or nothing.
+ */
+struct xfs_buf *
+xfs_buf_read_uncached(
+	struct xfs_mount	*mp,
+	struct xfs_buftarg	*target,
+	xfs_daddr_t		daddr,
+	size_t			length,
+	int			flags)
+{
+	xfs_buf_t		*bp;
+	int			error;
+
+	bp = xfs_buf_get_uncached(target, length, flags);
+	if (!bp)
+		return NULL;
+
+	/* set up the buffer for a read IO */
+	xfs_buf_lock(bp);
+	XFS_BUF_SET_ADDR(bp, daddr);
+	XFS_BUF_READ(bp);
+	XFS_BUF_BUSY(bp);
+
+	xfsbdstrat(mp, bp);
+	error = xfs_buf_iowait(bp);
+	if (error || bp->b_error) {
+		xfs_buf_relse(bp);
+		return NULL;
+	}
+	return bp;
 }
 
 xfs_buf_t *
@@ -707,9 +767,10 @@
 }
 
 xfs_buf_t *
-xfs_buf_get_noaddr(
+xfs_buf_get_uncached(
+	struct xfs_buftarg	*target,
 	size_t			len,
-	xfs_buftarg_t		*target)
+	int			flags)
 {
 	unsigned long		page_count = PAGE_ALIGN(len) >> PAGE_SHIFT;
 	int			error, i;
@@ -725,7 +786,7 @@
 		goto fail_free_buf;
 
 	for (i = 0; i < page_count; i++) {
-		bp->b_pages[i] = alloc_page(GFP_KERNEL);
+		bp->b_pages[i] = alloc_page(xb_to_gfp(flags));
 		if (!bp->b_pages[i])
 			goto fail_free_mem;
 	}
@@ -740,7 +801,7 @@
 
 	xfs_buf_unlock(bp);
 
-	trace_xfs_buf_get_noaddr(bp, _RET_IP_);
+	trace_xfs_buf_get_uncached(bp, _RET_IP_);
 	return bp;
 
  fail_free_mem:
@@ -774,29 +835,30 @@
 xfs_buf_rele(
 	xfs_buf_t		*bp)
 {
-	xfs_bufhash_t		*hash = bp->b_hash;
+	struct xfs_perag	*pag = bp->b_pag;
 
 	trace_xfs_buf_rele(bp, _RET_IP_);
 
-	if (unlikely(!hash)) {
+	if (!pag) {
 		ASSERT(!bp->b_relse);
+		ASSERT(RB_EMPTY_NODE(&bp->b_rbnode));
 		if (atomic_dec_and_test(&bp->b_hold))
 			xfs_buf_free(bp);
 		return;
 	}
 
+	ASSERT(!RB_EMPTY_NODE(&bp->b_rbnode));
 	ASSERT(atomic_read(&bp->b_hold) > 0);
-	if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) {
+	if (atomic_dec_and_lock(&bp->b_hold, &pag->pag_buf_lock)) {
 		if (bp->b_relse) {
 			atomic_inc(&bp->b_hold);
-			spin_unlock(&hash->bh_lock);
-			(*(bp->b_relse)) (bp);
-		} else if (bp->b_flags & XBF_FS_MANAGED) {
-			spin_unlock(&hash->bh_lock);
+			spin_unlock(&pag->pag_buf_lock);
+			bp->b_relse(bp);
 		} else {
 			ASSERT(!(bp->b_flags & (XBF_DELWRI|_XBF_DELWRI_Q)));
-			list_del_init(&bp->b_hash_list);
-			spin_unlock(&hash->bh_lock);
+			rb_erase(&bp->b_rbnode, &pag->pag_buf_tree);
+			spin_unlock(&pag->pag_buf_lock);
+			xfs_perag_put(pag);
 			xfs_buf_free(bp);
 		}
 	}
@@ -859,7 +921,7 @@
 	trace_xfs_buf_lock(bp, _RET_IP_);
 
 	if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE))
-		xfs_log_force(bp->b_mount, 0);
+		xfs_log_force(bp->b_target->bt_mount, 0);
 	if (atomic_read(&bp->b_io_remaining))
 		blk_run_address_space(bp->b_target->bt_mapping);
 	down(&bp->b_sema);
@@ -924,19 +986,7 @@
 	xfs_buf_t		*bp =
 		container_of(work, xfs_buf_t, b_iodone_work);
 
-	/*
-	 * We can get an EOPNOTSUPP to ordered writes.  Here we clear the
-	 * ordered flag and reissue them.  Because we can't tell the higher
-	 * layers directly that they should not issue ordered I/O anymore, they
-	 * need to check if the _XFS_BARRIER_FAILED flag was set during I/O completion.
-	 */
-	if ((bp->b_error == EOPNOTSUPP) &&
-	    (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) {
-		trace_xfs_buf_ordered_retry(bp, _RET_IP_);
-		bp->b_flags &= ~XBF_ORDERED;
-		bp->b_flags |= _XFS_BARRIER_FAILED;
-		xfs_buf_iorequest(bp);
-	} else if (bp->b_iodone)
+	if (bp->b_iodone)
 		(*(bp->b_iodone))(bp);
 	else if (bp->b_flags & XBF_ASYNC)
 		xfs_buf_relse(bp);
@@ -982,7 +1032,6 @@
 {
 	int			error;
 
-	bp->b_mount = mp;
 	bp->b_flags |= XBF_WRITE;
 	bp->b_flags &= ~(XBF_ASYNC | XBF_READ);
 
@@ -1003,8 +1052,6 @@
 {
 	trace_xfs_buf_bdwrite(bp, _RET_IP_);
 
-	bp->b_mount = mp;
-
 	bp->b_flags &= ~XBF_READ;
 	bp->b_flags |= (XBF_DELWRI | XBF_ASYNC);
 
@@ -1013,7 +1060,7 @@
 
 /*
  * Called when we want to stop a buffer from getting written or read.
- * We attach the EIO error, muck with its flags, and call biodone
+ * We attach the EIO error, muck with its flags, and call xfs_buf_ioend
  * so that the proper iodone callbacks get called.
  */
 STATIC int
@@ -1030,21 +1077,21 @@
 	XFS_BUF_ERROR(bp, EIO);
 
 	/*
-	 * We're calling biodone, so delete XBF_DONE flag.
+	 * We're calling xfs_buf_ioend, so delete XBF_DONE flag.
 	 */
 	XFS_BUF_UNREAD(bp);
 	XFS_BUF_UNDELAYWRITE(bp);
 	XFS_BUF_UNDONE(bp);
 	XFS_BUF_STALE(bp);
 
-	xfs_biodone(bp);
+	xfs_buf_ioend(bp, 0);
 
 	return EIO;
 }
 
 /*
  * Same as xfs_bioerror, except that we are releasing the buffer
- * here ourselves, and avoiding the biodone call.
+ * here ourselves, and avoiding the xfs_buf_ioend call.
  * This is meant for userdata errors; metadata bufs come with
  * iodone functions attached, so that we can track down errors.
  */
@@ -1093,7 +1140,7 @@
 xfs_bdstrat_cb(
 	struct xfs_buf	*bp)
 {
-	if (XFS_FORCED_SHUTDOWN(bp->b_mount)) {
+	if (XFS_FORCED_SHUTDOWN(bp->b_target->bt_mount)) {
 		trace_xfs_bdstrat_shut(bp, _RET_IP_);
 		/*
 		 * Metadata write that didn't get logged but
@@ -1195,7 +1242,7 @@
 
 	if (bp->b_flags & XBF_ORDERED) {
 		ASSERT(!(bp->b_flags & XBF_READ));
-		rw = WRITE_BARRIER;
+		rw = WRITE_FLUSH_FUA;
 	} else if (bp->b_flags & XBF_LOG_BUFFER) {
 		ASSERT(!(bp->b_flags & XBF_READ_AHEAD));
 		bp->b_flags &= ~_XBF_RUN_QUEUES;
@@ -1399,63 +1446,25 @@
  */
 void
 xfs_wait_buftarg(
-	xfs_buftarg_t	*btp)
+	struct xfs_buftarg	*btp)
 {
-	xfs_buf_t	*bp, *n;
-	xfs_bufhash_t	*hash;
-	uint		i;
+	struct xfs_perag	*pag;
+	uint			i;
 
-	for (i = 0; i < (1 << btp->bt_hashshift); i++) {
-		hash = &btp->bt_hash[i];
-again:
-		spin_lock(&hash->bh_lock);
-		list_for_each_entry_safe(bp, n, &hash->bh_list, b_hash_list) {
-			ASSERT(btp == bp->b_target);
-			if (!(bp->b_flags & XBF_FS_MANAGED)) {
-				spin_unlock(&hash->bh_lock);
-				/*
-				 * Catch superblock reference count leaks
-				 * immediately
-				 */
-				BUG_ON(bp->b_bn == 0);
-				delay(100);
-				goto again;
-			}
+	for (i = 0; i < btp->bt_mount->m_sb.sb_agcount; i++) {
+		pag = xfs_perag_get(btp->bt_mount, i);
+		spin_lock(&pag->pag_buf_lock);
+		while (rb_first(&pag->pag_buf_tree)) {
+			spin_unlock(&pag->pag_buf_lock);
+			delay(100);
+			spin_lock(&pag->pag_buf_lock);
 		}
-		spin_unlock(&hash->bh_lock);
+		spin_unlock(&pag->pag_buf_lock);
+		xfs_perag_put(pag);
 	}
 }
 
 /*
- *	Allocate buffer hash table for a given target.
- *	For devices containing metadata (i.e. not the log/realtime devices)
- *	we need to allocate a much larger hash table.
- */
-STATIC void
-xfs_alloc_bufhash(
-	xfs_buftarg_t		*btp,
-	int			external)
-{
-	unsigned int		i;
-
-	btp->bt_hashshift = external ? 3 : 12;	/* 8 or 4096 buckets */
-	btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) *
-					 sizeof(xfs_bufhash_t));
-	for (i = 0; i < (1 << btp->bt_hashshift); i++) {
-		spin_lock_init(&btp->bt_hash[i].bh_lock);
-		INIT_LIST_HEAD(&btp->bt_hash[i].bh_list);
-	}
-}
-
-STATIC void
-xfs_free_bufhash(
-	xfs_buftarg_t		*btp)
-{
-	kmem_free_large(btp->bt_hash);
-	btp->bt_hash = NULL;
-}
-
-/*
  *	buftarg list for delwrite queue processing
  */
 static LIST_HEAD(xfs_buftarg_list);
@@ -1487,7 +1496,6 @@
 	xfs_flush_buftarg(btp, 1);
 	if (mp->m_flags & XFS_MOUNT_BARRIER)
 		xfs_blkdev_issue_flush(btp);
-	xfs_free_bufhash(btp);
 	iput(btp->bt_mapping->host);
 
 	/* Unregister the buftarg first so that we don't get a
@@ -1609,6 +1617,7 @@
 
 xfs_buftarg_t *
 xfs_alloc_buftarg(
+	struct xfs_mount	*mp,
 	struct block_device	*bdev,
 	int			external,
 	const char		*fsname)
@@ -1617,6 +1626,7 @@
 
 	btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
 
+	btp->bt_mount = mp;
 	btp->bt_dev =  bdev->bd_dev;
 	btp->bt_bdev = bdev;
 	if (xfs_setsize_buftarg_early(btp, bdev))
@@ -1625,7 +1635,6 @@
 		goto error;
 	if (xfs_alloc_delwrite_queue(btp, fsname))
 		goto error;
-	xfs_alloc_bufhash(btp, external);
 	return btp;
 
 error:
@@ -1916,7 +1925,7 @@
 			bp = list_first_entry(&wait_list, struct xfs_buf, b_list);
 
 			list_del_init(&bp->b_list);
-			xfs_iowait(bp);
+			xfs_buf_iowait(bp);
 			xfs_buf_relse(bp);
 		}
 	}
@@ -1933,7 +1942,7 @@
 		goto out;
 
 	xfslogd_workqueue = alloc_workqueue("xfslogd",
-					WQ_RESCUER | WQ_HIGHPRI, 1);
+					WQ_MEM_RECLAIM | WQ_HIGHPRI, 1);
 	if (!xfslogd_workqueue)
 		goto out_free_buf_zone;
 
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 2a05614..383a3f3 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -51,7 +51,6 @@
 #define XBF_DONE	(1 << 5) /* all pages in the buffer uptodate */
 #define XBF_DELWRI	(1 << 6) /* buffer has dirty pages */
 #define XBF_STALE	(1 << 7) /* buffer has been staled, do not find it */
-#define XBF_FS_MANAGED	(1 << 8) /* filesystem controls freeing memory */
 #define XBF_ORDERED	(1 << 11)/* use ordered writes */
 #define XBF_READ_AHEAD	(1 << 12)/* asynchronous read-ahead */
 #define XBF_LOG_BUFFER	(1 << 13)/* this is a buffer used for the log */
@@ -86,14 +85,6 @@
  */
 #define _XBF_PAGE_LOCKED	(1 << 22)
 
-/*
- * If we try a barrier write, but it fails we have to communicate
- * this to the upper layers.  Unfortunately b_error gets overwritten
- * when the buffer is re-issued so we have to add another flag to
- * keep this information.
- */
-#define _XFS_BARRIER_FAILED	(1 << 23)
-
 typedef unsigned int xfs_buf_flags_t;
 
 #define XFS_BUF_FLAGS \
@@ -104,7 +95,6 @@
 	{ XBF_DONE,		"DONE" }, \
 	{ XBF_DELWRI,		"DELWRI" }, \
 	{ XBF_STALE,		"STALE" }, \
-	{ XBF_FS_MANAGED,	"FS_MANAGED" }, \
 	{ XBF_ORDERED,		"ORDERED" }, \
 	{ XBF_READ_AHEAD,	"READ_AHEAD" }, \
 	{ XBF_LOCK,		"LOCK" },  	/* should never be set */\
@@ -114,8 +104,7 @@
 	{ _XBF_PAGES,		"PAGES" }, \
 	{ _XBF_RUN_QUEUES,	"RUN_QUEUES" }, \
 	{ _XBF_DELWRI_Q,	"DELWRI_Q" }, \
-	{ _XBF_PAGE_LOCKED,	"PAGE_LOCKED" }, \
-	{ _XFS_BARRIER_FAILED,	"BARRIER_FAILED" }
+	{ _XBF_PAGE_LOCKED,	"PAGE_LOCKED" }
 
 
 typedef enum {
@@ -132,14 +121,11 @@
 	dev_t			bt_dev;
 	struct block_device	*bt_bdev;
 	struct address_space	*bt_mapping;
+	struct xfs_mount	*bt_mount;
 	unsigned int		bt_bsize;
 	unsigned int		bt_sshift;
 	size_t			bt_smask;
 
-	/* per device buffer hash table */
-	uint			bt_hashshift;
-	xfs_bufhash_t		*bt_hash;
-
 	/* per device delwri queue */
 	struct task_struct	*bt_task;
 	struct list_head	bt_list;
@@ -167,34 +153,41 @@
 #define XB_PAGES	2
 
 typedef struct xfs_buf {
-	struct semaphore	b_sema;		/* semaphore for lockables */
-	unsigned long		b_queuetime;	/* time buffer was queued */
-	atomic_t		b_pin_count;	/* pin count */
-	wait_queue_head_t	b_waiters;	/* unpin waiters */
-	struct list_head	b_list;
-	xfs_buf_flags_t		b_flags;	/* status flags */
-	struct list_head	b_hash_list;	/* hash table list */
-	xfs_bufhash_t		*b_hash;	/* hash table list start */
-	xfs_buftarg_t		*b_target;	/* buffer target (device) */
-	atomic_t		b_hold;		/* reference count */
-	xfs_daddr_t		b_bn;		/* block number for I/O */
+	/*
+	 * first cacheline holds all the fields needed for an uncontended cache
+	 * hit to be fully processed. The semaphore straddles the cacheline
+	 * boundary, but the counter and lock sits on the first cacheline,
+	 * which is the only bit that is touched if we hit the semaphore
+	 * fast-path on locking.
+	 */
+	struct rb_node		b_rbnode;	/* rbtree node */
 	xfs_off_t		b_file_offset;	/* offset in file */
 	size_t			b_buffer_length;/* size of buffer in bytes */
+	atomic_t		b_hold;		/* reference count */
+	xfs_buf_flags_t		b_flags;	/* status flags */
+	struct semaphore	b_sema;		/* semaphore for lockables */
+
+	wait_queue_head_t	b_waiters;	/* unpin waiters */
+	struct list_head	b_list;
+	struct xfs_perag	*b_pag;		/* contains rbtree root */
+	xfs_buftarg_t		*b_target;	/* buffer target (device) */
+	xfs_daddr_t		b_bn;		/* block number for I/O */
 	size_t			b_count_desired;/* desired transfer size */
 	void			*b_addr;	/* virtual address of buffer */
 	struct work_struct	b_iodone_work;
-	atomic_t		b_io_remaining;	/* #outstanding I/O requests */
 	xfs_buf_iodone_t	b_iodone;	/* I/O completion function */
 	xfs_buf_relse_t		b_relse;	/* releasing function */
 	struct completion	b_iowait;	/* queue for I/O waiters */
 	void			*b_fspriv;
 	void			*b_fspriv2;
-	struct xfs_mount	*b_mount;
-	unsigned short		b_error;	/* error code on I/O */
-	unsigned int		b_page_count;	/* size of page array */
-	unsigned int		b_offset;	/* page offset in first page */
 	struct page		**b_pages;	/* array of page pointers */
 	struct page		*b_page_array[XB_PAGES]; /* inline pages */
+	unsigned long		b_queuetime;	/* time buffer was queued */
+	atomic_t		b_pin_count;	/* pin count */
+	atomic_t		b_io_remaining;	/* #outstanding I/O requests */
+	unsigned int		b_page_count;	/* size of page array */
+	unsigned int		b_offset;	/* page offset in first page */
+	unsigned short		b_error;	/* error code on I/O */
 #ifdef XFS_BUF_LOCK_TRACKING
 	int			b_last_holder;
 #endif
@@ -213,11 +206,13 @@
 				xfs_buf_flags_t);
 
 extern xfs_buf_t *xfs_buf_get_empty(size_t, xfs_buftarg_t *);
-extern xfs_buf_t *xfs_buf_get_noaddr(size_t, xfs_buftarg_t *);
+extern xfs_buf_t *xfs_buf_get_uncached(struct xfs_buftarg *, size_t, int);
 extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t);
 extern void xfs_buf_hold(xfs_buf_t *);
-extern void xfs_buf_readahead(xfs_buftarg_t *, xfs_off_t, size_t,
-				xfs_buf_flags_t);
+extern void xfs_buf_readahead(xfs_buftarg_t *, xfs_off_t, size_t);
+struct xfs_buf *xfs_buf_read_uncached(struct xfs_mount *mp,
+				struct xfs_buftarg *target,
+				xfs_daddr_t daddr, size_t length, int flags);
 
 /* Releasing Buffers */
 extern void xfs_buf_free(xfs_buf_t *);
@@ -242,6 +237,8 @@
 extern int xfs_buf_iowait(xfs_buf_t *);
 extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
 				xfs_buf_rw_t);
+#define xfs_buf_zero(bp, off, len) \
+	    xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
 
 static inline int xfs_buf_geterror(xfs_buf_t *bp)
 {
@@ -276,8 +273,6 @@
 					XFS_BUF_DONE(bp);	\
 				} while (0)
 
-#define XFS_BUF_UNMANAGE(bp)	((bp)->b_flags &= ~XBF_FS_MANAGED)
-
 #define XFS_BUF_DELAYWRITE(bp)		((bp)->b_flags |= XBF_DELWRI)
 #define XFS_BUF_UNDELAYWRITE(bp)	xfs_buf_delwri_dequeue(bp)
 #define XFS_BUF_ISDELAYWRITE(bp)	((bp)->b_flags & XBF_DELWRI)
@@ -356,25 +351,11 @@
 	xfs_buf_rele(bp);
 }
 
-#define xfs_biodone(bp)		xfs_buf_ioend(bp, 0)
-
-#define xfs_biomove(bp, off, len, data, rw) \
-	    xfs_buf_iomove((bp), (off), (len), (data), \
-		((rw) == XBF_WRITE) ? XBRW_WRITE : XBRW_READ)
-
-#define xfs_biozero(bp, off, len) \
-	    xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
-
-#define xfs_iowait(bp)	xfs_buf_iowait(bp)
-
-#define xfs_baread(target, rablkno, ralen)  \
-	xfs_buf_readahead((target), (rablkno), (ralen), XBF_DONT_BLOCK)
-
-
 /*
  *	Handling of buftargs.
  */
-extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int, const char *);
+extern xfs_buftarg_t *xfs_alloc_buftarg(struct xfs_mount *,
+			struct block_device *, int, const char *);
 extern void xfs_free_buftarg(struct xfs_mount *, struct xfs_buftarg *);
 extern void xfs_wait_buftarg(xfs_buftarg_t *);
 extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
diff --git a/fs/xfs/linux-2.6/xfs_cred.h b/fs/xfs/linux-2.6/xfs_cred.h
deleted file mode 100644
index 55bddf3..0000000
--- a/fs/xfs/linux-2.6/xfs_cred.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_CRED_H__
-#define __XFS_CRED_H__
-
-#include <linux/capability.h>
-
-/*
- * Credentials
- */
-typedef const struct cred cred_t;
-
-#endif  /* __XFS_CRED_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
index 1f279b0..ed88ed1 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
@@ -32,10 +32,9 @@
 	xfs_off_t	last,
 	int		fiopt)
 {
-	struct address_space *mapping = VFS_I(ip)->i_mapping;
-
-	if (mapping->nrpages)
-		truncate_inode_pages(mapping, first);
+	/* can't toss partial tail pages, so mask them out */
+	last &= ~(PAGE_SIZE - 1);
+	truncate_inode_pages_range(VFS_I(ip)->i_mapping, first, last - 1);
 }
 
 int
@@ -50,12 +49,11 @@
 
 	trace_xfs_pagecache_inval(ip, first, last);
 
-	if (mapping->nrpages) {
-		xfs_iflags_clear(ip, XFS_ITRUNCATED);
-		ret = filemap_write_and_wait(mapping);
-		if (!ret)
-			truncate_inode_pages(mapping, first);
-	}
+	xfs_iflags_clear(ip, XFS_ITRUNCATED);
+	ret = filemap_write_and_wait_range(mapping, first,
+				last == -1 ? LLONG_MAX : last);
+	if (!ret)
+		truncate_inode_pages_range(mapping, first, last);
 	return -ret;
 }
 
@@ -71,10 +69,9 @@
 	int		ret = 0;
 	int		ret2;
 
-	if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
-		xfs_iflags_clear(ip, XFS_ITRUNCATED);
-		ret = -filemap_fdatawrite(mapping);
-	}
+	xfs_iflags_clear(ip, XFS_ITRUNCATED);
+	ret = -filemap_fdatawrite_range(mapping, first,
+				last == -1 ? LLONG_MAX : last);
 	if (flags & XBF_ASYNC)
 		return ret;
 	ret2 = xfs_wait_on_pages(ip, first, last);
@@ -91,7 +88,9 @@
 {
 	struct address_space *mapping = VFS_I(ip)->i_mapping;
 
-	if (mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK))
-		return -filemap_fdatawait(mapping);
+	if (mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK)) {
+		return -filemap_fdatawait_range(mapping, first,
+					last == -1 ? ip->i_size - 1 : last);
+	}
 	return 0;
 }
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index 2ae8b1c..76e81cf 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -16,7 +16,6 @@
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include "xfs.h"
-#include "xfs_cred.h"
 #include "xfs_sysctl.h"
 
 /*
diff --git a/fs/xfs/linux-2.6/xfs_globals.h b/fs/xfs/linux-2.6/xfs_globals.h
deleted file mode 100644
index 69f71ca..0000000
--- a/fs/xfs/linux-2.6/xfs_globals.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_GLOBALS_H__
-#define __XFS_GLOBALS_H__
-
-extern uint64_t	xfs_panic_mask;		/* set to cause more panics */
-
-#endif	/* __XFS_GLOBALS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 3b9e626..2ea238f6 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -790,7 +790,7 @@
 	xfs_ilock(ip, XFS_ILOCK_SHARED);
 	fa.fsx_xflags = xfs_ip2xflags(ip);
 	fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
-	fa.fsx_projid = ip->i_d.di_projid;
+	fa.fsx_projid = xfs_get_projid(ip);
 
 	if (attr) {
 		if (ip->i_afp) {
@@ -909,10 +909,10 @@
 		return XFS_ERROR(EIO);
 
 	/*
-	 * Disallow 32bit project ids because on-disk structure
-	 * is 16bit only.
+	 * Disallow 32bit project ids when projid32bit feature is not enabled.
 	 */
-	if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1))
+	if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1) &&
+			!xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
 		return XFS_ERROR(EINVAL);
 
 	/*
@@ -961,7 +961,7 @@
 	if (mask & FSX_PROJID) {
 		if (XFS_IS_QUOTA_RUNNING(mp) &&
 		    XFS_IS_PQUOTA_ON(mp) &&
-		    ip->i_d.di_projid != fa->fsx_projid) {
+		    xfs_get_projid(ip) != fa->fsx_projid) {
 			ASSERT(tp);
 			code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
 						capable(CAP_FOWNER) ?
@@ -1063,12 +1063,12 @@
 		 * Change the ownerships and register quota modifications
 		 * in the transaction.
 		 */
-		if (ip->i_d.di_projid != fa->fsx_projid) {
+		if (xfs_get_projid(ip) != fa->fsx_projid) {
 			if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
 				olddquot = xfs_qm_vop_chown(tp, ip,
 							&ip->i_gdquot, gdqp);
 			}
-			ip->i_d.di_projid = fa->fsx_projid;
+			xfs_set_projid(ip, fa->fsx_projid);
 
 			/*
 			 * We may have to rev the inode as well as
@@ -1088,8 +1088,8 @@
 		xfs_diflags_to_linux(ip);
 	}
 
+	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-	xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
 
 	XFS_STATS_INC(xs_ig_attrchg);
 
@@ -1301,7 +1301,8 @@
 	case XFS_IOC_ALLOCSP64:
 	case XFS_IOC_FREESP64:
 	case XFS_IOC_RESVSP64:
-	case XFS_IOC_UNRESVSP64: {
+	case XFS_IOC_UNRESVSP64:
+	case XFS_IOC_ZERO_RANGE: {
 		xfs_flock64_t		bf;
 
 		if (copy_from_user(&bf, arg, sizeof(bf)))
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 6c83f7f..b3486df 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -164,7 +164,8 @@
 	    get_user(bstat->bs_extsize,	&bstat32->bs_extsize)	||
 	    get_user(bstat->bs_extents,	&bstat32->bs_extents)	||
 	    get_user(bstat->bs_gen,	&bstat32->bs_gen)	||
-	    get_user(bstat->bs_projid,	&bstat32->bs_projid)	||
+	    get_user(bstat->bs_projid_lo, &bstat32->bs_projid_lo) ||
+	    get_user(bstat->bs_projid_hi, &bstat32->bs_projid_hi) ||
 	    get_user(bstat->bs_dmevmask, &bstat32->bs_dmevmask)	||
 	    get_user(bstat->bs_dmstate,	&bstat32->bs_dmstate)	||
 	    get_user(bstat->bs_aextents, &bstat32->bs_aextents))
@@ -218,6 +219,7 @@
 	    put_user(buffer->bs_extents,  &p32->bs_extents)	||
 	    put_user(buffer->bs_gen,	  &p32->bs_gen)		||
 	    put_user(buffer->bs_projid,	  &p32->bs_projid)	||
+	    put_user(buffer->bs_projid_hi,	&p32->bs_projid_hi)	||
 	    put_user(buffer->bs_dmevmask, &p32->bs_dmevmask)	||
 	    put_user(buffer->bs_dmstate,  &p32->bs_dmstate)	||
 	    put_user(buffer->bs_aextents, &p32->bs_aextents))
@@ -574,6 +576,7 @@
 	case XFS_IOC_FSGEOMETRY_V1:
 	case XFS_IOC_FSGROWFSDATA:
 	case XFS_IOC_FSGROWFSRT:
+	case XFS_IOC_ZERO_RANGE:
 		return xfs_file_ioctl(filp, cmd, p);
 #else
 	case XFS_IOC_ALLOCSP_32:
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h
index 1024c4f..08b6057 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.h
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.h
@@ -65,8 +65,10 @@
 	__s32		bs_extsize;	/* extent size			*/
 	__s32		bs_extents;	/* number of extents		*/
 	__u32		bs_gen;		/* generation count		*/
-	__u16		bs_projid;	/* project id			*/
-	unsigned char	bs_pad[14];	/* pad space, unused		*/
+	__u16		bs_projid_lo;	/* lower part of project id	*/
+#define	bs_projid	bs_projid_lo	/* (previously just bs_projid)	*/
+	__u16		bs_projid_hi;	/* high part of project id	*/
+	unsigned char	bs_pad[12];	/* pad space, unused		*/
 	__u32		bs_dmevmask;	/* DMIG event mask		*/
 	__u16		bs_dmstate;	/* DMIG state info		*/
 	__u16		bs_aextents;	/* attribute number of extents	*/
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index b1fc2a6..ec858e0 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -95,41 +95,6 @@
 }
 
 /*
- * Change the requested timestamp in the given inode.
- * We don't lock across timestamp updates, and we don't log them but
- * we do record the fact that there is dirty information in core.
- */
-void
-xfs_ichgtime(
-	xfs_inode_t	*ip,
-	int		flags)
-{
-	struct inode	*inode = VFS_I(ip);
-	timespec_t	tv;
-	int		sync_it = 0;
-
-	tv = current_fs_time(inode->i_sb);
-
-	if ((flags & XFS_ICHGTIME_MOD) &&
-	    !timespec_equal(&inode->i_mtime, &tv)) {
-		inode->i_mtime = tv;
-		sync_it = 1;
-	}
-	if ((flags & XFS_ICHGTIME_CHG) &&
-	    !timespec_equal(&inode->i_ctime, &tv)) {
-		inode->i_ctime = tv;
-		sync_it = 1;
-	}
-
-	/*
-	 * Update complete - now make sure everyone knows that the inode
-	 * is dirty.
-	 */
-	if (sync_it)
-		xfs_mark_inode_dirty_sync(ip);
-}
-
-/*
  * Hook in SELinux.  This is not quite correct yet, what we really need
  * here (as we do for default ACLs) is a mechanism by which creation of
  * these attrs can be journalled at inode creation time (along with the
@@ -224,7 +189,7 @@
 	}
 
 	xfs_dentry_to_name(&name, dentry);
-	error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL);
+	error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
 	if (unlikely(error))
 		goto out_free_acl;
 
@@ -397,7 +362,7 @@
 		(irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO);
 	xfs_dentry_to_name(&name, dentry);
 
-	error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL);
+	error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip);
 	if (unlikely(error))
 		goto out;
 
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 2fa0bd9..214ddd7 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -71,6 +71,7 @@
 #include <linux/random.h>
 #include <linux/ctype.h>
 #include <linux/writeback.h>
+#include <linux/capability.h>
 
 #include <asm/page.h>
 #include <asm/div64.h>
@@ -79,14 +80,12 @@
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
-#include <xfs_cred.h>
 #include <xfs_vnode.h>
 #include <xfs_stats.h>
 #include <xfs_sysctl.h>
 #include <xfs_iops.h>
 #include <xfs_aops.h>
 #include <xfs_super.h>
-#include <xfs_globals.h>
 #include <xfs_buf.h>
 
 /*
@@ -144,7 +143,7 @@
 #define SYNCHRONIZE()	barrier()
 #define __return_address __builtin_return_address(0)
 
-#define dfltprid	0
+#define XFS_PROJID_DEFAULT	0
 #define MAXPATHLEN	1024
 
 #define MIN(a,b)	(min(a,b))
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index a4e0797..ab31ce5 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -44,7 +44,6 @@
 #include "xfs_buf_item.h"
 #include "xfs_utils.h"
 #include "xfs_vnodeops.h"
-#include "xfs_version.h"
 #include "xfs_log_priv.h"
 #include "xfs_trans_priv.h"
 #include "xfs_filestream.h"
@@ -645,7 +644,7 @@
 	XFS_BUF_ORDERED(sbp);
 
 	xfsbdstrat(mp, sbp);
-	error = xfs_iowait(sbp);
+	error = xfs_buf_iowait(sbp);
 
 	/*
 	 * Clear all the flags we set and possible error state in the
@@ -693,8 +692,7 @@
 xfs_blkdev_issue_flush(
 	xfs_buftarg_t		*buftarg)
 {
-	blkdev_issue_flush(buftarg->bt_bdev, GFP_KERNEL, NULL,
-			BLKDEV_IFL_WAIT);
+	blkdev_issue_flush(buftarg->bt_bdev, GFP_KERNEL, NULL);
 }
 
 STATIC void
@@ -758,18 +756,20 @@
 	 * Setup xfs_mount buffer target pointers
 	 */
 	error = ENOMEM;
-	mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0, mp->m_fsname);
+	mp->m_ddev_targp = xfs_alloc_buftarg(mp, ddev, 0, mp->m_fsname);
 	if (!mp->m_ddev_targp)
 		goto out_close_rtdev;
 
 	if (rtdev) {
-		mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1, mp->m_fsname);
+		mp->m_rtdev_targp = xfs_alloc_buftarg(mp, rtdev, 1,
+							mp->m_fsname);
 		if (!mp->m_rtdev_targp)
 			goto out_free_ddev_targ;
 	}
 
 	if (logdev && logdev != ddev) {
-		mp->m_logdev_targp = xfs_alloc_buftarg(logdev, 1, mp->m_fsname);
+		mp->m_logdev_targp = xfs_alloc_buftarg(mp, logdev, 1,
+							mp->m_fsname);
 		if (!mp->m_logdev_targp)
 			goto out_free_rtdev_targ;
 	} else {
@@ -972,12 +972,7 @@
 
 /*
  * Dirty the XFS inode when mark_inode_dirty_sync() is called so that
- * we catch unlogged VFS level updates to the inode. Care must be taken
- * here - the transaction code calls mark_inode_dirty_sync() to mark the
- * VFS inode dirty in a transaction and clears the i_update_core field;
- * it must clear the field after calling mark_inode_dirty_sync() to
- * correctly indicate that the dirty state has been propagated into the
- * inode log item.
+ * we catch unlogged VFS level updates to the inode.
  *
  * We need the barrier() to maintain correct ordering between unlogged
  * updates and the transaction commit code that clears the i_update_core
@@ -1521,8 +1516,9 @@
 	if (error)
 		goto out_free_fsname;
 
-	if (xfs_icsb_init_counters(mp))
-		mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB;
+	error = xfs_icsb_init_counters(mp);
+	if (error)
+		goto out_close_devices;
 
 	error = xfs_readsb(mp, flags);
 	if (error)
@@ -1583,6 +1579,7 @@
 	xfs_freesb(mp);
  out_destroy_counters:
 	xfs_icsb_destroy_counters(mp);
+ out_close_devices:
 	xfs_close_devices(mp);
  out_free_fsname:
 	xfs_free_fsname(mp);
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 1ef4a4d..50a3266 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -62,6 +62,7 @@
 # define XFS_DBG_STRING		"no debug"
 #endif
 
+#define XFS_VERSION_STRING	"SGI XFS"
 #define XFS_BUILD_OPTIONS	XFS_ACL_STRING \
 				XFS_SECURITY_STRING \
 				XFS_REALTIME_STRING \
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 81976ff..37d3325 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -39,42 +39,39 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
+/*
+ * The inode lookup is done in batches to keep the amount of lock traffic and
+ * radix tree lookups to a minimum. The batch size is a trade off between
+ * lookup reduction and stack usage. This is in the reclaim path, so we can't
+ * be too greedy.
+ */
+#define XFS_LOOKUP_BATCH	32
 
-STATIC xfs_inode_t *
-xfs_inode_ag_lookup(
-	struct xfs_mount	*mp,
-	struct xfs_perag	*pag,
-	uint32_t		*first_index,
-	int			tag)
+STATIC int
+xfs_inode_ag_walk_grab(
+	struct xfs_inode	*ip)
 {
-	int			nr_found;
-	struct xfs_inode	*ip;
+	struct inode		*inode = VFS_I(ip);
 
-	/*
-	 * use a gang lookup to find the next inode in the tree
-	 * as the tree is sparse and a gang lookup walks to find
-	 * the number of objects requested.
-	 */
-	if (tag == XFS_ICI_NO_TAG) {
-		nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
-				(void **)&ip, *first_index, 1);
-	} else {
-		nr_found = radix_tree_gang_lookup_tag(&pag->pag_ici_root,
-				(void **)&ip, *first_index, 1, tag);
+	/* nothing to sync during shutdown */
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return EFSCORRUPTED;
+
+	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
+	if (xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
+		return ENOENT;
+
+	/* If we can't grab the inode, it must on it's way to reclaim. */
+	if (!igrab(inode))
+		return ENOENT;
+
+	if (is_bad_inode(inode)) {
+		IRELE(ip);
+		return ENOENT;
 	}
-	if (!nr_found)
-		return NULL;
 
-	/*
-	 * Update the index for the next lookup. Catch overflows
-	 * into the next AG range which can occur if we have inodes
-	 * in the last block of the AG and we are currently
-	 * pointing to the last inode.
-	 */
-	*first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
-	if (*first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
-		return NULL;
-	return ip;
+	/* inode is valid */
+	return 0;
 }
 
 STATIC int
@@ -83,49 +80,75 @@
 	struct xfs_perag	*pag,
 	int			(*execute)(struct xfs_inode *ip,
 					   struct xfs_perag *pag, int flags),
-	int			flags,
-	int			tag,
-	int			exclusive,
-	int			*nr_to_scan)
+	int			flags)
 {
 	uint32_t		first_index;
 	int			last_error = 0;
 	int			skipped;
+	int			done;
+	int			nr_found;
 
 restart:
+	done = 0;
 	skipped = 0;
 	first_index = 0;
+	nr_found = 0;
 	do {
+		struct xfs_inode *batch[XFS_LOOKUP_BATCH];
 		int		error = 0;
-		xfs_inode_t	*ip;
+		int		i;
 
-		if (exclusive)
-			write_lock(&pag->pag_ici_lock);
-		else
-			read_lock(&pag->pag_ici_lock);
-		ip = xfs_inode_ag_lookup(mp, pag, &first_index, tag);
-		if (!ip) {
-			if (exclusive)
-				write_unlock(&pag->pag_ici_lock);
-			else
-				read_unlock(&pag->pag_ici_lock);
+		read_lock(&pag->pag_ici_lock);
+		nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
+					(void **)batch, first_index,
+					XFS_LOOKUP_BATCH);
+		if (!nr_found) {
+			read_unlock(&pag->pag_ici_lock);
 			break;
 		}
 
-		/* execute releases pag->pag_ici_lock */
-		error = execute(ip, pag, flags);
-		if (error == EAGAIN) {
-			skipped++;
-			continue;
+		/*
+		 * Grab the inodes before we drop the lock. if we found
+		 * nothing, nr == 0 and the loop will be skipped.
+		 */
+		for (i = 0; i < nr_found; i++) {
+			struct xfs_inode *ip = batch[i];
+
+			if (done || xfs_inode_ag_walk_grab(ip))
+				batch[i] = NULL;
+
+			/*
+			 * Update the index for the next lookup. Catch overflows
+			 * into the next AG range which can occur if we have inodes
+			 * in the last block of the AG and we are currently
+			 * pointing to the last inode.
+			 */
+			first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
+			if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
+				done = 1;
 		}
-		if (error)
-			last_error = error;
+
+		/* unlock now we've grabbed the inodes. */
+		read_unlock(&pag->pag_ici_lock);
+
+		for (i = 0; i < nr_found; i++) {
+			if (!batch[i])
+				continue;
+			error = execute(batch[i], pag, flags);
+			IRELE(batch[i]);
+			if (error == EAGAIN) {
+				skipped++;
+				continue;
+			}
+			if (error && last_error != EFSCORRUPTED)
+				last_error = error;
+		}
 
 		/* bail out if the filesystem is corrupted.  */
 		if (error == EFSCORRUPTED)
 			break;
 
-	} while ((*nr_to_scan)--);
+	} while (nr_found && !done);
 
 	if (skipped) {
 		delay(1);
@@ -134,110 +157,32 @@
 	return last_error;
 }
 
-/*
- * Select the next per-ag structure to iterate during the walk. The reclaim
- * walk is optimised only to walk AGs with reclaimable inodes in them.
- */
-static struct xfs_perag *
-xfs_inode_ag_iter_next_pag(
-	struct xfs_mount	*mp,
-	xfs_agnumber_t		*first,
-	int			tag)
-{
-	struct xfs_perag	*pag = NULL;
-
-	if (tag == XFS_ICI_RECLAIM_TAG) {
-		int found;
-		int ref;
-
-		spin_lock(&mp->m_perag_lock);
-		found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
-				(void **)&pag, *first, 1, tag);
-		if (found <= 0) {
-			spin_unlock(&mp->m_perag_lock);
-			return NULL;
-		}
-		*first = pag->pag_agno + 1;
-		/* open coded pag reference increment */
-		ref = atomic_inc_return(&pag->pag_ref);
-		spin_unlock(&mp->m_perag_lock);
-		trace_xfs_perag_get_reclaim(mp, pag->pag_agno, ref, _RET_IP_);
-	} else {
-		pag = xfs_perag_get(mp, *first);
-		(*first)++;
-	}
-	return pag;
-}
-
 int
 xfs_inode_ag_iterator(
 	struct xfs_mount	*mp,
 	int			(*execute)(struct xfs_inode *ip,
 					   struct xfs_perag *pag, int flags),
-	int			flags,
-	int			tag,
-	int			exclusive,
-	int			*nr_to_scan)
+	int			flags)
 {
 	struct xfs_perag	*pag;
 	int			error = 0;
 	int			last_error = 0;
 	xfs_agnumber_t		ag;
-	int			nr;
 
-	nr = nr_to_scan ? *nr_to_scan : INT_MAX;
 	ag = 0;
-	while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag, tag))) {
-		error = xfs_inode_ag_walk(mp, pag, execute, flags, tag,
-						exclusive, &nr);
+	while ((pag = xfs_perag_get(mp, ag))) {
+		ag = pag->pag_agno + 1;
+		error = xfs_inode_ag_walk(mp, pag, execute, flags);
 		xfs_perag_put(pag);
 		if (error) {
 			last_error = error;
 			if (error == EFSCORRUPTED)
 				break;
 		}
-		if (nr <= 0)
-			break;
 	}
-	if (nr_to_scan)
-		*nr_to_scan = nr;
 	return XFS_ERROR(last_error);
 }
 
-/* must be called with pag_ici_lock held and releases it */
-int
-xfs_sync_inode_valid(
-	struct xfs_inode	*ip,
-	struct xfs_perag	*pag)
-{
-	struct inode		*inode = VFS_I(ip);
-	int			error = EFSCORRUPTED;
-
-	/* nothing to sync during shutdown */
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-		goto out_unlock;
-
-	/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
-	error = ENOENT;
-	if (xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
-		goto out_unlock;
-
-	/* If we can't grab the inode, it must on it's way to reclaim. */
-	if (!igrab(inode))
-		goto out_unlock;
-
-	if (is_bad_inode(inode)) {
-		IRELE(ip);
-		goto out_unlock;
-	}
-
-	/* inode is valid */
-	error = 0;
-out_unlock:
-	read_unlock(&pag->pag_ici_lock);
-	return error;
-}
-
 STATIC int
 xfs_sync_inode_data(
 	struct xfs_inode	*ip,
@@ -248,10 +193,6 @@
 	struct address_space *mapping = inode->i_mapping;
 	int			error = 0;
 
-	error = xfs_sync_inode_valid(ip, pag);
-	if (error)
-		return error;
-
 	if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
 		goto out_wait;
 
@@ -268,7 +209,6 @@
  out_wait:
 	if (flags & SYNC_WAIT)
 		xfs_ioend_wait(ip);
-	IRELE(ip);
 	return error;
 }
 
@@ -280,10 +220,6 @@
 {
 	int			error = 0;
 
-	error = xfs_sync_inode_valid(ip, pag);
-	if (error)
-		return error;
-
 	xfs_ilock(ip, XFS_ILOCK_SHARED);
 	if (xfs_inode_clean(ip))
 		goto out_unlock;
@@ -302,7 +238,6 @@
 
  out_unlock:
 	xfs_iunlock(ip, XFS_ILOCK_SHARED);
-	IRELE(ip);
 	return error;
 }
 
@@ -318,8 +253,7 @@
 
 	ASSERT((flags & ~(SYNC_TRYLOCK|SYNC_WAIT)) == 0);
 
-	error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags,
-				      XFS_ICI_NO_TAG, 0, NULL);
+	error = xfs_inode_ag_iterator(mp, xfs_sync_inode_data, flags);
 	if (error)
 		return XFS_ERROR(error);
 
@@ -337,8 +271,7 @@
 {
 	ASSERT((flags & ~SYNC_WAIT) == 0);
 
-	return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags,
-				     XFS_ICI_NO_TAG, 0, NULL);
+	return xfs_inode_ag_iterator(mp, xfs_sync_inode_attr, flags);
 }
 
 STATIC int
@@ -698,6 +631,43 @@
 }
 
 /*
+ * Grab the inode for reclaim exclusively.
+ * Return 0 if we grabbed it, non-zero otherwise.
+ */
+STATIC int
+xfs_reclaim_inode_grab(
+	struct xfs_inode	*ip,
+	int			flags)
+{
+
+	/*
+	 * do some unlocked checks first to avoid unnecceary lock traffic.
+	 * The first is a flush lock check, the second is a already in reclaim
+	 * check. Only do these checks if we are not going to block on locks.
+	 */
+	if ((flags & SYNC_TRYLOCK) &&
+	    (!ip->i_flush.done || __xfs_iflags_test(ip, XFS_IRECLAIM))) {
+		return 1;
+	}
+
+	/*
+	 * The radix tree lock here protects a thread in xfs_iget from racing
+	 * with us starting reclaim on the inode.  Once we have the
+	 * XFS_IRECLAIM flag set it will not touch us.
+	 */
+	spin_lock(&ip->i_flags_lock);
+	ASSERT_ALWAYS(__xfs_iflags_test(ip, XFS_IRECLAIMABLE));
+	if (__xfs_iflags_test(ip, XFS_IRECLAIM)) {
+		/* ignore as it is already under reclaim */
+		spin_unlock(&ip->i_flags_lock);
+		return 1;
+	}
+	__xfs_iflags_set(ip, XFS_IRECLAIM);
+	spin_unlock(&ip->i_flags_lock);
+	return 0;
+}
+
+/*
  * Inodes in different states need to be treated differently, and the return
  * value of xfs_iflush is not sufficient to get this right. The following table
  * lists the inode states and the reclaim actions necessary for non-blocking
@@ -755,23 +725,6 @@
 {
 	int	error = 0;
 
-	/*
-	 * The radix tree lock here protects a thread in xfs_iget from racing
-	 * with us starting reclaim on the inode.  Once we have the
-	 * XFS_IRECLAIM flag set it will not touch us.
-	 */
-	spin_lock(&ip->i_flags_lock);
-	ASSERT_ALWAYS(__xfs_iflags_test(ip, XFS_IRECLAIMABLE));
-	if (__xfs_iflags_test(ip, XFS_IRECLAIM)) {
-		/* ignore as it is already under reclaim */
-		spin_unlock(&ip->i_flags_lock);
-		write_unlock(&pag->pag_ici_lock);
-		return 0;
-	}
-	__xfs_iflags_set(ip, XFS_IRECLAIM);
-	spin_unlock(&ip->i_flags_lock);
-	write_unlock(&pag->pag_ici_lock);
-
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 	if (!xfs_iflock_nowait(ip)) {
 		if (!(sync_mode & SYNC_WAIT))
@@ -868,13 +821,126 @@
 
 }
 
+/*
+ * Walk the AGs and reclaim the inodes in them. Even if the filesystem is
+ * corrupted, we still want to try to reclaim all the inodes. If we don't,
+ * then a shut down during filesystem unmount reclaim walk leak all the
+ * unreclaimed inodes.
+ */
+int
+xfs_reclaim_inodes_ag(
+	struct xfs_mount	*mp,
+	int			flags,
+	int			*nr_to_scan)
+{
+	struct xfs_perag	*pag;
+	int			error = 0;
+	int			last_error = 0;
+	xfs_agnumber_t		ag;
+	int			trylock = flags & SYNC_TRYLOCK;
+	int			skipped;
+
+restart:
+	ag = 0;
+	skipped = 0;
+	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
+		unsigned long	first_index = 0;
+		int		done = 0;
+		int		nr_found = 0;
+
+		ag = pag->pag_agno + 1;
+
+		if (trylock) {
+			if (!mutex_trylock(&pag->pag_ici_reclaim_lock)) {
+				skipped++;
+				continue;
+			}
+			first_index = pag->pag_ici_reclaim_cursor;
+		} else
+			mutex_lock(&pag->pag_ici_reclaim_lock);
+
+		do {
+			struct xfs_inode *batch[XFS_LOOKUP_BATCH];
+			int	i;
+
+			write_lock(&pag->pag_ici_lock);
+			nr_found = radix_tree_gang_lookup_tag(
+					&pag->pag_ici_root,
+					(void **)batch, first_index,
+					XFS_LOOKUP_BATCH,
+					XFS_ICI_RECLAIM_TAG);
+			if (!nr_found) {
+				write_unlock(&pag->pag_ici_lock);
+				break;
+			}
+
+			/*
+			 * Grab the inodes before we drop the lock. if we found
+			 * nothing, nr == 0 and the loop will be skipped.
+			 */
+			for (i = 0; i < nr_found; i++) {
+				struct xfs_inode *ip = batch[i];
+
+				if (done || xfs_reclaim_inode_grab(ip, flags))
+					batch[i] = NULL;
+
+				/*
+				 * Update the index for the next lookup. Catch
+				 * overflows into the next AG range which can
+				 * occur if we have inodes in the last block of
+				 * the AG and we are currently pointing to the
+				 * last inode.
+				 */
+				first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
+				if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
+					done = 1;
+			}
+
+			/* unlock now we've grabbed the inodes. */
+			write_unlock(&pag->pag_ici_lock);
+
+			for (i = 0; i < nr_found; i++) {
+				if (!batch[i])
+					continue;
+				error = xfs_reclaim_inode(batch[i], pag, flags);
+				if (error && last_error != EFSCORRUPTED)
+					last_error = error;
+			}
+
+			*nr_to_scan -= XFS_LOOKUP_BATCH;
+
+		} while (nr_found && !done && *nr_to_scan > 0);
+
+		if (trylock && !done)
+			pag->pag_ici_reclaim_cursor = first_index;
+		else
+			pag->pag_ici_reclaim_cursor = 0;
+		mutex_unlock(&pag->pag_ici_reclaim_lock);
+		xfs_perag_put(pag);
+	}
+
+	/*
+	 * if we skipped any AG, and we still have scan count remaining, do
+	 * another pass this time using blocking reclaim semantics (i.e
+	 * waiting on the reclaim locks and ignoring the reclaim cursors). This
+	 * ensure that when we get more reclaimers than AGs we block rather
+	 * than spin trying to execute reclaim.
+	 */
+	if (trylock && skipped && *nr_to_scan > 0) {
+		trylock = 0;
+		goto restart;
+	}
+	return XFS_ERROR(last_error);
+}
+
 int
 xfs_reclaim_inodes(
 	xfs_mount_t	*mp,
 	int		mode)
 {
-	return xfs_inode_ag_iterator(mp, xfs_reclaim_inode, mode,
-					XFS_ICI_RECLAIM_TAG, 1, NULL);
+	int		nr_to_scan = INT_MAX;
+
+	return xfs_reclaim_inodes_ag(mp, mode, &nr_to_scan);
 }
 
 /*
@@ -896,17 +962,16 @@
 		if (!(gfp_mask & __GFP_FS))
 			return -1;
 
-		xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0,
-					XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan);
-		/* if we don't exhaust the scan, don't bother coming back */
+		xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK, &nr_to_scan);
+		/* terminate if we don't exhaust the scan */
 		if (nr_to_scan > 0)
 			return -1;
        }
 
 	reclaimable = 0;
 	ag = 0;
-	while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag,
-					XFS_ICI_RECLAIM_TAG))) {
+	while ((pag = xfs_perag_get_tag(mp, ag, XFS_ICI_RECLAIM_TAG))) {
+		ag = pag->pag_agno + 1;
 		reclaimable += pag->pag_ici_reclaimable;
 		xfs_perag_put(pag);
 	}
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index fe78726..32ba662 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -47,10 +47,10 @@
 void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag,
 				struct xfs_inode *ip);
 
-int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag);
+int xfs_sync_inode_grab(struct xfs_inode *ip);
 int xfs_inode_ag_iterator(struct xfs_mount *mp,
 	int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
-	int flags, int tag, int write_lock, int *nr_to_scan);
+	int flags);
 
 void xfs_inode_shrinker_register(struct xfs_mount *mp);
 void xfs_inode_shrinker_unregister(struct xfs_mount *mp);
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h
index be5dffd..acef2e9 100644
--- a/fs/xfs/linux-2.6/xfs_trace.h
+++ b/fs/xfs/linux-2.6/xfs_trace.h
@@ -124,7 +124,7 @@
 		 unsigned long caller_ip),					\
 	TP_ARGS(mp, agno, refcount, caller_ip))
 DEFINE_PERAG_REF_EVENT(xfs_perag_get);
-DEFINE_PERAG_REF_EVENT(xfs_perag_get_reclaim);
+DEFINE_PERAG_REF_EVENT(xfs_perag_get_tag);
 DEFINE_PERAG_REF_EVENT(xfs_perag_put);
 DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim);
 DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim);
@@ -325,13 +325,12 @@
 DEFINE_BUF_EVENT(xfs_buf_lock_done);
 DEFINE_BUF_EVENT(xfs_buf_cond_lock);
 DEFINE_BUF_EVENT(xfs_buf_unlock);
-DEFINE_BUF_EVENT(xfs_buf_ordered_retry);
 DEFINE_BUF_EVENT(xfs_buf_iowait);
 DEFINE_BUF_EVENT(xfs_buf_iowait_done);
 DEFINE_BUF_EVENT(xfs_buf_delwri_queue);
 DEFINE_BUF_EVENT(xfs_buf_delwri_dequeue);
 DEFINE_BUF_EVENT(xfs_buf_delwri_split);
-DEFINE_BUF_EVENT(xfs_buf_get_noaddr);
+DEFINE_BUF_EVENT(xfs_buf_get_uncached);
 DEFINE_BUF_EVENT(xfs_bdstrat_shut);
 DEFINE_BUF_EVENT(xfs_buf_item_relse);
 DEFINE_BUF_EVENT(xfs_buf_item_iodone);
diff --git a/fs/xfs/linux-2.6/xfs_version.h b/fs/xfs/linux-2.6/xfs_version.h
deleted file mode 100644
index f8d279d..0000000
--- a/fs/xfs/linux-2.6/xfs_version.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_VERSION_H__
-#define __XFS_VERSION_H__
-
-/*
- * Dummy file that can contain a timestamp to put into the
- * XFS init string, to help users keep track of what they're
- * running
- */
-
-#define XFS_VERSION_STRING "SGI XFS"
-
-#endif /* __XFS_VERSION_H__ */
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index e1a2f68..faf8e1a 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -463,88 +463,69 @@
 	uint			flags)
 {
 	xfs_bmbt_irec_t map;
-	int		nmaps, error;
+	int		nmaps = 1, error;
 	xfs_buf_t	*bp;
-	xfs_inode_t	*quotip;
-	xfs_mount_t	*mp;
+	xfs_inode_t	*quotip = XFS_DQ_TO_QIP(dqp);
+	xfs_mount_t	*mp = dqp->q_mount;
 	xfs_disk_dquot_t *ddq;
-	xfs_dqid_t	id;
-	boolean_t	newdquot;
+	xfs_dqid_t	id = be32_to_cpu(dqp->q_core.d_id);
 	xfs_trans_t	*tp = (tpp ? *tpp : NULL);
 
-	mp = dqp->q_mount;
-	id = be32_to_cpu(dqp->q_core.d_id);
-	nmaps = 1;
-	newdquot = B_FALSE;
+	dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk;
 
-	/*
-	 * If we don't know where the dquot lives, find out.
-	 */
-	if (dqp->q_blkno == (xfs_daddr_t) 0) {
-		/* We use the id as an index */
-		dqp->q_fileoffset = (xfs_fileoff_t)id /
-					mp->m_quotainfo->qi_dqperchunk;
-		nmaps = 1;
-		quotip = XFS_DQ_TO_QIP(dqp);
-		xfs_ilock(quotip, XFS_ILOCK_SHARED);
+	xfs_ilock(quotip, XFS_ILOCK_SHARED);
+	if (XFS_IS_THIS_QUOTA_OFF(dqp)) {
 		/*
-		 * Return if this type of quotas is turned off while we didn't
-		 * have an inode lock
+		 * Return if this type of quotas is turned off while we
+		 * didn't have the quota inode lock.
 		 */
-		if (XFS_IS_THIS_QUOTA_OFF(dqp)) {
-			xfs_iunlock(quotip, XFS_ILOCK_SHARED);
-			return (ESRCH);
-		}
-		/*
-		 * Find the block map; no allocations yet
-		 */
-		error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset,
-				  XFS_DQUOT_CLUSTER_SIZE_FSB,
-				  XFS_BMAPI_METADATA,
-				  NULL, 0, &map, &nmaps, NULL);
-
 		xfs_iunlock(quotip, XFS_ILOCK_SHARED);
-		if (error)
-			return (error);
-		ASSERT(nmaps == 1);
-		ASSERT(map.br_blockcount == 1);
-
-		/*
-		 * offset of dquot in the (fixed sized) dquot chunk.
-		 */
-		dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) *
-			sizeof(xfs_dqblk_t);
-		if (map.br_startblock == HOLESTARTBLOCK) {
-			/*
-			 * We don't allocate unless we're asked to
-			 */
-			if (!(flags & XFS_QMOPT_DQALLOC))
-				return (ENOENT);
-
-			ASSERT(tp);
-			if ((error = xfs_qm_dqalloc(tpp, mp, dqp, quotip,
-						dqp->q_fileoffset, &bp)))
-				return (error);
-			tp = *tpp;
-			newdquot = B_TRUE;
-		} else {
-			/*
-			 * store the blkno etc so that we don't have to do the
-			 * mapping all the time
-			 */
-			dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
-		}
+		return ESRCH;
 	}
-	ASSERT(dqp->q_blkno != DELAYSTARTBLOCK);
-	ASSERT(dqp->q_blkno != HOLESTARTBLOCK);
 
 	/*
-	 * Read in the buffer, unless we've just done the allocation
-	 * (in which case we already have the buf).
+	 * Find the block map; no allocations yet
 	 */
-	if (!newdquot) {
+	error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset,
+			  XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
+			  NULL, 0, &map, &nmaps, NULL);
+
+	xfs_iunlock(quotip, XFS_ILOCK_SHARED);
+	if (error)
+		return error;
+
+	ASSERT(nmaps == 1);
+	ASSERT(map.br_blockcount == 1);
+
+	/*
+	 * Offset of dquot in the (fixed sized) dquot chunk.
+	 */
+	dqp->q_bufoffset = (id % mp->m_quotainfo->qi_dqperchunk) *
+		sizeof(xfs_dqblk_t);
+
+	ASSERT(map.br_startblock != DELAYSTARTBLOCK);
+	if (map.br_startblock == HOLESTARTBLOCK) {
+		/*
+		 * We don't allocate unless we're asked to
+		 */
+		if (!(flags & XFS_QMOPT_DQALLOC))
+			return ENOENT;
+
+		ASSERT(tp);
+		error = xfs_qm_dqalloc(tpp, mp, dqp, quotip,
+					dqp->q_fileoffset, &bp);
+		if (error)
+			return error;
+		tp = *tpp;
+	} else {
 		trace_xfs_dqtobp_read(dqp);
 
+		/*
+		 * store the blkno etc so that we don't have to do the
+		 * mapping all the time
+		 */
+		dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
+
 		error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 					   dqp->q_blkno,
 					   mp->m_quotainfo->qi_dqchunklen,
@@ -552,13 +533,14 @@
 		if (error || !bp)
 			return XFS_ERROR(error);
 	}
+
 	ASSERT(XFS_BUF_ISBUSY(bp));
 	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
 
 	/*
 	 * calculate the location of the dquot inside the buffer.
 	 */
-	ddq = (xfs_disk_dquot_t *)((char *)XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+	ddq = (struct xfs_disk_dquot *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset);
 
 	/*
 	 * A simple sanity check in case we got a corrupted dquot...
@@ -1176,18 +1158,18 @@
 	xfs_dquot_t		*dqp,
 	uint			flags)
 {
-	xfs_mount_t		*mp;
-	xfs_buf_t		*bp;
-	xfs_disk_dquot_t	*ddqp;
+	struct xfs_mount	*mp = dqp->q_mount;
+	struct xfs_buf		*bp;
+	struct xfs_disk_dquot	*ddqp;
 	int			error;
 
 	ASSERT(XFS_DQ_IS_LOCKED(dqp));
 	ASSERT(!completion_done(&dqp->q_flush));
+
 	trace_xfs_dqflush(dqp);
 
 	/*
-	 * If not dirty, or it's pinned and we are not supposed to
-	 * block, nada.
+	 * If not dirty, or it's pinned and we are not supposed to block, nada.
 	 */
 	if (!XFS_DQ_IS_DIRTY(dqp) ||
 	    (!(flags & SYNC_WAIT) && atomic_read(&dqp->q_pincount) > 0)) {
@@ -1201,40 +1183,46 @@
 	 * down forcibly. If that's the case we must not write this dquot
 	 * to disk, because the log record didn't make it to disk!
 	 */
-	if (XFS_FORCED_SHUTDOWN(dqp->q_mount)) {
-		dqp->dq_flags &= ~(XFS_DQ_DIRTY);
+	if (XFS_FORCED_SHUTDOWN(mp)) {
+		dqp->dq_flags &= ~XFS_DQ_DIRTY;
 		xfs_dqfunlock(dqp);
 		return XFS_ERROR(EIO);
 	}
 
 	/*
 	 * Get the buffer containing the on-disk dquot
-	 * We don't need a transaction envelope because we know that the
-	 * the ondisk-dquot has already been allocated for.
 	 */
-	if ((error = xfs_qm_dqtobp(NULL, dqp, &ddqp, &bp, XFS_QMOPT_DOWARN))) {
+	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
+				   mp->m_quotainfo->qi_dqchunklen, 0, &bp);
+	if (error) {
 		ASSERT(error != ENOENT);
-		/*
-		 * Quotas could have gotten turned off (ESRCH)
-		 */
 		xfs_dqfunlock(dqp);
-		return (error);
+		return error;
 	}
 
-	if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id),
-			   0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
-		xfs_force_shutdown(dqp->q_mount, SHUTDOWN_CORRUPT_INCORE);
+	/*
+	 * Calculate the location of the dquot inside the buffer.
+	 */
+	ddqp = (struct xfs_disk_dquot *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+
+	/*
+	 * A simple sanity check in case we got a corrupted dquot..
+	 */
+	if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), 0,
+			   XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
+		xfs_buf_relse(bp);
+		xfs_dqfunlock(dqp);
+		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 		return XFS_ERROR(EIO);
 	}
 
 	/* This is the only portion of data that needs to persist */
-	memcpy(ddqp, &(dqp->q_core), sizeof(xfs_disk_dquot_t));
+	memcpy(ddqp, &dqp->q_core, sizeof(xfs_disk_dquot_t));
 
 	/*
 	 * Clear the dirty field and remember the flush lsn for later use.
 	 */
-	dqp->dq_flags &= ~(XFS_DQ_DIRTY);
-	mp = dqp->q_mount;
+	dqp->dq_flags &= ~XFS_DQ_DIRTY;
 
 	xfs_trans_ail_copy_lsn(mp->m_ail, &dqp->q_logitem.qli_flush_lsn,
 					&dqp->q_logitem.qli_item.li_lsn);
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 9a92407..f8e854b 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -55,8 +55,6 @@
 kmem_zone_t	*qm_dqzone;
 kmem_zone_t	*qm_dqtrxzone;
 
-static cred_t	xfs_zerocr;
-
 STATIC void	xfs_qm_list_init(xfs_dqlist_t *, char *, int);
 STATIC void	xfs_qm_list_destroy(xfs_dqlist_t *);
 
@@ -837,7 +835,7 @@
 			xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
 						flags & XFS_QMOPT_DQALLOC,
 						ip->i_udquot, &ip->i_gdquot) :
-			xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
+			xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
 						flags & XFS_QMOPT_DQALLOC,
 						ip->i_udquot, &ip->i_gdquot);
 		/*
@@ -1199,87 +1197,6 @@
 	mutex_destroy(&(list->qh_lock));
 }
 
-
-/*
- * Stripped down version of dqattach. This doesn't attach, or even look at the
- * dquots attached to the inode. The rationale is that there won't be any
- * attached at the time this is called from quotacheck.
- */
-STATIC int
-xfs_qm_dqget_noattach(
-	xfs_inode_t	*ip,
-	xfs_dquot_t	**O_udqpp,
-	xfs_dquot_t	**O_gdqpp)
-{
-	int		error;
-	xfs_mount_t	*mp;
-	xfs_dquot_t	*udqp, *gdqp;
-
-	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-	mp = ip->i_mount;
-	udqp = NULL;
-	gdqp = NULL;
-
-	if (XFS_IS_UQUOTA_ON(mp)) {
-		ASSERT(ip->i_udquot == NULL);
-		/*
-		 * We want the dquot allocated if it doesn't exist.
-		 */
-		if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_uid, XFS_DQ_USER,
-					 XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN,
-					 &udqp))) {
-			/*
-			 * Shouldn't be able to turn off quotas here.
-			 */
-			ASSERT(error != ESRCH);
-			ASSERT(error != ENOENT);
-			return error;
-		}
-		ASSERT(udqp);
-	}
-
-	if (XFS_IS_OQUOTA_ON(mp)) {
-		ASSERT(ip->i_gdquot == NULL);
-		if (udqp)
-			xfs_dqunlock(udqp);
-		error = XFS_IS_GQUOTA_ON(mp) ?
-				xfs_qm_dqget(mp, ip,
-					     ip->i_d.di_gid, XFS_DQ_GROUP,
-					     XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
-					     &gdqp) :
-				xfs_qm_dqget(mp, ip,
-					     ip->i_d.di_projid, XFS_DQ_PROJ,
-					     XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
-					     &gdqp);
-		if (error) {
-			if (udqp)
-				xfs_qm_dqrele(udqp);
-			ASSERT(error != ESRCH);
-			ASSERT(error != ENOENT);
-			return error;
-		}
-		ASSERT(gdqp);
-
-		/* Reacquire the locks in the right order */
-		if (udqp) {
-			if (! xfs_qm_dqlock_nowait(udqp)) {
-				xfs_dqunlock(gdqp);
-				xfs_dqlock(udqp);
-				xfs_dqlock(gdqp);
-			}
-		}
-	}
-
-	*O_udqpp = udqp;
-	*O_gdqpp = gdqp;
-
-#ifdef QUOTADEBUG
-	if (udqp) ASSERT(XFS_DQ_IS_LOCKED(udqp));
-	if (gdqp) ASSERT(XFS_DQ_IS_LOCKED(gdqp));
-#endif
-	return 0;
-}
-
 /*
  * Create an inode and return with a reference already taken, but unlocked
  * This is how we create quota inodes
@@ -1305,8 +1222,8 @@
 		return error;
 	}
 
-	if ((error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0,
-				   &xfs_zerocr, 0, 1, ip, &committed))) {
+	error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, &committed);
+	if (error) {
 		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
 				 XFS_TRANS_ABORT);
 		return error;
@@ -1516,7 +1433,7 @@
 				rablkcnt =  map[i+1].br_blockcount;
 				rablkno = map[i+1].br_startblock;
 				while (rablkcnt--) {
-					xfs_baread(mp->m_ddev_targp,
+					xfs_buf_readahead(mp->m_ddev_targp,
 					       XFS_FSB_TO_DADDR(mp, rablkno),
 					       mp->m_quotainfo->qi_dqchunklen);
 					rablkno++;
@@ -1546,18 +1463,34 @@
 
 /*
  * Called by dqusage_adjust in doing a quotacheck.
- * Given the inode, and a dquot (either USR or GRP, doesn't matter),
- * this updates its incore copy as well as the buffer copy. This is
- * so that once the quotacheck is done, we can just log all the buffers,
- * as opposed to logging numerous updates to individual dquots.
+ *
+ * Given the inode, and a dquot id this updates both the incore dqout as well
+ * as the buffer copy. This is so that once the quotacheck is done, we can
+ * just log all the buffers, as opposed to logging numerous updates to
+ * individual dquots.
  */
-STATIC void
+STATIC int
 xfs_qm_quotacheck_dqadjust(
-	xfs_dquot_t		*dqp,
+	struct xfs_inode	*ip,
+	xfs_dqid_t		id,
+	uint			type,
 	xfs_qcnt_t		nblks,
 	xfs_qcnt_t		rtblks)
 {
-	ASSERT(XFS_DQ_IS_LOCKED(dqp));
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_dquot	*dqp;
+	int			error;
+
+	error = xfs_qm_dqget(mp, ip, id, type,
+			     XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN, &dqp);
+	if (error) {
+		/*
+		 * Shouldn't be able to turn off quotas here.
+		 */
+		ASSERT(error != ESRCH);
+		ASSERT(error != ENOENT);
+		return error;
+	}
 
 	trace_xfs_dqadjust(dqp);
 
@@ -1582,11 +1515,13 @@
 	 * There are no timers for the default values set in the root dquot.
 	 */
 	if (dqp->q_core.d_id) {
-		xfs_qm_adjust_dqlimits(dqp->q_mount, &dqp->q_core);
-		xfs_qm_adjust_dqtimers(dqp->q_mount, &dqp->q_core);
+		xfs_qm_adjust_dqlimits(mp, &dqp->q_core);
+		xfs_qm_adjust_dqtimers(mp, &dqp->q_core);
 	}
 
 	dqp->dq_flags |= XFS_DQ_DIRTY;
+	xfs_qm_dqput(dqp);
+	return 0;
 }
 
 STATIC int
@@ -1629,8 +1564,7 @@
 	int		*res)		/* result code value */
 {
 	xfs_inode_t	*ip;
-	xfs_dquot_t	*udqp, *gdqp;
-	xfs_qcnt_t	nblks, rtblks;
+	xfs_qcnt_t	nblks, rtblks = 0;
 	int		error;
 
 	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
@@ -1650,51 +1584,24 @@
 	 * the case in all other instances. It's OK that we do this because
 	 * quotacheck is done only at mount time.
 	 */
-	if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip))) {
+	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip);
+	if (error) {
 		*res = BULKSTAT_RV_NOTHING;
 		return error;
 	}
 
-	/*
-	 * Obtain the locked dquots. In case of an error (eg. allocation
-	 * fails for ENOSPC), we return the negative of the error number
-	 * to bulkstat, so that it can get propagated to quotacheck() and
-	 * making us disable quotas for the file system.
-	 */
-	if ((error = xfs_qm_dqget_noattach(ip, &udqp, &gdqp))) {
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-		IRELE(ip);
-		*res = BULKSTAT_RV_GIVEUP;
-		return error;
-	}
+	ASSERT(ip->i_delayed_blks == 0);
 
-	rtblks = 0;
-	if (! XFS_IS_REALTIME_INODE(ip)) {
-		nblks = (xfs_qcnt_t)ip->i_d.di_nblocks;
-	} else {
+	if (XFS_IS_REALTIME_INODE(ip)) {
 		/*
 		 * Walk thru the extent list and count the realtime blocks.
 		 */
-		if ((error = xfs_qm_get_rtblks(ip, &rtblks))) {
-			xfs_iunlock(ip, XFS_ILOCK_EXCL);
-			IRELE(ip);
-			if (udqp)
-				xfs_qm_dqput(udqp);
-			if (gdqp)
-				xfs_qm_dqput(gdqp);
-			*res = BULKSTAT_RV_GIVEUP;
-			return error;
-		}
-		nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
+		error = xfs_qm_get_rtblks(ip, &rtblks);
+		if (error)
+			goto error0;
 	}
-	ASSERT(ip->i_delayed_blks == 0);
 
-	/*
-	 * We can't release the inode while holding its dquot locks.
-	 * The inode can go into inactive and might try to acquire the dquotlocks.
-	 * So, just unlock here and do a vn_rele at the end.
-	 */
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
 
 	/*
 	 * Add the (disk blocks and inode) resources occupied by this
@@ -1709,26 +1616,36 @@
 	 * and quotaoffs don't race. (Quotachecks happen at mount time only).
 	 */
 	if (XFS_IS_UQUOTA_ON(mp)) {
-		ASSERT(udqp);
-		xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
-		xfs_qm_dqput(udqp);
+		error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_uid,
+						   XFS_DQ_USER, nblks, rtblks);
+		if (error)
+			goto error0;
 	}
-	if (XFS_IS_OQUOTA_ON(mp)) {
-		ASSERT(gdqp);
-		xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
-		xfs_qm_dqput(gdqp);
-	}
-	/*
-	 * Now release the inode. This will send it to 'inactive', and
-	 * possibly even free blocks.
-	 */
-	IRELE(ip);
 
-	/*
-	 * Goto next inode.
-	 */
+	if (XFS_IS_GQUOTA_ON(mp)) {
+		error = xfs_qm_quotacheck_dqadjust(ip, ip->i_d.di_gid,
+						   XFS_DQ_GROUP, nblks, rtblks);
+		if (error)
+			goto error0;
+	}
+
+	if (XFS_IS_PQUOTA_ON(mp)) {
+		error = xfs_qm_quotacheck_dqadjust(ip, xfs_get_projid(ip),
+						   XFS_DQ_PROJ, nblks, rtblks);
+		if (error)
+			goto error0;
+	}
+
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	IRELE(ip);
 	*res = BULKSTAT_RV_DIDONE;
 	return 0;
+
+error0:
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	IRELE(ip);
+	*res = BULKSTAT_RV_GIVEUP;
+	return error;
 }
 
 /*
@@ -2224,7 +2141,7 @@
 
 
 /*
- * Given an inode, a uid and gid (from cred_t) make sure that we have
+ * Given an inode, a uid, gid and prid make sure that we have
  * allocated relevant dquot(s) on disk, and that we won't exceed inode
  * quotas by creating this file.
  * This also attaches dquot(s) to the given inode after locking it,
@@ -2332,7 +2249,7 @@
 			xfs_dqunlock(gq);
 		}
 	} else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
-		if (ip->i_d.di_projid != prid) {
+		if (xfs_get_projid(ip) != prid) {
 			xfs_iunlock(ip, lockflags);
 			if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
 						 XFS_DQ_PROJ,
@@ -2454,7 +2371,7 @@
 	}
 	if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
 		if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
-		     ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
+		     xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id))
 			prjflags = XFS_QMOPT_ENOSPC;
 
 		if (prjflags ||
@@ -2558,7 +2475,7 @@
 		ip->i_gdquot = gdqp;
 		ASSERT(XFS_IS_OQUOTA_ON(mp));
 		ASSERT((XFS_IS_GQUOTA_ON(mp) ?
-			ip->i_d.di_gid : ip->i_d.di_projid) ==
+			ip->i_d.di_gid : xfs_get_projid(ip)) ==
 				be32_to_cpu(gdqp->q_core.d_id));
 		xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
 	}
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index bea02d7..45b5cb1 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -81,7 +81,7 @@
 	xfs_mount_t		*mp = ip->i_mount;
 	xfs_dquot_t		*dqp;
 
-	if (!xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) {
+	if (!xfs_qm_dqget(mp, NULL, xfs_get_projid(ip), XFS_DQ_PROJ, 0, &dqp)) {
 		xfs_fill_statvfs_from_dquot(statp, &dqp->q_core);
 		xfs_qm_dqput(dqp);
 	}
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 45e5849..bdebc18 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -276,7 +276,7 @@
 		goto out_unlock;
 	}
 
-	xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 
 out_unlock:
@@ -875,21 +875,14 @@
 	struct xfs_perag	*pag,
 	int			flags)
 {
-	int			error;
-
 	/* skip quota inodes */
 	if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
 	    ip == ip->i_mount->m_quotainfo->qi_gquotaip) {
 		ASSERT(ip->i_udquot == NULL);
 		ASSERT(ip->i_gdquot == NULL);
-		read_unlock(&pag->pag_ici_lock);
 		return 0;
 	}
 
-	error = xfs_sync_inode_valid(ip, pag);
-	if (error)
-		return error;
-
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 	if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
 		xfs_qm_dqrele(ip->i_udquot);
@@ -900,8 +893,6 @@
 		ip->i_gdquot = NULL;
 	}
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
-	IRELE(ip);
 	return 0;
 }
 
@@ -918,8 +909,7 @@
 	uint		 flags)
 {
 	ASSERT(mp->m_quotainfo);
-	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags,
-				XFS_ICI_NO_TAG, 0, NULL);
+	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags);
 }
 
 /*------------------------------------------------------------------------*/
@@ -1175,7 +1165,7 @@
 	}
 	xfs_qm_internalqcheck_get_dquots(mp,
 					(xfs_dqid_t) ip->i_d.di_uid,
-					(xfs_dqid_t) ip->i_d.di_projid,
+					(xfs_dqid_t) xfs_get_projid(ip),
 					(xfs_dqid_t) ip->i_d.di_gid,
 					&ud, &gd);
 	if (XFS_IS_UQUOTA_ON(mp)) {
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 4917d4e..63c7a1a 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -230,6 +230,15 @@
 	rwlock_t	pag_ici_lock;	/* incore inode lock */
 	struct radix_tree_root pag_ici_root;	/* incore inode cache root */
 	int		pag_ici_reclaimable;	/* reclaimable inodes */
+	struct mutex	pag_ici_reclaim_lock;	/* serialisation point */
+	unsigned long	pag_ici_reclaim_cursor;	/* reclaim restart point */
+
+	/* buffer cache index */
+	spinlock_t	pag_buf_lock;	/* lock for pag_buf_tree */
+	struct rb_root	pag_buf_tree;	/* ordered tree of active buffers */
+
+	/* for rcu-safe freeing */
+	struct rcu_head	rcu_head;
 #endif
 	int		pagb_count;	/* pagb slots in use */
 } xfs_perag_t;
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index af168fa..112abc4 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -675,7 +675,7 @@
 	xfs_agblock_t	gtbnoa;		/* aligned ... */
 	xfs_extlen_t	gtdiff;		/* difference to right side entry */
 	xfs_extlen_t	gtlen;		/* length of right side entry */
-	xfs_extlen_t	gtlena;		/* aligned ... */
+	xfs_extlen_t	gtlena = 0;	/* aligned ... */
 	xfs_agblock_t	gtnew;		/* useful start bno of right side */
 	int		error;		/* error code */
 	int		i;		/* result code, temporary */
@@ -684,7 +684,7 @@
 	xfs_agblock_t	ltbnoa;		/* aligned ... */
 	xfs_extlen_t	ltdiff;		/* difference to left side entry */
 	xfs_extlen_t	ltlen;		/* length of left side entry */
-	xfs_extlen_t	ltlena;		/* aligned ... */
+	xfs_extlen_t	ltlena = 0;	/* aligned ... */
 	xfs_agblock_t	ltnew;		/* useful start bno of left side */
 	xfs_extlen_t	rlen;		/* length of returned extent */
 #if defined(DEBUG) && defined(__KERNEL__)
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 97f7328..3916925 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -280,38 +280,6 @@
 	return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock;
 }
 
-STATIC int
-xfs_allocbt_kill_root(
-	struct xfs_btree_cur	*cur,
-	struct xfs_buf		*bp,
-	int			level,
-	union xfs_btree_ptr	*newroot)
-{
-	int			error;
-
-	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
-	XFS_BTREE_STATS_INC(cur, killroot);
-
-	/*
-	 * Update the root pointer, decreasing the level by 1 and then
-	 * free the old root.
-	 */
-	xfs_allocbt_set_root(cur, newroot, -1);
-	error = xfs_allocbt_free_block(cur, bp);
-	if (error) {
-		XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
-		return error;
-	}
-
-	XFS_BTREE_STATS_INC(cur, free);
-
-	xfs_btree_setbuf(cur, level, NULL);
-	cur->bc_nlevels--;
-
-	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
-	return 0;
-}
-
 #ifdef DEBUG
 STATIC int
 xfs_allocbt_keys_inorder(
@@ -423,7 +391,6 @@
 
 	.dup_cursor		= xfs_allocbt_dup_cursor,
 	.set_root		= xfs_allocbt_set_root,
-	.kill_root		= xfs_allocbt_kill_root,
 	.alloc_block		= xfs_allocbt_alloc_block,
 	.free_block		= xfs_allocbt_free_block,
 	.update_lastrec		= xfs_allocbt_update_lastrec,
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index c256824..c863753 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -355,16 +355,15 @@
 			if (mp->m_flags & XFS_MOUNT_WSYNC) {
 				xfs_trans_set_sync(args.trans);
 			}
+
+			if (!error && (flags & ATTR_KERNOTIME) == 0) {
+				xfs_trans_ichgtime(args.trans, dp,
+							XFS_ICHGTIME_CHG);
+			}
 			err2 = xfs_trans_commit(args.trans,
 						 XFS_TRANS_RELEASE_LOG_RES);
 			xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
-			/*
-			 * Hit the inode change time.
-			 */
-			if (!error && (flags & ATTR_KERNOTIME) == 0) {
-				xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
-			}
 			return(error == 0 ? err2 : error);
 		}
 
@@ -420,6 +419,9 @@
 		xfs_trans_set_sync(args.trans);
 	}
 
+	if ((flags & ATTR_KERNOTIME) == 0)
+		xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
+
 	/*
 	 * Commit the last in the sequence of transactions.
 	 */
@@ -427,13 +429,6 @@
 	error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
-	/*
-	 * Hit the inode change time.
-	 */
-	if (!error && (flags & ATTR_KERNOTIME) == 0) {
-		xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
-	}
-
 	return(error);
 
 out:
@@ -567,6 +562,9 @@
 		xfs_trans_set_sync(args.trans);
 	}
 
+	if ((flags & ATTR_KERNOTIME) == 0)
+		xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
+
 	/*
 	 * Commit the last in the sequence of transactions.
 	 */
@@ -574,13 +572,6 @@
 	error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
 
-	/*
-	 * Hit the inode change time.
-	 */
-	if (!error && (flags & ATTR_KERNOTIME) == 0) {
-		xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
-	}
-
 	return(error);
 
 out:
@@ -1995,7 +1986,7 @@
 
 			tmp = (valuelen < XFS_BUF_SIZE(bp))
 				? valuelen : XFS_BUF_SIZE(bp);
-			xfs_biomove(bp, 0, tmp, dst, XBF_READ);
+			xfs_buf_iomove(bp, 0, tmp, dst, XBRW_READ);
 			xfs_buf_relse(bp);
 			dst += tmp;
 			valuelen -= tmp;
@@ -2125,9 +2116,9 @@
 
 		tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :
 							XFS_BUF_SIZE(bp);
-		xfs_biomove(bp, 0, tmp, src, XBF_WRITE);
+		xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE);
 		if (tmp < XFS_BUF_SIZE(bp))
-			xfs_biozero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
+			xfs_buf_zero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
 		if ((error = xfs_bwrite(mp, bp))) {/* GROT: NOTE: synchronous write */
 			return (error);
 		}
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index f90dadd..8abd12e 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -614,7 +614,7 @@
 			nblks += cur->bc_private.b.allocated;
 		ASSERT(nblks <= da_old);
 		if (nblks < da_old)
-			xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
+			xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
 				(int64_t)(da_old - nblks), rsvd);
 	}
 	/*
@@ -1079,7 +1079,8 @@
 		diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
 			(cur ? cur->bc_private.b.allocated : 0));
 		if (diff > 0 &&
-		    xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd)) {
+		    xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
+					     -((int64_t)diff), rsvd)) {
 			/*
 			 * Ick gross gag me with a spoon.
 			 */
@@ -1089,16 +1090,18 @@
 					temp--;
 					diff--;
 					if (!diff ||
-					    !xfs_mod_incore_sb(ip->i_mount,
-						    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
+					    !xfs_icsb_modify_counters(ip->i_mount,
+						    XFS_SBS_FDBLOCKS,
+						    -((int64_t)diff), rsvd))
 						break;
 				}
 				if (temp2) {
 					temp2--;
 					diff--;
 					if (!diff ||
-					    !xfs_mod_incore_sb(ip->i_mount,
-						    XFS_SBS_FDBLOCKS, -((int64_t)diff), rsvd))
+					    !xfs_icsb_modify_counters(ip->i_mount,
+						    XFS_SBS_FDBLOCKS,
+						    -((int64_t)diff), rsvd))
 						break;
 				}
 			}
@@ -1766,7 +1769,7 @@
 	}
 	if (oldlen != newlen) {
 		ASSERT(oldlen > newlen);
-		xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
+		xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
 			(int64_t)(oldlen - newlen), rsvd);
 		/*
 		 * Nothing to do for disk quota accounting here.
@@ -3111,9 +3114,10 @@
 	 * Nothing to do for disk quota accounting here.
 	 */
 	ASSERT(da_old >= da_new);
-	if (da_old > da_new)
-		xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new),
-			rsvd);
+	if (da_old > da_new) {
+		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+			(int64_t)(da_old - da_new), rsvd);
+	}
 done:
 	*logflagsp = flags;
 	return error;
@@ -4526,13 +4530,13 @@
 							-((int64_t)extsz), (flags &
 							XFS_BMAPI_RSVBLOCKS));
 				} else {
-					error = xfs_mod_incore_sb(mp,
+					error = xfs_icsb_modify_counters(mp,
 							XFS_SBS_FDBLOCKS,
 							-((int64_t)alen), (flags &
 							XFS_BMAPI_RSVBLOCKS));
 				}
 				if (!error) {
-					error = xfs_mod_incore_sb(mp,
+					error = xfs_icsb_modify_counters(mp,
 							XFS_SBS_FDBLOCKS,
 							-((int64_t)indlen), (flags &
 							XFS_BMAPI_RSVBLOCKS));
@@ -4542,7 +4546,7 @@
 							(int64_t)extsz, (flags &
 							XFS_BMAPI_RSVBLOCKS));
 					else if (error)
-						xfs_mod_incore_sb(mp,
+						xfs_icsb_modify_counters(mp,
 							XFS_SBS_FDBLOCKS,
 							(int64_t)alen, (flags &
 							XFS_BMAPI_RSVBLOCKS));
@@ -4744,8 +4748,12 @@
 		 * Check if writing previously allocated but
 		 * unwritten extents.
 		 */
-		if (wr && mval->br_state == XFS_EXT_UNWRITTEN &&
-		    ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) {
+		if (wr &&
+		    ((mval->br_state == XFS_EXT_UNWRITTEN &&
+		      ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) ||
+		     (mval->br_state == XFS_EXT_NORM &&
+		      ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT)) ==
+				(XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT))))) {
 			/*
 			 * Modify (by adding) the state flag, if writing.
 			 */
@@ -4757,7 +4765,9 @@
 					*firstblock;
 				cur->bc_private.b.flist = flist;
 			}
-			mval->br_state = XFS_EXT_NORM;
+			mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN)
+						? XFS_EXT_NORM
+						: XFS_EXT_UNWRITTEN;
 			error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
 				firstblock, flist, &tmp_logflags,
 				whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
@@ -5200,7 +5210,7 @@
 					ip, -((long)del.br_blockcount), 0,
 					XFS_QMOPT_RES_RTBLKS);
 			} else {
-				xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
+				xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
 						(int64_t)del.br_blockcount, rsvd);
 				(void)xfs_trans_reserve_quota_nblks(NULL,
 					ip, -((long)del.br_blockcount), 0,
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index b13569a..71ec9b6 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -74,9 +74,12 @@
 #define	XFS_BMAPI_IGSTATE	0x080	/* Ignore state - */
 					/* combine contig. space */
 #define	XFS_BMAPI_CONTIG	0x100	/* must allocate only one extent */
-#define XFS_BMAPI_CONVERT	0x200	/* unwritten extent conversion - */
-					/* need write cache flushing and no */
-					/* additional allocation alignments */
+/*
+ * unwritten extent conversion - this needs write cache flushing and no additional
+ * allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts
+ * from written to unwritten, otherwise convert from unwritten to written.
+ */
+#define XFS_BMAPI_CONVERT	0x200
 
 #define XFS_BMAPI_FLAGS \
 	{ XFS_BMAPI_WRITE,	"WRITE" }, \
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 829af92..04f9cca 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -217,7 +217,7 @@
 	 */
 	for (i = 0; i < cur->bc_nlevels; i++) {
 		if (cur->bc_bufs[i])
-			xfs_btree_setbuf(cur, i, NULL);
+			xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]);
 		else if (!error)
 			break;
 	}
@@ -656,7 +656,7 @@
 
 	ASSERT(fsbno != NULLFSBLOCK);
 	d = XFS_FSB_TO_DADDR(mp, fsbno);
-	xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
+	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
 }
 
 /*
@@ -676,7 +676,7 @@
 	ASSERT(agno != NULLAGNUMBER);
 	ASSERT(agbno != NULLAGBLOCK);
 	d = XFS_AGB_TO_DADDR(mp, agno, agbno);
-	xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
+	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
 }
 
 STATIC int
@@ -763,22 +763,19 @@
  * Set the buffer for level "lev" in the cursor to bp, releasing
  * any previous buffer.
  */
-void
+STATIC void
 xfs_btree_setbuf(
 	xfs_btree_cur_t		*cur,	/* btree cursor */
 	int			lev,	/* level in btree */
 	xfs_buf_t		*bp)	/* new buffer to set */
 {
 	struct xfs_btree_block	*b;	/* btree block */
-	xfs_buf_t		*obp;	/* old buffer pointer */
 
-	obp = cur->bc_bufs[lev];
-	if (obp)
-		xfs_trans_brelse(cur->bc_tp, obp);
+	if (cur->bc_bufs[lev])
+		xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[lev]);
 	cur->bc_bufs[lev] = bp;
 	cur->bc_ra[lev] = 0;
-	if (!bp)
-		return;
+
 	b = XFS_BUF_TO_BLOCK(bp);
 	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
 		if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO)
@@ -3011,6 +3008,43 @@
 	return 0;
 }
 
+/*
+ * Kill the current root node, and replace it with it's only child node.
+ */
+STATIC int
+xfs_btree_kill_root(
+	struct xfs_btree_cur	*cur,
+	struct xfs_buf		*bp,
+	int			level,
+	union xfs_btree_ptr	*newroot)
+{
+	int			error;
+
+	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
+	XFS_BTREE_STATS_INC(cur, killroot);
+
+	/*
+	 * Update the root pointer, decreasing the level by 1 and then
+	 * free the old root.
+	 */
+	cur->bc_ops->set_root(cur, newroot, -1);
+
+	error = cur->bc_ops->free_block(cur, bp);
+	if (error) {
+		XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
+		return error;
+	}
+
+	XFS_BTREE_STATS_INC(cur, free);
+
+	cur->bc_bufs[level] = NULL;
+	cur->bc_ra[level] = 0;
+	cur->bc_nlevels--;
+
+	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+	return 0;
+}
+
 STATIC int
 xfs_btree_dec_cursor(
 	struct xfs_btree_cur	*cur,
@@ -3195,7 +3229,7 @@
 			 * Make it the new root of the btree.
 			 */
 			pp = xfs_btree_ptr_addr(cur, 1, block);
-			error = cur->bc_ops->kill_root(cur, bp, level, pp);
+			error = xfs_btree_kill_root(cur, bp, level, pp);
 			if (error)
 				goto error0;
 		} else if (level > 0) {
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 7fa0706..82fafc6 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -152,9 +152,7 @@
 
 	/* update btree root pointer */
 	void	(*set_root)(struct xfs_btree_cur *cur,
-				union xfs_btree_ptr *nptr, int level_change);
-	int	(*kill_root)(struct xfs_btree_cur *cur, struct xfs_buf *bp,
-				int level, union xfs_btree_ptr *newroot);
+			    union xfs_btree_ptr *nptr, int level_change);
 
 	/* block allocation / freeing */
 	int	(*alloc_block)(struct xfs_btree_cur *cur,
@@ -399,16 +397,6 @@
 	xfs_agblock_t		agbno,	/* allocation group block number */
 	xfs_extlen_t		count);	/* count of filesystem blocks */
 
-/*
- * Set the buffer for level "lev" in the cursor to bp, releasing
- * any previous buffer.
- */
-void
-xfs_btree_setbuf(
-	xfs_btree_cur_t		*cur,	/* btree cursor */
-	int			lev,	/* level in btree */
-	struct xfs_buf		*bp);	/* new buffer to set */
-
 
 /*
  * Common btree core entry points.
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 1b09d7a..2686d0d 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -692,8 +692,7 @@
 	 * the first.  If we do already have one, there is
 	 * nothing to do here so return.
 	 */
-	if (bp->b_mount != mp)
-		bp->b_mount = mp;
+	ASSERT(bp->b_target->bt_mount == mp);
 	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
 		lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
 		if (lip->li_type == XFS_LI_BUF) {
@@ -974,7 +973,7 @@
 			xfs_buf_do_callbacks(bp, lip);
 			XFS_BUF_SET_FSPRIVATE(bp, NULL);
 			XFS_BUF_CLR_IODONE_FUNC(bp);
-			xfs_biodone(bp);
+			xfs_buf_ioend(bp, 0);
 			return;
 		}
 
@@ -1033,7 +1032,7 @@
 	xfs_buf_do_callbacks(bp, lip);
 	XFS_BUF_SET_FSPRIVATE(bp, NULL);
 	XFS_BUF_CLR_IODONE_FUNC(bp);
-	xfs_biodone(bp);
+	xfs_buf_ioend(bp, 0);
 }
 
 /*
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 30fa0e2..1c00bed 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -2042,7 +2042,7 @@
 				mappedbno, nmapped, 0, &bp);
 			break;
 		case 3:
-			xfs_baread(mp->m_ddev_targp, mappedbno, nmapped);
+			xfs_buf_readahead(mp->m_ddev_targp, mappedbno, nmapped);
 			error = 0;
 			bp = NULL;
 			break;
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index e5b153b..dffba9b 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -49,8 +49,9 @@
 	__be32		di_uid;		/* owner's user id */
 	__be32		di_gid;		/* owner's group id */
 	__be32		di_nlink;	/* number of links to file */
-	__be16		di_projid;	/* owner's project id */
-	__u8		di_pad[8];	/* unused, zeroed space */
+	__be16		di_projid_lo;	/* lower part of owner's project id */
+	__be16		di_projid_hi;	/* higher part owner's project id */
+	__u8		di_pad[6];	/* unused, zeroed space */
 	__be16		di_flushiter;	/* incremented on flush */
 	xfs_timestamp_t	di_atime;	/* time last accessed */
 	xfs_timestamp_t	di_mtime;	/* time last modified */
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 504be86..ae89122 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -961,7 +961,7 @@
 				if (i > ra_current &&
 				    map[ra_index].br_blockcount >=
 				    mp->m_dirblkfsbs) {
-					xfs_baread(mp->m_ddev_targp,
+					xfs_buf_readahead(mp->m_ddev_targp,
 						XFS_FSB_TO_DADDR(mp,
 						   map[ra_index].br_startblock +
 						   ra_offset),
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 87c2e9d..8f6fc1a 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -293,9 +293,11 @@
 	__s32		bs_extsize;	/* extent size			*/
 	__s32		bs_extents;	/* number of extents		*/
 	__u32		bs_gen;		/* generation count		*/
-	__u16		bs_projid;	/* project id			*/
+	__u16		bs_projid_lo;	/* lower part of project id	*/
+#define	bs_projid	bs_projid_lo	/* (previously just bs_projid)	*/
 	__u16		bs_forkoff;	/* inode fork offset in bytes	*/
-	unsigned char	bs_pad[12];	/* pad space, unused		*/
+	__u16		bs_projid_hi;	/* higher part of project id	*/
+	unsigned char	bs_pad[10];	/* pad space, unused		*/
 	__u32		bs_dmevmask;	/* DMIG event mask		*/
 	__u16		bs_dmstate;	/* DMIG state info		*/
 	__u16		bs_aextents;	/* attribute number of extents	*/
@@ -448,6 +450,7 @@
 /*	XFS_IOC_SETBIOSIZE ---- deprecated 46	   */
 /*	XFS_IOC_GETBIOSIZE ---- deprecated 47	   */
 #define XFS_IOC_GETBMAPX	_IOWR('X', 56, struct getbmap)
+#define XFS_IOC_ZERO_RANGE	_IOW ('X', 57, struct xfs_flock64)
 
 /*
  * ioctl commands that replace IRIX syssgi()'s
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 43b1d56..a7c116e 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -144,12 +144,11 @@
 	if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
 		return error;
 	dpct = pct - mp->m_sb.sb_imax_pct;
-	error = xfs_read_buf(mp, mp->m_ddev_targp,
-			XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
-			XFS_FSS_TO_BB(mp, 1), 0, &bp);
-	if (error)
-		return error;
-	ASSERT(bp);
+	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
+				XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
+				BBTOB(XFS_FSS_TO_BB(mp, 1)), 0);
+	if (!bp)
+		return EIO;
 	xfs_buf_relse(bp);
 
 	new = nb;	/* use new as a temporary here */
@@ -597,7 +596,8 @@
 		 * the extra reserve blocks from the reserve.....
 		 */
 		int error;
-		error = xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, fdblks_delta, 0);
+		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+						 fdblks_delta, 0);
 		if (error == ENOSPC)
 			goto retry;
 	}
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 5371d2d..0626a32 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -212,7 +212,7 @@
 		 *	to log a whole cluster of inodes instead of all the
 		 *	individual transactions causing a lot of log traffic.
 		 */
-		xfs_biozero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);
+		xfs_buf_zero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);
 		for (i = 0; i < ninodes; i++) {
 			int	ioffset = i << mp->m_sb.sb_inodelog;
 			uint	isize = sizeof(struct xfs_dinode);
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index d352862..16921f5 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -183,38 +183,6 @@
 			  cur->bc_rec.i.ir_startino;
 }
 
-STATIC int
-xfs_inobt_kill_root(
-	struct xfs_btree_cur	*cur,
-	struct xfs_buf		*bp,
-	int			level,
-	union xfs_btree_ptr	*newroot)
-{
-	int			error;
-
-	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
-	XFS_BTREE_STATS_INC(cur, killroot);
-
-	/*
-	 * Update the root pointer, decreasing the level by 1 and then
-	 * free the old root.
-	 */
-	xfs_inobt_set_root(cur, newroot, -1);
-	error = xfs_inobt_free_block(cur, bp);
-	if (error) {
-		XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
-		return error;
-	}
-
-	XFS_BTREE_STATS_INC(cur, free);
-
-	cur->bc_bufs[level] = NULL;
-	cur->bc_nlevels--;
-
-	XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
-	return 0;
-}
-
 #ifdef DEBUG
 STATIC int
 xfs_inobt_keys_inorder(
@@ -309,7 +277,6 @@
 
 	.dup_cursor		= xfs_inobt_dup_cursor,
 	.set_root		= xfs_inobt_set_root,
-	.kill_root		= xfs_inobt_kill_root,
 	.alloc_block		= xfs_inobt_alloc_block,
 	.free_block		= xfs_inobt_free_block,
 	.get_minrecs		= xfs_inobt_get_minrecs,
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index b1ecc6f..0cdd269 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -365,8 +365,8 @@
 	xfs_perag_t	*pag;
 	xfs_agino_t	agino;
 
-	/* the radix tree exists only in inode capable AGs */
-	if (XFS_INO_TO_AGNO(mp, ino) >= mp->m_maxagi)
+	/* reject inode numbers outside existing AGs */
+	if (XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount)
 		return EINVAL;
 
 	/* get the perag structure and ensure that it's inode capable */
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 34798f3..108c7a0 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -660,7 +660,8 @@
 	to->di_uid = be32_to_cpu(from->di_uid);
 	to->di_gid = be32_to_cpu(from->di_gid);
 	to->di_nlink = be32_to_cpu(from->di_nlink);
-	to->di_projid = be16_to_cpu(from->di_projid);
+	to->di_projid_lo = be16_to_cpu(from->di_projid_lo);
+	to->di_projid_hi = be16_to_cpu(from->di_projid_hi);
 	memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
 	to->di_flushiter = be16_to_cpu(from->di_flushiter);
 	to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec);
@@ -695,7 +696,8 @@
 	to->di_uid = cpu_to_be32(from->di_uid);
 	to->di_gid = cpu_to_be32(from->di_gid);
 	to->di_nlink = cpu_to_be32(from->di_nlink);
-	to->di_projid = cpu_to_be16(from->di_projid);
+	to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
+	to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
 	memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
 	to->di_flushiter = cpu_to_be16(from->di_flushiter);
 	to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
@@ -874,7 +876,7 @@
 	if (ip->i_d.di_version == 1) {
 		ip->i_d.di_nlink = ip->i_d.di_onlink;
 		ip->i_d.di_onlink = 0;
-		ip->i_d.di_projid = 0;
+		xfs_set_projid(ip, 0);
 	}
 
 	ip->i_delayed_blks = 0;
@@ -982,8 +984,7 @@
 	mode_t		mode,
 	xfs_nlink_t	nlink,
 	xfs_dev_t	rdev,
-	cred_t		*cr,
-	xfs_prid_t	prid,
+	prid_t		prid,
 	int		okalloc,
 	xfs_buf_t	**ialloc_context,
 	boolean_t	*call_again,
@@ -1027,7 +1028,7 @@
 	ASSERT(ip->i_d.di_nlink == nlink);
 	ip->i_d.di_uid = current_fsuid();
 	ip->i_d.di_gid = current_fsgid();
-	ip->i_d.di_projid = prid;
+	xfs_set_projid(ip, prid);
 	memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
 
 	/*
@@ -2725,7 +2726,7 @@
 			XFS_BUF_UNDONE(bp);
 			XFS_BUF_STALE(bp);
 			XFS_BUF_ERROR(bp,EIO);
-			xfs_biodone(bp);
+			xfs_buf_ioend(bp, 0);
 		} else {
 			XFS_BUF_STALE(bp);
 			xfs_buf_relse(bp);
@@ -3008,7 +3009,7 @@
 			memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
 			memset(&(dip->di_pad[0]), 0,
 			      sizeof(dip->di_pad));
-			ASSERT(ip->i_d.di_projid == 0);
+			ASSERT(xfs_get_projid(ip) == 0);
 		}
 	}
 
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 0898c54..fac5229 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -134,8 +134,9 @@
 	__uint32_t	di_uid;		/* owner's user id */
 	__uint32_t	di_gid;		/* owner's group id */
 	__uint32_t	di_nlink;	/* number of links to file */
-	__uint16_t	di_projid;	/* owner's project id */
-	__uint8_t	di_pad[8];	/* unused, zeroed space */
+	__uint16_t	di_projid_lo;	/* lower part of owner's project id */
+	__uint16_t	di_projid_hi;	/* higher part of owner's project id */
+	__uint8_t	di_pad[6];	/* unused, zeroed space */
 	__uint16_t	di_flushiter;	/* incremented on flush */
 	xfs_ictimestamp_t di_atime;	/* time last accessed */
 	xfs_ictimestamp_t di_mtime;	/* time last modified */
@@ -212,7 +213,6 @@
 #ifdef __KERNEL__
 
 struct bhv_desc;
-struct cred;
 struct xfs_buf;
 struct xfs_bmap_free;
 struct xfs_bmbt_irec;
@@ -335,6 +335,25 @@
 }
 
 /*
+ * Project quota id helpers (previously projid was 16bit only
+ * and using two 16bit values to hold new 32bit projid was choosen
+ * to retain compatibility with "old" filesystems).
+ */
+static inline prid_t
+xfs_get_projid(struct xfs_inode *ip)
+{
+	return (prid_t)ip->i_d.di_projid_hi << 16 | ip->i_d.di_projid_lo;
+}
+
+static inline void
+xfs_set_projid(struct xfs_inode *ip,
+		prid_t projid)
+{
+	ip->i_d.di_projid_hi = (__uint16_t) (projid >> 16);
+	ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff);
+}
+
+/*
  * Manage the i_flush queue embedded in the inode.  This completion
  * queue synchronizes processes attempting to flush the in-core
  * inode back to disk.
@@ -456,8 +475,8 @@
  * xfs_inode.c prototypes.
  */
 int		xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
-			   xfs_nlink_t, xfs_dev_t, cred_t *, xfs_prid_t,
-			   int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
+			   xfs_nlink_t, xfs_dev_t, prid_t, int,
+			   struct xfs_buf **, boolean_t *, xfs_inode_t **);
 
 uint		xfs_ip2xflags(struct xfs_inode *);
 uint		xfs_dic2xflags(struct xfs_dinode *);
@@ -471,7 +490,6 @@
 void		xfs_iext_realloc(xfs_inode_t *, int, int);
 void		xfs_iunpin_wait(xfs_inode_t *);
 int		xfs_iflush(xfs_inode_t *, uint);
-void		xfs_ichgtime(xfs_inode_t *, int);
 void		xfs_lock_inodes(xfs_inode_t **, int, uint);
 void		xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
 
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index fe00777..c7ac020 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -223,15 +223,6 @@
 	nvecs	     = 1;
 
 	/*
-	 * Make sure the linux inode is dirty. We do this before
-	 * clearing i_update_core as the VFS will call back into
-	 * XFS here and set i_update_core, so we need to dirty the
-	 * inode first so that the ordering of i_update_core and
-	 * unlogged modifications still works as described below.
-	 */
-	xfs_mark_inode_dirty_sync(ip);
-
-	/*
 	 * Clear i_update_core if the timestamps (or any other
 	 * non-transactional modification) need flushing/logging
 	 * and we're about to log them with the rest of the core.
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 7e3626e..dc1882a 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -92,7 +92,8 @@
 	 * further change.
 	 */
 	buf->bs_nlink = dic->di_nlink;
-	buf->bs_projid = dic->di_projid;
+	buf->bs_projid_lo = dic->di_projid_lo;
+	buf->bs_projid_hi = dic->di_projid_hi;
 	buf->bs_ino = ino;
 	buf->bs_mode = dic->di_mode;
 	buf->bs_uid = dic->di_uid;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 33f718f..cee4ab9 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -917,19 +917,6 @@
 	l = iclog->ic_log;
 
 	/*
-	 * If the _XFS_BARRIER_FAILED flag was set by a lower
-	 * layer, it means the underlying device no longer supports
-	 * barrier I/O. Warn loudly and turn off barriers.
-	 */
-	if (bp->b_flags & _XFS_BARRIER_FAILED) {
-		bp->b_flags &= ~_XFS_BARRIER_FAILED;
-		l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER;
-		xfs_fs_cmn_err(CE_WARN, l->l_mp,
-				"xlog_iodone: Barriers are no longer supported"
-				" by device. Disabling barriers\n");
-	}
-
-	/*
 	 * Race to shutdown the filesystem if we see an error.
 	 */
 	if (XFS_TEST_ERROR((XFS_BUF_GETERROR(bp)), l->l_mp,
@@ -1131,7 +1118,8 @@
 		iclog->ic_prev = prev_iclog;
 		prev_iclog = iclog;
 
-		bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
+		bp = xfs_buf_get_uncached(mp->m_logdev_targp,
+						log->l_iclog_size, 0);
 		if (!bp)
 			goto out_free_iclog;
 		if (!XFS_BUF_CPSEMA(bp))
@@ -1309,7 +1297,7 @@
 	if (iclog->ic_state & XLOG_STATE_IOERROR) {
 		XFS_BUF_ERROR(bp, EIO);
 		XFS_BUF_STALE(bp);
-		xfs_biodone(bp);
+		xfs_buf_ioend(bp, 0);
 		/*
 		 * It would seem logical to return EIO here, but we rely on
 		 * the log state machine to propagate I/O errors instead of
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 7e206fc..23d6ceb 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -146,102 +146,6 @@
 }
 
 /*
- * Insert the log item into the CIL and calculate the difference in space
- * consumed by the item. Add the space to the checkpoint ticket and calculate
- * if the change requires additional log metadata. If it does, take that space
- * as well. Remove the amount of space we addded to the checkpoint ticket from
- * the current transaction ticket so that the accounting works out correctly.
- *
- * If this is the first time the item is being placed into the CIL in this
- * context, pin it so it can't be written to disk until the CIL is flushed to
- * the iclog and the iclog written to disk.
- */
-static void
-xlog_cil_insert(
-	struct log		*log,
-	struct xlog_ticket	*ticket,
-	struct xfs_log_item	*item,
-	struct xfs_log_vec	*lv)
-{
-	struct xfs_cil		*cil = log->l_cilp;
-	struct xfs_log_vec	*old = lv->lv_item->li_lv;
-	struct xfs_cil_ctx	*ctx = cil->xc_ctx;
-	int			len;
-	int			diff_iovecs;
-	int			iclog_space;
-
-	if (old) {
-		/* existing lv on log item, space used is a delta */
-		ASSERT(!list_empty(&item->li_cil));
-		ASSERT(old->lv_buf && old->lv_buf_len && old->lv_niovecs);
-
-		len = lv->lv_buf_len - old->lv_buf_len;
-		diff_iovecs = lv->lv_niovecs - old->lv_niovecs;
-		kmem_free(old->lv_buf);
-		kmem_free(old);
-	} else {
-		/* new lv, must pin the log item */
-		ASSERT(!lv->lv_item->li_lv);
-		ASSERT(list_empty(&item->li_cil));
-
-		len = lv->lv_buf_len;
-		diff_iovecs = lv->lv_niovecs;
-		IOP_PIN(lv->lv_item);
-
-	}
-	len += diff_iovecs * sizeof(xlog_op_header_t);
-
-	/* attach new log vector to log item */
-	lv->lv_item->li_lv = lv;
-
-	spin_lock(&cil->xc_cil_lock);
-	list_move_tail(&item->li_cil, &cil->xc_cil);
-	ctx->nvecs += diff_iovecs;
-
-	/*
-	 * If this is the first time the item is being committed to the CIL,
-	 * store the sequence number on the log item so we can tell
-	 * in future commits whether this is the first checkpoint the item is
-	 * being committed into.
-	 */
-	if (!item->li_seq)
-		item->li_seq = ctx->sequence;
-
-	/*
-	 * Now transfer enough transaction reservation to the context ticket
-	 * for the checkpoint. The context ticket is special - the unit
-	 * reservation has to grow as well as the current reservation as we
-	 * steal from tickets so we can correctly determine the space used
-	 * during the transaction commit.
-	 */
-	if (ctx->ticket->t_curr_res == 0) {
-		/* first commit in checkpoint, steal the header reservation */
-		ASSERT(ticket->t_curr_res >= ctx->ticket->t_unit_res + len);
-		ctx->ticket->t_curr_res = ctx->ticket->t_unit_res;
-		ticket->t_curr_res -= ctx->ticket->t_unit_res;
-	}
-
-	/* do we need space for more log record headers? */
-	iclog_space = log->l_iclog_size - log->l_iclog_hsize;
-	if (len > 0 && (ctx->space_used / iclog_space !=
-				(ctx->space_used + len) / iclog_space)) {
-		int hdrs;
-
-		hdrs = (len + iclog_space - 1) / iclog_space;
-		/* need to take into account split region headers, too */
-		hdrs *= log->l_iclog_hsize + sizeof(struct xlog_op_header);
-		ctx->ticket->t_unit_res += hdrs;
-		ctx->ticket->t_curr_res += hdrs;
-		ticket->t_curr_res -= hdrs;
-		ASSERT(ticket->t_curr_res >= len);
-	}
-	ticket->t_curr_res -= len;
-	ctx->space_used += len;
-
-	spin_unlock(&cil->xc_cil_lock);
-}
-
-/*
  * Format log item into a flat buffers
  *
  * For delayed logging, we need to hold a formatted buffer containing all the
@@ -286,7 +190,7 @@
 			len += lv->lv_iovecp[index].i_len;
 
 		lv->lv_buf_len = len;
-		lv->lv_buf = kmem_zalloc(lv->lv_buf_len, KM_SLEEP|KM_NOFS);
+		lv->lv_buf = kmem_alloc(lv->lv_buf_len, KM_SLEEP|KM_NOFS);
 		ptr = lv->lv_buf;
 
 		for (index = 0; index < lv->lv_niovecs; index++) {
@@ -300,21 +204,136 @@
 	}
 }
 
+/*
+ * Prepare the log item for insertion into the CIL. Calculate the difference in
+ * log space and vectors it will consume, and if it is a new item pin it as
+ * well.
+ */
+STATIC void
+xfs_cil_prepare_item(
+	struct log		*log,
+	struct xfs_log_vec	*lv,
+	int			*len,
+	int			*diff_iovecs)
+{
+	struct xfs_log_vec	*old = lv->lv_item->li_lv;
+
+	if (old) {
+		/* existing lv on log item, space used is a delta */
+		ASSERT(!list_empty(&lv->lv_item->li_cil));
+		ASSERT(old->lv_buf && old->lv_buf_len && old->lv_niovecs);
+
+		*len += lv->lv_buf_len - old->lv_buf_len;
+		*diff_iovecs += lv->lv_niovecs - old->lv_niovecs;
+		kmem_free(old->lv_buf);
+		kmem_free(old);
+	} else {
+		/* new lv, must pin the log item */
+		ASSERT(!lv->lv_item->li_lv);
+		ASSERT(list_empty(&lv->lv_item->li_cil));
+
+		*len += lv->lv_buf_len;
+		*diff_iovecs += lv->lv_niovecs;
+		IOP_PIN(lv->lv_item);
+
+	}
+
+	/* attach new log vector to log item */
+	lv->lv_item->li_lv = lv;
+
+	/*
+	 * If this is the first time the item is being committed to the
+	 * CIL, store the sequence number on the log item so we can
+	 * tell in future commits whether this is the first checkpoint
+	 * the item is being committed into.
+	 */
+	if (!lv->lv_item->li_seq)
+		lv->lv_item->li_seq = log->l_cilp->xc_ctx->sequence;
+}
+
+/*
+ * Insert the log items into the CIL and calculate the difference in space
+ * consumed by the item. Add the space to the checkpoint ticket and calculate
+ * if the change requires additional log metadata. If it does, take that space
+ * as well. Remove the amount of space we addded to the checkpoint ticket from
+ * the current transaction ticket so that the accounting works out correctly.
+ */
 static void
 xlog_cil_insert_items(
 	struct log		*log,
 	struct xfs_log_vec	*log_vector,
-	struct xlog_ticket	*ticket,
-	xfs_lsn_t		*start_lsn)
+	struct xlog_ticket	*ticket)
 {
-	struct xfs_log_vec *lv;
-
-	if (start_lsn)
-		*start_lsn = log->l_cilp->xc_ctx->sequence;
+	struct xfs_cil		*cil = log->l_cilp;
+	struct xfs_cil_ctx	*ctx = cil->xc_ctx;
+	struct xfs_log_vec	*lv;
+	int			len = 0;
+	int			diff_iovecs = 0;
+	int			iclog_space;
 
 	ASSERT(log_vector);
+
+	/*
+	 * Do all the accounting aggregation and switching of log vectors
+	 * around in a separate loop to the insertion of items into the CIL.
+	 * Then we can do a separate loop to update the CIL within a single
+	 * lock/unlock pair. This reduces the number of round trips on the CIL
+	 * lock from O(nr_logvectors) to O(1) and greatly reduces the overall
+	 * hold time for the transaction commit.
+	 *
+	 * If this is the first time the item is being placed into the CIL in
+	 * this context, pin it so it can't be written to disk until the CIL is
+	 * flushed to the iclog and the iclog written to disk.
+	 *
+	 * We can do this safely because the context can't checkpoint until we
+	 * are done so it doesn't matter exactly how we update the CIL.
+	 */
 	for (lv = log_vector; lv; lv = lv->lv_next)
-		xlog_cil_insert(log, ticket, lv->lv_item, lv);
+		xfs_cil_prepare_item(log, lv, &len, &diff_iovecs);
+
+	/* account for space used by new iovec headers  */
+	len += diff_iovecs * sizeof(xlog_op_header_t);
+
+	spin_lock(&cil->xc_cil_lock);
+
+	/* move the items to the tail of the CIL */
+	for (lv = log_vector; lv; lv = lv->lv_next)
+		list_move_tail(&lv->lv_item->li_cil, &cil->xc_cil);
+
+	ctx->nvecs += diff_iovecs;
+
+	/*
+	 * Now transfer enough transaction reservation to the context ticket
+	 * for the checkpoint. The context ticket is special - the unit
+	 * reservation has to grow as well as the current reservation as we
+	 * steal from tickets so we can correctly determine the space used
+	 * during the transaction commit.
+	 */
+	if (ctx->ticket->t_curr_res == 0) {
+		/* first commit in checkpoint, steal the header reservation */
+		ASSERT(ticket->t_curr_res >= ctx->ticket->t_unit_res + len);
+		ctx->ticket->t_curr_res = ctx->ticket->t_unit_res;
+		ticket->t_curr_res -= ctx->ticket->t_unit_res;
+	}
+
+	/* do we need space for more log record headers? */
+	iclog_space = log->l_iclog_size - log->l_iclog_hsize;
+	if (len > 0 && (ctx->space_used / iclog_space !=
+				(ctx->space_used + len) / iclog_space)) {
+		int hdrs;
+
+		hdrs = (len + iclog_space - 1) / iclog_space;
+		/* need to take into account split region headers, too */
+		hdrs *= log->l_iclog_hsize + sizeof(struct xlog_op_header);
+		ctx->ticket->t_unit_res += hdrs;
+		ctx->ticket->t_curr_res += hdrs;
+		ticket->t_curr_res -= hdrs;
+		ASSERT(ticket->t_curr_res >= len);
+	}
+	ticket->t_curr_res -= len;
+	ctx->space_used += len;
+
+	spin_unlock(&cil->xc_cil_lock);
 }
 
 static void
@@ -638,7 +657,10 @@
 
 	/* lock out background commit */
 	down_read(&log->l_cilp->xc_ctx_lock);
-	xlog_cil_insert_items(log, log_vector, tp->t_ticket, commit_lsn);
+	if (commit_lsn)
+		*commit_lsn = log->l_cilp->xc_ctx->sequence;
+
+	xlog_cil_insert_items(log, log_vector, tp->t_ticket);
 
 	/* check we didn't blow the reservation */
 	if (tp->t_ticket->t_curr_res < 0)
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 6f3f5fa..966d3f9 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -107,7 +107,8 @@
 		nbblks += log->l_sectBBsize;
 	nbblks = round_up(nbblks, log->l_sectBBsize);
 
-	return xfs_buf_get_noaddr(BBTOB(nbblks), log->l_mp->m_logdev_targp);
+	return xfs_buf_get_uncached(log->l_mp->m_logdev_targp,
+					BBTOB(nbblks), 0);
 }
 
 STATIC void
@@ -167,7 +168,7 @@
 	XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
 
 	xfsbdstrat(log->l_mp, bp);
-	error = xfs_iowait(bp);
+	error = xfs_buf_iowait(bp);
 	if (error)
 		xfs_ioerror_alert("xlog_bread", log->l_mp,
 				  bp, XFS_BUF_ADDR(bp));
@@ -321,12 +322,13 @@
 		 * this during recovery. One strike!
 		 */
 		xfs_ioerror_alert("xlog_recover_iodone",
-				  bp->b_mount, bp, XFS_BUF_ADDR(bp));
-		xfs_force_shutdown(bp->b_mount, SHUTDOWN_META_IO_ERROR);
+					bp->b_target->bt_mount, bp,
+					XFS_BUF_ADDR(bp));
+		xfs_force_shutdown(bp->b_target->bt_mount,
+					SHUTDOWN_META_IO_ERROR);
 	}
-	bp->b_mount = NULL;
 	XFS_BUF_CLR_IODONE_FUNC(bp);
-	xfs_biodone(bp);
+	xfs_buf_ioend(bp, 0);
 }
 
 /*
@@ -2275,8 +2277,7 @@
 		XFS_BUF_STALE(bp);
 		error = xfs_bwrite(mp, bp);
 	} else {
-		ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
-		bp->b_mount = mp;
+		ASSERT(bp->b_target->bt_mount == mp);
 		XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
 		xfs_bdwrite(mp, bp);
 	}
@@ -2540,8 +2541,7 @@
 	}
 
 write_inode_buffer:
-	ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
-	bp->b_mount = mp;
+	ASSERT(bp->b_target->bt_mount == mp);
 	XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
 	xfs_bdwrite(mp, bp);
 error:
@@ -2678,8 +2678,7 @@
 	memcpy(ddq, recddq, item->ri_buf[1].i_len);
 
 	ASSERT(dq_f->qlf_size == 2);
-	ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
-	bp->b_mount = mp;
+	ASSERT(bp->b_target->bt_mount == mp);
 	XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
 	xfs_bdwrite(mp, bp);
 
@@ -3817,7 +3816,7 @@
 	XFS_BUF_READ(bp);
 	XFS_BUF_UNASYNC(bp);
 	xfsbdstrat(log->l_mp, bp);
-	error = xfs_iowait(bp);
+	error = xfs_buf_iowait(bp);
 	if (error) {
 		xfs_ioerror_alert("xlog_do_recover",
 				  log->l_mp, bp, XFS_BUF_ADDR(bp));
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index aeb9d72..b1498ab 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -52,16 +52,11 @@
 						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 void	xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
-
 #else
 
 #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
 
 static const struct {
@@ -199,6 +194,8 @@
 
 /*
  * Reference counting access wrappers to the perag structures.
+ * Because we never free per-ag structures, the only thing we
+ * have to protect against changes is the tree structure itself.
  */
 struct xfs_perag *
 xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno)
@@ -206,19 +203,43 @@
 	struct xfs_perag	*pag;
 	int			ref = 0;
 
-	spin_lock(&mp->m_perag_lock);
+	rcu_read_lock();
 	pag = radix_tree_lookup(&mp->m_perag_tree, agno);
 	if (pag) {
 		ASSERT(atomic_read(&pag->pag_ref) >= 0);
-		/* catch leaks in the positive direction during testing */
-		ASSERT(atomic_read(&pag->pag_ref) < 1000);
 		ref = atomic_inc_return(&pag->pag_ref);
 	}
-	spin_unlock(&mp->m_perag_lock);
+	rcu_read_unlock();
 	trace_xfs_perag_get(mp, agno, ref, _RET_IP_);
 	return pag;
 }
 
+/*
+ * search from @first to find the next perag with the given tag set.
+ */
+struct xfs_perag *
+xfs_perag_get_tag(
+	struct xfs_mount	*mp,
+	xfs_agnumber_t		first,
+	int			tag)
+{
+	struct xfs_perag	*pag;
+	int			found;
+	int			ref;
+
+	rcu_read_lock();
+	found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
+					(void **)&pag, first, 1, tag);
+	if (found <= 0) {
+		rcu_read_unlock();
+		return NULL;
+	}
+	ref = atomic_inc_return(&pag->pag_ref);
+	rcu_read_unlock();
+	trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_);
+	return pag;
+}
+
 void
 xfs_perag_put(struct xfs_perag *pag)
 {
@@ -229,10 +250,18 @@
 	trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_);
 }
 
+STATIC void
+__xfs_free_perag(
+	struct rcu_head	*head)
+{
+	struct xfs_perag *pag = container_of(head, struct xfs_perag, rcu_head);
+
+	ASSERT(atomic_read(&pag->pag_ref) == 0);
+	kmem_free(pag);
+}
+
 /*
- * Free up the resources associated with a mount structure.  Assume that
- * the structure was initially zeroed, so we can tell which fields got
- * initialized.
+ * Free up the per-ag resources associated with the mount structure.
  */
 STATIC void
 xfs_free_perag(
@@ -244,10 +273,9 @@
 	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
 		spin_lock(&mp->m_perag_lock);
 		pag = radix_tree_delete(&mp->m_perag_tree, agno);
-		ASSERT(pag);
-		ASSERT(atomic_read(&pag->pag_ref) == 0);
 		spin_unlock(&mp->m_perag_lock);
-		kmem_free(pag);
+		ASSERT(pag);
+		call_rcu(&pag->rcu_head, __xfs_free_perag);
 	}
 }
 
@@ -444,7 +472,10 @@
 		pag->pag_agno = index;
 		pag->pag_mount = mp;
 		rwlock_init(&pag->pag_ici_lock);
+		mutex_init(&pag->pag_ici_reclaim_lock);
 		INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
+		spin_lock_init(&pag->pag_buf_lock);
+		pag->pag_buf_tree = RB_ROOT;
 
 		if (radix_tree_preload(GFP_NOFS))
 			goto out_unwind;
@@ -639,7 +670,6 @@
 xfs_readsb(xfs_mount_t *mp, int flags)
 {
 	unsigned int	sector_size;
-	unsigned int	extra_flags;
 	xfs_buf_t	*bp;
 	int		error;
 
@@ -652,28 +682,24 @@
 	 * access to the superblock.
 	 */
 	sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
-	extra_flags = XBF_LOCK | XBF_FS_MANAGED | XBF_MAPPED;
 
-	bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR, BTOBB(sector_size),
-			  extra_flags);
-	if (!bp || XFS_BUF_ISERROR(bp)) {
-		xfs_fs_mount_cmn_err(flags, "SB read failed");
-		error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
-		goto fail;
+reread:
+	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
+					XFS_SB_DADDR, sector_size, 0);
+	if (!bp) {
+		xfs_fs_mount_cmn_err(flags, "SB buffer read failed");
+		return EIO;
 	}
-	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
 
 	/*
 	 * Initialize the mount structure from the superblock.
 	 * But first do some basic consistency checking.
 	 */
 	xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
-
 	error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
 	if (error) {
 		xfs_fs_mount_cmn_err(flags, "SB validate failed");
-		goto fail;
+		goto release_buf;
 	}
 
 	/*
@@ -684,7 +710,7 @@
 			"device supports only %u byte sectors (not %u)",
 			sector_size, mp->m_sb.sb_sectsize);
 		error = ENOSYS;
-		goto fail;
+		goto release_buf;
 	}
 
 	/*
@@ -692,33 +718,20 @@
 	 * re-read the superblock so the buffer is correctly sized.
 	 */
 	if (sector_size < mp->m_sb.sb_sectsize) {
-		XFS_BUF_UNMANAGE(bp);
 		xfs_buf_relse(bp);
 		sector_size = mp->m_sb.sb_sectsize;
-		bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR,
-				  BTOBB(sector_size), extra_flags);
-		if (!bp || XFS_BUF_ISERROR(bp)) {
-			xfs_fs_mount_cmn_err(flags, "SB re-read failed");
-			error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
-			goto fail;
-		}
-		ASSERT(XFS_BUF_ISBUSY(bp));
-		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
+		goto reread;
 	}
 
 	/* Initialize per-cpu counters */
 	xfs_icsb_reinit_counters(mp);
 
 	mp->m_sb_bp = bp;
-	xfs_buf_relse(bp);
-	ASSERT(XFS_BUF_VALUSEMA(bp) > 0);
+	xfs_buf_unlock(bp);
 	return 0;
 
- fail:
-	if (bp) {
-		XFS_BUF_UNMANAGE(bp);
-		xfs_buf_relse(bp);
-	}
+release_buf:
+	xfs_buf_relse(bp);
 	return error;
 }
 
@@ -991,42 +1004,35 @@
 {
 	xfs_buf_t	*bp;
 	xfs_daddr_t	d;
-	int		error;
 
 	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
 	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
-		cmn_err(CE_WARN, "XFS: size check 1 failed");
+		cmn_err(CE_WARN, "XFS: filesystem size mismatch detected");
 		return XFS_ERROR(EFBIG);
 	}
-	error = xfs_read_buf(mp, mp->m_ddev_targp,
-			     d - XFS_FSS_TO_BB(mp, 1),
-			     XFS_FSS_TO_BB(mp, 1), 0, &bp);
-	if (!error) {
-		xfs_buf_relse(bp);
-	} else {
-		cmn_err(CE_WARN, "XFS: size check 2 failed");
-		if (error == ENOSPC)
-			error = XFS_ERROR(EFBIG);
-		return error;
+	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
+					d - XFS_FSS_TO_BB(mp, 1),
+					BBTOB(XFS_FSS_TO_BB(mp, 1)), 0);
+	if (!bp) {
+		cmn_err(CE_WARN, "XFS: last sector read failed");
+		return EIO;
 	}
+	xfs_buf_relse(bp);
 
 	if (mp->m_logdev_targp != mp->m_ddev_targp) {
 		d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
 		if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
-			cmn_err(CE_WARN, "XFS: size check 3 failed");
+			cmn_err(CE_WARN, "XFS: log size mismatch detected");
 			return XFS_ERROR(EFBIG);
 		}
-		error = xfs_read_buf(mp, mp->m_logdev_targp,
-				     d - XFS_FSB_TO_BB(mp, 1),
-				     XFS_FSB_TO_BB(mp, 1), 0, &bp);
-		if (!error) {
-			xfs_buf_relse(bp);
-		} else {
-			cmn_err(CE_WARN, "XFS: size check 3 failed");
-			if (error == ENOSPC)
-				error = XFS_ERROR(EFBIG);
-			return error;
+		bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp,
+					d - XFS_FSB_TO_BB(mp, 1),
+					XFS_FSB_TO_B(mp, 1), 0);
+		if (!bp) {
+			cmn_err(CE_WARN, "XFS: log device read failed");
+			return EIO;
 		}
+		xfs_buf_relse(bp);
 	}
 	return 0;
 }
@@ -1601,7 +1607,7 @@
 		XFS_BUF_UNASYNC(sbp);
 		ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp);
 		xfsbdstrat(mp, sbp);
-		error = xfs_iowait(sbp);
+		error = xfs_buf_iowait(sbp);
 		if (error)
 			xfs_ioerror_alert("xfs_unmountfs_writesb",
 					  mp, sbp, XFS_BUF_ADDR(sbp));
@@ -1832,135 +1838,72 @@
  */
 int
 xfs_mod_incore_sb(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t	field,
-	int64_t		delta,
-	int		rsvd)
+	struct xfs_mount	*mp,
+	xfs_sb_field_t		field,
+	int64_t			delta,
+	int			rsvd)
 {
-	int	status;
+	int			status;
 
-	/* check for per-cpu counters */
-	switch (field) {
 #ifdef HAVE_PERCPU_SB
-	case XFS_SBS_ICOUNT:
-	case XFS_SBS_IFREE:
-	case XFS_SBS_FDBLOCKS:
-		if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-			status = xfs_icsb_modify_counters(mp, field,
-							delta, rsvd);
-			break;
-		}
-		/* FALLTHROUGH */
+	ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS);
 #endif
-	default:
-		spin_lock(&mp->m_sb_lock);
-		status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
-		spin_unlock(&mp->m_sb_lock);
-		break;
-	}
+	spin_lock(&mp->m_sb_lock);
+	status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
+	spin_unlock(&mp->m_sb_lock);
 
 	return status;
 }
 
 /*
- * xfs_mod_incore_sb_batch() is used to change more than one field
- * in the in-core superblock structure at a time.  This modification
- * is protected by a lock internal to this module.  The fields and
- * changes to those fields are specified in the array of xfs_mod_sb
- * structures passed in.
+ * Change more than one field in the in-core superblock structure at a time.
  *
- * Either all of the specified deltas will be applied or none of
- * them will.  If any modified field dips below 0, then all modifications
- * will be backed out and EINVAL will be returned.
+ * The fields and changes to those fields are specified in the array of
+ * xfs_mod_sb structures passed in.  Either all of the specified deltas
+ * will be applied or none of them will.  If any modified field dips below 0,
+ * then all modifications will be backed out and EINVAL will be returned.
+ *
+ * Note that this function may not be used for the superblock values that
+ * are tracked with the in-memory per-cpu counters - a direct call to
+ * xfs_icsb_modify_counters is required for these.
  */
 int
-xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
+xfs_mod_incore_sb_batch(
+	struct xfs_mount	*mp,
+	xfs_mod_sb_t		*msb,
+	uint			nmsb,
+	int			rsvd)
 {
-	int		status=0;
-	xfs_mod_sb_t	*msbp;
+	xfs_mod_sb_t		*msbp = &msb[0];
+	int			error = 0;
 
 	/*
-	 * Loop through the array of mod structures and apply each
-	 * individually.  If any fail, then back out all those
-	 * which have already been applied.  Do all of this within
-	 * the scope of the m_sb_lock so that all of the changes will
-	 * be atomic.
+	 * Loop through the array of mod structures and apply each individually.
+	 * If any fail, then back out all those which have already been applied.
+	 * Do all of this within the scope of the m_sb_lock so that all of the
+	 * changes will be atomic.
 	 */
 	spin_lock(&mp->m_sb_lock);
-	msbp = &msb[0];
 	for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) {
-		/*
-		 * Apply the delta at index n.  If it fails, break
-		 * from the loop so we'll fall into the undo loop
-		 * below.
-		 */
-		switch (msbp->msb_field) {
-#ifdef HAVE_PERCPU_SB
-		case XFS_SBS_ICOUNT:
-		case XFS_SBS_IFREE:
-		case XFS_SBS_FDBLOCKS:
-			if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-				spin_unlock(&mp->m_sb_lock);
-				status = xfs_icsb_modify_counters(mp,
-							msbp->msb_field,
-							msbp->msb_delta, rsvd);
-				spin_lock(&mp->m_sb_lock);
-				break;
-			}
-			/* FALLTHROUGH */
-#endif
-		default:
-			status = xfs_mod_incore_sb_unlocked(mp,
-						msbp->msb_field,
-						msbp->msb_delta, rsvd);
-			break;
-		}
+		ASSERT(msbp->msb_field < XFS_SBS_ICOUNT ||
+		       msbp->msb_field > XFS_SBS_FDBLOCKS);
 
-		if (status != 0) {
-			break;
-		}
-	}
-
-	/*
-	 * If we didn't complete the loop above, then back out
-	 * any changes made to the superblock.  If you add code
-	 * between the loop above and here, make sure that you
-	 * preserve the value of status. Loop back until
-	 * we step below the beginning of the array.  Make sure
-	 * we don't touch anything back there.
-	 */
-	if (status != 0) {
-		msbp--;
-		while (msbp >= msb) {
-			switch (msbp->msb_field) {
-#ifdef HAVE_PERCPU_SB
-			case XFS_SBS_ICOUNT:
-			case XFS_SBS_IFREE:
-			case XFS_SBS_FDBLOCKS:
-				if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
-					spin_unlock(&mp->m_sb_lock);
-					status = xfs_icsb_modify_counters(mp,
-							msbp->msb_field,
-							-(msbp->msb_delta),
-							rsvd);
-					spin_lock(&mp->m_sb_lock);
-					break;
-				}
-				/* FALLTHROUGH */
-#endif
-			default:
-				status = xfs_mod_incore_sb_unlocked(mp,
-							msbp->msb_field,
-							-(msbp->msb_delta),
-							rsvd);
-				break;
-			}
-			ASSERT(status == 0);
-			msbp--;
-		}
+		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
+						   msbp->msb_delta, rsvd);
+		if (error)
+			goto unwind;
 	}
 	spin_unlock(&mp->m_sb_lock);
-	return status;
+	return 0;
+
+unwind:
+	while (--msbp >= msb) {
+		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
+						   -msbp->msb_delta, rsvd);
+		ASSERT(error == 0);
+	}
+	spin_unlock(&mp->m_sb_lock);
+	return error;
 }
 
 /*
@@ -1998,18 +1941,13 @@
  */
 void
 xfs_freesb(
-	xfs_mount_t	*mp)
+	struct xfs_mount	*mp)
 {
-	xfs_buf_t	*bp;
+	struct xfs_buf		*bp = mp->m_sb_bp;
 
-	/*
-	 * Use xfs_getsb() so that the buffer will be locked
-	 * when we call xfs_buf_relse().
-	 */
-	bp = xfs_getsb(mp, 0);
-	XFS_BUF_UNMANAGE(bp);
-	xfs_buf_relse(bp);
+	xfs_buf_lock(bp);
 	mp->m_sb_bp = NULL;
+	xfs_buf_relse(bp);
 }
 
 /*
@@ -2496,7 +2434,7 @@
 	spin_unlock(&mp->m_sb_lock);
 }
 
-STATIC int
+int
 xfs_icsb_modify_counters(
 	xfs_mount_t	*mp,
 	xfs_sb_field_t	field,
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 622da21..5861b49 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -53,7 +53,6 @@
 
 #include "xfs_sync.h"
 
-struct cred;
 struct log;
 struct xfs_mount_args;
 struct xfs_inode;
@@ -91,6 +90,8 @@
 extern void	xfs_icsb_destroy_counters(struct xfs_mount *);
 extern void	xfs_icsb_sync_counters(struct xfs_mount *, int);
 extern void	xfs_icsb_sync_counters_locked(struct xfs_mount *, int);
+extern int	xfs_icsb_modify_counters(struct xfs_mount *, xfs_sb_field_t,
+						int64_t, int);
 
 #else
 #define xfs_icsb_init_counters(mp)		(0)
@@ -98,6 +99,8 @@
 #define xfs_icsb_reinit_counters(mp)		do { } while (0)
 #define xfs_icsb_sync_counters(mp, flags)	do { } while (0)
 #define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0)
+#define xfs_icsb_modify_counters(mp, field, delta, rsvd) \
+	xfs_mod_incore_sb(mp, field, delta, rsvd)
 #endif
 
 typedef struct xfs_mount {
@@ -232,8 +235,6 @@
 #define XFS_MOUNT_DIRSYNC	(1ULL << 21)	/* synchronous directory ops */
 #define XFS_MOUNT_COMPAT_IOSIZE	(1ULL << 22)	/* don't report large preferred
 						 * I/O size in stat() */
-#define XFS_MOUNT_NO_PERCPU_SB	(1ULL << 23)	/* don't use per-cpu superblock
-						   counters */
 #define XFS_MOUNT_FILESTREAMS	(1ULL << 24)	/* enable the filestreams
 						   allocator */
 #define XFS_MOUNT_NOATTR2	(1ULL << 25)	/* disable use of attr2 format */
@@ -327,6 +328,8 @@
  * perag get/put wrappers for ref counting
  */
 struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
+struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
+					int tag);
 void	xfs_perag_put(struct xfs_perag *pag);
 
 /*
diff --git a/fs/xfs/xfs_refcache.h b/fs/xfs/xfs_refcache.h
deleted file mode 100644
index 2dec79e..0000000
--- a/fs/xfs/xfs_refcache.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_REFCACHE_H__
-#define __XFS_REFCACHE_H__
-
-#ifdef HAVE_REFCACHE
-/*
- * Maximum size (in inodes) for the NFS reference cache
- */
-#define XFS_REFCACHE_SIZE_MAX	512
-
-struct xfs_inode;
-struct xfs_mount;
-
-extern void xfs_refcache_insert(struct xfs_inode *);
-extern void xfs_refcache_purge_ip(struct xfs_inode *);
-extern void xfs_refcache_purge_mp(struct xfs_mount *);
-extern void xfs_refcache_purge_some(struct xfs_mount *);
-extern void xfs_refcache_resize(int);
-extern void xfs_refcache_destroy(void);
-
-extern void xfs_refcache_iunlock(struct xfs_inode *, uint);
-
-#else
-
-#define xfs_refcache_insert(ip)		do { } while (0)
-#define xfs_refcache_purge_ip(ip)	do { } while (0)
-#define xfs_refcache_purge_mp(mp)	do { } while (0)
-#define xfs_refcache_purge_some(mp)	do { } while (0)
-#define xfs_refcache_resize(size)	do { } while (0)
-#define xfs_refcache_destroy()		do { } while (0)
-
-#define xfs_refcache_iunlock(ip, flags)	xfs_iunlock(ip, flags)
-
-#endif
-
-#endif	/* __XFS_REFCACHE_H__ */
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 8fca957..d2af0a8 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -183,7 +183,7 @@
 	 * 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))) {
+		     (xfs_get_projid(target_dp) != xfs_get_projid(src_ip)))) {
 		error = XFS_ERROR(EXDEV);
 		goto error_return;
 	}
@@ -211,7 +211,9 @@
 			goto error_return;
 		if (error)
 			goto abort_return;
-		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+
+		xfs_trans_ichgtime(tp, target_dp,
+					XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 		if (new_parent && src_is_directory) {
 			error = xfs_bumplink(tp, target_dp);
@@ -249,7 +251,9 @@
 					&first_block, &free_list, spaceres);
 		if (error)
 			goto abort_return;
-		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+
+		xfs_trans_ichgtime(tp, target_dp,
+					XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 		/*
 		 * Decrement the link count on the target since the target
@@ -292,7 +296,7 @@
 	 * inode isn't really being changed, but old unix file systems did
 	 * it and some incremental backup programs won't work without it.
 	 */
-	xfs_ichgtime(src_ip, XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, src_ip, XFS_ICHGTIME_CHG);
 
 	/*
 	 * Adjust the link count on src_dp.  This is necessary when
@@ -315,7 +319,7 @@
 	if (error)
 		goto abort_return;
 
-	xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, src_dp, XFS_ILOG_CORE);
 	if (new_parent)
 		xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE);
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 891260f..12a1913 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -39,6 +39,7 @@
 #include "xfs_trans_space.h"
 #include "xfs_utils.h"
 #include "xfs_trace.h"
+#include "xfs_buf.h"
 
 
 /*
@@ -1883,13 +1884,13 @@
 	/*
 	 * Read in the last block of the device, make sure it exists.
 	 */
-	error = xfs_read_buf(mp, mp->m_rtdev_targp,
-			XFS_FSB_TO_BB(mp, nrblocks - 1),
-			XFS_FSB_TO_BB(mp, 1), 0, &bp);
-	if (error)
-		return error;
-	ASSERT(bp);
+	bp = xfs_buf_read_uncached(mp, mp->m_rtdev_targp,
+				XFS_FSB_TO_BB(mp, nrblocks - 1),
+				XFS_FSB_TO_B(mp, 1), 0);
+	if (!bp)
+		return EIO;
 	xfs_buf_relse(bp);
+
 	/*
 	 * Calculate new parameters.  These are the final values to be reached.
 	 */
@@ -2215,7 +2216,6 @@
 {
 	xfs_buf_t	*bp;	/* buffer for last block of subvolume */
 	xfs_daddr_t	d;	/* address of last block of subvolume */
-	int		error;	/* error return value */
 	xfs_sb_t	*sbp;	/* filesystem superblock copy in mount */
 
 	sbp = &mp->m_sb;
@@ -2242,15 +2242,12 @@
 			(unsigned long long) mp->m_sb.sb_rblocks);
 		return XFS_ERROR(EFBIG);
 	}
-	error = xfs_read_buf(mp, mp->m_rtdev_targp,
-				d - XFS_FSB_TO_BB(mp, 1),
-				XFS_FSB_TO_BB(mp, 1), 0, &bp);
-	if (error) {
-		cmn_err(CE_WARN,
-	"XFS: realtime mount -- xfs_read_buf failed, returned %d", error);
-		if (error == ENOSPC)
-			return XFS_ERROR(EFBIG);
-		return error;
+	bp = xfs_buf_read_uncached(mp, mp->m_rtdev_targp,
+					d - XFS_FSB_TO_BB(mp, 1),
+					XFS_FSB_TO_B(mp, 1), 0);
+	if (!bp) {
+		cmn_err(CE_WARN, "XFS: realtime device size check failed");
+		return EIO;
 	}
 	xfs_buf_relse(bp);
 	return 0;
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 1b017c6..1eb2ba5 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -80,10 +80,12 @@
 #define XFS_SB_VERSION2_RESERVED4BIT	0x00000004
 #define XFS_SB_VERSION2_ATTR2BIT	0x00000008	/* Inline attr rework */
 #define XFS_SB_VERSION2_PARENTBIT	0x00000010	/* parent pointers */
+#define XFS_SB_VERSION2_PROJID32BIT	0x00000080	/* 32 bit project id */
 
 #define	XFS_SB_VERSION2_OKREALFBITS	\
 	(XFS_SB_VERSION2_LAZYSBCOUNTBIT	| \
-	 XFS_SB_VERSION2_ATTR2BIT)
+	 XFS_SB_VERSION2_ATTR2BIT	| \
+	 XFS_SB_VERSION2_PROJID32BIT)
 #define	XFS_SB_VERSION2_OKSASHFBITS	\
 	(0)
 #define XFS_SB_VERSION2_OKREALBITS	\
@@ -495,6 +497,12 @@
 		sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
 }
 
+static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp)
+{
+	return xfs_sb_version_hasmorebits(sbp) &&
+		(sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT);
+}
+
 /*
  * end of superblock version macros
  */
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 1c47eda..f6d956b 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -696,7 +696,7 @@
 	 * fail if the count would go below zero.
 	 */
 	if (blocks > 0) {
-		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
+		error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
 					  -((int64_t)blocks), rsvd);
 		if (error != 0) {
 			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
@@ -767,7 +767,7 @@
 
 undo_blocks:
 	if (blocks > 0) {
-		(void) xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
+		xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
 					 (int64_t)blocks, rsvd);
 		tp->t_blk_res = 0;
 	}
@@ -1009,7 +1009,7 @@
 xfs_trans_unreserve_and_mod_sb(
 	xfs_trans_t	*tp)
 {
-	xfs_mod_sb_t	msb[14];	/* If you add cases, add entries */
+	xfs_mod_sb_t	msb[9];	/* If you add cases, add entries */
 	xfs_mod_sb_t	*msbp;
 	xfs_mount_t	*mp = tp->t_mountp;
 	/* REFERENCED */
@@ -1017,55 +1017,61 @@
 	int		rsvd;
 	int64_t		blkdelta = 0;
 	int64_t		rtxdelta = 0;
+	int64_t		idelta = 0;
+	int64_t		ifreedelta = 0;
 
 	msbp = msb;
 	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
 
-	/* calculate free blocks delta */
+	/* calculate deltas */
 	if (tp->t_blk_res > 0)
 		blkdelta = tp->t_blk_res;
-
 	if ((tp->t_fdblocks_delta != 0) &&
 	    (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
 	     (tp->t_flags & XFS_TRANS_SB_DIRTY)))
 	        blkdelta += tp->t_fdblocks_delta;
 
-	if (blkdelta != 0) {
-		msbp->msb_field = XFS_SBS_FDBLOCKS;
-		msbp->msb_delta = blkdelta;
-		msbp++;
-	}
-
-	/* calculate free realtime extents delta */
 	if (tp->t_rtx_res > 0)
 		rtxdelta = tp->t_rtx_res;
-
 	if ((tp->t_frextents_delta != 0) &&
 	    (tp->t_flags & XFS_TRANS_SB_DIRTY))
 		rtxdelta += tp->t_frextents_delta;
 
+	if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
+	     (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
+		idelta = tp->t_icount_delta;
+		ifreedelta = tp->t_ifree_delta;
+	}
+
+	/* apply the per-cpu counters */
+	if (blkdelta) {
+		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
+						 blkdelta, rsvd);
+		if (error)
+			goto out;
+	}
+
+	if (idelta) {
+		error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT,
+						 idelta, rsvd);
+		if (error)
+			goto out_undo_fdblocks;
+	}
+
+	if (ifreedelta) {
+		error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE,
+						 ifreedelta, rsvd);
+		if (error)
+			goto out_undo_icount;
+	}
+
+	/* apply remaining deltas */
 	if (rtxdelta != 0) {
 		msbp->msb_field = XFS_SBS_FREXTENTS;
 		msbp->msb_delta = rtxdelta;
 		msbp++;
 	}
 
-	/* apply remaining deltas */
-
-	if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
-	     (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
-		if (tp->t_icount_delta != 0) {
-			msbp->msb_field = XFS_SBS_ICOUNT;
-			msbp->msb_delta = tp->t_icount_delta;
-			msbp++;
-		}
-		if (tp->t_ifree_delta != 0) {
-			msbp->msb_field = XFS_SBS_IFREE;
-			msbp->msb_delta = tp->t_ifree_delta;
-			msbp++;
-		}
-	}
-
 	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
 		if (tp->t_dblocks_delta != 0) {
 			msbp->msb_field = XFS_SBS_DBLOCKS;
@@ -1115,8 +1121,24 @@
 	if (msbp > msb) {
 		error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
 			(uint)(msbp - msb), rsvd);
-		ASSERT(error == 0);
+		if (error)
+			goto out_undo_ifreecount;
 	}
+
+	return;
+
+out_undo_ifreecount:
+	if (ifreedelta)
+		xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
+out_undo_icount:
+	if (idelta)
+		xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd);
+out_undo_fdblocks:
+	if (blkdelta)
+		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
+out:
+	ASSERT(error = 0);
+	return;
 }
 
 /*
@@ -1389,15 +1411,12 @@
  */
 STATIC void
 xfs_trans_committed(
-	struct xfs_trans	*tp,
+	void			*arg,
 	int			abortflag)
 {
+	struct xfs_trans	*tp = arg;
 	struct xfs_log_item_desc *lidp, *next;
 
-	/* Call the transaction's completion callback if there is one. */
-	if (tp->t_callback != NULL)
-		tp->t_callback(tp, tp->t_callarg);
-
 	list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
 		xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag);
 		xfs_trans_free_item_desc(lidp);
@@ -1525,7 +1544,7 @@
 	 * running in simulation mode (the log is explicitly turned
 	 * off).
 	 */
-	tp->t_logcb.cb_func = (void(*)(void*, int))xfs_trans_committed;
+	tp->t_logcb.cb_func = xfs_trans_committed;
 	tp->t_logcb.cb_arg = tp;
 
 	/*
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index c13c0f9..246286b 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -399,8 +399,6 @@
 						 * transaction. */
 	struct xfs_mount	*t_mountp;	/* ptr to fs mount struct */
 	struct xfs_dquot_acct   *t_dqinfo;	/* acctg info for dquots */
-	xfs_trans_callback_t	t_callback;	/* transaction callback */
-	void			*t_callarg;	/* callback arg */
 	unsigned int		t_flags;	/* misc flags */
 	int64_t			t_icount_delta;	/* superblock icount change */
 	int64_t			t_ifree_delta;	/* superblock ifree change */
@@ -473,6 +471,7 @@
 void		xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
 int		xfs_trans_iget(struct xfs_mount *, xfs_trans_t *,
 			       xfs_ino_t , uint, uint, struct xfs_inode **);
+void		xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
 void		xfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, uint);
 void		xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *);
 void		xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 90af025..c47918c 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -336,7 +336,7 @@
 			ASSERT(!XFS_BUF_ISASYNC(bp));
 			XFS_BUF_READ(bp);
 			xfsbdstrat(tp->t_mountp, bp);
-			error = xfs_iowait(bp);
+			error = xfs_buf_iowait(bp);
 			if (error) {
 				xfs_ioerror_alert("xfs_trans_read_buf", mp,
 						  bp, blkno);
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index cdc53a1..ccb3453 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -118,6 +118,36 @@
 }
 
 /*
+ * Transactional inode timestamp update. Requires the inode to be locked and
+ * joined to the transaction supplied. Relies on the transaction subsystem to
+ * track dirty state and update/writeback the inode accordingly.
+ */
+void
+xfs_trans_ichgtime(
+	struct xfs_trans	*tp,
+	struct xfs_inode	*ip,
+	int			flags)
+{
+	struct inode		*inode = VFS_I(ip);
+	timespec_t		tv;
+
+	ASSERT(tp);
+	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+	ASSERT(ip->i_transp == tp);
+
+	tv = current_fs_time(inode->i_sb);
+
+	if ((flags & XFS_ICHGTIME_MOD) &&
+	    !timespec_equal(&inode->i_mtime, &tv)) {
+		inode->i_mtime = tv;
+	}
+	if ((flags & XFS_ICHGTIME_CHG) &&
+	    !timespec_equal(&inode->i_ctime, &tv)) {
+		inode->i_ctime = tv;
+	}
+}
+
+/*
  * This is called to mark the fields indicated in fieldmask as needing
  * to be logged when the transaction is committed.  The inode must
  * already be associated with the given transaction.
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index 3207752..26d1867 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -73,8 +73,6 @@
 typedef	__uint32_t	xfs_dablk_t;	/* dir/attr block number (in file) */
 typedef	__uint32_t	xfs_dahash_t;	/* dir/attr hash value */
 
-typedef __uint16_t	xfs_prid_t;	/* prid_t truncated to 16bits in XFS */
-
 typedef __uint32_t	xlog_tid_t;	/* transaction ID type */
 
 /*
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index b7d5769..8b32d1a 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -56,7 +56,6 @@
 	mode_t		mode,
 	xfs_nlink_t	nlink,
 	xfs_dev_t	rdev,
-	cred_t		*credp,
 	prid_t		prid,		/* project id */
 	int		okalloc,	/* ok to allocate new space */
 	xfs_inode_t	**ipp,		/* pointer to inode; it will be
@@ -93,7 +92,7 @@
 	 * transaction commit so that no other process can steal
 	 * the inode(s) that we've just allocated.
 	 */
-	code = xfs_ialloc(tp, dp, mode, nlink, rdev, credp, prid, okalloc,
+	code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid, okalloc,
 			  &ialloc_context, &call_again, &ip);
 
 	/*
@@ -197,7 +196,7 @@
 		 * other allocations in this allocation group,
 		 * this call should always succeed.
 		 */
-		code = xfs_ialloc(tp, dp, mode, nlink, rdev, credp, prid,
+		code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid,
 				  okalloc, &ialloc_context, &call_again, &ip);
 
 		/*
@@ -235,7 +234,7 @@
 {
 	int	error;
 
-	xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
 
 	ASSERT (ip->i_d.di_nlink > 0);
 	ip->i_d.di_nlink--;
@@ -299,7 +298,7 @@
 {
 	if (ip->i_d.di_nlink >= XFS_MAXLINK)
 		return XFS_ERROR(EMLINK);
-	xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
 
 	ASSERT(ip->i_d.di_nlink > 0);
 	ip->i_d.di_nlink++;
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index f55b967..456fca3 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -19,8 +19,7 @@
 #define __XFS_UTILS_H__
 
 extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
-				xfs_dev_t, cred_t *, prid_t, int,
-				xfs_inode_t **, int *);
+				xfs_dev_t, prid_t, int, xfs_inode_t **, int *);
 extern int xfs_droplink(xfs_trans_t *, xfs_inode_t *);
 extern int xfs_bumplink(xfs_trans_t *, xfs_inode_t *);
 extern void xfs_bump_ino_vers2(xfs_trans_t *, xfs_inode_t *);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 4c7c7bf..8e4a63c 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -114,7 +114,7 @@
 		 */
 		ASSERT(udqp == NULL);
 		ASSERT(gdqp == NULL);
-		code = xfs_qm_vop_dqalloc(ip, uid, gid, ip->i_d.di_projid,
+		code = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip),
 					 qflags, &udqp, &gdqp);
 		if (code)
 			return code;
@@ -184,8 +184,11 @@
 		    ip->i_size == 0 && ip->i_d.di_nextents == 0) {
 			xfs_iunlock(ip, XFS_ILOCK_EXCL);
 			lock_flags &= ~XFS_ILOCK_EXCL;
-			if (mask & ATTR_CTIME)
-				xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+			if (mask & ATTR_CTIME) {
+				inode->i_mtime = inode->i_ctime =
+						current_fs_time(inode->i_sb);
+				xfs_mark_inode_dirty_sync(ip);
+			}
 			code = 0;
 			goto error_return;
 		}
@@ -1253,8 +1256,7 @@
 	struct xfs_name		*name,
 	mode_t			mode,
 	xfs_dev_t		rdev,
-	xfs_inode_t		**ipp,
-	cred_t			*credp)
+	xfs_inode_t		**ipp)
 {
 	int			is_dir = S_ISDIR(mode);
 	struct xfs_mount	*mp = dp->i_mount;
@@ -1266,7 +1268,7 @@
 	boolean_t		unlock_dp_on_error = B_FALSE;
 	uint			cancel_flags;
 	int			committed;
-	xfs_prid_t		prid;
+	prid_t			prid;
 	struct xfs_dquot	*udqp = NULL;
 	struct xfs_dquot	*gdqp = NULL;
 	uint			resblks;
@@ -1279,9 +1281,9 @@
 		return XFS_ERROR(EIO);
 
 	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
-		prid = dp->i_d.di_projid;
+		prid = xfs_get_projid(dp);
 	else
-		prid = dfltprid;
+		prid = XFS_PROJID_DEFAULT;
 
 	/*
 	 * Make sure that we have allocated dquot(s) on disk.
@@ -1360,7 +1362,7 @@
 	 * entry pointing to them, but a directory also the "." entry
 	 * pointing to itself.
 	 */
-	error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev, credp,
+	error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev,
 			       prid, resblks > 0, &ip, &committed);
 	if (error) {
 		if (error == ENOSPC)
@@ -1391,7 +1393,7 @@
 		ASSERT(error != ENOSPC);
 		goto out_trans_abort;
 	}
-	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
 	if (is_dir) {
@@ -1742,7 +1744,7 @@
 		ASSERT(error != ENOENT);
 		goto out_bmap_cancel;
 	}
-	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 	if (is_dir) {
 		/*
@@ -1880,7 +1882,7 @@
 	 * the tree quota mechanism could be circumvented.
 	 */
 	if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
-		     (tdp->i_d.di_projid != sip->i_d.di_projid))) {
+		     (xfs_get_projid(tdp) != xfs_get_projid(sip)))) {
 		error = XFS_ERROR(EXDEV);
 		goto error_return;
 	}
@@ -1895,7 +1897,7 @@
 					&first_block, &free_list, resblks);
 	if (error)
 		goto abort_return;
-	xfs_ichgtime(tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
 
 	error = xfs_bumplink(tp, sip);
@@ -1933,8 +1935,7 @@
 	struct xfs_name		*link_name,
 	const char		*target_path,
 	mode_t			mode,
-	xfs_inode_t		**ipp,
-	cred_t			*credp)
+	xfs_inode_t		**ipp)
 {
 	xfs_mount_t		*mp = dp->i_mount;
 	xfs_trans_t		*tp;
@@ -1955,7 +1956,7 @@
 	int			byte_cnt;
 	int			n;
 	xfs_buf_t		*bp;
-	xfs_prid_t		prid;
+	prid_t			prid;
 	struct xfs_dquot	*udqp, *gdqp;
 	uint			resblks;
 
@@ -1978,9 +1979,9 @@
 
 	udqp = gdqp = NULL;
 	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
-		prid = dp->i_d.di_projid;
+		prid = xfs_get_projid(dp);
 	else
-		prid = (xfs_prid_t)dfltprid;
+		prid = XFS_PROJID_DEFAULT;
 
 	/*
 	 * Make sure that we have allocated dquot(s) on disk.
@@ -2046,8 +2047,8 @@
 	/*
 	 * Allocate an inode for the symlink.
 	 */
-	error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT),
-			       1, 0, credp, prid, resblks > 0, &ip, NULL);
+	error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT), 1, 0,
+			       prid, resblks > 0, &ip, NULL);
 	if (error) {
 		if (error == ENOSPC)
 			goto error_return;
@@ -2129,7 +2130,7 @@
 					&first_block, &free_list, resblks);
 	if (error)
 		goto error1;
-	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
 	/*
@@ -2272,7 +2273,7 @@
 	count = len;
 	imapp = &imaps[0];
 	nimaps = 1;
-	bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
+	bmapi_flag = XFS_BMAPI_WRITE | alloc_type;
 	startoffset_fsb	= XFS_B_TO_FSBT(mp, offset);
 	allocatesize_fsb = XFS_B_TO_FSB(mp, count);
 
@@ -2431,9 +2432,9 @@
 	if (endoff > ip->i_size)
 		endoff = ip->i_size;
 
-	bp = xfs_buf_get_noaddr(mp->m_sb.sb_blocksize,
-				XFS_IS_REALTIME_INODE(ip) ?
-				mp->m_rtdev_targp : mp->m_ddev_targp);
+	bp = xfs_buf_get_uncached(XFS_IS_REALTIME_INODE(ip) ?
+					mp->m_rtdev_targp : mp->m_ddev_targp,
+				mp->m_sb.sb_blocksize, XBF_DONT_BLOCK);
 	if (!bp)
 		return XFS_ERROR(ENOMEM);
 
@@ -2459,7 +2460,7 @@
 		XFS_BUF_READ(bp);
 		XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
 		xfsbdstrat(mp, bp);
-		error = xfs_iowait(bp);
+		error = xfs_buf_iowait(bp);
 		if (error) {
 			xfs_ioerror_alert("xfs_zero_remaining_bytes(read)",
 					  mp, bp, XFS_BUF_ADDR(bp));
@@ -2472,7 +2473,7 @@
 		XFS_BUF_UNREAD(bp);
 		XFS_BUF_WRITE(bp);
 		xfsbdstrat(mp, bp);
-		error = xfs_iowait(bp);
+		error = xfs_buf_iowait(bp);
 		if (error) {
 			xfs_ioerror_alert("xfs_zero_remaining_bytes(write)",
 					  mp, bp, XFS_BUF_ADDR(bp));
@@ -2711,6 +2712,7 @@
 	xfs_off_t	llen;
 	xfs_trans_t	*tp;
 	struct iattr	iattr;
+	int		prealloc_type;
 
 	if (!S_ISREG(ip->i_d.di_mode))
 		return XFS_ERROR(EINVAL);
@@ -2753,12 +2755,17 @@
 	 * size to be changed.
 	 */
 	setprealloc = clrprealloc = 0;
+	prealloc_type = XFS_BMAPI_PREALLOC;
 
 	switch (cmd) {
+	case XFS_IOC_ZERO_RANGE:
+		prealloc_type |= XFS_BMAPI_CONVERT;
+		xfs_tosspages(ip, startoffset, startoffset + bf->l_len, 0);
+		/* FALLTHRU */
 	case XFS_IOC_RESVSP:
 	case XFS_IOC_RESVSP64:
 		error = xfs_alloc_file_space(ip, startoffset, bf->l_len,
-								1, attr_flags);
+						prealloc_type, attr_flags);
 		if (error)
 			return error;
 		setprealloc = 1;
@@ -2827,7 +2834,7 @@
 		if (ip->i_d.di_mode & S_IXGRP)
 			ip->i_d.di_mode &= ~S_ISGID;
 
-		xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+		xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	}
 	if (setprealloc)
 		ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index d8dfa8d..f6702927 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -2,7 +2,6 @@
 #define _XFS_VNODEOPS_H 1
 
 struct attrlist_cursor_kern;
-struct cred;
 struct file;
 struct iattr;
 struct inode;
@@ -26,7 +25,7 @@
 int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
 		struct xfs_inode **ipp, struct xfs_name *ci_name);
 int xfs_create(struct xfs_inode *dp, struct xfs_name *name, mode_t mode,
-		xfs_dev_t rdev, struct xfs_inode **ipp, cred_t *credp);
+		xfs_dev_t rdev, struct xfs_inode **ipp);
 int xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
 		struct xfs_inode *ip);
 int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
@@ -34,8 +33,7 @@
 int xfs_readdir(struct xfs_inode	*dp, void *dirent, size_t bufsize,
 		       xfs_off_t *offset, filldir_t filldir);
 int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
-		const char *target_path, mode_t mode, struct xfs_inode **ipp,
-		cred_t *credp);
+		const char *target_path, mode_t mode, struct xfs_inode **ipp);
 int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
 int xfs_change_file_space(struct xfs_inode *ip, int cmd,
 		xfs_flock64_t *bf, xfs_off_t offset, int attr_flags);
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index fd57b847..e994197 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -120,14 +120,23 @@
 #define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
 #define atomic_inc_and_test(v)		(atomic_add_return(1, (v)) == 0)
 
-#define atomic_add_unless(v, a, u)				\
-({								\
-	int c, old;						\
-	c = atomic_read(v);					\
-	while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
-		c = old;					\
-	c != (u);						\
-})
+#define atomic_xchg(ptr, v)		(xchg(&(ptr)->counter, (v)))
+#define atomic_cmpxchg(v, old, new)	(cmpxchg(&((v)->counter), (old), (new)))
+
+#define cmpxchg_local(ptr, o, n)				  	       \
+	((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+			(unsigned long)(n), sizeof(*(ptr))))
+
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+  int c, old;
+  c = atomic_read(v);
+  while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
+    c = old;
+  return c != u;
+}
 
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
@@ -141,15 +150,6 @@
 	raw_local_irq_restore(flags);
 }
 
-#define atomic_xchg(ptr, v)		(xchg(&(ptr)->counter, (v)))
-#define atomic_cmpxchg(v, old, new)	(cmpxchg(&((v)->counter), (old), (new)))
-
-#define cmpxchg_local(ptr, o, n)				  	       \
-	((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-			(unsigned long)(n), sizeof(*(ptr))))
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
 /* Assume that atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()	barrier()
 #define smp_mb__after_atomic_dec()	barrier()
diff --git a/include/asm-generic/bitops/find.h b/include/asm-generic/bitops/find.h
index 1914e97..110fa70 100644
--- a/include/asm-generic/bitops/find.h
+++ b/include/asm-generic/bitops/find.h
@@ -1,15 +1,50 @@
 #ifndef _ASM_GENERIC_BITOPS_FIND_H_
 #define _ASM_GENERIC_BITOPS_FIND_H_
 
-#ifndef 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
+
+#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);
+#else /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
 #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)
 
+#endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
+
 #endif /*_ASM_GENERIC_BITOPS_FIND_H_ */
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index a70b2d2..0fc16e3 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -122,7 +122,7 @@
 
 struct f_owner_ex {
 	int	type;
-	pid_t	pid;
+	__kernel_pid_t	pid;
 };
 
 /* for F_[GET|SET]FL */
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 118601f..3577ca1 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -19,7 +19,9 @@
 #include <asm-generic/iomap.h>
 #endif
 
+#ifndef mmiowb
 #define mmiowb() do {} while (0)
+#endif
 
 /*****************************************************************************/
 /*
@@ -28,39 +30,51 @@
  * differently. On the simple architectures, we just read/write the
  * memory location directly.
  */
+#ifndef __raw_readb
 static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
 	return *(const volatile u8 __force *) addr;
 }
+#endif
 
+#ifndef __raw_readw
 static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
 	return *(const volatile u16 __force *) addr;
 }
+#endif
 
+#ifndef __raw_readl
 static inline u32 __raw_readl(const volatile void __iomem *addr)
 {
 	return *(const volatile u32 __force *) addr;
 }
+#endif
 
 #define readb __raw_readb
 #define readw(addr) __le16_to_cpu(__raw_readw(addr))
 #define readl(addr) __le32_to_cpu(__raw_readl(addr))
 
+#ifndef __raw_writeb
 static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
 {
 	*(volatile u8 __force *) addr = b;
 }
+#endif
 
+#ifndef __raw_writew
 static inline void __raw_writew(u16 b, volatile void __iomem *addr)
 {
 	*(volatile u16 __force *) addr = b;
 }
+#endif
 
+#ifndef __raw_writel
 static inline void __raw_writel(u32 b, volatile void __iomem *addr)
 {
 	*(volatile u32 __force *) addr = b;
 }
+#endif
 
 #define writeb __raw_writeb
 #define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr)
@@ -122,6 +136,7 @@
 #define outw_p(x, addr)	outw((x), (addr))
 #define outl_p(x, addr)	outl((x), (addr))
 
+#ifndef insb
 static inline void insb(unsigned long addr, void *buffer, int count)
 {
 	if (count) {
@@ -132,7 +147,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef insw
 static inline void insw(unsigned long addr, void *buffer, int count)
 {
 	if (count) {
@@ -143,7 +160,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef insl
 static inline void insl(unsigned long addr, void *buffer, int count)
 {
 	if (count) {
@@ -154,7 +173,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef outsb
 static inline void outsb(unsigned long addr, const void *buffer, int count)
 {
 	if (count) {
@@ -164,7 +185,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef outsw
 static inline void outsw(unsigned long addr, const void *buffer, int count)
 {
 	if (count) {
@@ -174,7 +197,9 @@
 		} while (--count);
 	}
 }
+#endif
 
+#ifndef outsl
 static inline void outsl(unsigned long addr, const void *buffer, int count)
 {
 	if (count) {
@@ -184,6 +209,7 @@
 		} while (--count);
 	}
 }
+#endif
 
 #ifndef CONFIG_GENERIC_IOMAP
 #define ioread8(addr)		readb(addr)
diff --git a/include/asm-generic/ioctls.h b/include/asm-generic/ioctls.h
index 8554cb6..a321665 100644
--- a/include/asm-generic/ioctls.h
+++ b/include/asm-generic/ioctls.h
@@ -62,7 +62,9 @@
 #define TCSETSW2	_IOW('T', 0x2C, struct termios2)
 #define TCSETSF2	_IOW('T', 0x2D, struct termios2)
 #define TIOCGRS485	0x542E
+#ifndef TIOCSRS485
 #define TIOCSRS485	0x542F
+#endif
 #define TIOCGPTN	_IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T', 0x31, int)  /* Lock/unlock Pty */
 #define TCGETX		0x5432 /* SYS5 TCGETX compatibility */
diff --git a/include/asm-generic/kdebug.h b/include/asm-generic/kdebug.h
index 11e57b6..d181449 100644
--- a/include/asm-generic/kdebug.h
+++ b/include/asm-generic/kdebug.h
@@ -3,7 +3,7 @@
 
 enum die_val {
 	DIE_UNUSED,
-	DIE_OOPS=1
+	DIE_OOPS = 1,
 };
 
 #endif /* _ASM_GENERIC_KDEBUG_H */
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index 08923b6..d17784e 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -55,14 +55,18 @@
  */
 #define per_cpu(var, cpu) \
 	(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
-#define __get_cpu_var(var) \
-	(*SHIFT_PERCPU_PTR(&(var), my_cpu_offset))
-#define __raw_get_cpu_var(var) \
-	(*SHIFT_PERCPU_PTR(&(var), __my_cpu_offset))
 
-#define this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, my_cpu_offset)
+#ifndef __this_cpu_ptr
 #define __this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset)
+#endif
+#ifdef CONFIG_DEBUG_PREEMPT
+#define this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, my_cpu_offset)
+#else
+#define this_cpu_ptr(ptr) __this_cpu_ptr(ptr)
+#endif
 
+#define __get_cpu_var(var) (*this_cpu_ptr(&(var)))
+#define __raw_get_cpu_var(var) (*__this_cpu_ptr(&(var)))
 
 #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA
 extern void setup_per_cpu_areas(void);
diff --git a/include/asm-generic/system.h b/include/asm-generic/system.h
index efa403b..4b0b9cb 100644
--- a/include/asm-generic/system.h
+++ b/include/asm-generic/system.h
@@ -21,6 +21,7 @@
 #include <linux/irqflags.h>
 
 #include <asm/cmpxchg-local.h>
+#include <asm/cmpxchg.h>
 
 struct task_struct;
 
@@ -136,25 +137,6 @@
 #define xchg(ptr, x) \
 	((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
 
-static inline unsigned long __cmpxchg(volatile unsigned long *m,
-				      unsigned long old, unsigned long new)
-{
-	unsigned long retval;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	retval = *m;
-	if (retval == old)
-		*m = new;
-	local_irq_restore(flags);
-	return retval;
-}
-
-#define cmpxchg(ptr, o, n)					\
-	((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
-					(unsigned long)(o),	\
-					(unsigned long)(n)))
-
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/altera_uart.h b/include/linux/altera_uart.h
index 8d44106..a10a907 100644
--- a/include/linux/altera_uart.h
+++ b/include/linux/altera_uart.h
@@ -5,10 +5,15 @@
 #ifndef	__ALTUART_H
 #define	__ALTUART_H
 
+#include <linux/init.h>
+
 struct altera_uart_platform_uart {
 	unsigned long mapbase;	/* Physical address base */
 	unsigned int irq;	/* Interrupt vector */
 	unsigned int uartclk;	/* UART clock rate */
+	unsigned int bus_shift;	/* Bus shift (address stride) */
 };
 
+int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp);
+
 #endif /* __ALTUART_H */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 5274103..ba67999 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -346,8 +346,15 @@
 }
 
 #else
-#define bvec_kmap_irq(bvec, flags)	(page_address((bvec)->bv_page) + (bvec)->bv_offset)
-#define bvec_kunmap_irq(buf, flags)	do { *(flags) = 0; } while (0)
+static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
+{
+	return page_address(bvec->bv_page) + bvec->bv_offset;
+}
+
+static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
+{
+	*flags = 0;
+}
 #endif
 
 static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
@@ -496,6 +503,10 @@
 #define bip_for_each_vec(bvl, bip, i)					\
 	__bip_for_each_vec(bvl, bip, i, (bip)->bip_idx)
 
+#define bio_for_each_integrity_vec(_bvl, _bio, _iter)			\
+	for_each_bio(_bio)						\
+		bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
+
 #define bio_integrity(bio) (bio->bi_integrity != NULL)
 
 extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *);
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index fc68053..827cc95 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -136,28 +136,6 @@
 }
 
 #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_LAST_BIT
 /**
@@ -171,28 +149,5 @@
 				   unsigned long size);
 #endif /* CONFIG_GENERIC_FIND_LAST_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/blk_types.h b/include/linux/blk_types.h
index ca83a97..0437ab6 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -97,6 +97,7 @@
 #define BIO_NULL_MAPPED 9	/* contains invalid user pages */
 #define BIO_FS_INTEGRITY 10	/* fs owns integrity data, not block layer */
 #define BIO_QUIET	11	/* Make BIO Quiet */
+#define BIO_MAPPED_INTEGRITY 12/* integrity metadata has been remapped */
 #define bio_flagged(bio, flag)	((bio)->bi_flags & (1 << (flag)))
 
 /*
@@ -130,6 +131,8 @@
 	/* bio only flags */
 	__REQ_UNPLUG,		/* unplug the immediately after submission */
 	__REQ_RAHEAD,		/* read ahead, can fail anytime */
+	__REQ_THROTTLED,	/* This bio has already been subjected to
+				 * throttling rules. Don't do it again. */
 
 	/* request only flags */
 	__REQ_SORTED,		/* elevator knows about this request */
@@ -143,10 +146,8 @@
 	__REQ_FAILED,		/* set if the request failed */
 	__REQ_QUIET,		/* don't worry about errors */
 	__REQ_PREEMPT,		/* set for "ide_preempt" requests */
-	__REQ_ORDERED_COLOR,	/* is before or after barrier */
 	__REQ_ALLOCED,		/* request came from our alloc pool */
 	__REQ_COPY_USER,	/* contains copies of user pages */
-	__REQ_INTEGRITY,	/* integrity metadata has been remapped */
 	__REQ_FLUSH,		/* request for cache flush */
 	__REQ_IO_STAT,		/* account I/O stat */
 	__REQ_MIXED_MERGE,	/* merge of different types, fail separately */
@@ -168,10 +169,12 @@
 	(REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
 #define REQ_COMMON_MASK \
 	(REQ_WRITE | REQ_FAILFAST_MASK | REQ_HARDBARRIER | REQ_SYNC | \
-	 REQ_META| REQ_DISCARD | REQ_NOIDLE)
+	 REQ_META | REQ_DISCARD | REQ_NOIDLE | REQ_FLUSH | REQ_FUA)
+#define REQ_CLONE_MASK		REQ_COMMON_MASK
 
 #define REQ_UNPLUG		(1 << __REQ_UNPLUG)
 #define REQ_RAHEAD		(1 << __REQ_RAHEAD)
+#define REQ_THROTTLED		(1 << __REQ_THROTTLED)
 
 #define REQ_SORTED		(1 << __REQ_SORTED)
 #define REQ_SOFTBARRIER		(1 << __REQ_SOFTBARRIER)
@@ -184,10 +187,8 @@
 #define REQ_FAILED		(1 << __REQ_FAILED)
 #define REQ_QUIET		(1 << __REQ_QUIET)
 #define REQ_PREEMPT		(1 << __REQ_PREEMPT)
-#define REQ_ORDERED_COLOR	(1 << __REQ_ORDERED_COLOR)
 #define REQ_ALLOCED		(1 << __REQ_ALLOCED)
 #define REQ_COPY_USER		(1 << __REQ_COPY_USER)
-#define REQ_INTEGRITY		(1 << __REQ_INTEGRITY)
 #define REQ_FLUSH		(1 << __REQ_FLUSH)
 #define REQ_IO_STAT		(1 << __REQ_IO_STAT)
 #define REQ_MIXED_MERGE		(1 << __REQ_MIXED_MERGE)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 2c54906..009b80e 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -115,6 +115,7 @@
 	void *elevator_private3;
 
 	struct gendisk *rq_disk;
+	struct hd_struct *part;
 	unsigned long start_time;
 #ifdef CONFIG_BLK_CGROUP
 	unsigned long long start_time_ns;
@@ -124,6 +125,9 @@
 	 * physical address coalescing is performed.
 	 */
 	unsigned short nr_phys_segments;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+	unsigned short nr_integrity_segments;
+#endif
 
 	unsigned short ioprio;
 
@@ -243,6 +247,7 @@
 
 	unsigned short		logical_block_size;
 	unsigned short		max_segments;
+	unsigned short		max_integrity_segments;
 
 	unsigned char		misaligned;
 	unsigned char		discard_misaligned;
@@ -355,18 +360,25 @@
 	struct blk_trace	*blk_trace;
 #endif
 	/*
-	 * reserved for flush operations
+	 * for flush operations
 	 */
-	unsigned int		ordered, next_ordered, ordseq;
-	int			orderr, ordcolor;
-	struct request		pre_flush_rq, bar_rq, post_flush_rq;
-	struct request		*orig_bar_rq;
+	unsigned int		flush_flags;
+	unsigned int		flush_seq;
+	int			flush_err;
+	struct request		flush_rq;
+	struct request		*orig_flush_rq;
+	struct list_head	pending_flushes;
 
 	struct mutex		sysfs_lock;
 
 #if defined(CONFIG_BLK_DEV_BSG)
 	struct bsg_class_device bsg_dev;
 #endif
+
+#ifdef CONFIG_BLK_DEV_THROTTLING
+	/* Throttle data */
+	struct throtl_data *td;
+#endif
 };
 
 #define QUEUE_FLAG_CLUSTER	0	/* cluster several segments into 1 */
@@ -462,56 +474,6 @@
 	__clear_bit(flag, &q->queue_flags);
 }
 
-enum {
-	/*
-	 * Hardbarrier is supported with one of the following methods.
-	 *
-	 * NONE		: hardbarrier unsupported
-	 * DRAIN	: ordering by draining is enough
-	 * DRAIN_FLUSH	: ordering by draining w/ pre and post flushes
-	 * DRAIN_FUA	: ordering by draining w/ pre flush and FUA write
-	 * TAG		: ordering by tag is enough
-	 * TAG_FLUSH	: ordering by tag w/ pre and post flushes
-	 * TAG_FUA	: ordering by tag w/ pre flush and FUA write
-	 */
-	QUEUE_ORDERED_BY_DRAIN		= 0x01,
-	QUEUE_ORDERED_BY_TAG		= 0x02,
-	QUEUE_ORDERED_DO_PREFLUSH	= 0x10,
-	QUEUE_ORDERED_DO_BAR		= 0x20,
-	QUEUE_ORDERED_DO_POSTFLUSH	= 0x40,
-	QUEUE_ORDERED_DO_FUA		= 0x80,
-
-	QUEUE_ORDERED_NONE		= 0x00,
-
-	QUEUE_ORDERED_DRAIN		= QUEUE_ORDERED_BY_DRAIN |
-					  QUEUE_ORDERED_DO_BAR,
-	QUEUE_ORDERED_DRAIN_FLUSH	= QUEUE_ORDERED_DRAIN |
-					  QUEUE_ORDERED_DO_PREFLUSH |
-					  QUEUE_ORDERED_DO_POSTFLUSH,
-	QUEUE_ORDERED_DRAIN_FUA		= QUEUE_ORDERED_DRAIN |
-					  QUEUE_ORDERED_DO_PREFLUSH |
-					  QUEUE_ORDERED_DO_FUA,
-
-	QUEUE_ORDERED_TAG		= QUEUE_ORDERED_BY_TAG |
-					  QUEUE_ORDERED_DO_BAR,
-	QUEUE_ORDERED_TAG_FLUSH		= QUEUE_ORDERED_TAG |
-					  QUEUE_ORDERED_DO_PREFLUSH |
-					  QUEUE_ORDERED_DO_POSTFLUSH,
-	QUEUE_ORDERED_TAG_FUA		= QUEUE_ORDERED_TAG |
-					  QUEUE_ORDERED_DO_PREFLUSH |
-					  QUEUE_ORDERED_DO_FUA,
-
-	/*
-	 * Ordered operation sequence
-	 */
-	QUEUE_ORDSEQ_STARTED	= 0x01,	/* flushing in progress */
-	QUEUE_ORDSEQ_DRAIN	= 0x02,	/* waiting for the queue to be drained */
-	QUEUE_ORDSEQ_PREFLUSH	= 0x04,	/* pre-flushing in progress */
-	QUEUE_ORDSEQ_BAR	= 0x08,	/* original barrier req in progress */
-	QUEUE_ORDSEQ_POSTFLUSH	= 0x10,	/* post-flushing in progress */
-	QUEUE_ORDSEQ_DONE	= 0x20,
-};
-
 #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)
@@ -521,7 +483,6 @@
 #define blk_queue_nonrot(q)	test_bit(QUEUE_FLAG_NONROT, &(q)->queue_flags)
 #define blk_queue_io_stat(q)	test_bit(QUEUE_FLAG_IO_STAT, &(q)->queue_flags)
 #define blk_queue_add_random(q)	test_bit(QUEUE_FLAG_ADD_RANDOM, &(q)->queue_flags)
-#define blk_queue_flushing(q)	((q)->ordseq)
 #define blk_queue_stackable(q)	\
 	test_bit(QUEUE_FLAG_STACKABLE, &(q)->queue_flags)
 #define blk_queue_discard(q)	test_bit(QUEUE_FLAG_DISCARD, &(q)->queue_flags)
@@ -592,7 +553,8 @@
  * it already be started by driver.
  */
 #define RQ_NOMERGE_FLAGS	\
-	(REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER)
+	(REQ_NOMERGE | REQ_STARTED | REQ_HARDBARRIER | REQ_SOFTBARRIER | \
+	 REQ_FLUSH | REQ_FUA)
 #define rq_mergeable(rq)	\
 	(!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \
 	 (((rq)->cmd_flags & REQ_DISCARD) || \
@@ -851,7 +813,7 @@
 extern void blk_queue_max_discard_sectors(struct request_queue *q,
 		unsigned int max_discard_sectors);
 extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
-extern void blk_queue_physical_block_size(struct request_queue *, unsigned short);
+extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
 extern void blk_queue_alignment_offset(struct request_queue *q,
 				       unsigned int alignment);
 extern void blk_limits_io_min(struct queue_limits *limits, unsigned int min);
@@ -881,12 +843,8 @@
 extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *);
 extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *);
 extern void blk_queue_rq_timeout(struct request_queue *, unsigned int);
+extern void blk_queue_flush(struct request_queue *q, unsigned int flush);
 extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
-extern int blk_queue_ordered(struct request_queue *, unsigned);
-extern bool blk_do_ordered(struct request_queue *, struct request **);
-extern unsigned blk_ordered_cur_seq(struct request_queue *);
-extern unsigned blk_ordered_req_seq(struct request *);
-extern bool blk_ordered_complete_seq(struct request_queue *, unsigned, int);
 
 extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *);
 extern void blk_dump_rq_flags(struct request *, char *);
@@ -919,27 +877,20 @@
 		return NULL;
 	return bqt->tag_index[tag];
 }
-enum{
-	BLKDEV_WAIT,	/* wait for completion */
-	BLKDEV_BARRIER,	/* issue request with barrier */
-	BLKDEV_SECURE,	/* secure discard */
-};
-#define BLKDEV_IFL_WAIT		(1 << BLKDEV_WAIT)
-#define BLKDEV_IFL_BARRIER	(1 << BLKDEV_BARRIER)
-#define BLKDEV_IFL_SECURE	(1 << BLKDEV_SECURE)
-extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *,
-			unsigned long);
+
+#define BLKDEV_DISCARD_SECURE  0x01    /* secure discard */
+
+extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *);
 extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);
 extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
-			sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);
-static inline int sb_issue_discard(struct super_block *sb,
-				   sector_t block, sector_t nr_blocks)
+			sector_t nr_sects, gfp_t gfp_mask);
+static inline int sb_issue_discard(struct super_block *sb, sector_t block,
+		sector_t nr_blocks, gfp_t gfp_mask, unsigned long flags)
 {
-	block <<= (sb->s_blocksize_bits - 9);
-	nr_blocks <<= (sb->s_blocksize_bits - 9);
-	return blkdev_issue_discard(sb->s_bdev, block, nr_blocks, GFP_NOFS,
-				   BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+	return blkdev_issue_discard(sb->s_bdev, block << (sb->s_blocksize_bits - 9),
+				    nr_blocks << (sb->s_blocksize_bits - 9),
+				    gfp_mask, flags);
 }
 
 extern int blk_verify_command(unsigned char *cmd, fmode_t has_write_perm);
@@ -1004,7 +955,7 @@
 	return q->limits.physical_block_size;
 }
 
-static inline int bdev_physical_block_size(struct block_device *bdev)
+static inline unsigned int bdev_physical_block_size(struct block_device *bdev)
 {
 	return queue_physical_block_size(bdev_get_queue(bdev));
 }
@@ -1093,11 +1044,11 @@
 	return q ? q->dma_alignment : 511;
 }
 
-static inline int blk_rq_aligned(struct request_queue *q, void *addr,
+static inline int blk_rq_aligned(struct request_queue *q, unsigned long addr,
 				 unsigned int len)
 {
 	unsigned int alignment = queue_dma_alignment(q) | q->dma_pad_mask;
-	return !((unsigned long)addr & alignment) && !(len & alignment);
+	return !(addr & alignment) && !(len & alignment);
 }
 
 /* assumes size > 256 */
@@ -1127,6 +1078,7 @@
 
 struct work_struct;
 int kblockd_schedule_work(struct request_queue *q, struct work_struct *work);
+int kblockd_schedule_delayed_work(struct request_queue *q, struct delayed_work *dwork, unsigned long delay);
 
 #ifdef CONFIG_BLK_CGROUP
 /*
@@ -1170,6 +1122,24 @@
 }
 #endif
 
+#ifdef CONFIG_BLK_DEV_THROTTLING
+extern int blk_throtl_init(struct request_queue *q);
+extern void blk_throtl_exit(struct request_queue *q);
+extern int blk_throtl_bio(struct request_queue *q, struct bio **bio);
+extern void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay);
+extern void throtl_shutdown_timer_wq(struct request_queue *q);
+#else /* CONFIG_BLK_DEV_THROTTLING */
+static inline int blk_throtl_bio(struct request_queue *q, struct bio **bio)
+{
+	return 0;
+}
+
+static inline int blk_throtl_init(struct request_queue *q) { return 0; }
+static inline int blk_throtl_exit(struct request_queue *q) { return 0; }
+static inline void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay) {}
+static inline void throtl_shutdown_timer_wq(struct request_queue *q) {}
+#endif /* CONFIG_BLK_DEV_THROTTLING */
+
 #define MODULE_ALIAS_BLOCKDEV(major,minor) \
 	MODULE_ALIAS("block-major-" __stringify(major) "-" __stringify(minor))
 #define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \
@@ -1213,8 +1183,13 @@
 extern int blk_integrity_register(struct gendisk *, struct blk_integrity *);
 extern void blk_integrity_unregister(struct gendisk *);
 extern int blk_integrity_compare(struct gendisk *, struct gendisk *);
-extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *);
-extern int blk_rq_count_integrity_sg(struct request *);
+extern int blk_rq_map_integrity_sg(struct request_queue *, struct bio *,
+				   struct scatterlist *);
+extern int blk_rq_count_integrity_sg(struct request_queue *, struct bio *);
+extern int blk_integrity_merge_rq(struct request_queue *, struct request *,
+				  struct request *);
+extern int blk_integrity_merge_bio(struct request_queue *, struct request *,
+				   struct bio *);
 
 static inline
 struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
@@ -1235,16 +1210,32 @@
 	return bio_integrity(rq->bio);
 }
 
+static inline void blk_queue_max_integrity_segments(struct request_queue *q,
+						    unsigned int segs)
+{
+	q->limits.max_integrity_segments = segs;
+}
+
+static inline unsigned short
+queue_max_integrity_segments(struct request_queue *q)
+{
+	return q->limits.max_integrity_segments;
+}
+
 #else /* CONFIG_BLK_DEV_INTEGRITY */
 
 #define blk_integrity_rq(rq)			(0)
-#define blk_rq_count_integrity_sg(a)		(0)
-#define blk_rq_map_integrity_sg(a, b)		(0)
+#define blk_rq_count_integrity_sg(a, b)		(0)
+#define blk_rq_map_integrity_sg(a, b, c)	(0)
 #define bdev_get_integrity(a)			(0)
 #define blk_get_integrity(a)			(0)
 #define blk_integrity_compare(a, b)		(0)
 #define blk_integrity_register(a, b)		(0)
 #define blk_integrity_unregister(a)		do { } while (0);
+#define blk_queue_max_integrity_segments(a, b)	do { } while (0);
+#define queue_max_integrity_segments(a)		(0)
+#define blk_integrity_merge_rq(a, b, c)		(0)
+#define blk_integrity_merge_bio(a, b, c)	(0)
 
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index ec94c12..dd1b25b 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -32,7 +32,6 @@
 	BH_Delay,	/* Buffer is not yet allocated on disk */
 	BH_Boundary,	/* Block is followed by a discontiguity */
 	BH_Write_EIO,	/* I/O error on write */
-	BH_Eopnotsupp,	/* operation not supported (barrier) */
 	BH_Unwritten,	/* Buffer is allocated on disk but not written */
 	BH_Quiet,	/* Buffer Error Prinks to be quiet */
 
@@ -124,7 +123,6 @@
 BUFFER_FNS(Delay, delay)
 BUFFER_FNS(Boundary, boundary)
 BUFFER_FNS(Write_EIO, write_io_error)
-BUFFER_FNS(Eopnotsupp, eopnotsupp)
 BUFFER_FNS(Unwritten, unwritten)
 
 #define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
diff --git a/include/linux/device.h b/include/linux/device.h
index 516feca..dd48953 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -751,4 +751,11 @@
 	MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
 #define MODULE_ALIAS_CHARDEV_MAJOR(major) \
 	MODULE_ALIAS("char-major-" __stringify(major) "-*")
+
+#ifdef CONFIG_SYSFS_DEPRECATED
+extern long sysfs_deprecated;
+#else
+#define sysfs_deprecated 0
+#endif
+
 #endif /* _DEVICE_H_ */
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 0b3518c..d4e02f5 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -48,10 +48,10 @@
  *
  * 0 if lock request was successful
  * -EAGAIN if request would block and is flagged DLM_LKF_NOQUEUE
- * -ENOMEM if there is no memory to process request
- * -EINVAL if there are invalid parameters
  * -DLM_EUNLOCK if unlock request was successful
  * -DLM_ECANCEL if a cancel completed successfully
+ * -EDEADLK if a deadlock was detected
+ * -ETIMEDOUT if the lock request was canceled due to a timeout
  */
 
 #define DLM_SBF_DEMOTED		0x01
diff --git a/include/linux/drbd.h b/include/linux/drbd.h
index 479ee3a..9b2a015 100644
--- a/include/linux/drbd.h
+++ b/include/linux/drbd.h
@@ -53,10 +53,10 @@
 
 
 extern const char *drbd_buildtag(void);
-#define REL_VERSION "8.3.8.1"
+#define REL_VERSION "8.3.9rc2"
 #define API_VERSION 88
 #define PRO_VERSION_MIN 86
-#define PRO_VERSION_MAX 94
+#define PRO_VERSION_MAX 95
 
 
 enum drbd_io_error_p {
@@ -91,6 +91,11 @@
 	ASB_VIOLENTLY
 };
 
+enum drbd_on_no_data {
+	OND_IO_ERROR,
+	OND_SUSPEND_IO
+};
+
 /* KEEP the order, do not delete or insert. Only append. */
 enum drbd_ret_codes {
 	ERR_CODE_BASE		= 100,
@@ -140,6 +145,7 @@
 	ERR_CONNECTED		= 151, /* DRBD 8.3 only */
 	ERR_PERM		= 152,
 	ERR_NEED_APV_93		= 153,
+	ERR_STONITH_AND_PROT_A  = 154,
 
 	/* insert new ones above this line */
 	AFTER_LAST_ERR_CODE
@@ -226,13 +232,17 @@
 		unsigned conn:5 ;   /* 17/32	 cstates */
 		unsigned disk:4 ;   /* 8/16	 from D_DISKLESS to D_UP_TO_DATE */
 		unsigned pdsk:4 ;   /* 8/16	 from D_DISKLESS to D_UP_TO_DATE */
-		unsigned susp:1 ;   /* 2/2	 IO suspended  no/yes */
+		unsigned susp:1 ;   /* 2/2	 IO suspended no/yes (by user) */
 		unsigned aftr_isp:1 ; /* isp .. imposed sync pause */
 		unsigned peer_isp:1 ;
 		unsigned user_isp:1 ;
-		unsigned _pad:11;   /* 0	 unused */
+		unsigned susp_nod:1 ; /* IO suspended because no data */
+		unsigned susp_fen:1 ; /* IO suspended because fence peer handler runs*/
+		unsigned _pad:9;   /* 0	 unused */
 #elif defined(__BIG_ENDIAN_BITFIELD)
-		unsigned _pad:11;   /* 0	 unused */
+		unsigned _pad:9;
+		unsigned susp_fen:1 ;
+		unsigned susp_nod:1 ;
 		unsigned user_isp:1 ;
 		unsigned peer_isp:1 ;
 		unsigned aftr_isp:1 ; /* isp .. imposed sync pause */
@@ -312,6 +322,8 @@
 
 #define DRBD_MAGIC 0x83740267
 #define BE_DRBD_MAGIC __constant_cpu_to_be32(DRBD_MAGIC)
+#define DRBD_MAGIC_BIG 0x835a
+#define BE_DRBD_MAGIC_BIG __constant_cpu_to_be16(DRBD_MAGIC_BIG)
 
 /* these are of type "int" */
 #define DRBD_MD_INDEX_INTERNAL -1
diff --git a/include/linux/drbd_limits.h b/include/linux/drbd_limits.h
index 440b42e..4ac33f3 100644
--- a/include/linux/drbd_limits.h
+++ b/include/linux/drbd_limits.h
@@ -128,26 +128,31 @@
 #define DRBD_AFTER_SB_1P_DEF ASB_DISCONNECT
 #define DRBD_AFTER_SB_2P_DEF ASB_DISCONNECT
 #define DRBD_RR_CONFLICT_DEF ASB_DISCONNECT
+#define DRBD_ON_NO_DATA_DEF OND_IO_ERROR
 
 #define DRBD_MAX_BIO_BVECS_MIN 0
 #define DRBD_MAX_BIO_BVECS_MAX 128
 #define DRBD_MAX_BIO_BVECS_DEF 0
 
-#define DRBD_DP_VOLUME_MIN 4
-#define DRBD_DP_VOLUME_MAX 1048576
-#define DRBD_DP_VOLUME_DEF 16384
+#define DRBD_C_PLAN_AHEAD_MIN  0
+#define DRBD_C_PLAN_AHEAD_MAX  300
+#define DRBD_C_PLAN_AHEAD_DEF  0 /* RS rate controller disabled by default */
 
-#define DRBD_DP_INTERVAL_MIN 1
-#define DRBD_DP_INTERVAL_MAX 600
-#define DRBD_DP_INTERVAL_DEF 5
+#define DRBD_C_DELAY_TARGET_MIN 1
+#define DRBD_C_DELAY_TARGET_MAX 100
+#define DRBD_C_DELAY_TARGET_DEF 10
 
-#define DRBD_RS_THROTTLE_TH_MIN 1
-#define DRBD_RS_THROTTLE_TH_MAX 600
-#define DRBD_RS_THROTTLE_TH_DEF 20
+#define DRBD_C_FILL_TARGET_MIN 0
+#define DRBD_C_FILL_TARGET_MAX (1<<20) /* 500MByte in sec */
+#define DRBD_C_FILL_TARGET_DEF 0 /* By default disabled -> controlled by delay_target */
 
-#define DRBD_RS_HOLD_OFF_TH_MIN 1
-#define DRBD_RS_HOLD_OFF_TH_MAX 6000
-#define DRBD_RS_HOLD_OFF_TH_DEF 100
+#define DRBD_C_MAX_RATE_MIN     250 /* kByte/sec */
+#define DRBD_C_MAX_RATE_MAX     (4 << 20)
+#define DRBD_C_MAX_RATE_DEF     102400
+
+#define DRBD_C_MIN_RATE_MIN     0 /* kByte/sec */
+#define DRBD_C_MIN_RATE_MAX     (4 << 20)
+#define DRBD_C_MIN_RATE_DEF     4096
 
 #undef RANGE
 #endif
diff --git a/include/linux/drbd_nl.h b/include/linux/drbd_nl.h
index 5f04281..ade9110 100644
--- a/include/linux/drbd_nl.h
+++ b/include/linux/drbd_nl.h
@@ -87,6 +87,12 @@
 	NL_STRING(      51,     T_MAY_IGNORE,   cpu_mask,       32)
 	NL_STRING(	64,	T_MAY_IGNORE,	csums_alg,	SHARED_SECRET_MAX)
 	NL_BIT(         65,     T_MAY_IGNORE,   use_rle)
+	NL_INTEGER(	75,	T_MAY_IGNORE,	on_no_data)
+	NL_INTEGER(	76,	T_MAY_IGNORE,	c_plan_ahead)
+	NL_INTEGER(     77,	T_MAY_IGNORE,	c_delay_target)
+	NL_INTEGER(     78,	T_MAY_IGNORE,	c_fill_target)
+	NL_INTEGER(     79,	T_MAY_IGNORE,	c_max_rate)
+	NL_INTEGER(     80,	T_MAY_IGNORE,	c_min_rate)
 )
 
 NL_PACKET(invalidate, 9, )
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index bef3cda..a90b389 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -83,7 +83,7 @@
 
 #define dynamic_pr_debug(fmt, ...)					\
 	do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
-#define dynamic_dev_dbg(dev, format, ...)				\
+#define dynamic_dev_dbg(dev, fmt, ...)					\
 	do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0)
 #endif
 
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 4fd978e..80a0ece 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -122,6 +122,8 @@
 extern int elv_set_request(struct request_queue *, struct request *, gfp_t);
 extern void elv_put_request(struct request_queue *, struct request *);
 extern void elv_drain_elevator(struct request_queue *);
+extern void elv_quiesce_start(struct request_queue *);
+extern void elv_quiesce_end(struct request_queue *);
 
 /*
  * io scheduler registration
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7d6f18f..4f34ff6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -135,12 +135,12 @@
  *			immediately after submission. The write equivalent
  *			of READ_SYNC.
  * WRITE_ODIRECT_PLUG	Special case write for O_DIRECT only.
- * WRITE_BARRIER	Like WRITE_SYNC, but tells the block layer that all
- *			previously submitted writes must be safely on storage
- *			before this one is started. Also guarantees that when
- *			this write is complete, it itself is also safely on
- *			storage. Prevents reordering of writes on both sides
- *			of this IO.
+ * WRITE_FLUSH		Like WRITE_SYNC but with preceding cache flush.
+ * WRITE_FUA		Like WRITE_SYNC but data is guaranteed to be on
+ *			non-volatile media on completion.
+ * WRITE_FLUSH_FUA	Combination of WRITE_FLUSH and FUA. The IO is preceded
+ *			by a cache flush and data is guaranteed to be on
+ *			non-volatile media on completion.
  *
  */
 #define RW_MASK			REQ_WRITE
@@ -156,16 +156,12 @@
 #define WRITE_SYNC		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG)
 #define WRITE_ODIRECT_PLUG	(WRITE | REQ_SYNC)
 #define WRITE_META		(WRITE | REQ_META)
-#define WRITE_BARRIER		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \
-				 REQ_HARDBARRIER)
-
-/*
- * These aren't really reads or writes, they pass down information about
- * parts of device that are now unused by the file system.
- */
-#define DISCARD_NOBARRIER	(WRITE | REQ_DISCARD)
-#define DISCARD_BARRIER		(WRITE | REQ_DISCARD | REQ_HARDBARRIER)
-#define DISCARD_SECURE		(DISCARD_NOBARRIER | REQ_SECURE)
+#define WRITE_FLUSH		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \
+				 REQ_FLUSH)
+#define WRITE_FUA		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \
+				 REQ_FUA)
+#define WRITE_FLUSH_FUA		(WRITE | REQ_SYNC | REQ_NOIDLE | REQ_UNPLUG | \
+				 REQ_FLUSH | REQ_FUA)
 
 #define SEL_IN		1
 #define SEL_OUT		2
@@ -1093,10 +1089,6 @@
 
 #include <linux/fcntl.h>
 
-/* temporary stubs for BKL removal */
-#define lock_flocks() lock_kernel()
-#define unlock_flocks() unlock_kernel()
-
 extern void send_sigio(struct fown_struct *fown, int fd, int band);
 
 #ifdef CONFIG_FILE_LOCKING
@@ -1135,6 +1127,8 @@
 extern int lease_modify(struct file_lock **, int);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
+extern void lock_flocks(void);
+extern void unlock_flocks(void);
 #else /* !CONFIG_FILE_LOCKING */
 static inline int fcntl_getlk(struct file *file, struct flock __user *user)
 {
@@ -1277,6 +1271,14 @@
 	return 1;
 }
 
+static inline void lock_flocks(void)
+{
+}
+
+static inline void unlock_flocks(void)
+{
+}
+
 #endif /* !CONFIG_FILE_LOCKING */
 
 
@@ -2456,6 +2458,7 @@
 	.release = simple_attr_release,					\
 	.read	 = simple_attr_read,					\
 	.write	 = simple_attr_write,					\
+	.llseek	 = generic_file_llseek,					\
 };
 
 static inline void __attribute__((format(printf, 1, 2)))
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 28e33fe..4eb56ed 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -58,17 +58,35 @@
 	FSL_USB2_PHY_SERIAL,
 };
 
+struct clk;
+struct platform_device;
+
 struct fsl_usb2_platform_data {
 	/* board specific information */
 	enum fsl_usb2_operating_modes	operating_mode;
 	enum fsl_usb2_phy_modes		phy_mode;
 	unsigned int			port_enables;
+	unsigned int			workaround;
+
+	int		(*init)(struct platform_device *);
+	void		(*exit)(struct platform_device *);
+	void __iomem	*regs;		/* ioremap'd register base */
+	struct clk	*clk;
+	unsigned	big_endian_mmio:1;
+	unsigned	big_endian_desc:1;
+	unsigned	es:1;		/* need USBMODE:ES */
+	unsigned	le_setup_buf:1;
+	unsigned	have_sysif_regs:1;
+	unsigned	invert_drvvbus:1;
+	unsigned	invert_pwr_fault:1;
 };
 
 /* Flags in fsl_usb2_mph_platform_data */
 #define FSL_USB2_PORT0_ENABLED	0x00000001
 #define FSL_USB2_PORT1_ENABLED	0x00000002
 
+#define FLS_USB2_WORKAROUND_ENGCM09152	(1 << 0)
+
 struct spi_device;
 
 struct fsl_spi_platform_data {
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index af3f06b..557c392 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 #include <linux/rcupdate.h>
+#include <linux/slab.h>
 
 #ifdef CONFIG_BLOCK
 
@@ -86,7 +87,15 @@
 	unsigned long io_ticks;
 	unsigned long time_in_queue;
 };
-	
+
+#define PARTITION_META_INFO_VOLNAMELTH	64
+#define PARTITION_META_INFO_UUIDLTH	16
+
+struct partition_meta_info {
+	u8 uuid[PARTITION_META_INFO_UUIDLTH];	/* always big endian */
+	u8 volname[PARTITION_META_INFO_VOLNAMELTH];
+};
+
 struct hd_struct {
 	sector_t start_sect;
 	sector_t nr_sects;
@@ -95,6 +104,7 @@
 	struct device __dev;
 	struct kobject *holder_dir;
 	int policy, partno;
+	struct partition_meta_info *info;
 #ifdef CONFIG_FAIL_MAKE_REQUEST
 	int make_it_fail;
 #endif
@@ -130,6 +140,7 @@
 	struct rcu_head rcu_head;
 	int len;
 	struct hd_struct __rcu *last_lookup;
+	struct gendisk *disk;
 	struct hd_struct __rcu *part[];
 };
 
@@ -181,6 +192,30 @@
 	return NULL;
 }
 
+static inline void part_pack_uuid(const u8 *uuid_str, u8 *to)
+{
+	int i;
+	for (i = 0; i < 16; ++i) {
+		*to++ = (hex_to_bin(*uuid_str) << 4) |
+			(hex_to_bin(*(uuid_str + 1)));
+		uuid_str += 2;
+		switch (i) {
+		case 3:
+		case 5:
+		case 7:
+		case 9:
+			uuid_str++;
+			continue;
+		}
+	}
+}
+
+static inline char *part_unpack_uuid(const u8 *uuid, char *out)
+{
+	sprintf(out, "%pU", uuid);
+	return out;
+}
+
 static inline int disk_max_parts(struct gendisk *disk)
 {
 	if (disk->flags & GENHD_FL_EXT_DEVT)
@@ -342,6 +377,19 @@
 	return part->in_flight[0] + part->in_flight[1];
 }
 
+static inline struct partition_meta_info *alloc_part_info(struct gendisk *disk)
+{
+	if (disk)
+		return kzalloc_node(sizeof(struct partition_meta_info),
+				    GFP_KERNEL, disk->node_id);
+	return kzalloc(sizeof(struct partition_meta_info), GFP_KERNEL);
+}
+
+static inline void free_part_info(struct hd_struct *part)
+{
+	kfree(part->info);
+}
+
 /* block/blk-core.c */
 extern void part_round_stats(int cpu, struct hd_struct *part);
 
@@ -533,7 +581,9 @@
 extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
 extern struct hd_struct * __must_check add_partition(struct gendisk *disk,
 						     int partno, sector_t start,
-						     sector_t len, int flags);
+						     sector_t len, int flags,
+						     struct partition_meta_info
+						       *info);
 extern void delete_partition(struct gendisk *, int);
 extern void printk_all_partitions(void);
 
diff --git a/include/linux/init.h b/include/linux/init.h
index de99430..577671c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -46,16 +46,23 @@
 #define __exitdata	__section(.exit.data)
 #define __exit_call	__used __section(.exitcall.exit)
 
-/* modpost check for section mismatches during the kernel build.
+/*
+ * modpost check for section mismatches during the kernel build.
  * A section mismatch happens when there are references from a
  * code or data section to an init section (both code or data).
  * The init sections are (for most archs) discarded by the kernel
  * when early init has completed so all such references are potential bugs.
  * For exit sections the same issue exists.
+ *
  * The following markers are used for the cases where the reference to
  * the *init / *exit section (code or data) is valid and will teach
- * modpost not to issue a warning.
- * The markers follow same syntax rules as __init / __initdata. */
+ * modpost not to issue a warning.  Intended semantics is that a code or
+ * data tagged __ref* can reference code or data from init section without
+ * producing a warning (of course, no warning does not mean code is
+ * correct, so optimally document why the __ref is needed and why it's OK).
+ *
+ * The markers follow same syntax rules as __init / __initdata.
+ */
 #define __ref            __section(.ref.text) noinline
 #define __refdata        __section(.ref.data)
 #define __refconst       __section(.ref.rodata)
diff --git a/include/linux/kdb.h b/include/linux/kdb.h
index ea6e524..aadff7c 100644
--- a/include/linux/kdb.h
+++ b/include/linux/kdb.h
@@ -28,6 +28,41 @@
 extern int kdb_initial_cpu;
 extern atomic_t kdb_event;
 
+/* Types and messages used for dynamically added kdb shell commands */
+
+#define KDB_MAXARGS    16 /* Maximum number of arguments to a function  */
+
+typedef enum {
+	KDB_REPEAT_NONE = 0,	/* Do not repeat this command */
+	KDB_REPEAT_NO_ARGS,	/* Repeat the command without arguments */
+	KDB_REPEAT_WITH_ARGS,	/* Repeat the command including its arguments */
+} kdb_repeat_t;
+
+typedef int (*kdb_func_t)(int, const char **);
+
+/* KDB return codes from a command or internal kdb function */
+#define KDB_NOTFOUND	(-1)
+#define KDB_ARGCOUNT	(-2)
+#define KDB_BADWIDTH	(-3)
+#define KDB_BADRADIX	(-4)
+#define KDB_NOTENV	(-5)
+#define KDB_NOENVVALUE	(-6)
+#define KDB_NOTIMP	(-7)
+#define KDB_ENVFULL	(-8)
+#define KDB_ENVBUFFULL	(-9)
+#define KDB_TOOMANYBPT	(-10)
+#define KDB_TOOMANYDBREGS (-11)
+#define KDB_DUPBPT	(-12)
+#define KDB_BPTNOTFOUND	(-13)
+#define KDB_BADMODE	(-14)
+#define KDB_BADINT	(-15)
+#define KDB_INVADDRFMT  (-16)
+#define KDB_BADREG      (-17)
+#define KDB_BADCPUNUM   (-18)
+#define KDB_BADLENGTH	(-19)
+#define KDB_NOBP	(-20)
+#define KDB_BADADDR	(-21)
+
 /*
  * kdb_diemsg
  *
@@ -104,10 +139,26 @@
 
 /* kdb access to register set for stack dumping */
 extern struct pt_regs *kdb_current_regs;
+#ifdef CONFIG_KALLSYMS
+extern const char *kdb_walk_kallsyms(loff_t *pos);
+#else /* ! CONFIG_KALLSYMS */
+static inline const char *kdb_walk_kallsyms(loff_t *pos)
+{
+	return NULL;
+}
+#endif /* ! CONFIG_KALLSYMS */
 
+/* Dynamic kdb shell command registration */
+extern int kdb_register(char *, kdb_func_t, char *, char *, short);
+extern int kdb_register_repeat(char *, kdb_func_t, char *, char *,
+			       short, kdb_repeat_t);
+extern int kdb_unregister(char *);
 #else /* ! CONFIG_KGDB_KDB */
 #define kdb_printf(...)
 #define kdb_init(x)
+#define kdb_register(...)
+#define kdb_register_repeat(...)
+#define kdb_uregister(x)
 #endif	/* CONFIG_KGDB_KDB */
 enum {
 	KDB_NOT_INITIALIZED,
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 1759ba5..edef168 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -652,6 +652,16 @@
 	_max1 > _max2 ? _max1 : _max2; })
 
 /**
+ * min_not_zero - return the minimum that is _not_ zero, unless both are zero
+ * @x: value1
+ * @y: value2
+ */
+#define min_not_zero(x, y) ({			\
+	typeof(x) __x = (x);			\
+	typeof(y) __y = (y);			\
+	__x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); })
+
+/**
  * clamp - return a value clamped to a given range with strict typechecking
  * @val: current value
  * @min: minimum allowable value
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 7950a37..8f6d121 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -191,6 +191,8 @@
 }
 
 extern struct kobject *kset_find_obj(struct kset *, const char *);
+extern struct kobject *kset_find_obj_hinted(struct kset *, const char *,
+						struct kobject *);
 
 /* The global /sys/kernel/ kobject for people to chain off of */
 extern struct kobject *kernel_kobj;
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 85582e1..06c1fa0 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -23,6 +23,8 @@
 struct memory_block {
 	unsigned long phys_index;
 	unsigned long state;
+	int section_count;
+
 	/*
 	 * This serializes all state change requests.  It isn't
 	 * held during creation because the control files are
@@ -113,6 +115,8 @@
 extern int remove_memory_block(unsigned long, struct mem_section *, int);
 extern int memory_notify(unsigned long val, void *v);
 extern int memory_isolate_notify(unsigned long val, void *v);
+extern struct memory_block *find_memory_block_hinted(struct mem_section *,
+							struct memory_block *);
 extern struct memory_block *find_memory_block(struct mem_section *);
 #define CONFIG_MEM_BLOCK_SIZE	(PAGES_PER_SECTION<<PAGE_SHIFT)
 enum mem_add_context { BOOT, HOTPLUG };
diff --git a/include/linux/mtio.h b/include/linux/mtio.h
index ef01d6a..8f82575 100644
--- a/include/linux/mtio.h
+++ b/include/linux/mtio.h
@@ -63,6 +63,7 @@
 #define MTCOMPRESSION 32/* control compression with SCSI mode page 15 */
 #define MTSETPART 33	/* Change the active tape partition */
 #define MTMKPART  34	/* Format the tape with one or two partitions */
+#define MTWEOFI	35	/* write an end-of-file record (mark) in immediate mode */
 
 /* structure for MTIOCGET - mag tape get status command */
 
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 4522aed..ef66306 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -241,34 +241,6 @@
 /* linux/fs/ncpfs/ncplib_kernel.c */
 int ncp_make_closed(struct inode *);
 
-#define ncp_namespace(i)	(NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
-
-static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
-{
-#ifdef CONFIG_NCPFS_SMALLDOS
-	int ns = ncp_namespace(i);
-
-	if ((ns == NW_NS_DOS)
-#ifdef CONFIG_NCPFS_OS2_NS
-		|| ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
-#endif /* CONFIG_NCPFS_OS2_NS */
-				)
-		return 0;
-#endif /* CONFIG_NCPFS_SMALLDOS */
-	return 1;
-}
-
-#define ncp_preserve_case(i)	(ncp_namespace(i) != NW_NS_DOS)
-
-static inline int ncp_case_sensitive(struct inode *i)
-{
-#ifdef CONFIG_NCPFS_NFS_NS
-	return ncp_namespace(i) == NW_NS_NFS;
-#else
-	return 0;
-#endif	/* CONFIG_NCPFS_NFS_NS */
-} 
-
 #endif				/* __KERNEL__ */
 
 #endif				/* _LINUX_NCP_FS_H */
diff --git a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h
index 8da05bc..d64b0e8 100644
--- a/include/linux/ncp_fs_sb.h
+++ b/include/linux/ncp_fs_sb.h
@@ -62,6 +62,7 @@
 	int ncp_reply_size;
 
 	int root_setuped;
+	struct mutex root_setup_lock;
 
 	/* info for packet signing */
 	int sign_wanted;	/* 1=Server needs signed packets */
@@ -81,13 +82,14 @@
 		size_t	len;
 		void*	data;
 	} priv;
+	struct rw_semaphore auth_rwsem;
 
 	/* nls info: codepage for volume and charset for I/O */
 	struct nls_table *nls_vol;
 	struct nls_table *nls_io;
 
 	/* maximum age in jiffies */
-	int dentry_ttl;
+	atomic_t dentry_ttl;
 
 	/* miscellaneous */
 	unsigned int flags;
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index dad3073..e4471b2 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -743,6 +743,7 @@
 #define PCI_DEVICE_ID_HP_CISSC		0x3230
 #define PCI_DEVICE_ID_HP_CISSD		0x3238
 #define PCI_DEVICE_ID_HP_CISSE		0x323a
+#define PCI_DEVICE_ID_HP_CISSF		0x323b
 #define PCI_DEVICE_ID_HP_ZX2_IOC	0x4031
 
 #define PCI_VENDOR_ID_PCTECH		0x1042
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
index 27ef6b1..018db9a 100644
--- a/include/linux/percpu-defs.h
+++ b/include/linux/percpu-defs.h
@@ -148,6 +148,18 @@
 	DEFINE_PER_CPU_SECTION(type, name, "..readmostly")
 
 /*
+ * Declaration/definition used for large per-CPU variables that must be
+ * aligned to something larger than the pagesize.
+ */
+#define DECLARE_PER_CPU_MULTIPAGE_ALIGNED(type, name, size)		\
+	DECLARE_PER_CPU_SECTION(type, name, "..page_aligned")		\
+	__aligned(size)
+
+#define DEFINE_PER_CPU_MULTIPAGE_ALIGNED(type, name, size)		\
+	DEFINE_PER_CPU_SECTION(type, name, "..page_aligned")		\
+	__aligned(size)
+
+/*
  * Intermodule exports for per-CPU variables.  sparse forgets about
  * address space across EXPORT_SYMBOL(), change EXPORT_SYMBOL() to
  * noop if __CHECKER__.
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 0eb5083..5095b83 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -48,10 +48,8 @@
 	preempt_enable();				\
 } while (0)
 
-#ifdef CONFIG_SMP
-
 /* minimum unit size, also is the maximum supported allocation size */
-#define PCPU_MIN_UNIT_SIZE		PFN_ALIGN(64 << 10)
+#define PCPU_MIN_UNIT_SIZE		PFN_ALIGN(32 << 10)
 
 /*
  * Percpu allocator can serve percpu allocations before slab is
@@ -146,37 +144,20 @@
  * dynamically allocated. Non-atomic access to the current CPU's
  * version should probably be combined with get_cpu()/put_cpu().
  */
+#ifdef CONFIG_SMP
 #define per_cpu_ptr(ptr, cpu)	SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu)))
+#else
+#define per_cpu_ptr(ptr, cpu)	({ (void)(cpu); VERIFY_PERCPU_PTR((ptr)); })
+#endif
 
 extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align);
 extern bool is_kernel_percpu_address(unsigned long addr);
 
-#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
+#if !defined(CONFIG_SMP) || !defined(CONFIG_HAVE_SETUP_PER_CPU_AREA)
 extern void __init setup_per_cpu_areas(void);
 #endif
 extern void __init percpu_init_late(void);
 
-#else /* CONFIG_SMP */
-
-#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); VERIFY_PERCPU_PTR((ptr)); })
-
-/* can't distinguish from other static vars, always false */
-static inline bool is_kernel_percpu_address(unsigned long addr)
-{
-	return false;
-}
-
-static inline void __init setup_per_cpu_areas(void) { }
-
-static inline void __init percpu_init_late(void) { }
-
-static inline void *pcpu_lpage_remapped(void *kaddr)
-{
-	return NULL;
-}
-
-#endif /* CONFIG_SMP */
-
 extern void __percpu *__alloc_percpu(size_t size, size_t align);
 extern void free_percpu(void __percpu *__pdata);
 extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index d7ecad0..2e700ec 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -138,6 +138,9 @@
 					struct resource *res, unsigned int n_res,
 					const void *data, size_t size);
 
+extern const struct dev_pm_ops * platform_bus_get_pm_ops(void);
+extern void platform_bus_set_pm_ops(const struct dev_pm_ops *pm);
+
 /* early platform driver interface */
 struct early_platform_driver {
 	const char *class_str;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 0383601..56154bb 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -336,6 +336,9 @@
 extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
 					 void __user *buffer,
 					 size_t *lenp, loff_t *ppos);
+#else
+/* Avoid need for ifdefs elsewhere in the code */
+enum { sysctl_hung_task_timeout_secs = 0 };
 #endif
 
 /* Attach to any functions which should be ignored in wchan output. */
diff --git a/include/linux/selection.h b/include/linux/selection.h
index 8cdaa11..85193aa 100644
--- a/include/linux/selection.h
+++ b/include/linux/selection.h
@@ -39,5 +39,6 @@
 
 extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org);
 extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
+extern void vcs_scr_updated(struct vc_data *vc);
 
 #endif
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 7638dea..97f5b45 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -35,6 +35,8 @@
 	void		(*set_termios)(struct uart_port *,
 			               struct ktermios *new,
 			               struct ktermios *old);
+	void		(*pm)(struct uart_port *, unsigned int state,
+			      unsigned old);
 };
 
 /*
@@ -76,5 +78,11 @@
 extern int setup_early_serial8250_console(char *cmdline);
 extern void serial8250_do_set_termios(struct uart_port *port,
 		struct ktermios *termios, struct ktermios *old);
+extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
+			     unsigned int oldstate);
+
+extern void serial8250_set_isa_configurator(void (*v)
+					(int port, struct uart_port *up,
+						unsigned short *capabilities));
 
 #endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 563e234..99e5994 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -289,6 +289,8 @@
 	void			(*set_termios)(struct uart_port *,
 				               struct ktermios *new,
 				               struct ktermios *old);
+	void			(*pm)(struct uart_port *, unsigned int state,
+				      unsigned int old);
 	unsigned int		irq;			/* irq number */
 	unsigned long		irqflags;		/* irq flags  */
 	unsigned int		uartclk;		/* base uart clock */
@@ -411,6 +413,14 @@
 				unsigned int max);
 unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud);
 
+/* Base timer interval for polling */
+static inline int uart_poll_timeout(struct uart_port *port)
+{
+	int timeout = port->timeout;
+
+	return timeout > 6 ? (timeout / 2 - 2) : 1;
+}
+
 /*
  * Console helpers.
  */
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
index 2ea1dd1..291f721 100644
--- a/include/linux/smp_lock.h
+++ b/include/linux/smp_lock.h
@@ -54,12 +54,15 @@
 
 #else
 
+#ifdef CONFIG_BKL /* provoke build bug if not set */
 #define lock_kernel()
 #define unlock_kernel()
-#define release_kernel_lock(task)		do { } while(0)
 #define cycle_kernel_lock()			do { } while(0)
-#define reacquire_kernel_lock(task)		0
 #define kernel_locked()				1
+#endif /* CONFIG_BKL */
+
+#define release_kernel_lock(task)		do { } while(0)
+#define reacquire_kernel_lock(task)		0
 
 #endif /* CONFIG_LOCK_KERNEL */
 #endif /* __LINUX_SMPLOCK_H */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 67d64e6..86be0cd 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -256,6 +256,7 @@
 struct tty_struct {
 	int	magic;
 	struct kref kref;
+	struct device *dev;
 	struct tty_driver *driver;
 	const struct tty_operations *ops;
 	int index;
@@ -465,7 +466,7 @@
 extern struct tty_struct *get_current_tty(void);
 extern void tty_default_fops(struct file_operations *fops);
 extern struct tty_struct *alloc_tty_struct(void);
-extern void tty_add_file(struct tty_struct *tty, struct file *file);
+extern int tty_add_file(struct tty_struct *tty, struct file *file);
 extern void free_tty_struct(struct tty_struct *tty);
 extern void initialize_tty_struct(struct tty_struct *tty,
 		struct tty_driver *driver, int idx);
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index b086779..db2d227 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -224,6 +224,12 @@
  *	unless the tty also has a valid tty->termiox pointer.
  *
  *	Optional: Called under the termios lock
+ *
+ * int (*get_icount)(struct tty_struct *tty, struct serial_icounter *icount);
+ *
+ *	Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel
+ *	structure to complete. This method is optional and will only be called
+ *	if provided (otherwise EINVAL will be returned).
  */
 
 #include <linux/fs.h>
@@ -232,6 +238,7 @@
 
 struct tty_struct;
 struct tty_driver;
+struct serial_icounter_struct;
 
 struct tty_operations {
 	struct tty_struct * (*lookup)(struct tty_driver *driver,
@@ -268,6 +275,8 @@
 			unsigned int set, unsigned int clear);
 	int (*resize)(struct tty_struct *tty, struct winsize *ws);
 	int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
+	int (*get_icount)(struct tty_struct *tty,
+				struct serial_icounter_struct *icount);
 #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);
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
index 5dcc9ff..d6188e5 100644
--- a/include/linux/uio_driver.h
+++ b/include/linux/uio_driver.h
@@ -108,7 +108,7 @@
 
 /* defines for uio_info->irq */
 #define UIO_IRQ_CUSTOM	-1
-#define UIO_IRQ_NONE	-2
+#define UIO_IRQ_NONE	0
 
 /* defines for uio_mem->memtype */
 #define UIO_MEM_NONE	0
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
index c117a68..5e86dc7 100644
--- a/include/linux/usb/cdc.h
+++ b/include/linux/usb/cdc.h
@@ -32,6 +32,8 @@
 
 #define USB_CDC_PROTO_EEM			7
 
+#define USB_CDC_NCM_PROTO_NTB			1
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -274,13 +276,13 @@
 /*
  * Class Specific structures and constants
  *
- * CDC NCM parameter structure, CDC NCM subclass 6.2.1
+ * CDC NCM NTB parameters structure, CDC NCM subclass 6.2.1
  *
  */
 
-struct usb_cdc_ncm_ntb_parameter {
+struct usb_cdc_ncm_ntb_parameters {
 	__le16	wLength;
-	__le16	bmNtbFormatSupported;
+	__le16	bmNtbFormatsSupported;
 	__le32	dwNtbInMaxSize;
 	__le16	wNdpInDivisor;
 	__le16	wNdpInPayloadRemainder;
@@ -297,8 +299,8 @@
  * CDC NCM transfer headers, CDC NCM subclass 3.2
  */
 
-#define NCM_NTH16_SIGN		0x484D434E /* NCMH */
-#define NCM_NTH32_SIGN		0x686D636E /* ncmh */
+#define USB_CDC_NCM_NTH16_SIGN		0x484D434E /* NCMH */
+#define USB_CDC_NCM_NTH32_SIGN		0x686D636E /* ncmh */
 
 struct usb_cdc_ncm_nth16 {
 	__le32	dwSignature;
@@ -320,25 +322,78 @@
  * CDC NCM datagram pointers, CDC NCM subclass 3.3
  */
 
-#define NCM_NDP16_CRC_SIGN	0x314D434E /* NCM1 */
-#define NCM_NDP16_NOCRC_SIGN	0x304D434E /* NCM0 */
-#define NCM_NDP32_CRC_SIGN	0x316D636E /* ncm1 */
-#define NCM_NDP32_NOCRC_SIGN	0x306D636E /* ncm0 */
+#define USB_CDC_NCM_NDP16_CRC_SIGN	0x314D434E /* NCM1 */
+#define USB_CDC_NCM_NDP16_NOCRC_SIGN	0x304D434E /* NCM0 */
+#define USB_CDC_NCM_NDP32_CRC_SIGN	0x316D636E /* ncm1 */
+#define USB_CDC_NCM_NDP32_NOCRC_SIGN	0x306D636E /* ncm0 */
 
+/* 16-bit NCM Datagram Pointer Entry */
+struct usb_cdc_ncm_dpe16 {
+	__le16	wDatagramIndex;
+	__le16	wDatagramLength;
+} __attribute__((__packed__));
+
+/* 16-bit NCM Datagram Pointer Table */
 struct usb_cdc_ncm_ndp16 {
 	__le32	dwSignature;
 	__le16	wLength;
 	__le16	wNextFpIndex;
-	__u8	data[0];
+	struct	usb_cdc_ncm_dpe16 dpe16[0];
 } __attribute__ ((packed));
 
+/* 32-bit NCM Datagram Pointer Entry */
+struct usb_cdc_ncm_dpe32 {
+	__le32	dwDatagramIndex;
+	__le32	dwDatagramLength;
+} __attribute__((__packed__));
+
+/* 32-bit NCM Datagram Pointer Table */
 struct usb_cdc_ncm_ndp32 {
 	__le32	dwSignature;
 	__le16	wLength;
 	__le16	wReserved6;
-	__le32	dwNextFpIndex;
+	__le32	dwNextNdpIndex;
 	__le32	dwReserved12;
-	__u8	data[0];
+	struct	usb_cdc_ncm_dpe32 dpe32[0];
 } __attribute__ ((packed));
 
+/* CDC NCM subclass 3.2.1 and 3.2.2 */
+#define USB_CDC_NCM_NDP16_INDEX_MIN			0x000C
+#define USB_CDC_NCM_NDP32_INDEX_MIN			0x0010
+
+/* CDC NCM subclass 3.3.3 Datagram Formatting */
+#define USB_CDC_NCM_DATAGRAM_FORMAT_CRC			0x30
+#define USB_CDC_NCM_DATAGRAM_FORMAT_NOCRC		0X31
+
+/* CDC NCM subclass 4.2 NCM Communications Interface Protocol Code */
+#define USB_CDC_NCM_PROTO_CODE_NO_ENCAP_COMMANDS	0x00
+#define USB_CDC_NCM_PROTO_CODE_EXTERN_PROTO		0xFE
+
+/* CDC NCM subclass 5.2.1 NCM Functional Descriptor, bmNetworkCapabilities */
+#define USB_CDC_NCM_NCAP_ETH_FILTER			(1 << 0)
+#define USB_CDC_NCM_NCAP_NET_ADDRESS			(1 << 1)
+#define USB_CDC_NCM_NCAP_ENCAP_COMMAND			(1 << 2)
+#define USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE		(1 << 3)
+#define USB_CDC_NCM_NCAP_CRC_MODE			(1 << 4)
+
+/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
+#define USB_CDC_NCM_NTB16_SUPPORTED			(1 << 0)
+#define USB_CDC_NCM_NTB32_SUPPORTED			(1 << 1)
+
+/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
+#define USB_CDC_NCM_NDP_ALIGN_MIN_SIZE			0x04
+#define USB_CDC_NCM_NTB_MAX_LENGTH			0x1C
+
+/* CDC NCM subclass 6.2.5 SetNtbFormat */
+#define USB_CDC_NCM_NTB16_FORMAT			0x00
+#define USB_CDC_NCM_NTB32_FORMAT			0x01
+
+/* CDC NCM subclass 6.2.7 SetNtbInputSize */
+#define USB_CDC_NCM_NTB_MIN_IN_SIZE			2048
+#define USB_CDC_NCM_NTB_MIN_OUT_SIZE			2048
+
+/* CDC NCM subclass 6.2.11 SetCrcMode */
+#define USB_CDC_NCM_CRC_NOT_APPENDED			0x00
+#define USB_CDC_NCM_CRC_APPENDED			0x01
+
 #endif /* __LINUX_USB_CDC_H */
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index da2ed77..f917bbb 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -123,8 +123,23 @@
 #define USB_DEVICE_A_ALT_HNP_SUPPORT	5	/* (otg) other RH port does */
 #define USB_DEVICE_DEBUG_MODE		6	/* (special devices only) */
 
+/*
+ * New Feature Selectors as added by USB 3.0
+ * See USB 3.0 spec Table 9-6
+ */
+#define USB_DEVICE_U1_ENABLE	48	/* dev may initiate U1 transition */
+#define USB_DEVICE_U2_ENABLE	49	/* dev may initiate U2 transition */
+#define USB_DEVICE_LTM_ENABLE	50	/* dev may send LTM */
+#define USB_INTRF_FUNC_SUSPEND	0	/* function suspend */
+
+#define USB_INTR_FUNC_SUSPEND_OPT_MASK	0xFF00
+
 #define USB_ENDPOINT_HALT		0	/* IN/OUT will STALL */
 
+/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
+#define USB_DEV_STAT_U1_ENABLED		2	/* transition into U1 state */
+#define USB_DEV_STAT_U2_ENABLED		3	/* transition into U2 state */
+#define USB_DEV_STAT_LTM_ENABLED	4	/* Latency tolerance messages */
 
 /**
  * struct usb_ctrlrequest - SETUP data for a USB device control request
@@ -675,6 +690,7 @@
 	__u8  bNumDeviceCaps;
 } __attribute__((packed));
 
+#define USB_DT_BOS_SIZE		5
 /*-------------------------------------------------------------------------*/
 
 /* USB_DT_DEVICE_CAPABILITY:  grouped with BOS */
@@ -712,16 +728,56 @@
 	__u8  bReserved;
 } __attribute__((packed));
 
+/* USB 2.0 Extension descriptor */
 #define	USB_CAP_TYPE_EXT		2
 
 struct usb_ext_cap_descriptor {		/* Link Power Management */
 	__u8  bLength;
 	__u8  bDescriptorType;
 	__u8  bDevCapabilityType;
-	__u8  bmAttributes;
+	__le32 bmAttributes;
 #define USB_LPM_SUPPORT			(1 << 1)	/* supports LPM */
 } __attribute__((packed));
 
+#define USB_DT_USB_EXT_CAP_SIZE	7
+
+/*
+ * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB
+ * specific device level capabilities
+ */
+#define		USB_SS_CAP_TYPE		3
+struct usb_ss_cap_descriptor {		/* Link Power Management */
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u8  bDevCapabilityType;
+	__u8  bmAttributes;
+#define USB_LTM_SUPPORT			(1 << 1) /* supports LTM */
+	__le16 wSpeedSupported;
+#define USB_LOW_SPEED_OPERATION		(1)	 /* Low speed operation */
+#define USB_FULL_SPEED_OPERATION	(1 << 1) /* Full speed operation */
+#define USB_HIGH_SPEED_OPERATION	(1 << 2) /* High speed operation */
+#define USB_5GBPS_OPERATION		(1 << 3) /* Operation at 5Gbps */
+	__u8  bFunctionalitySupport;
+	__u8  bU1devExitLat;
+	__le16 bU2DevExitLat;
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CAP_SIZE	10
+
+/*
+ * Container ID Capability descriptor: Defines the instance unique ID used to
+ * identify the instance across all operating modes
+ */
+#define	CONTAINER_ID_TYPE	4
+struct usb_ss_container_id_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u8  bDevCapabilityType;
+	__u8  bReserved;
+	__u8  ContainerID[16]; /* 128-bit number */
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CONTN_ID_SIZE	20
 /*-------------------------------------------------------------------------*/
 
 /* USB_DT_WIRELESS_ENDPOINT_COMP:  companion descriptor associated with
@@ -808,4 +864,14 @@
 	 */
 };
 
+/*-------------------------------------------------------------------------*/
+
+/*
+ * As per USB compliance update, a device that is actively drawing
+ * more than 100mA from USB must report itself as bus-powered in
+ * the GetStatus(DEVICE) call.
+ * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34
+ */
+#define USB_SELF_POWER_VBUS_MAX_DRAW		100
+
 #endif /* __LINUX_USB_CH9_H */
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 6170681..3d29a7d 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -161,8 +161,6 @@
  *	and by language IDs provided in control requests.
  * @descriptors: Table of descriptors preceding all function descriptors.
  *	Examples include OTG and vendor-specific descriptors.
- * @bind: Called from @usb_add_config() to allocate resources unique to this
- *	configuration and to call @usb_add_function() for each function used.
  * @unbind: Reverses @bind; called as a side effect of unregistering the
  *	driver which added this configuration.
  * @setup: Used to delegate control requests that aren't handled by standard
@@ -207,8 +205,7 @@
 	 * we can't restructure things to avoid mismatching...
 	 */
 
-	/* configuration management:  bind/unbind */
-	int			(*bind)(struct usb_configuration *);
+	/* configuration management: unbind/setup */
 	void			(*unbind)(struct usb_configuration *);
 	int			(*setup)(struct usb_configuration *,
 					const struct usb_ctrlrequest *);
@@ -232,20 +229,24 @@
 };
 
 int usb_add_config(struct usb_composite_dev *,
-		struct usb_configuration *);
+		struct usb_configuration *,
+		int (*)(struct usb_configuration *));
 
 /**
  * struct usb_composite_driver - groups configurations into a gadget
  * @name: For diagnostics, identifies the driver.
+ * @iProduct: Used as iProduct override if @dev->iProduct is not set.
+ *	If NULL value of @name is taken.
+ * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is
+ *	not set. If NULL a default "<system> <release> with <udc>" value
+ *	will be used.
  * @dev: Template descriptor for the device, including default device
  *	identifiers.
  * @strings: tables of strings, keyed by identifiers assigned during bind()
  *	and language IDs provided in control requests
- * @bind: (REQUIRED) Used to allocate resources that are shared across the
- *	whole device, such as string IDs, and add its configurations using
- *	@usb_add_config().  This may fail by returning a negative errno
- *	value; it should return zero on successful initialization.
- * @unbind: Reverses @bind(); called as a side effect of unregistering
+ * @needs_serial: set to 1 if the gadget needs userspace to provide
+ * 	a serial number.  If one is not provided, warning will be printed.
+ * @unbind: Reverses bind; called as a side effect of unregistering
  *	this driver.
  * @disconnect: optional driver disconnect method
  * @suspend: Notifies when the host stops sending USB traffic,
@@ -256,7 +257,7 @@
  * Devices default to reporting self powered operation.  Devices which rely
  * on bus powered operation should report this in their @bind() method.
  *
- * Before returning from @bind, various fields in the template descriptor
+ * Before returning from bind, various fields in the template descriptor
  * may be overridden.  These include the idVendor/idProduct/bcdDevice values
  * normally to bind the appropriate host side driver, and the three strings
  * (iManufacturer, iProduct, iSerialNumber) normally used to provide user
@@ -266,15 +267,12 @@
  */
 struct usb_composite_driver {
 	const char				*name;
+	const char				*iProduct;
+	const char				*iManufacturer;
 	const struct usb_device_descriptor	*dev;
 	struct usb_gadget_strings		**strings;
+	unsigned		needs_serial:1;
 
-	/* REVISIT:  bind() functions can be marked __init, which
-	 * makes trouble for section mismatch analysis.  See if
-	 * we can't restructure things to avoid mismatching...
-	 */
-
-	int			(*bind)(struct usb_composite_dev *);
 	int			(*unbind)(struct usb_composite_dev *);
 
 	void			(*disconnect)(struct usb_composite_dev *);
@@ -284,8 +282,9 @@
 	void			(*resume)(struct usb_composite_dev *);
 };
 
-extern int usb_composite_register(struct usb_composite_driver *);
-extern void usb_composite_unregister(struct usb_composite_driver *);
+extern int usb_composite_probe(struct usb_composite_driver *driver,
+			       int (*bind)(struct usb_composite_dev *cdev));
+extern void usb_composite_unregister(struct usb_composite_driver *driver);
 
 
 /**
@@ -334,6 +333,9 @@
 	struct list_head		configs;
 	struct usb_composite_driver	*driver;
 	u8				next_string_id;
+	u8				manufacturer_override;
+	u8				product_override;
+	u8				serial_override;
 
 	/* the gadget driver won't enable the data pullup
 	 * while the deactivation count is nonzero.
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index d3ef42d..006412c 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -705,11 +705,6 @@
  * struct usb_gadget_driver - driver for usb 'slave' devices
  * @function: String describing the gadget's function
  * @speed: Highest speed the driver handles.
- * @bind: Invoked when the driver is bound to a gadget, usually
- *	after registering the driver.
- *	At that point, ep0 is fully initialized, and ep_list holds
- *	the currently-available endpoints.
- *	Called in a context that permits sleeping.
  * @setup: Invoked for ep0 control requests that aren't handled by
  *	the hardware level driver. Most calls must be handled by
  *	the gadget driver, including descriptor and configuration
@@ -774,7 +769,6 @@
 struct usb_gadget_driver {
 	char			*function;
 	enum usb_device_speed	speed;
-	int			(*bind)(struct usb_gadget *);
 	void			(*unbind)(struct usb_gadget *);
 	int			(*setup)(struct usb_gadget *,
 					const struct usb_ctrlrequest *);
@@ -798,17 +792,19 @@
  */
 
 /**
- * usb_gadget_register_driver - register a gadget driver
- * @driver:the driver being registered
+ * usb_gadget_probe_driver - probe a gadget driver
+ * @driver: the driver being registered
+ * @bind: the driver's bind callback
  * Context: can sleep
  *
  * Call this in your gadget driver's module initialization function,
  * to tell the underlying usb controller driver about your driver.
- * The driver's bind() function will be called to bind it to a
- * gadget before this registration call returns.  It's expected that
- * the bind() functions will be in init sections.
+ * The @bind() function will be called to bind it to a gadget before this
+ * registration call returns.  It's expected that the @bind() function will
+ * be in init sections.
  */
-int usb_gadget_register_driver(struct usb_gadget_driver *driver);
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *));
 
 /**
  * usb_gadget_unregister_driver - unregister a gadget driver
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 3b571f1..0b6e751 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -329,6 +329,8 @@
 extern int usb_hcd_unlink_urb(struct urb *urb, int status);
 extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
 		int status);
+extern void unmap_urb_setup_for_dma(struct usb_hcd *, struct urb *);
+extern void unmap_urb_for_dma(struct usb_hcd *, struct urb *);
 extern void usb_hcd_flush_endpoint(struct usb_device *udev,
 		struct usb_host_endpoint *ep);
 extern void usb_hcd_disable_endpoint(struct usb_device *udev,
diff --git a/include/linux/usb/intel_mid_otg.h b/include/linux/usb/intel_mid_otg.h
new file mode 100644
index 0000000..a0ccf79
--- /dev/null
+++ b/include/linux/usb/intel_mid_otg.h
@@ -0,0 +1,180 @@
+/*
+ * Intel MID (Langwell/Penwell) USB OTG Transceiver driver
+ * Copyright (C) 2008 - 2010, 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __INTEL_MID_OTG_H
+#define __INTEL_MID_OTG_H
+
+#include <linux/pm.h>
+#include <linux/usb/otg.h>
+#include <linux/notifier.h>
+
+struct intel_mid_otg_xceiv;
+
+/* This is a common data structure for Intel MID platform to
+ * save values of the OTG state machine */
+struct otg_hsm {
+	/* Input */
+	int a_bus_resume;
+	int a_bus_suspend;
+	int a_conn;
+	int a_sess_vld;
+	int a_srp_det;
+	int a_vbus_vld;
+	int b_bus_resume;
+	int b_bus_suspend;
+	int b_conn;
+	int b_se0_srp;
+	int b_ssend_srp;
+	int b_sess_end;
+	int b_sess_vld;
+	int id;
+/* id values */
+#define ID_B		0x05
+#define ID_A		0x04
+#define ID_ACA_C	0x03
+#define ID_ACA_B	0x02
+#define ID_ACA_A	0x01
+	int power_up;
+	int adp_change;
+	int test_device;
+
+	/* Internal variables */
+	int a_set_b_hnp_en;
+	int b_srp_done;
+	int b_hnp_enable;
+	int hnp_poll_enable;
+
+	/* Timeout indicator for timers */
+	int a_wait_vrise_tmout;
+	int a_wait_bcon_tmout;
+	int a_aidl_bdis_tmout;
+	int a_bidl_adis_tmout;
+	int a_bidl_adis_tmr;
+	int a_wait_vfall_tmout;
+	int b_ase0_brst_tmout;
+	int b_bus_suspend_tmout;
+	int b_srp_init_tmout;
+	int b_srp_fail_tmout;
+	int b_srp_fail_tmr;
+	int b_adp_sense_tmout;
+
+	/* Informative variables */
+	int a_bus_drop;
+	int a_bus_req;
+	int a_clr_err;
+	int b_bus_req;
+	int a_suspend_req;
+	int b_bus_suspend_vld;
+
+	/* Output */
+	int drv_vbus;
+	int loc_conn;
+	int loc_sof;
+
+	/* Others */
+	int vbus_srp_up;
+};
+
+/* must provide ULPI access function to read/write registers implemented in
+ * ULPI address space */
+struct iotg_ulpi_access_ops {
+	int	(*read)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 *val);
+	int	(*write)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 val);
+};
+
+#define OTG_A_DEVICE	0x0
+#define OTG_B_DEVICE	0x1
+
+/*
+ * the Intel MID (Langwell/Penwell) otg transceiver driver needs to interact
+ * with device and host drivers to implement the USB OTG related feature. More
+ * function members are added based on otg_transceiver data structure for this
+ * purpose.
+ */
+struct intel_mid_otg_xceiv {
+	struct otg_transceiver	otg;
+	struct otg_hsm		hsm;
+
+	/* base address */
+	void __iomem		*base;
+
+	/* ops to access ulpi */
+	struct iotg_ulpi_access_ops	ulpi_ops;
+
+	/* atomic notifier for interrupt context */
+	struct atomic_notifier_head	iotg_notifier;
+
+	/* start/stop USB Host function */
+	int	(*start_host)(struct intel_mid_otg_xceiv *iotg);
+	int	(*stop_host)(struct intel_mid_otg_xceiv *iotg);
+
+	/* start/stop USB Peripheral function */
+	int	(*start_peripheral)(struct intel_mid_otg_xceiv *iotg);
+	int	(*stop_peripheral)(struct intel_mid_otg_xceiv *iotg);
+
+	/* start/stop ADP sense/probe function */
+	int	(*set_adp_probe)(struct intel_mid_otg_xceiv *iotg,
+					bool enabled, int dev);
+	int	(*set_adp_sense)(struct intel_mid_otg_xceiv *iotg,
+					bool enabled);
+
+#ifdef CONFIG_PM
+	/* suspend/resume USB host function */
+	int	(*suspend_host)(struct intel_mid_otg_xceiv *iotg,
+					pm_message_t message);
+	int	(*resume_host)(struct intel_mid_otg_xceiv *iotg);
+
+	int	(*suspend_peripheral)(struct intel_mid_otg_xceiv *iotg,
+					pm_message_t message);
+	int	(*resume_peripheral)(struct intel_mid_otg_xceiv *iotg);
+#endif
+
+};
+static inline
+struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct otg_transceiver *otg)
+{
+	return container_of(otg, struct intel_mid_otg_xceiv, otg);
+}
+
+#define MID_OTG_NOTIFY_CONNECT		0x0001
+#define MID_OTG_NOTIFY_DISCONN		0x0002
+#define MID_OTG_NOTIFY_HSUSPEND		0x0003
+#define MID_OTG_NOTIFY_HRESUME		0x0004
+#define MID_OTG_NOTIFY_CSUSPEND		0x0005
+#define MID_OTG_NOTIFY_CRESUME		0x0006
+#define MID_OTG_NOTIFY_HOSTADD		0x0007
+#define MID_OTG_NOTIFY_HOSTREMOVE	0x0008
+#define MID_OTG_NOTIFY_CLIENTADD	0x0009
+#define MID_OTG_NOTIFY_CLIENTREMOVE	0x000a
+
+static inline int
+intel_mid_otg_register_notifier(struct intel_mid_otg_xceiv *iotg,
+				struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&iotg->iotg_notifier, nb);
+}
+
+static inline void
+intel_mid_otg_unregister_notifier(struct intel_mid_otg_xceiv *iotg,
+				struct notifier_block *nb)
+{
+	atomic_notifier_chain_unregister(&iotg->iotg_notifier, nb);
+}
+
+#endif /* __INTEL_MID_OTG_H */
diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h
new file mode 100644
index 0000000..51f17b1
--- /dev/null
+++ b/include/linux/usb/langwell_otg.h
@@ -0,0 +1,139 @@
+/*
+ * Intel Langwell USB OTG transceiver driver
+ * Copyright (C) 2008 - 2010, 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __LANGWELL_OTG_H
+#define __LANGWELL_OTG_H
+
+#include <linux/usb/intel_mid_otg.h>
+
+#define CI_USBCMD		0x30
+#	define USBCMD_RST		BIT(1)
+#	define USBCMD_RS		BIT(0)
+#define CI_USBSTS		0x34
+#	define USBSTS_SLI		BIT(8)
+#	define USBSTS_URI		BIT(6)
+#	define USBSTS_PCI		BIT(2)
+#define CI_PORTSC1		0x74
+#	define PORTSC_PP		BIT(12)
+#	define PORTSC_LS		(BIT(11) | BIT(10))
+#	define PORTSC_SUSP		BIT(7)
+#	define PORTSC_CCS		BIT(0)
+#define CI_HOSTPC1		0xb4
+#	define HOSTPC1_PHCD		BIT(22)
+#define CI_OTGSC		0xf4
+#	define OTGSC_DPIE		BIT(30)
+#	define OTGSC_1MSE		BIT(29)
+#	define OTGSC_BSEIE		BIT(28)
+#	define OTGSC_BSVIE		BIT(27)
+#	define OTGSC_ASVIE		BIT(26)
+#	define OTGSC_AVVIE		BIT(25)
+#	define OTGSC_IDIE		BIT(24)
+#	define OTGSC_DPIS		BIT(22)
+#	define OTGSC_1MSS		BIT(21)
+#	define OTGSC_BSEIS		BIT(20)
+#	define OTGSC_BSVIS		BIT(19)
+#	define OTGSC_ASVIS		BIT(18)
+#	define OTGSC_AVVIS		BIT(17)
+#	define OTGSC_IDIS		BIT(16)
+#	define OTGSC_DPS		BIT(14)
+#	define OTGSC_1MST		BIT(13)
+#	define OTGSC_BSE		BIT(12)
+#	define OTGSC_BSV		BIT(11)
+#	define OTGSC_ASV		BIT(10)
+#	define OTGSC_AVV		BIT(9)
+#	define OTGSC_ID			BIT(8)
+#	define OTGSC_HABA		BIT(7)
+#	define OTGSC_HADP		BIT(6)
+#	define OTGSC_IDPU		BIT(5)
+#	define OTGSC_DP			BIT(4)
+#	define OTGSC_OT			BIT(3)
+#	define OTGSC_HAAR		BIT(2)
+#	define OTGSC_VC			BIT(1)
+#	define OTGSC_VD			BIT(0)
+#	define OTGSC_INTEN_MASK		(0x7f << 24)
+#	define OTGSC_INT_MASK		(0x5f << 24)
+#	define OTGSC_INTSTS_MASK	(0x7f << 16)
+#define CI_USBMODE		0xf8
+#	define USBMODE_CM		(BIT(1) | BIT(0))
+#	define USBMODE_IDLE		0
+#	define USBMODE_DEVICE		0x2
+#	define USBMODE_HOST		0x3
+#define USBCFG_ADDR			0xff10801c
+#define USBCFG_LEN			4
+#	define USBCFG_VBUSVAL		BIT(14)
+#	define USBCFG_AVALID		BIT(13)
+#	define USBCFG_BVALID		BIT(12)
+#	define USBCFG_SESEND		BIT(11)
+
+#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI)
+
+enum langwell_otg_timer_type {
+	TA_WAIT_VRISE_TMR,
+	TA_WAIT_BCON_TMR,
+	TA_AIDL_BDIS_TMR,
+	TB_ASE0_BRST_TMR,
+	TB_SE0_SRP_TMR,
+	TB_SRP_INIT_TMR,
+	TB_SRP_FAIL_TMR,
+	TB_BUS_SUSPEND_TMR
+};
+
+#define TA_WAIT_VRISE	100
+#define TA_WAIT_BCON	30000
+#define TA_AIDL_BDIS	15000
+#define TB_ASE0_BRST	5000
+#define TB_SE0_SRP	2
+#define TB_SRP_INIT	100
+#define TB_SRP_FAIL	5500
+#define TB_BUS_SUSPEND	500
+
+struct langwell_otg_timer {
+	unsigned long expires;	/* Number of count increase to timeout */
+	unsigned long count;	/* Tick counter */
+	void (*function)(unsigned long);	/* Timeout function */
+	unsigned long data;	/* Data passed to function */
+	struct list_head list;
+};
+
+struct langwell_otg {
+	struct intel_mid_otg_xceiv	iotg;
+	struct device			*dev;
+
+	void __iomem			*usbcfg;	/* SCCBUSB config Reg */
+
+	unsigned			region;
+	unsigned			cfg_region;
+
+	struct work_struct		work;
+	struct workqueue_struct		*qwork;
+	struct timer_list		hsm_timer;
+
+	spinlock_t			lock;
+	spinlock_t			wq_lock;
+
+	struct notifier_block		iotg_notifier;
+};
+
+static inline
+struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg)
+{
+	return container_of(iotg, struct langwell_otg, iotg);
+}
+
+#endif /* __LANGWELL_OTG_H__ */
diff --git a/include/linux/usb/ncm.h b/include/linux/usb/ncm.h
deleted file mode 100644
index 006d106..0000000
--- a/include/linux/usb/ncm.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * USB CDC NCM auxiliary definitions
- */
-
-#ifndef __LINUX_USB_NCM_H
-#define __LINUX_USB_NCM_H
-
-#include <linux/types.h>
-#include <linux/usb/cdc.h>
-#include <asm/unaligned.h>
-
-#define NCM_NTB_MIN_IN_SIZE		2048
-#define NCM_NTB_MIN_OUT_SIZE		2048
-
-#define NCM_CONTROL_TIMEOUT		(5 * 1000)
-
-/* bmNetworkCapabilities */
-
-#define NCM_NCAP_ETH_FILTER	(1 << 0)
-#define NCM_NCAP_NET_ADDRESS	(1 << 1)
-#define NCM_NCAP_ENCAP_COMM	(1 << 2)
-#define NCM_NCAP_MAX_DGRAM	(1 << 3)
-#define NCM_NCAP_CRC_MODE	(1 << 4)
-
-/*
- * Here are options for NCM Datagram Pointer table (NDP) parser.
- * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3),
- * in NDP16 offsets and sizes fields are 1 16bit word wide,
- * in NDP32 -- 2 16bit words wide. Also signatures are different.
- * To make the parser code the same, put the differences in the structure,
- * and switch pointers to the structures when the format is changed.
- */
-
-struct ndp_parser_opts {
-	u32		nth_sign;
-	u32		ndp_sign;
-	unsigned	nth_size;
-	unsigned	ndp_size;
-	unsigned	ndplen_align;
-	/* sizes in u16 units */
-	unsigned	dgram_item_len; /* index or length */
-	unsigned	block_length;
-	unsigned	fp_index;
-	unsigned	reserved1;
-	unsigned	reserved2;
-	unsigned	next_fp_index;
-};
-
-#define INIT_NDP16_OPTS {					\
-		.nth_sign = NCM_NTH16_SIGN,			\
-		.ndp_sign = NCM_NDP16_NOCRC_SIGN,		\
-		.nth_size = sizeof(struct usb_cdc_ncm_nth16),	\
-		.ndp_size = sizeof(struct usb_cdc_ncm_ndp16),	\
-		.ndplen_align = 4,				\
-		.dgram_item_len = 1,				\
-		.block_length = 1,				\
-		.fp_index = 1,					\
-		.reserved1 = 0,					\
-		.reserved2 = 0,					\
-		.next_fp_index = 1,				\
-	}
-
-
-#define INIT_NDP32_OPTS {					\
-		.nth_sign = NCM_NTH32_SIGN,			\
-		.ndp_sign = NCM_NDP32_NOCRC_SIGN,		\
-		.nth_size = sizeof(struct usb_cdc_ncm_nth32),	\
-		.ndp_size = sizeof(struct usb_cdc_ncm_ndp32),	\
-		.ndplen_align = 8,				\
-		.dgram_item_len = 2,				\
-		.block_length = 2,				\
-		.fp_index = 2,					\
-		.reserved1 = 1,					\
-		.reserved2 = 2,					\
-		.next_fp_index = 2,				\
-	}
-
-static inline void put_ncm(__le16 **p, unsigned size, unsigned val)
-{
-	switch (size) {
-	case 1:
-		put_unaligned_le16((u16)val, *p);
-		break;
-	case 2:
-		put_unaligned_le32((u32)val, *p);
-
-		break;
-	default:
-		BUG();
-	}
-
-	*p += size;
-}
-
-static inline unsigned get_ncm(__le16 **p, unsigned size)
-{
-	unsigned tmp;
-
-	switch (size) {
-	case 1:
-		tmp = get_unaligned_le16(*p);
-		break;
-	case 2:
-		tmp = get_unaligned_le32(*p);
-		break;
-	default:
-		BUG();
-	}
-
-	*p += size;
-	return tmp;
-}
-
-#endif /* __LINUX_USB_NCM_H */
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 545cba7..0a5b371 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -164,8 +164,19 @@
 }
 
 /* for usb host and peripheral controller drivers */
+#ifdef CONFIG_USB_OTG_UTILS
 extern struct otg_transceiver *otg_get_transceiver(void);
 extern void otg_put_transceiver(struct otg_transceiver *);
+#else
+static inline struct otg_transceiver *otg_get_transceiver(void)
+{
+	return NULL;
+}
+
+static inline void otg_put_transceiver(struct otg_transceiver *x)
+{
+}
+#endif
 
 /* Context: can sleep */
 static inline int
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 55675b1..16d682f 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -271,6 +271,8 @@
 	int  (*tiocmget)(struct tty_struct *tty, struct file *file);
 	int  (*tiocmset)(struct tty_struct *tty, struct file *file,
 			 unsigned int set, unsigned int clear);
+	int  (*get_icount)(struct tty_struct *tty,
+			struct serial_icounter_struct *icount);
 	/* Called by the tty layer for port level work. There may or may not
 	   be an attached tty at this point */
 	void (*dtr_rts)(struct usb_serial_port *port, int on);
diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h
new file mode 100644
index 0000000..d7fc910
--- /dev/null
+++ b/include/linux/usb/storage.h
@@ -0,0 +1,48 @@
+#ifndef __LINUX_USB_STORAGE_H
+#define __LINUX_USB_STORAGE_H
+
+/*
+ * linux/usb/storage.h
+ *
+ * Copyright Matthew Wilcox for Intel Corp, 2010
+ *
+ * This file contains definitions taken from the
+ * USB Mass Storage Class Specification Overview
+ *
+ * Distributed under the terms of the GNU GPL, version two.
+ */
+
+/* Storage subclass codes */
+
+#define USB_SC_RBC	0x01		/* Typically, flash devices */
+#define USB_SC_8020	0x02		/* CD-ROM */
+#define USB_SC_QIC	0x03		/* QIC-157 Tapes */
+#define USB_SC_UFI	0x04		/* Floppy */
+#define USB_SC_8070	0x05		/* Removable media */
+#define USB_SC_SCSI	0x06		/* Transparent */
+#define USB_SC_LOCKABLE	0x07		/* Password-protected */
+
+#define USB_SC_ISD200	0xf0		/* ISD200 ATA */
+#define USB_SC_CYP_ATACB	0xf1	/* Cypress ATACB */
+#define USB_SC_DEVICE	0xff		/* Use device's value */
+
+/* Storage protocol codes */
+
+#define USB_PR_CBI	0x00		/* Control/Bulk/Interrupt */
+#define USB_PR_CB	0x01		/* Control/Bulk w/o interrupt */
+#define USB_PR_BULK	0x50		/* bulk only */
+#define USB_PR_UAS	0x62		/* USB Attached SCSI */
+
+#define USB_PR_USBAT	0x80		/* SCM-ATAPI bridge */
+#define USB_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
+#define USB_PR_SDDR55	0x82		/* SDDR-55 (made up) */
+#define USB_PR_DPCM_USB	0xf0		/* Combination CB/SDDR09 */
+#define USB_PR_FREECOM	0xf1		/* Freecom */
+#define USB_PR_DATAFAB	0xf2		/* Datafab chipsets */
+#define USB_PR_JUMPSHOT	0xf3		/* Lexar Jumpshot */
+#define USB_PR_ALAUDA	0xf4		/* Alauda chipsets */
+#define USB_PR_KARMA	0xf5		/* Rio Karma */
+
+#define USB_PR_DEVICE	0xff		/* Use device's value */
+
+#endif
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index a4b947e..71693d4 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -58,7 +58,11 @@
 	US_FLAG(CAPACITY_OK,	0x00010000)			\
 		/* READ CAPACITY response is correct */		\
 	US_FLAG(BAD_SENSE,	0x00020000)			\
-		/* Bad Sense (never more than 18 bytes) */
+		/* Bad Sense (never more than 18 bytes) */	\
+	US_FLAG(NO_READ_DISC_INFO,	0x00040000)		\
+		/* cannot handle READ_DISC_INFO */		\
+	US_FLAG(NO_READ_CAPACITY_16,	0x00080000)		\
+		/* cannot handle READ_CAPACITY_16 */
 
 #define US_FLAG(name, value)	US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
@@ -74,42 +78,7 @@
 #define USB_US_TYPE(flags) 		(((flags) >> 24) & 0xFF)
 #define USB_US_ORIG_FLAGS(flags)	((flags) & 0x00FFFFFF)
 
-/*
- * This is probably not the best place to keep these constants, conceptually.
- * But it's the only header included into all places which need them.
- */
-
-/* Sub Classes */
-
-#define US_SC_RBC	0x01		/* Typically, flash devices */
-#define US_SC_8020	0x02		/* CD-ROM */
-#define US_SC_QIC	0x03		/* QIC-157 Tapes */
-#define US_SC_UFI	0x04		/* Floppy */
-#define US_SC_8070	0x05		/* Removable media */
-#define US_SC_SCSI	0x06		/* Transparent */
-#define US_SC_LOCKABLE	0x07		/* Password-protected */
-
-#define US_SC_ISD200    0xf0		/* ISD200 ATA */
-#define US_SC_CYP_ATACB 0xf1		/* Cypress ATACB */
-#define US_SC_DEVICE	0xff		/* Use device's value */
-
-/* Protocols */
-
-#define US_PR_CBI	0x00		/* Control/Bulk/Interrupt */
-#define US_PR_CB	0x01		/* Control/Bulk w/o interrupt */
-#define US_PR_BULK	0x50		/* bulk only */
-
-#define US_PR_USBAT	0x80		/* SCM-ATAPI bridge */
-#define US_PR_EUSB_SDDR09	0x81	/* SCM-SCSI bridge for SDDR-09 */
-#define US_PR_SDDR55	0x82		/* SDDR-55 (made up) */
-#define US_PR_DPCM_USB  0xf0		/* Combination CB/SDDR09 */
-#define US_PR_FREECOM   0xf1		/* Freecom */
-#define US_PR_DATAFAB   0xf2		/* Datafab chipsets */
-#define US_PR_JUMPSHOT  0xf3		/* Lexar Jumpshot */
-#define US_PR_ALAUDA    0xf4		/* Alauda chipsets */
-#define US_PR_KARMA     0xf5		/* Rio Karma */
-
-#define US_PR_DEVICE	0xff		/* Use device's value */
+#include <linux/usb/storage.h>
 
 /*
  */
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 01c2145..63a4fe6 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -117,10 +117,12 @@
 extern struct vm_struct *vmlist;
 extern __init void vm_area_register_early(struct vm_struct *vm, size_t align);
 
+#ifdef CONFIG_SMP
 struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
 				     const size_t *sizes, int nr_vms,
 				     size_t align, gfp_t gfp_mask);
 
 void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms);
+#endif
 
 #endif /* _LINUX_VMALLOC_H */
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 25e02c9..070bb7a 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -243,11 +243,12 @@
 	WQ_NON_REENTRANT	= 1 << 0, /* guarantee non-reentrance */
 	WQ_UNBOUND		= 1 << 1, /* not bound to any cpu */
 	WQ_FREEZEABLE		= 1 << 2, /* freeze during suspend */
-	WQ_RESCUER		= 1 << 3, /* has an rescue worker */
+	WQ_MEM_RECLAIM		= 1 << 3, /* may be used for memory reclaim */
 	WQ_HIGHPRI		= 1 << 4, /* high priority */
 	WQ_CPU_INTENSIVE	= 1 << 5, /* cpu instensive workqueue */
 
 	WQ_DYING		= 1 << 6, /* internal: workqueue is dying */
+	WQ_RESCUER		= 1 << 7, /* internal: workqueue has rescuer */
 
 	WQ_MAX_ACTIVE		= 512,	  /* I like 512, better ideas? */
 	WQ_MAX_UNBOUND_PER_CPU	= 4,	  /* 4 * #cpus for unbound wq */
@@ -306,12 +307,30 @@
 	__alloc_workqueue_key((name), (flags), (max_active), NULL, NULL)
 #endif
 
+/**
+ * alloc_ordered_workqueue - allocate an ordered workqueue
+ * @name: name of the workqueue
+ * @flags: WQ_* flags (only WQ_FREEZEABLE and WQ_MEM_RECLAIM are meaningful)
+ *
+ * Allocate an ordered workqueue.  An ordered workqueue executes at
+ * most one work item at any given time in the queued order.  They are
+ * implemented as unbound workqueues with @max_active of one.
+ *
+ * RETURNS:
+ * Pointer to the allocated workqueue on success, %NULL on failure.
+ */
+static inline struct workqueue_struct *
+alloc_ordered_workqueue(const char *name, unsigned int flags)
+{
+	return alloc_workqueue(name, WQ_UNBOUND | flags, 1);
+}
+
 #define create_workqueue(name)					\
-	alloc_workqueue((name), WQ_RESCUER, 1)
+	alloc_workqueue((name), WQ_MEM_RECLAIM, 1)
 #define create_freezeable_workqueue(name)			\
-	alloc_workqueue((name), WQ_FREEZEABLE | WQ_UNBOUND | WQ_RESCUER, 1)
+	alloc_workqueue((name), WQ_FREEZEABLE | WQ_UNBOUND | WQ_MEM_RECLAIM, 1)
 #define create_singlethread_workqueue(name)			\
-	alloc_workqueue((name), WQ_UNBOUND | WQ_RESCUER, 1)
+	alloc_workqueue((name), WQ_UNBOUND | WQ_MEM_RECLAIM, 1)
 
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
@@ -325,7 +344,6 @@
 
 extern void flush_workqueue(struct workqueue_struct *wq);
 extern void flush_scheduled_work(void);
-extern void flush_delayed_work(struct delayed_work *work);
 
 extern int schedule_work(struct work_struct *work);
 extern int schedule_work_on(int cpu, struct work_struct *work);
@@ -337,8 +355,13 @@
 
 int execute_in_process_context(work_func_t fn, struct execute_work *);
 
-extern int flush_work(struct work_struct *work);
-extern int cancel_work_sync(struct work_struct *work);
+extern bool flush_work(struct work_struct *work);
+extern bool flush_work_sync(struct work_struct *work);
+extern bool cancel_work_sync(struct work_struct *work);
+
+extern bool flush_delayed_work(struct delayed_work *dwork);
+extern bool flush_delayed_work_sync(struct delayed_work *work);
+extern bool cancel_delayed_work_sync(struct delayed_work *dwork);
 
 extern void workqueue_set_max_active(struct workqueue_struct *wq,
 				     int max_active);
@@ -352,9 +375,9 @@
  * it returns 1 and the work doesn't re-arm itself. Run flush_workqueue() or
  * cancel_work_sync() to wait on it.
  */
-static inline int cancel_delayed_work(struct delayed_work *work)
+static inline bool cancel_delayed_work(struct delayed_work *work)
 {
-	int ret;
+	bool ret;
 
 	ret = del_timer_sync(&work->timer);
 	if (ret)
@@ -367,9 +390,9 @@
  * if it returns 0 the timer function may be running and the queueing is in
  * progress.
  */
-static inline int __cancel_delayed_work(struct delayed_work *work)
+static inline bool __cancel_delayed_work(struct delayed_work *work)
 {
-	int ret;
+	bool ret;
 
 	ret = del_timer(&work->timer);
 	if (ret)
@@ -377,8 +400,6 @@
 	return ret;
 }
 
-extern int cancel_delayed_work_sync(struct delayed_work *work);
-
 /* Obsolete. use cancel_delayed_work_sync() */
 static inline
 void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
@@ -409,8 +430,4 @@
 extern void thaw_workqueues(void);
 #endif /* CONFIG_FREEZER */
 
-#ifdef CONFIG_LOCKDEP
-int in_workqueue_context(struct workqueue_struct *wq);
-#endif
-
 #endif
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index d830c87..8479b66 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -259,6 +259,8 @@
 #define CONF_ENABLE_SPKR        0x0002
 #define CONF_ENABLE_PULSE_IRQ   0x0004
 #define CONF_ENABLE_ESR         0x0008
+#define CONF_ENABLE_IOCARD	0x0010 /* auto-enabled if IO resources or IRQ
+					* (CONF_ENABLE_IRQ) in use */
 
 /* flags used by pcmcia_loop_config() autoconfiguration */
 #define CONF_AUTO_CHECK_VCC	0x0100 /* check for matching Vcc? */
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index d06e13b..3dec194 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -205,6 +205,7 @@
         };
 
         void *lldd_dev;
+	int gone;
 };
 
 struct sas_discovery_event {
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 8fcb6e0..216af85 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -32,6 +32,12 @@
 #endif
 
 /*
+ * DIX-capable adapters effectively support infinite chaining for the
+ * protection information scatterlist
+ */
+#define SCSI_MAX_PROT_SG_SEGMENTS	0xFFFF
+
+/*
  * Special value for scanning to specify scanning or rescanning of all
  * possible channels, (target) ids, or luns on a given shost.
  */
@@ -67,6 +73,7 @@
 #define SEND_DIAGNOSTIC       0x1d
 #define ALLOW_MEDIUM_REMOVAL  0x1e
 
+#define READ_FORMAT_CAPACITIES 0x23
 #define SET_WINDOW            0x24
 #define READ_CAPACITY         0x25
 #define READ_10               0x28
@@ -96,6 +103,7 @@
 #define WRITE_SAME            0x41
 #define UNMAP		      0x42
 #define READ_TOC              0x43
+#define READ_HEADER           0x44
 #define LOG_SELECT            0x4c
 #define LOG_SENSE             0x4d
 #define XDWRITEREAD_10        0x53
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 50cb34f..85867dc 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -148,6 +148,8 @@
 	unsigned retry_hwerror:1;	/* Retry HARDWARE_ERROR */
 	unsigned last_sector_bug:1;	/* do not use multisector accesses on
 					   SD_LAST_BUGGY_SECTORS */
+	unsigned no_read_disc_info:1;	/* Avoid READ_DISC_INFO cmds */
+	unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
 	unsigned is_visible:1;	/* is the device visible in sysfs */
 
 	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index b7bdecb..d0a6a84 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -388,6 +388,7 @@
 	 * of scatter-gather.
 	 */
 	unsigned short sg_tablesize;
+	unsigned short sg_prot_tablesize;
 
 	/*
 	 * Set this if the host adapter has limitations beside segment count.
@@ -599,6 +600,7 @@
 	int can_queue;
 	short cmd_per_lun;
 	short unsigned int sg_tablesize;
+	short unsigned int sg_prot_tablesize;
 	short unsigned int max_sectors;
 	unsigned long dma_boundary;
 	/* 
@@ -823,6 +825,11 @@
 	return shost->prot_capabilities;
 }
 
+static inline int scsi_host_prot_dma(struct Scsi_Host *shost)
+{
+	return shost->prot_capabilities >= SHOST_DIX_TYPE0_PROTECTION;
+}
+
 static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsigned int target_type)
 {
 	static unsigned char cap[] = { 0,
diff --git a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h
index 1723138..d6e7994 100644
--- a/include/scsi/scsi_tcq.h
+++ b/include/scsi/scsi_tcq.h
@@ -97,13 +97,9 @@
 static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg)
 {
         struct request *req = cmd->request;
-	struct scsi_device *sdev = cmd->device;
 
         if (blk_rq_tagged(req)) {
-		if (sdev->ordered_tags && req->cmd_flags & REQ_HARDBARRIER)
-        	        *msg++ = MSG_ORDERED_TAG;
-        	else
-        	        *msg++ = MSG_SIMPLE_TAG;
+		*msg++ = MSG_SIMPLE_TAG;
         	*msg++ = req->tag;
         	return 2;
 	}
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 87d81b3..59816fe 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -496,6 +496,7 @@
 	u64 fabric_name;
 	char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
 	char system_hostname[FC_SYMBOLIC_NAME_SIZE];
+	u32 dev_loss_tmo;
 
 	/* Private (Transport-managed) Attributes */
 	enum fc_tgtid_binding_type  tgtid_bind_type;
@@ -580,6 +581,8 @@
 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q_name)
 #define fc_host_devloss_work_q(x) \
 	(((struct fc_host_attrs *)(x)->shost_data)->devloss_work_q)
+#define fc_host_dev_loss_tmo(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
 
 
 struct fc_bsg_buffer {
diff --git a/include/sound/core.h b/include/sound/core.h
index 89e0ac1..df26ebb 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -133,9 +133,7 @@
 	int free_on_last_close;		/* free in context of file_release */
 	wait_queue_head_t shutdown_sleep;
 	struct device *dev;		/* device assigned to this card */
-#ifndef CONFIG_SYSFS_DEPRECATED
 	struct device *card_dev;	/* cardX object for sysfs */
-#endif
 
 #ifdef CONFIG_PM
 	unsigned int power_state;	/* power state */
@@ -196,11 +194,7 @@
 /* return a device pointer linked to each sound device as a parent */
 static inline struct device *snd_card_get_device_link(struct snd_card *card)
 {
-#ifdef CONFIG_SYSFS_DEPRECATED
-	return card ? card->dev : NULL;
-#else
 	return card ? card->card_dev : NULL;
-#endif
 }
 
 /* sound.c */
diff --git a/include/trace/events/workqueue.h b/include/trace/events/workqueue.h
index 49682d7..7d49729 100644
--- a/include/trace/events/workqueue.h
+++ b/include/trace/events/workqueue.h
@@ -7,6 +7,76 @@
 #include <linux/tracepoint.h>
 #include <linux/workqueue.h>
 
+DECLARE_EVENT_CLASS(workqueue_work,
+
+	TP_PROTO(struct work_struct *work),
+
+	TP_ARGS(work),
+
+	TP_STRUCT__entry(
+		__field( void *,	work	)
+	),
+
+	TP_fast_assign(
+		__entry->work		= work;
+	),
+
+	TP_printk("work struct %p", __entry->work)
+);
+
+/**
+ * workqueue_queue_work - called when a work gets queued
+ * @req_cpu:	the requested cpu
+ * @cwq:	pointer to struct cpu_workqueue_struct
+ * @work:	pointer to struct work_struct
+ *
+ * This event occurs when a work is queued immediately or once a
+ * delayed work is actually queued on a workqueue (ie: once the delay
+ * has been reached).
+ */
+TRACE_EVENT(workqueue_queue_work,
+
+	TP_PROTO(unsigned int req_cpu, struct cpu_workqueue_struct *cwq,
+		 struct work_struct *work),
+
+	TP_ARGS(req_cpu, cwq, work),
+
+	TP_STRUCT__entry(
+		__field( void *,	work	)
+		__field( void *,	function)
+		__field( void *,	workqueue)
+		__field( unsigned int,	req_cpu	)
+		__field( unsigned int,	cpu	)
+	),
+
+	TP_fast_assign(
+		__entry->work		= work;
+		__entry->function	= work->func;
+		__entry->workqueue	= cwq->wq;
+		__entry->req_cpu	= req_cpu;
+		__entry->cpu		= cwq->gcwq->cpu;
+	),
+
+	TP_printk("work struct=%p function=%pf workqueue=%p req_cpu=%u cpu=%u",
+		  __entry->work, __entry->function, __entry->workqueue,
+		  __entry->req_cpu, __entry->cpu)
+);
+
+/**
+ * workqueue_activate_work - called when a work gets activated
+ * @work:	pointer to struct work_struct
+ *
+ * This event occurs when a queued work is put on the active queue,
+ * which happens immediately after queueing unless @max_active limit
+ * is reached.
+ */
+DEFINE_EVENT(workqueue_work, workqueue_activate_work,
+
+	TP_PROTO(struct work_struct *work),
+
+	TP_ARGS(work)
+);
+
 /**
  * workqueue_execute_start - called immediately before the workqueue callback
  * @work:	pointer to struct work_struct
@@ -38,24 +108,13 @@
  *
  * Allows to track workqueue execution.
  */
-TRACE_EVENT(workqueue_execute_end,
+DEFINE_EVENT(workqueue_work, workqueue_execute_end,
 
 	TP_PROTO(struct work_struct *work),
 
-	TP_ARGS(work),
-
-	TP_STRUCT__entry(
-		__field( void *,	work	)
-	),
-
-	TP_fast_assign(
-		__entry->work		= work;
-	),
-
-	TP_printk("work struct %p", __entry->work)
+	TP_ARGS(work)
 );
 
-
 #endif /*  _TRACE_WORKQUEUE_H */
 
 /* This part must be outside protection */
diff --git a/init/Kconfig b/init/Kconfig
index 36890f0..fdfd97e 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -71,7 +71,7 @@
 
 config LOCK_KERNEL
 	bool
-	depends on SMP || PREEMPT
+	depends on (SMP || PREEMPT) && BKL
 	default y
 
 config INIT_ENV_ARG_LIMIT
@@ -661,11 +661,14 @@
 
 	Currently, CFQ IO scheduler uses it to recognize task groups and
 	control disk bandwidth allocation (proportional time slice allocation)
-	to such task groups.
+	to such task groups. It is also used by bio throttling logic in
+	block layer to implement upper limit in IO rates on a device.
 
 	This option only enables generic Block IO controller infrastructure.
-	One needs to also enable actual IO controlling logic in CFQ for it
-	to take effect. (CONFIG_CFQ_GROUP_IOSCHED=y).
+	One needs to also enable actual IO controlling logic/policy. For
+	enabling proportional weight division of disk bandwidth in CFQ seti
+	CONFIG_CFQ_GROUP_IOSCHED=y and for enabling throttling policy set
+	CONFIG_BLK_THROTTLE=y.
 
 	See Documentation/cgroups/blkio-controller.txt for more information.
 
@@ -683,40 +686,42 @@
 	bool
 
 config SYSFS_DEPRECATED
-	bool
-
-config SYSFS_DEPRECATED_V2
 	bool "enable deprecated sysfs features to support old userspace tools"
 	depends on SYSFS
 	default n
-	select SYSFS_DEPRECATED
 	help
-	  This option switches the layout of sysfs to the deprecated
-	  version. Do not use it on recent distributions.
+	  This option adds code that switches the layout of the "block" class
+	  devices, to not show up in /sys/class/block/, but only in
+	  /sys/block/.
 
-	  The current sysfs layout features a unified device tree at
-	  /sys/devices/, which is able to express a hierarchy between
-	  class devices. If the deprecated option is set to Y, the
-	  unified device tree is split into a bus device tree at
-	  /sys/devices/ and several individual class device trees at
-	  /sys/class/. The class and bus devices will be connected by
-	  "<subsystem>:<name>" and the "device" links. The "block"
-	  class devices, will not show up in /sys/class/block/. Some
-	  subsystems will suppress the creation of some devices which
-	  depend on the unified device tree.
+	  This switch is only active when the sysfs.deprecated=1 boot option is
+	  passed or the SYSFS_DEPRECATED_V2 option is set.
 
-	  This option is not a pure compatibility option that can
-	  be safely enabled on newer distributions. It will change the
-	  layout of sysfs to the non-extensible deprecated version,
-	  and disable some features, which can not be exported without
-	  confusing older userspace tools. Since 2007/2008 all major
-	  distributions do not enable this option, and ship no tools which
-	  depend on the deprecated layout or this option.
+	  This option allows new kernels to run on old distributions and tools,
+	  which might get confused by /sys/class/block/. Since 2007/2008 all
+	  major distributions and tools handle this just fine.
 
-	  If you are using a new kernel on an older distribution, or use
-	  older userspace tools, you might need to say Y here. Do not say Y,
-	  if the original kernel, that came with your distribution, has
-	  this option set to N.
+	  Recent distributions and userspace tools after 2009/2010 depend on
+	  the existence of /sys/class/block/, and will not work with this
+	  option enabled.
+
+	  Only if you are using a new kernel on an old distribution, you might
+	  need to say Y here.
+
+config SYSFS_DEPRECATED_V2
+	bool "enabled deprecated sysfs features by default"
+	default n
+	depends on SYSFS
+	depends on SYSFS_DEPRECATED
+	help
+	  Enable deprecated sysfs by default.
+
+	  See the CONFIG_SYSFS_DEPRECATED option for more details about this
+	  option.
+
+	  Only if you are using a new kernel on an old distribution, you might
+	  need to say Y here. Even then, odds are you would not need it
+	  enabled, you can always pass the boot option if absolutely necessary.
 
 config RELAY
 	bool "Kernel->user space relay support (formerly relayfs)"
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 02e3ca4..42db055 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -58,6 +58,62 @@
 __setup("ro", readonly);
 __setup("rw", readwrite);
 
+#ifdef CONFIG_BLOCK
+/**
+ * match_dev_by_uuid - callback for finding a partition using its uuid
+ * @dev:	device passed in by the caller
+ * @data:	opaque pointer to a 36 byte char array with a UUID
+ *
+ * Returns 1 if the device matches, and 0 otherwise.
+ */
+static int match_dev_by_uuid(struct device *dev, void *data)
+{
+	u8 *uuid = data;
+	struct hd_struct *part = dev_to_part(dev);
+
+	if (!part->info)
+		goto no_match;
+
+	if (memcmp(uuid, part->info->uuid, sizeof(part->info->uuid)))
+			goto no_match;
+
+	return 1;
+no_match:
+	return 0;
+}
+
+
+/**
+ * devt_from_partuuid - looks up the dev_t of a partition by its UUID
+ * @uuid:	36 byte char array containing a hex ascii UUID
+ *
+ * The function will return the first partition which contains a matching
+ * UUID value in its partition_meta_info struct.  This does not search
+ * by filesystem UUIDs.
+ *
+ * Returns the matching dev_t on success or 0 on failure.
+ */
+static dev_t __init devt_from_partuuid(char *uuid_str)
+{
+	dev_t res = 0;
+	struct device *dev = NULL;
+	u8 uuid[16];
+
+	/* Pack the requested UUID in the expected format. */
+	part_pack_uuid(uuid_str, uuid);
+
+	dev = class_find_device(&block_class, NULL, uuid, &match_dev_by_uuid);
+	if (!dev)
+		goto done;
+
+	res = dev->devt;
+	put_device(dev);
+
+done:
+	return res;
+}
+#endif
+
 /*
  *	Convert a name into device number.  We accept the following variants:
  *
@@ -68,6 +124,8 @@
  *         of partition - device number of disk plus the partition number
  *	5) /dev/<disk_name>p<decimal> - same as the above, that form is
  *	   used when disk name of partitioned disk ends on a digit.
+ *	6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
+ *	   unique id of a partition if the partition table provides it.
  *
  *	If name doesn't have fall into the categories above, we return (0,0).
  *	block_class is used to check if something is a disk name. If the disk
@@ -82,6 +140,18 @@
 	dev_t res = 0;
 	int part;
 
+#ifdef CONFIG_BLOCK
+	if (strncmp(name, "PARTUUID=", 9) == 0) {
+		name += 9;
+		if (strlen(name) != 36)
+			goto fail;
+		res = devt_from_partuuid(name);
+		if (!res)
+			goto fail;
+		goto done;
+	}
+#endif
+
 	if (strncmp(name, "/dev/", 5) != 0) {
 		unsigned maj, min;
 
diff --git a/init/main.c b/init/main.c
index 9684c96..e59af24 100644
--- a/init/main.c
+++ b/init/main.c
@@ -424,7 +424,6 @@
 static __initdata DECLARE_COMPLETION(kthreadd_done);
 
 static noinline void __init_refok rest_init(void)
-	__releases(kernel_lock)
 {
 	int pid;
 
@@ -818,7 +817,6 @@
  * makes it inline to init() and it becomes part of init.text section
  */
 static noinline int init_post(void)
-	__releases(kernel_lock)
 {
 	/* need to finish all async __init code before freeing the memory */
 	async_synchronize_full();
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index c60e519..e1e7b96 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -1219,6 +1219,7 @@
 	.flush = mqueue_flush_file,
 	.poll = mqueue_poll_file,
 	.read = mqueue_read_file,
+	.llseek = default_llseek,
 };
 
 static const struct super_operations mqueue_super_ops = {
diff --git a/ipc/shm.c b/ipc/shm.c
index 52ed77e..7bc46a9 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -298,6 +298,7 @@
 #ifndef CONFIG_MMU
 	.get_unmapped_area	= shm_get_unmapped_area,
 #endif
+	.llseek		= noop_llseek,
 };
 
 static const struct file_operations shm_file_operations_huge = {
@@ -305,6 +306,7 @@
 	.fsync		= shm_fsync,
 	.release	= shm_release,
 	.get_unmapped_area	= shm_get_unmapped_area,
+	.llseek		= noop_llseek,
 };
 
 int is_file_shm_hugepages(struct file *file)
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 291ba3d..7b69b8d 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -52,7 +52,6 @@
 #include <linux/cgroupstats.h>
 #include <linux/hash.h>
 #include <linux/namei.h>
-#include <linux/smp_lock.h>
 #include <linux/pid_namespace.h>
 #include <linux/idr.h>
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
@@ -1222,7 +1221,6 @@
 	struct cgroup *cgrp = &root->top_cgroup;
 	struct cgroup_sb_opts opts;
 
-	lock_kernel();
 	mutex_lock(&cgrp->dentry->d_inode->i_mutex);
 	mutex_lock(&cgroup_mutex);
 
@@ -1255,7 +1253,6 @@
 	kfree(opts.name);
 	mutex_unlock(&cgroup_mutex);
 	mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
-	unlock_kernel();
 	return ret;
 }
 
@@ -1568,7 +1565,6 @@
  out_err:
 	kfree(opts.release_agent);
 	kfree(opts.name);
-
 	return ret;
 }
 
diff --git a/kernel/configs.c b/kernel/configs.c
index abaee68..b4066b4 100644
--- a/kernel/configs.c
+++ b/kernel/configs.c
@@ -66,6 +66,7 @@
 static const struct file_operations ikconfig_file_ops = {
 	.owner = THIS_MODULE,
 	.read = ikconfig_read_current,
+	.llseek = default_llseek,
 };
 
 static int __init ikconfig_init(void)
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index de407c7..fec596d 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -47,6 +47,7 @@
 #include <linux/pid.h>
 #include <linux/smp.h>
 #include <linux/mm.h>
+#include <linux/rcupdate.h>
 
 #include <asm/cacheflush.h>
 #include <asm/byteorder.h>
@@ -109,13 +110,15 @@
  */
 atomic_t			kgdb_active = ATOMIC_INIT(-1);
 EXPORT_SYMBOL_GPL(kgdb_active);
+static DEFINE_RAW_SPINLOCK(dbg_master_lock);
+static DEFINE_RAW_SPINLOCK(dbg_slave_lock);
 
 /*
  * We use NR_CPUs not PERCPU, in case kgdb is used to debug early
  * bootup code (which might not have percpu set up yet):
  */
-static atomic_t			passive_cpu_wait[NR_CPUS];
-static atomic_t			cpu_in_kgdb[NR_CPUS];
+static atomic_t			masters_in_kgdb;
+static atomic_t			slaves_in_kgdb;
 static atomic_t			kgdb_break_tasklet_var;
 atomic_t			kgdb_setting_breakpoint;
 
@@ -457,26 +460,32 @@
 	return 1;
 }
 
-static void dbg_cpu_switch(int cpu, int next_cpu)
+static void dbg_touch_watchdogs(void)
 {
-	/* Mark the cpu we are switching away from as a slave when it
-	 * holds the kgdb_active token.  This must be done so that the
-	 * that all the cpus wait in for the debug core will not enter
-	 * again as the master. */
-	if (cpu == atomic_read(&kgdb_active)) {
-		kgdb_info[cpu].exception_state |= DCPU_IS_SLAVE;
-		kgdb_info[cpu].exception_state &= ~DCPU_WANT_MASTER;
-	}
-	kgdb_info[next_cpu].exception_state |= DCPU_NEXT_MASTER;
+	touch_softlockup_watchdog_sync();
+	clocksource_touch_watchdog();
+	rcu_cpu_stall_reset();
 }
 
-static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs)
+static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
+		int exception_state)
 {
 	unsigned long flags;
 	int sstep_tries = 100;
 	int error;
-	int i, cpu;
+	int cpu;
 	int trace_on = 0;
+	int online_cpus = num_online_cpus();
+
+	kgdb_info[ks->cpu].enter_kgdb++;
+	kgdb_info[ks->cpu].exception_state |= exception_state;
+
+	if (exception_state == DCPU_WANT_MASTER)
+		atomic_inc(&masters_in_kgdb);
+	else
+		atomic_inc(&slaves_in_kgdb);
+	kgdb_disable_hw_debug(ks->linux_regs);
+
 acquirelock:
 	/*
 	 * Interrupts will be restored by the 'trap return' code, except when
@@ -489,14 +498,15 @@
 	kgdb_info[cpu].task = current;
 	kgdb_info[cpu].ret_state = 0;
 	kgdb_info[cpu].irq_depth = hardirq_count() >> HARDIRQ_SHIFT;
-	/*
-	 * Make sure the above info reaches the primary CPU before
-	 * our cpu_in_kgdb[] flag setting does:
-	 */
-	atomic_inc(&cpu_in_kgdb[cpu]);
 
-	if (exception_level == 1)
+	/* Make sure the above info reaches the primary CPU */
+	smp_mb();
+
+	if (exception_level == 1) {
+		if (raw_spin_trylock(&dbg_master_lock))
+			atomic_xchg(&kgdb_active, cpu);
 		goto cpu_master_loop;
+	}
 
 	/*
 	 * CPU will loop if it is a slave or request to become a kgdb
@@ -508,10 +518,12 @@
 			kgdb_info[cpu].exception_state &= ~DCPU_NEXT_MASTER;
 			goto cpu_master_loop;
 		} else if (kgdb_info[cpu].exception_state & DCPU_WANT_MASTER) {
-			if (atomic_cmpxchg(&kgdb_active, -1, cpu) == cpu)
+			if (raw_spin_trylock(&dbg_master_lock)) {
+				atomic_xchg(&kgdb_active, cpu);
 				break;
+			}
 		} else if (kgdb_info[cpu].exception_state & DCPU_IS_SLAVE) {
-			if (!atomic_read(&passive_cpu_wait[cpu]))
+			if (!raw_spin_is_locked(&dbg_slave_lock))
 				goto return_normal;
 		} else {
 return_normal:
@@ -522,9 +534,12 @@
 				arch_kgdb_ops.correct_hw_break();
 			if (trace_on)
 				tracing_on();
-			atomic_dec(&cpu_in_kgdb[cpu]);
-			touch_softlockup_watchdog_sync();
-			clocksource_touch_watchdog();
+			kgdb_info[cpu].exception_state &=
+				~(DCPU_WANT_MASTER | DCPU_IS_SLAVE);
+			kgdb_info[cpu].enter_kgdb--;
+			smp_mb__before_atomic_dec();
+			atomic_dec(&slaves_in_kgdb);
+			dbg_touch_watchdogs();
 			local_irq_restore(flags);
 			return 0;
 		}
@@ -541,8 +556,8 @@
 	    (kgdb_info[cpu].task &&
 	     kgdb_info[cpu].task->pid != kgdb_sstep_pid) && --sstep_tries) {
 		atomic_set(&kgdb_active, -1);
-		touch_softlockup_watchdog_sync();
-		clocksource_touch_watchdog();
+		raw_spin_unlock(&dbg_master_lock);
+		dbg_touch_watchdogs();
 		local_irq_restore(flags);
 
 		goto acquirelock;
@@ -563,16 +578,12 @@
 	if (dbg_io_ops->pre_exception)
 		dbg_io_ops->pre_exception();
 
-	kgdb_disable_hw_debug(ks->linux_regs);
-
 	/*
 	 * Get the passive CPU lock which will hold all the non-primary
 	 * CPU in a spin state while the debugger is active
 	 */
-	if (!kgdb_single_step) {
-		for (i = 0; i < NR_CPUS; i++)
-			atomic_inc(&passive_cpu_wait[i]);
-	}
+	if (!kgdb_single_step)
+		raw_spin_lock(&dbg_slave_lock);
 
 #ifdef CONFIG_SMP
 	/* Signal the other CPUs to enter kgdb_wait() */
@@ -583,10 +594,9 @@
 	/*
 	 * Wait for the other CPUs to be notified and be waiting for us:
 	 */
-	for_each_online_cpu(i) {
-		while (kgdb_do_roundup && !atomic_read(&cpu_in_kgdb[i]))
-			cpu_relax();
-	}
+	while (kgdb_do_roundup && (atomic_read(&masters_in_kgdb) +
+				atomic_read(&slaves_in_kgdb)) != online_cpus)
+		cpu_relax();
 
 	/*
 	 * At this point the primary processor is completely
@@ -615,7 +625,8 @@
 		if (error == DBG_PASS_EVENT) {
 			dbg_kdb_mode = !dbg_kdb_mode;
 		} else if (error == DBG_SWITCH_CPU_EVENT) {
-			dbg_cpu_switch(cpu, dbg_switch_cpu);
+			kgdb_info[dbg_switch_cpu].exception_state |=
+				DCPU_NEXT_MASTER;
 			goto cpu_loop;
 		} else {
 			kgdb_info[cpu].ret_state = error;
@@ -627,24 +638,11 @@
 	if (dbg_io_ops->post_exception)
 		dbg_io_ops->post_exception();
 
-	atomic_dec(&cpu_in_kgdb[ks->cpu]);
-
 	if (!kgdb_single_step) {
-		for (i = NR_CPUS-1; i >= 0; i--)
-			atomic_dec(&passive_cpu_wait[i]);
-		/*
-		 * Wait till all the CPUs have quit from the debugger,
-		 * but allow a CPU that hit an exception and is
-		 * waiting to become the master to remain in the debug
-		 * core.
-		 */
-		for_each_online_cpu(i) {
-			while (kgdb_do_roundup &&
-			       atomic_read(&cpu_in_kgdb[i]) &&
-			       !(kgdb_info[i].exception_state &
-				 DCPU_WANT_MASTER))
-				cpu_relax();
-		}
+		raw_spin_unlock(&dbg_slave_lock);
+		/* Wait till all the CPUs have quit from the debugger. */
+		while (kgdb_do_roundup && atomic_read(&slaves_in_kgdb))
+			cpu_relax();
 	}
 
 kgdb_restore:
@@ -655,12 +653,20 @@
 		else
 			kgdb_sstep_pid = 0;
 	}
+	if (arch_kgdb_ops.correct_hw_break)
+		arch_kgdb_ops.correct_hw_break();
 	if (trace_on)
 		tracing_on();
+
+	kgdb_info[cpu].exception_state &=
+		~(DCPU_WANT_MASTER | DCPU_IS_SLAVE);
+	kgdb_info[cpu].enter_kgdb--;
+	smp_mb__before_atomic_dec();
+	atomic_dec(&masters_in_kgdb);
 	/* Free kgdb_active */
 	atomic_set(&kgdb_active, -1);
-	touch_softlockup_watchdog_sync();
-	clocksource_touch_watchdog();
+	raw_spin_unlock(&dbg_master_lock);
+	dbg_touch_watchdogs();
 	local_irq_restore(flags);
 
 	return kgdb_info[cpu].ret_state;
@@ -678,7 +684,6 @@
 {
 	struct kgdb_state kgdb_var;
 	struct kgdb_state *ks = &kgdb_var;
-	int ret;
 
 	ks->cpu			= raw_smp_processor_id();
 	ks->ex_vector		= evector;
@@ -689,11 +694,10 @@
 
 	if (kgdb_reenter_check(ks))
 		return 0; /* Ouch, double exception ! */
-	kgdb_info[ks->cpu].exception_state |= DCPU_WANT_MASTER;
-	ret = kgdb_cpu_enter(ks, regs);
-	kgdb_info[ks->cpu].exception_state &= ~(DCPU_WANT_MASTER |
-						DCPU_IS_SLAVE);
-	return ret;
+	if (kgdb_info[ks->cpu].enter_kgdb != 0)
+		return 0;
+
+	return kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER);
 }
 
 int kgdb_nmicallback(int cpu, void *regs)
@@ -706,12 +710,9 @@
 	ks->cpu			= cpu;
 	ks->linux_regs		= regs;
 
-	if (!atomic_read(&cpu_in_kgdb[cpu]) &&
-	    atomic_read(&kgdb_active) != -1 &&
-	    atomic_read(&kgdb_active) != cpu) {
-		kgdb_info[cpu].exception_state |= DCPU_IS_SLAVE;
-		kgdb_cpu_enter(ks, regs);
-		kgdb_info[cpu].exception_state &= ~DCPU_IS_SLAVE;
+	if (kgdb_info[ks->cpu].enter_kgdb == 0 &&
+			raw_spin_is_locked(&dbg_master_lock)) {
+		kgdb_cpu_enter(ks, regs, DCPU_IS_SLAVE);
 		return 0;
 	}
 #endif
diff --git a/kernel/debug/debug_core.h b/kernel/debug/debug_core.h
index c5d753d..3494c28 100644
--- a/kernel/debug/debug_core.h
+++ b/kernel/debug/debug_core.h
@@ -40,6 +40,7 @@
 	int			exception_state;
 	int			ret_state;
 	int			irq_depth;
+	int			enter_kgdb;
 };
 
 extern struct debuggerinfo_struct kgdb_info[];
diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c
index bf6e827..dd0b1b7 100644
--- a/kernel/debug/kdb/kdb_debugger.c
+++ b/kernel/debug/kdb/kdb_debugger.c
@@ -86,7 +86,7 @@
 	}
 	/* Set initial kdb state variables */
 	KDB_STATE_CLEAR(KGDB_TRANS);
-	kdb_initial_cpu = ks->cpu;
+	kdb_initial_cpu = atomic_read(&kgdb_active);
 	kdb_current_task = kgdb_info[ks->cpu].task;
 	kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
 	/* Remove any breakpoints as needed by kdb and clear single step */
@@ -105,7 +105,6 @@
 		ks->pass_exception = 1;
 		KDB_FLAG_SET(CATASTROPHIC);
 	}
-	kdb_initial_cpu = ks->cpu;
 	if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) {
 		KDB_STATE_CLEAR(SSBPT);
 		KDB_STATE_CLEAR(DOING_SS);
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index c9b7f4f9..96fdaac 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -823,4 +823,4 @@
 
 	return r;
 }
-
+EXPORT_SYMBOL_GPL(kdb_printf);
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index caf057a..d7bda21 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -1749,13 +1749,13 @@
 	int nextarg;
 	long offset;
 
+	if (raw_smp_processor_id() != kdb_initial_cpu) {
+		kdb_printf("go must execute on the entry cpu, "
+			   "please use \"cpu %d\" and then execute go\n",
+			   kdb_initial_cpu);
+		return KDB_BADCPUNUM;
+	}
 	if (argc == 1) {
-		if (raw_smp_processor_id() != kdb_initial_cpu) {
-			kdb_printf("go <address> must be issued from the "
-				   "initial cpu, do cpu %d first\n",
-				   kdb_initial_cpu);
-			return KDB_ARGCOUNT;
-		}
 		nextarg = 1;
 		diag = kdbgetaddrarg(argc, argv, &nextarg,
 				     &addr, &offset, NULL);
@@ -2783,6 +2783,8 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(kdb_register_repeat);
+
 
 /*
  * kdb_register - Compatibility register function for commands that do
@@ -2805,6 +2807,7 @@
 	return kdb_register_repeat(cmd, func, usage, help, minlen,
 				   KDB_REPEAT_NONE);
 }
+EXPORT_SYMBOL_GPL(kdb_register);
 
 /*
  * kdb_unregister - This function is used to unregister a kernel
@@ -2823,7 +2826,7 @@
 	/*
 	 *  find the command.
 	 */
-	for (i = 0, kp = kdb_commands; i < kdb_max_commands; i++, kp++) {
+	for_each_kdbcmd(kp, i) {
 		if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
 			kp->cmd_name = NULL;
 			return 0;
@@ -2833,6 +2836,7 @@
 	/* Couldn't find it.  */
 	return 1;
 }
+EXPORT_SYMBOL_GPL(kdb_unregister);
 
 /* Initialize the kdb command table. */
 static void __init kdb_inittab(void)
diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h
index be775f7..35d69ed 100644
--- a/kernel/debug/kdb/kdb_private.h
+++ b/kernel/debug/kdb/kdb_private.h
@@ -15,29 +15,6 @@
 #include <linux/kgdb.h>
 #include "../debug_core.h"
 
-/* Kernel Debugger Error codes.  Must not overlap with command codes. */
-#define KDB_NOTFOUND	(-1)
-#define KDB_ARGCOUNT	(-2)
-#define KDB_BADWIDTH	(-3)
-#define KDB_BADRADIX	(-4)
-#define KDB_NOTENV	(-5)
-#define KDB_NOENVVALUE	(-6)
-#define KDB_NOTIMP	(-7)
-#define KDB_ENVFULL	(-8)
-#define KDB_ENVBUFFULL	(-9)
-#define KDB_TOOMANYBPT	(-10)
-#define KDB_TOOMANYDBREGS (-11)
-#define KDB_DUPBPT	(-12)
-#define KDB_BPTNOTFOUND	(-13)
-#define KDB_BADMODE	(-14)
-#define KDB_BADINT	(-15)
-#define KDB_INVADDRFMT  (-16)
-#define KDB_BADREG      (-17)
-#define KDB_BADCPUNUM   (-18)
-#define KDB_BADLENGTH	(-19)
-#define KDB_NOBP	(-20)
-#define KDB_BADADDR	(-21)
-
 /* Kernel Debugger Command codes.  Must not overlap with error codes. */
 #define KDB_CMD_GO	(-1001)
 #define KDB_CMD_CPU	(-1002)
@@ -93,17 +70,6 @@
  */
 #define KDB_MAXBPT	16
 
-/* Maximum number of arguments to a function  */
-#define KDB_MAXARGS    16
-
-typedef enum {
-	KDB_REPEAT_NONE = 0,	/* Do not repeat this command */
-	KDB_REPEAT_NO_ARGS,	/* Repeat the command without arguments */
-	KDB_REPEAT_WITH_ARGS,	/* Repeat the command including its arguments */
-} kdb_repeat_t;
-
-typedef int (*kdb_func_t)(int, const char **);
-
 /* Symbol table format returned by kallsyms. */
 typedef struct __ksymtab {
 		unsigned long value;	/* Address of symbol */
@@ -123,11 +89,6 @@
 extern int kallsyms_symbol_complete(char *prefix_name, int max_len);
 
 /* Exported Symbols for kernel loadable modules to use. */
-extern int kdb_register(char *, kdb_func_t, char *, char *, short);
-extern int kdb_register_repeat(char *, kdb_func_t, char *, char *,
-			       short, kdb_repeat_t);
-extern int kdb_unregister(char *);
-
 extern int kdb_getarea_size(void *, unsigned long, size_t);
 extern int kdb_putarea_size(unsigned long, void *, size_t);
 
@@ -144,6 +105,7 @@
 extern int kdb_putword(unsigned long, unsigned long, size_t);
 
 extern int kdbgetularg(const char *, unsigned long *);
+extern int kdbgetu64arg(const char *, u64 *);
 extern char *kdbgetenv(const char *);
 extern int kdbgetaddrarg(int, const char **, int*, unsigned long *,
 			 long *, char **);
@@ -255,14 +217,6 @@
 extern void kdb_print_nameval(const char *name, unsigned long val);
 extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
 extern void kdb_meminfo_proc_show(void);
-#ifdef CONFIG_KALLSYMS
-extern const char *kdb_walk_kallsyms(loff_t *pos);
-#else /* ! CONFIG_KALLSYMS */
-static inline const char *kdb_walk_kallsyms(loff_t *pos)
-{
-	return NULL;
-}
-#endif /* ! CONFIG_KALLSYMS */
 extern char *kdb_getstr(char *, size_t, char *);
 
 /* Defines for kdb_symbol_print */
diff --git a/kernel/gcov/fs.c b/kernel/gcov/fs.c
index f83972b..9bd0934 100644
--- a/kernel/gcov/fs.c
+++ b/kernel/gcov/fs.c
@@ -561,6 +561,7 @@
 static const struct file_operations gcov_reset_fops = {
 	.write	= reset_write,
 	.read	= reset_read,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index ec4210c..56a8919 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2000,6 +2000,7 @@
 static const struct file_operations fops_kp = {
 	.read =         read_enabled_file_bool,
 	.write =        write_enabled_file_bool,
+	.llseek =	default_llseek,
 };
 
 static int __kprobes debugfs_kprobe_init(void)
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 645e541..a96b850 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -110,6 +110,7 @@
 	.write = pm_qos_power_write,
 	.open = pm_qos_power_open,
 	.release = pm_qos_power_release,
+	.llseek = noop_llseek,
 };
 
 /* unlocked internal variant */
diff --git a/kernel/profile.c b/kernel/profile.c
index b22a899..66f841b 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -555,6 +555,7 @@
 static const struct file_operations proc_profile_operations = {
 	.read		= read_profile,
 	.write		= write_profile,
+	.llseek		= default_llseek,
 };
 
 #ifdef CONFIG_SMP
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index a56f629..66cb89b 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -76,7 +76,9 @@
 		}
 
 		if (!lockwakeup && td->bkl == 4) {
+#ifdef CONFIG_LOCK_KERNEL
 			unlock_kernel();
+#endif
 			td->bkl = 0;
 		}
 		return 0;
@@ -133,14 +135,18 @@
 		if (td->bkl)
 			return 0;
 		td->bkl = 1;
+#ifdef CONFIG_LOCK_KERNEL
 		lock_kernel();
+#endif
 		td->bkl = 4;
 		return 0;
 
 	case RTTEST_UNLOCKBKL:
 		if (td->bkl != 4)
 			break;
+#ifdef CONFIG_LOCK_KERNEL
 		unlock_kernel();
+#endif
 		td->bkl = 0;
 		return 0;
 
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 959f8d6..bc251ed 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -23,7 +23,6 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/debugfs.h>
-#include <linux/smp_lock.h>
 #include <linux/time.h>
 #include <linux/uaccess.h>
 
@@ -326,6 +325,7 @@
 	.owner =	THIS_MODULE,
 	.open =		blk_dropped_open,
 	.read =		blk_dropped_read,
+	.llseek =	default_llseek,
 };
 
 static int blk_msg_open(struct inode *inode, struct file *filp)
@@ -365,6 +365,7 @@
 	.owner =	THIS_MODULE,
 	.open =		blk_msg_open,
 	.write =	blk_msg_write,
+	.llseek =	noop_llseek,
 };
 
 /*
@@ -639,7 +640,6 @@
 	if (!q)
 		return -ENXIO;
 
-	lock_kernel();
 	mutex_lock(&bdev->bd_mutex);
 
 	switch (cmd) {
@@ -667,7 +667,6 @@
 	}
 
 	mutex_unlock(&bdev->bd_mutex);
-	unlock_kernel();
 	return ret;
 }
 
@@ -1652,10 +1651,9 @@
 	struct block_device *bdev;
 	ssize_t ret = -ENXIO;
 
-	lock_kernel();
 	bdev = bdget(part_devt(p));
 	if (bdev == NULL)
-		goto out_unlock_kernel;
+		goto out;
 
 	q = blk_trace_get_queue(bdev);
 	if (q == NULL)
@@ -1683,8 +1681,7 @@
 	mutex_unlock(&bdev->bd_mutex);
 out_bdput:
 	bdput(bdev);
-out_unlock_kernel:
-	unlock_kernel();
+out:
 	return ret;
 }
 
@@ -1714,11 +1711,10 @@
 
 	ret = -ENXIO;
 
-	lock_kernel();
 	p = dev_to_part(dev);
 	bdev = bdget(part_devt(p));
 	if (bdev == NULL)
-		goto out_unlock_kernel;
+		goto out;
 
 	q = blk_trace_get_queue(bdev);
 	if (q == NULL)
@@ -1753,8 +1749,6 @@
 	mutex_unlock(&bdev->bd_mutex);
 out_bdput:
 	bdput(bdev);
-out_unlock_kernel:
-	unlock_kernel();
 out:
 	return ret ? ret : count;
 }
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index ebd80d5..f3dadae 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -800,6 +800,7 @@
 	.open		= tracing_open_generic,
 	.read		= ftrace_profile_read,
 	.write		= ftrace_profile_write,
+	.llseek		= default_llseek,
 };
 
 /* used to initialize the real stat files */
@@ -2669,6 +2670,7 @@
 	.read		= seq_read,
 	.write		= ftrace_graph_write,
 	.release	= ftrace_graph_release,
+	.llseek		= seq_lseek,
 };
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index c5a632a..c3dab05 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -3974,6 +3974,7 @@
 	.open		= tracing_open_generic,
 	.read		= rb_simple_read,
 	.write		= rb_simple_write,
+	.llseek		= default_llseek,
 };
 
 
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 398c0e8..0725eea 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -932,6 +932,7 @@
 	.open = tracing_open_generic,
 	.read = event_enable_read,
 	.write = event_enable_write,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_event_format_fops = {
@@ -944,29 +945,34 @@
 static const struct file_operations ftrace_event_id_fops = {
 	.open = tracing_open_generic,
 	.read = event_id_read,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_event_filter_fops = {
 	.open = tracing_open_generic,
 	.read = event_filter_read,
 	.write = event_filter_write,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_subsystem_filter_fops = {
 	.open = tracing_open_generic,
 	.read = subsystem_filter_read,
 	.write = subsystem_filter_write,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_system_enable_fops = {
 	.open = tracing_open_generic,
 	.read = system_enable_read,
 	.write = system_enable_write,
+	.llseek = default_llseek,
 };
 
 static const struct file_operations ftrace_show_header_fops = {
 	.open = tracing_open_generic,
 	.read = show_header,
+	.llseek = default_llseek,
 };
 
 static struct dentry *event_trace_events_dir(void)
diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c
index 7b8ecd7..3c5c5df 100644
--- a/kernel/trace/trace_kdb.c
+++ b/kernel/trace/trace_kdb.c
@@ -13,7 +13,6 @@
 #include <linux/kdb.h>
 #include <linux/ftrace.h>
 
-#include "../debug/kdb/kdb_private.h"
 #include "trace.h"
 #include "trace_output.h"
 
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index a6b7e0e..4c5dead 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -195,6 +195,7 @@
 	.open		= tracing_open_generic,
 	.read		= stack_max_size_read,
 	.write		= stack_max_size_write,
+	.llseek		= default_llseek,
 };
 
 static void *
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index f77afd9..30acdb7 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -42,9 +42,6 @@
 #include <linux/lockdep.h>
 #include <linux/idr.h>
 
-#define CREATE_TRACE_POINTS
-#include <trace/events/workqueue.h>
-
 #include "workqueue_sched.h"
 
 enum {
@@ -257,6 +254,9 @@
 EXPORT_SYMBOL_GPL(system_nrt_wq);
 EXPORT_SYMBOL_GPL(system_unbound_wq);
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/workqueue.h>
+
 #define for_each_busy_worker(worker, i, pos, gcwq)			\
 	for (i = 0; i < BUSY_WORKER_HASH_SIZE; i++)			\
 		hlist_for_each_entry(worker, pos, &gcwq->busy_hash[i], hentry)
@@ -310,21 +310,6 @@
 	     (cpu) < WORK_CPU_NONE;					\
 	     (cpu) = __next_wq_cpu((cpu), cpu_possible_mask, (wq)))
 
-#ifdef CONFIG_LOCKDEP
-/**
- * in_workqueue_context() - in context of specified workqueue?
- * @wq: the workqueue of interest
- *
- * Checks lockdep state to see if the current task is executing from
- * within a workqueue item.  This function exists only if lockdep is
- * enabled.
- */
-int in_workqueue_context(struct workqueue_struct *wq)
-{
-	return lock_is_held(&wq->lockdep_map);
-}
-#endif
-
 #ifdef CONFIG_DEBUG_OBJECTS_WORK
 
 static struct debug_obj_descr work_debug_descr;
@@ -604,7 +589,9 @@
 {
 	atomic_t *nr_running = get_gcwq_nr_running(gcwq->cpu);
 
-	return !list_empty(&gcwq->worklist) && atomic_read(nr_running) <= 1;
+	return !list_empty(&gcwq->worklist) &&
+		(atomic_read(nr_running) <= 1 ||
+		 gcwq->flags & GCWQ_HIGHPRI_PENDING);
 }
 
 /* Do we need a new worker?  Called from manager. */
@@ -997,6 +984,7 @@
 
 	/* gcwq determined, get cwq and queue */
 	cwq = get_cwq(gcwq->cpu, wq);
+	trace_workqueue_queue_work(cpu, cwq, work);
 
 	BUG_ON(!list_empty(&work->entry));
 
@@ -1004,6 +992,7 @@
 	work_flags = work_color_to_flags(cwq->work_color);
 
 	if (likely(cwq->nr_active < cwq->max_active)) {
+		trace_workqueue_activate_work(work);
 		cwq->nr_active++;
 		worklist = gcwq_determine_ins_pos(gcwq, cwq);
 	} else {
@@ -1679,6 +1668,7 @@
 						    struct work_struct, entry);
 	struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq);
 
+	trace_workqueue_activate_work(work);
 	move_linked_works(work, pos, NULL);
 	__clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work));
 	cwq->nr_active++;
@@ -2326,27 +2316,17 @@
 }
 EXPORT_SYMBOL_GPL(flush_workqueue);
 
-/**
- * flush_work - block until a work_struct's callback has terminated
- * @work: the work which is to be flushed
- *
- * Returns false if @work has already terminated.
- *
- * It is expected that, prior to calling flush_work(), the caller has
- * arranged for the work to not be requeued, otherwise it doesn't make
- * sense to use this function.
- */
-int flush_work(struct work_struct *work)
+static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr,
+			     bool wait_executing)
 {
 	struct worker *worker = NULL;
 	struct global_cwq *gcwq;
 	struct cpu_workqueue_struct *cwq;
-	struct wq_barrier barr;
 
 	might_sleep();
 	gcwq = get_work_gcwq(work);
 	if (!gcwq)
-		return 0;
+		return false;
 
 	spin_lock_irq(&gcwq->lock);
 	if (!list_empty(&work->entry)) {
@@ -2359,28 +2339,127 @@
 		cwq = get_work_cwq(work);
 		if (unlikely(!cwq || gcwq != cwq->gcwq))
 			goto already_gone;
-	} else {
+	} else if (wait_executing) {
 		worker = find_worker_executing_work(gcwq, work);
 		if (!worker)
 			goto already_gone;
 		cwq = worker->current_cwq;
-	}
+	} else
+		goto already_gone;
 
-	insert_wq_barrier(cwq, &barr, work, worker);
+	insert_wq_barrier(cwq, barr, work, worker);
 	spin_unlock_irq(&gcwq->lock);
 
 	lock_map_acquire(&cwq->wq->lockdep_map);
 	lock_map_release(&cwq->wq->lockdep_map);
-
-	wait_for_completion(&barr.done);
-	destroy_work_on_stack(&barr.work);
-	return 1;
+	return true;
 already_gone:
 	spin_unlock_irq(&gcwq->lock);
-	return 0;
+	return false;
+}
+
+/**
+ * flush_work - wait for a work to finish executing the last queueing instance
+ * @work: the work to flush
+ *
+ * Wait until @work has finished execution.  This function considers
+ * only the last queueing instance of @work.  If @work has been
+ * enqueued across different CPUs on a non-reentrant workqueue or on
+ * multiple workqueues, @work might still be executing on return on
+ * some of the CPUs from earlier queueing.
+ *
+ * If @work was queued only on a non-reentrant, ordered or unbound
+ * workqueue, @work is guaranteed to be idle on return if it hasn't
+ * been requeued since flush started.
+ *
+ * RETURNS:
+ * %true if flush_work() waited for the work to finish execution,
+ * %false if it was already idle.
+ */
+bool flush_work(struct work_struct *work)
+{
+	struct wq_barrier barr;
+
+	if (start_flush_work(work, &barr, true)) {
+		wait_for_completion(&barr.done);
+		destroy_work_on_stack(&barr.work);
+		return true;
+	} else
+		return false;
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
+static bool wait_on_cpu_work(struct global_cwq *gcwq, struct work_struct *work)
+{
+	struct wq_barrier barr;
+	struct worker *worker;
+
+	spin_lock_irq(&gcwq->lock);
+
+	worker = find_worker_executing_work(gcwq, work);
+	if (unlikely(worker))
+		insert_wq_barrier(worker->current_cwq, &barr, work, worker);
+
+	spin_unlock_irq(&gcwq->lock);
+
+	if (unlikely(worker)) {
+		wait_for_completion(&barr.done);
+		destroy_work_on_stack(&barr.work);
+		return true;
+	} else
+		return false;
+}
+
+static bool wait_on_work(struct work_struct *work)
+{
+	bool ret = false;
+	int cpu;
+
+	might_sleep();
+
+	lock_map_acquire(&work->lockdep_map);
+	lock_map_release(&work->lockdep_map);
+
+	for_each_gcwq_cpu(cpu)
+		ret |= wait_on_cpu_work(get_gcwq(cpu), work);
+	return ret;
+}
+
+/**
+ * flush_work_sync - wait until a work has finished execution
+ * @work: the work to flush
+ *
+ * Wait until @work has finished execution.  On return, it's
+ * guaranteed that all queueing instances of @work which happened
+ * before this function is called are finished.  In other words, if
+ * @work hasn't been requeued since this function was called, @work is
+ * guaranteed to be idle on return.
+ *
+ * RETURNS:
+ * %true if flush_work_sync() waited for the work to finish execution,
+ * %false if it was already idle.
+ */
+bool flush_work_sync(struct work_struct *work)
+{
+	struct wq_barrier barr;
+	bool pending, waited;
+
+	/* we'll wait for executions separately, queue barr only if pending */
+	pending = start_flush_work(work, &barr, false);
+
+	/* wait for executions to finish */
+	waited = wait_on_work(work);
+
+	/* wait for the pending one */
+	if (pending) {
+		wait_for_completion(&barr.done);
+		destroy_work_on_stack(&barr.work);
+	}
+
+	return pending || waited;
+}
+EXPORT_SYMBOL_GPL(flush_work_sync);
+
 /*
  * Upon a successful return (>= 0), the caller "owns" WORK_STRUCT_PENDING bit,
  * so this work can't be re-armed in any way.
@@ -2423,39 +2502,7 @@
 	return ret;
 }
 
-static void wait_on_cpu_work(struct global_cwq *gcwq, struct work_struct *work)
-{
-	struct wq_barrier barr;
-	struct worker *worker;
-
-	spin_lock_irq(&gcwq->lock);
-
-	worker = find_worker_executing_work(gcwq, work);
-	if (unlikely(worker))
-		insert_wq_barrier(worker->current_cwq, &barr, work, worker);
-
-	spin_unlock_irq(&gcwq->lock);
-
-	if (unlikely(worker)) {
-		wait_for_completion(&barr.done);
-		destroy_work_on_stack(&barr.work);
-	}
-}
-
-static void wait_on_work(struct work_struct *work)
-{
-	int cpu;
-
-	might_sleep();
-
-	lock_map_acquire(&work->lockdep_map);
-	lock_map_release(&work->lockdep_map);
-
-	for_each_gcwq_cpu(cpu)
-		wait_on_cpu_work(get_gcwq(cpu), work);
-}
-
-static int __cancel_work_timer(struct work_struct *work,
+static bool __cancel_work_timer(struct work_struct *work,
 				struct timer_list* timer)
 {
 	int ret;
@@ -2472,42 +2519,81 @@
 }
 
 /**
- * cancel_work_sync - block until a work_struct's callback has terminated
- * @work: the work which is to be flushed
+ * cancel_work_sync - cancel a work and wait for it to finish
+ * @work: the work to cancel
  *
- * Returns true if @work was pending.
+ * Cancel @work and wait for its execution to finish.  This function
+ * can be used even if the work re-queues itself or migrates to
+ * another workqueue.  On return from this function, @work is
+ * guaranteed to be not pending or executing on any CPU.
  *
- * cancel_work_sync() will cancel the work if it is queued. If the work's
- * callback appears to be running, cancel_work_sync() will block until it
- * has completed.
+ * cancel_work_sync(&delayed_work->work) must not be used for
+ * delayed_work's.  Use cancel_delayed_work_sync() instead.
  *
- * It is possible to use this function if the work re-queues itself. It can
- * cancel the work even if it migrates to another workqueue, however in that
- * case it only guarantees that work->func() has completed on the last queued
- * workqueue.
- *
- * cancel_work_sync(&delayed_work->work) should be used only if ->timer is not
- * pending, otherwise it goes into a busy-wait loop until the timer expires.
- *
- * The caller must ensure that workqueue_struct on which this work was last
+ * The caller must ensure that the workqueue on which @work was last
  * queued can't be destroyed before this function returns.
+ *
+ * RETURNS:
+ * %true if @work was pending, %false otherwise.
  */
-int cancel_work_sync(struct work_struct *work)
+bool cancel_work_sync(struct work_struct *work)
 {
 	return __cancel_work_timer(work, NULL);
 }
 EXPORT_SYMBOL_GPL(cancel_work_sync);
 
 /**
- * cancel_delayed_work_sync - reliably kill off a delayed work.
- * @dwork: the delayed work struct
+ * flush_delayed_work - wait for a dwork to finish executing the last queueing
+ * @dwork: the delayed work to flush
  *
- * Returns true if @dwork was pending.
+ * Delayed timer is cancelled and the pending work is queued for
+ * immediate execution.  Like flush_work(), this function only
+ * considers the last queueing instance of @dwork.
  *
- * It is possible to use this function if @dwork rearms itself via queue_work()
- * or queue_delayed_work(). See also the comment for cancel_work_sync().
+ * RETURNS:
+ * %true if flush_work() waited for the work to finish execution,
+ * %false if it was already idle.
  */
-int cancel_delayed_work_sync(struct delayed_work *dwork)
+bool flush_delayed_work(struct delayed_work *dwork)
+{
+	if (del_timer_sync(&dwork->timer))
+		__queue_work(raw_smp_processor_id(),
+			     get_work_cwq(&dwork->work)->wq, &dwork->work);
+	return flush_work(&dwork->work);
+}
+EXPORT_SYMBOL(flush_delayed_work);
+
+/**
+ * flush_delayed_work_sync - wait for a dwork to finish
+ * @dwork: the delayed work to flush
+ *
+ * Delayed timer is cancelled and the pending work is queued for
+ * execution immediately.  Other than timer handling, its behavior
+ * is identical to flush_work_sync().
+ *
+ * RETURNS:
+ * %true if flush_work_sync() waited for the work to finish execution,
+ * %false if it was already idle.
+ */
+bool flush_delayed_work_sync(struct delayed_work *dwork)
+{
+	if (del_timer_sync(&dwork->timer))
+		__queue_work(raw_smp_processor_id(),
+			     get_work_cwq(&dwork->work)->wq, &dwork->work);
+	return flush_work_sync(&dwork->work);
+}
+EXPORT_SYMBOL(flush_delayed_work_sync);
+
+/**
+ * cancel_delayed_work_sync - cancel a delayed work and wait for it to finish
+ * @dwork: the delayed work cancel
+ *
+ * This is cancel_work_sync() for delayed works.
+ *
+ * RETURNS:
+ * %true if @dwork was pending, %false otherwise.
+ */
+bool cancel_delayed_work_sync(struct delayed_work *dwork)
 {
 	return __cancel_work_timer(&dwork->work, &dwork->timer);
 }
@@ -2559,23 +2645,6 @@
 EXPORT_SYMBOL(schedule_delayed_work);
 
 /**
- * flush_delayed_work - block until a dwork_struct's callback has terminated
- * @dwork: the delayed work which is to be flushed
- *
- * Any timeout is cancelled, and any pending work is run immediately.
- */
-void flush_delayed_work(struct delayed_work *dwork)
-{
-	if (del_timer_sync(&dwork->timer)) {
-		__queue_work(get_cpu(), get_work_cwq(&dwork->work)->wq,
-			     &dwork->work);
-		put_cpu();
-	}
-	flush_work(&dwork->work);
-}
-EXPORT_SYMBOL(flush_delayed_work);
-
-/**
  * schedule_delayed_work_on - queue work in global workqueue on CPU after delay
  * @cpu: cpu to use
  * @dwork: job to be done
@@ -2592,13 +2661,15 @@
 EXPORT_SYMBOL(schedule_delayed_work_on);
 
 /**
- * schedule_on_each_cpu - call a function on each online CPU from keventd
+ * schedule_on_each_cpu - execute a function synchronously on each online CPU
  * @func: the function to call
  *
- * Returns zero on success.
- * Returns -ve errno on failure.
- *
+ * schedule_on_each_cpu() executes @func on each online CPU using the
+ * system workqueue and blocks until all CPUs have completed.
  * schedule_on_each_cpu() is very slow.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
  */
 int schedule_on_each_cpu(work_func_t func)
 {
@@ -2764,6 +2835,13 @@
 	unsigned int cpu;
 
 	/*
+	 * Workqueues which may be used during memory reclaim should
+	 * have a rescuer to guarantee forward progress.
+	 */
+	if (flags & WQ_MEM_RECLAIM)
+		flags |= WQ_RESCUER;
+
+	/*
 	 * Unbound workqueues aren't concurrency managed and should be
 	 * dispatched to workers immediately.
 	 */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 21ac830..7b2a8ca9 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -461,6 +461,15 @@
 	 This feature allows mutex semantics violations to be detected and
 	 reported.
 
+config BKL
+	bool "Big Kernel Lock" if (SMP || PREEMPT)
+	default y
+	help
+	  This is the traditional lock that is used in old code instead
+	  of proper locking. All drivers that use the BKL should depend
+	  on this symbol.
+	  Say Y here unless you are working on removing the BKL.
+
 config DEBUG_LOCK_ALLOC
 	bool "Lock debugging: detect incorrect freeing of live locks"
 	depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 01e6427..4bfb047 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -590,6 +590,7 @@
 static const struct file_operations filter_fops = {
 	.read  = filter_read,
 	.write = filter_write,
+	.llseek = default_llseek,
 };
 
 static int dma_debug_fs_init(void)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 7bd6df7..3094318 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -393,6 +393,40 @@
 	return 0;
 }
 
+static int ddebug_exec_query(char *query_string)
+{
+	unsigned int flags = 0, mask = 0;
+	struct ddebug_query query;
+#define MAXWORDS 9
+	int nwords;
+	char *words[MAXWORDS];
+
+	nwords = ddebug_tokenize(query_string, words, MAXWORDS);
+	if (nwords <= 0)
+		return -EINVAL;
+	if (ddebug_parse_query(words, nwords-1, &query))
+		return -EINVAL;
+	if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
+		return -EINVAL;
+
+	/* actually go and implement the change */
+	ddebug_change(&query, flags, mask);
+	return 0;
+}
+
+static __initdata char ddebug_setup_string[1024];
+static __init int ddebug_setup_query(char *str)
+{
+	if (strlen(str) >= 1024) {
+		pr_warning("ddebug boot param string too large\n");
+		return 0;
+	}
+	strcpy(ddebug_setup_string, str);
+	return 1;
+}
+
+__setup("ddebug_query=", ddebug_setup_query);
+
 /*
  * File_ops->write method for <debugfs>/dynamic_debug/conrol.  Gathers the
  * command text from userspace, parses and executes it.
@@ -400,12 +434,8 @@
 static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
 				  size_t len, loff_t *offp)
 {
-	unsigned int flags = 0, mask = 0;
-	struct ddebug_query query;
-#define MAXWORDS 9
-	int nwords;
-	char *words[MAXWORDS];
 	char tmpbuf[256];
+	int ret;
 
 	if (len == 0)
 		return 0;
@@ -419,16 +449,9 @@
 		printk(KERN_INFO "%s: read %d bytes from userspace\n",
 			__func__, (int)len);
 
-	nwords = ddebug_tokenize(tmpbuf, words, MAXWORDS);
-	if (nwords <= 0)
-		return -EINVAL;
-	if (ddebug_parse_query(words, nwords-1, &query))
-		return -EINVAL;
-	if (ddebug_parse_flags(words[nwords-1], &flags, &mask))
-		return -EINVAL;
-
-	/* actually go and implement the change */
-	ddebug_change(&query, flags, mask);
+	ret = ddebug_exec_query(tmpbuf);
+	if (ret)
+		return ret;
 
 	*offp += len;
 	return len;
@@ -689,13 +712,14 @@
 	mutex_unlock(&ddebug_lock);
 }
 
-static int __init dynamic_debug_init(void)
+static __initdata int ddebug_init_success;
+
+static int __init dynamic_debug_init_debugfs(void)
 {
 	struct dentry *dir, *file;
-	struct _ddebug *iter, *iter_start;
-	const char *modname = NULL;
-	int ret = 0;
-	int n = 0;
+
+	if (!ddebug_init_success)
+		return -ENODEV;
 
 	dir = debugfs_create_dir("dynamic_debug", NULL);
 	if (!dir)
@@ -706,6 +730,16 @@
 		debugfs_remove(dir);
 		return -ENOMEM;
 	}
+	return 0;
+}
+
+static int __init dynamic_debug_init(void)
+{
+	struct _ddebug *iter, *iter_start;
+	const char *modname = NULL;
+	int ret = 0;
+	int n = 0;
+
 	if (__start___verbose != __stop___verbose) {
 		iter = __start___verbose;
 		modname = iter->modname;
@@ -723,12 +757,26 @@
 		}
 		ret = ddebug_add_module(iter_start, n, modname);
 	}
-out_free:
-	if (ret) {
-		ddebug_remove_all_tables();
-		debugfs_remove(dir);
-		debugfs_remove(file);
+
+	/* ddebug_query boot param got passed -> set it up */
+	if (ddebug_setup_string[0] != '\0') {
+		ret = ddebug_exec_query(ddebug_setup_string);
+		if (ret)
+			pr_warning("Invalid ddebug boot param %s",
+				   ddebug_setup_string);
+		else
+			pr_info("ddebug initialized with string %s",
+				ddebug_setup_string);
 	}
+
+out_free:
+	if (ret)
+		ddebug_remove_all_tables();
+	else
+		ddebug_init_success = 1;
 	return 0;
 }
-module_init(dynamic_debug_init);
+/* Allow early initialization for boot messages via boot param */
+arch_initcall(dynamic_debug_init);
+/* Debugfs setup must be done later */
+module_init(dynamic_debug_init_debugfs);
diff --git a/lib/kobject.c b/lib/kobject.c
index f07c572..82dc34c 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -746,17 +746,56 @@
  */
 struct kobject *kset_find_obj(struct kset *kset, const char *name)
 {
+	return kset_find_obj_hinted(kset, name, NULL);
+}
+
+/**
+ * kset_find_obj_hinted - search for object in kset given a predecessor hint.
+ * @kset: kset we're looking in.
+ * @name: object's name.
+ * @hint: hint to possible object's predecessor.
+ *
+ * Check the hint's next object and if it is a match return it directly,
+ * otherwise, fall back to the behavior of kset_find_obj().  Either way
+ * a reference for the returned object is held and the reference on the
+ * hinted object is released.
+ */
+struct kobject *kset_find_obj_hinted(struct kset *kset, const char *name,
+				     struct kobject *hint)
+{
 	struct kobject *k;
 	struct kobject *ret = NULL;
 
 	spin_lock(&kset->list_lock);
+
+	if (!hint)
+		goto slow_search;
+
+	/* end of list detection */
+	if (hint->entry.next == kset->list.next)
+		goto slow_search;
+
+	k = container_of(hint->entry.next, struct kobject, entry);
+	if (!kobject_name(k) || strcmp(kobject_name(k), name))
+		goto slow_search;
+
+	ret = kobject_get(k);
+	goto unlock_exit;
+
+slow_search:
 	list_for_each_entry(k, &kset->list, entry) {
 		if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
 			ret = kobject_get(k);
 			break;
 		}
 	}
+
+unlock_exit:
 	spin_unlock(&kset->list_lock);
+
+	if (hint)
+		kobject_put(hint);
+
 	return ret;
 }
 
diff --git a/mm/Kconfig b/mm/Kconfig
index f0fb912..c2c8a4a 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -301,3 +301,11 @@
 	  of 1 says that all excess pages should be trimmed.
 
 	  See Documentation/nommu-mmap.txt for more information.
+
+#
+# UP and nommu archs use km based percpu allocator
+#
+config NEED_PER_CPU_KM
+	depends on !SMP
+	bool
+	default y
diff --git a/mm/Makefile b/mm/Makefile
index 34b2546..f73f75a 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -11,7 +11,7 @@
 			   maccess.o page_alloc.o page-writeback.o \
 			   readahead.o swap.o truncate.o vmscan.o shmem.o \
 			   prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
-			   page_isolation.o mm_init.o mmu_context.o \
+			   page_isolation.o mm_init.o mmu_context.o percpu.o \
 			   $(mmu-y)
 obj-y += init-mm.o
 
@@ -36,11 +36,6 @@
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
 obj-$(CONFIG_FS_XIP) += filemap_xip.o
 obj-$(CONFIG_MIGRATION) += migrate.o
-ifdef CONFIG_SMP
-obj-y += percpu.o
-else
-obj-y += percpu_up.o
-endif
 obj-$(CONFIG_QUICKLIST) += quicklist.o
 obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
 obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index dd186c1..d4e940a 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -840,7 +840,6 @@
 	ret = 0;
 	if (drain) {
 		lru_add_drain_all();
-		flush_scheduled_work();
 		cond_resched();
 		drain_all_pages();
 	}
@@ -862,7 +861,6 @@
 	}
 	/* drain all zone's lru pagevec, this is asyncronous... */
 	lru_add_drain_all();
-	flush_scheduled_work();
 	yield();
 	/* drain pcp pages , this is synchrouns. */
 	drain_all_pages();
diff --git a/mm/percpu-km.c b/mm/percpu-km.c
index df68085..89633fe 100644
--- a/mm/percpu-km.c
+++ b/mm/percpu-km.c
@@ -27,7 +27,7 @@
  *   chunk size is not aligned.  percpu-km code will whine about it.
  */
 
-#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
+#if defined(CONFIG_SMP) && defined(CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK)
 #error "contiguous percpu allocation is incompatible with paged first chunk"
 #endif
 
@@ -35,7 +35,11 @@
 
 static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size)
 {
-	/* noop */
+	unsigned int cpu;
+
+	for_each_possible_cpu(cpu)
+		memset((void *)pcpu_chunk_addr(chunk, cpu, 0) + off, 0, size);
+
 	return 0;
 }
 
diff --git a/mm/percpu.c b/mm/percpu.c
index c76ef38..6fc9015 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -76,6 +76,7 @@
 #define PCPU_SLOT_BASE_SHIFT		5	/* 1-31 shares the same slot */
 #define PCPU_DFL_MAP_ALLOC		16	/* start a map with 16 ents */
 
+#ifdef CONFIG_SMP
 /* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */
 #ifndef __addr_to_pcpu_ptr
 #define __addr_to_pcpu_ptr(addr)					\
@@ -89,6 +90,11 @@
 			 (unsigned long)pcpu_base_addr -		\
 			 (unsigned long)__per_cpu_start)
 #endif
+#else	/* CONFIG_SMP */
+/* on UP, it's always identity mapped */
+#define __addr_to_pcpu_ptr(addr)	(void __percpu *)(addr)
+#define __pcpu_ptr_to_addr(ptr)		(void __force *)(ptr)
+#endif	/* CONFIG_SMP */
 
 struct pcpu_chunk {
 	struct list_head	list;		/* linked to pcpu_slot lists */
@@ -820,8 +826,8 @@
  * @size: size of area to allocate in bytes
  * @align: alignment of area (max PAGE_SIZE)
  *
- * Allocate percpu area of @size bytes aligned at @align.  Might
- * sleep.  Might trigger writeouts.
+ * Allocate zero-filled percpu area of @size bytes aligned at @align.
+ * Might sleep.  Might trigger writeouts.
  *
  * CONTEXT:
  * Does GFP_KERNEL allocation.
@@ -840,9 +846,10 @@
  * @size: size of area to allocate in bytes
  * @align: alignment of area (max PAGE_SIZE)
  *
- * Allocate percpu area of @size bytes aligned at @align from reserved
- * percpu area if arch has set it up; otherwise, allocation is served
- * from the same dynamic area.  Might sleep.  Might trigger writeouts.
+ * Allocate zero-filled percpu area of @size bytes aligned at @align
+ * from reserved percpu area if arch has set it up; otherwise,
+ * allocation is served from the same dynamic area.  Might sleep.
+ * Might trigger writeouts.
  *
  * CONTEXT:
  * Does GFP_KERNEL allocation.
@@ -949,6 +956,7 @@
  */
 bool is_kernel_percpu_address(unsigned long addr)
 {
+#ifdef CONFIG_SMP
 	const size_t static_size = __per_cpu_end - __per_cpu_start;
 	void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
 	unsigned int cpu;
@@ -959,6 +967,8 @@
 		if ((void *)addr >= start && (void *)addr < start + static_size)
 			return true;
         }
+#endif
+	/* on UP, can't distinguish from other static vars, always false */
 	return false;
 }
 
@@ -1067,6 +1077,321 @@
 }
 
 /**
+ * pcpu_dump_alloc_info - print out information about pcpu_alloc_info
+ * @lvl: loglevel
+ * @ai: allocation info to dump
+ *
+ * Print out information about @ai using loglevel @lvl.
+ */
+static void pcpu_dump_alloc_info(const char *lvl,
+				 const struct pcpu_alloc_info *ai)
+{
+	int group_width = 1, cpu_width = 1, width;
+	char empty_str[] = "--------";
+	int alloc = 0, alloc_end = 0;
+	int group, v;
+	int upa, apl;	/* units per alloc, allocs per line */
+
+	v = ai->nr_groups;
+	while (v /= 10)
+		group_width++;
+
+	v = num_possible_cpus();
+	while (v /= 10)
+		cpu_width++;
+	empty_str[min_t(int, cpu_width, sizeof(empty_str) - 1)] = '\0';
+
+	upa = ai->alloc_size / ai->unit_size;
+	width = upa * (cpu_width + 1) + group_width + 3;
+	apl = rounddown_pow_of_two(max(60 / width, 1));
+
+	printk("%spcpu-alloc: s%zu r%zu d%zu u%zu alloc=%zu*%zu",
+	       lvl, ai->static_size, ai->reserved_size, ai->dyn_size,
+	       ai->unit_size, ai->alloc_size / ai->atom_size, ai->atom_size);
+
+	for (group = 0; group < ai->nr_groups; group++) {
+		const struct pcpu_group_info *gi = &ai->groups[group];
+		int unit = 0, unit_end = 0;
+
+		BUG_ON(gi->nr_units % upa);
+		for (alloc_end += gi->nr_units / upa;
+		     alloc < alloc_end; alloc++) {
+			if (!(alloc % apl)) {
+				printk("\n");
+				printk("%spcpu-alloc: ", lvl);
+			}
+			printk("[%0*d] ", group_width, group);
+
+			for (unit_end += upa; unit < unit_end; unit++)
+				if (gi->cpu_map[unit] != NR_CPUS)
+					printk("%0*d ", cpu_width,
+					       gi->cpu_map[unit]);
+				else
+					printk("%s ", empty_str);
+		}
+	}
+	printk("\n");
+}
+
+/**
+ * pcpu_setup_first_chunk - initialize the first percpu chunk
+ * @ai: pcpu_alloc_info describing how to percpu area is shaped
+ * @base_addr: mapped address
+ *
+ * Initialize the first percpu chunk which contains the kernel static
+ * perpcu area.  This function is to be called from arch percpu area
+ * setup path.
+ *
+ * @ai contains all information necessary to initialize the first
+ * chunk and prime the dynamic percpu allocator.
+ *
+ * @ai->static_size is the size of static percpu area.
+ *
+ * @ai->reserved_size, if non-zero, specifies the amount of bytes to
+ * reserve after the static area in the first chunk.  This reserves
+ * the first chunk such that it's available only through reserved
+ * percpu allocation.  This is primarily used to serve module percpu
+ * static areas on architectures where the addressing model has
+ * limited offset range for symbol relocations to guarantee module
+ * percpu symbols fall inside the relocatable range.
+ *
+ * @ai->dyn_size determines the number of bytes available for dynamic
+ * allocation in the first chunk.  The area between @ai->static_size +
+ * @ai->reserved_size + @ai->dyn_size and @ai->unit_size is unused.
+ *
+ * @ai->unit_size specifies unit size and must be aligned to PAGE_SIZE
+ * and equal to or larger than @ai->static_size + @ai->reserved_size +
+ * @ai->dyn_size.
+ *
+ * @ai->atom_size is the allocation atom size and used as alignment
+ * for vm areas.
+ *
+ * @ai->alloc_size is the allocation size and always multiple of
+ * @ai->atom_size.  This is larger than @ai->atom_size if
+ * @ai->unit_size is larger than @ai->atom_size.
+ *
+ * @ai->nr_groups and @ai->groups describe virtual memory layout of
+ * percpu areas.  Units which should be colocated are put into the
+ * same group.  Dynamic VM areas will be allocated according to these
+ * groupings.  If @ai->nr_groups is zero, a single group containing
+ * all units is assumed.
+ *
+ * The caller should have mapped the first chunk at @base_addr and
+ * copied static data to each unit.
+ *
+ * If the first chunk ends up with both reserved and dynamic areas, it
+ * is served by two chunks - one to serve the core static and reserved
+ * areas and the other for the dynamic area.  They share the same vm
+ * and page map but uses different area allocation map to stay away
+ * from each other.  The latter chunk is circulated in the chunk slots
+ * and available for dynamic allocation like any other chunks.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
+				  void *base_addr)
+{
+	static char cpus_buf[4096] __initdata;
+	static int smap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
+	static int dmap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
+	size_t dyn_size = ai->dyn_size;
+	size_t size_sum = ai->static_size + ai->reserved_size + dyn_size;
+	struct pcpu_chunk *schunk, *dchunk = NULL;
+	unsigned long *group_offsets;
+	size_t *group_sizes;
+	unsigned long *unit_off;
+	unsigned int cpu;
+	int *unit_map;
+	int group, unit, i;
+
+	cpumask_scnprintf(cpus_buf, sizeof(cpus_buf), cpu_possible_mask);
+
+#define PCPU_SETUP_BUG_ON(cond)	do {					\
+	if (unlikely(cond)) {						\
+		pr_emerg("PERCPU: failed to initialize, %s", #cond);	\
+		pr_emerg("PERCPU: cpu_possible_mask=%s\n", cpus_buf);	\
+		pcpu_dump_alloc_info(KERN_EMERG, ai);			\
+		BUG();							\
+	}								\
+} while (0)
+
+	/* sanity checks */
+	PCPU_SETUP_BUG_ON(ai->nr_groups <= 0);
+#ifdef CONFIG_SMP
+	PCPU_SETUP_BUG_ON(!ai->static_size);
+#endif
+	PCPU_SETUP_BUG_ON(!base_addr);
+	PCPU_SETUP_BUG_ON(ai->unit_size < size_sum);
+	PCPU_SETUP_BUG_ON(ai->unit_size & ~PAGE_MASK);
+	PCPU_SETUP_BUG_ON(ai->unit_size < PCPU_MIN_UNIT_SIZE);
+	PCPU_SETUP_BUG_ON(ai->dyn_size < PERCPU_DYNAMIC_EARLY_SIZE);
+	PCPU_SETUP_BUG_ON(pcpu_verify_alloc_info(ai) < 0);
+
+	/* process group information and build config tables accordingly */
+	group_offsets = alloc_bootmem(ai->nr_groups * sizeof(group_offsets[0]));
+	group_sizes = alloc_bootmem(ai->nr_groups * sizeof(group_sizes[0]));
+	unit_map = alloc_bootmem(nr_cpu_ids * sizeof(unit_map[0]));
+	unit_off = alloc_bootmem(nr_cpu_ids * sizeof(unit_off[0]));
+
+	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+		unit_map[cpu] = UINT_MAX;
+	pcpu_first_unit_cpu = NR_CPUS;
+
+	for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
+		const struct pcpu_group_info *gi = &ai->groups[group];
+
+		group_offsets[group] = gi->base_offset;
+		group_sizes[group] = gi->nr_units * ai->unit_size;
+
+		for (i = 0; i < gi->nr_units; i++) {
+			cpu = gi->cpu_map[i];
+			if (cpu == NR_CPUS)
+				continue;
+
+			PCPU_SETUP_BUG_ON(cpu > nr_cpu_ids);
+			PCPU_SETUP_BUG_ON(!cpu_possible(cpu));
+			PCPU_SETUP_BUG_ON(unit_map[cpu] != UINT_MAX);
+
+			unit_map[cpu] = unit + i;
+			unit_off[cpu] = gi->base_offset + i * ai->unit_size;
+
+			if (pcpu_first_unit_cpu == NR_CPUS)
+				pcpu_first_unit_cpu = cpu;
+			pcpu_last_unit_cpu = cpu;
+		}
+	}
+	pcpu_nr_units = unit;
+
+	for_each_possible_cpu(cpu)
+		PCPU_SETUP_BUG_ON(unit_map[cpu] == UINT_MAX);
+
+	/* we're done parsing the input, undefine BUG macro and dump config */
+#undef PCPU_SETUP_BUG_ON
+	pcpu_dump_alloc_info(KERN_INFO, ai);
+
+	pcpu_nr_groups = ai->nr_groups;
+	pcpu_group_offsets = group_offsets;
+	pcpu_group_sizes = group_sizes;
+	pcpu_unit_map = unit_map;
+	pcpu_unit_offsets = unit_off;
+
+	/* determine basic parameters */
+	pcpu_unit_pages = ai->unit_size >> PAGE_SHIFT;
+	pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT;
+	pcpu_atom_size = ai->atom_size;
+	pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) +
+		BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long);
+
+	/*
+	 * Allocate chunk slots.  The additional last slot is for
+	 * empty chunks.
+	 */
+	pcpu_nr_slots = __pcpu_size_to_slot(pcpu_unit_size) + 2;
+	pcpu_slot = alloc_bootmem(pcpu_nr_slots * sizeof(pcpu_slot[0]));
+	for (i = 0; i < pcpu_nr_slots; i++)
+		INIT_LIST_HEAD(&pcpu_slot[i]);
+
+	/*
+	 * Initialize static chunk.  If reserved_size is zero, the
+	 * static chunk covers static area + dynamic allocation area
+	 * in the first chunk.  If reserved_size is not zero, it
+	 * covers static area + reserved area (mostly used for module
+	 * static percpu allocation).
+	 */
+	schunk = alloc_bootmem(pcpu_chunk_struct_size);
+	INIT_LIST_HEAD(&schunk->list);
+	schunk->base_addr = base_addr;
+	schunk->map = smap;
+	schunk->map_alloc = ARRAY_SIZE(smap);
+	schunk->immutable = true;
+	bitmap_fill(schunk->populated, pcpu_unit_pages);
+
+	if (ai->reserved_size) {
+		schunk->free_size = ai->reserved_size;
+		pcpu_reserved_chunk = schunk;
+		pcpu_reserved_chunk_limit = ai->static_size + ai->reserved_size;
+	} else {
+		schunk->free_size = dyn_size;
+		dyn_size = 0;			/* dynamic area covered */
+	}
+	schunk->contig_hint = schunk->free_size;
+
+	schunk->map[schunk->map_used++] = -ai->static_size;
+	if (schunk->free_size)
+		schunk->map[schunk->map_used++] = schunk->free_size;
+
+	/* init dynamic chunk if necessary */
+	if (dyn_size) {
+		dchunk = alloc_bootmem(pcpu_chunk_struct_size);
+		INIT_LIST_HEAD(&dchunk->list);
+		dchunk->base_addr = base_addr;
+		dchunk->map = dmap;
+		dchunk->map_alloc = ARRAY_SIZE(dmap);
+		dchunk->immutable = true;
+		bitmap_fill(dchunk->populated, pcpu_unit_pages);
+
+		dchunk->contig_hint = dchunk->free_size = dyn_size;
+		dchunk->map[dchunk->map_used++] = -pcpu_reserved_chunk_limit;
+		dchunk->map[dchunk->map_used++] = dchunk->free_size;
+	}
+
+	/* link the first chunk in */
+	pcpu_first_chunk = dchunk ?: schunk;
+	pcpu_chunk_relocate(pcpu_first_chunk, -1);
+
+	/* we're done */
+	pcpu_base_addr = base_addr;
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+
+const char *pcpu_fc_names[PCPU_FC_NR] __initdata = {
+	[PCPU_FC_AUTO]	= "auto",
+	[PCPU_FC_EMBED]	= "embed",
+	[PCPU_FC_PAGE]	= "page",
+};
+
+enum pcpu_fc pcpu_chosen_fc __initdata = PCPU_FC_AUTO;
+
+static int __init percpu_alloc_setup(char *str)
+{
+	if (0)
+		/* nada */;
+#ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK
+	else if (!strcmp(str, "embed"))
+		pcpu_chosen_fc = PCPU_FC_EMBED;
+#endif
+#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
+	else if (!strcmp(str, "page"))
+		pcpu_chosen_fc = PCPU_FC_PAGE;
+#endif
+	else
+		pr_warning("PERCPU: unknown allocator %s specified\n", str);
+
+	return 0;
+}
+early_param("percpu_alloc", percpu_alloc_setup);
+
+/*
+ * pcpu_embed_first_chunk() is used by the generic percpu setup.
+ * Build it if needed by the arch config or the generic setup is going
+ * to be used.
+ */
+#if defined(CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK) || \
+	!defined(CONFIG_HAVE_SETUP_PER_CPU_AREA)
+#define BUILD_EMBED_FIRST_CHUNK
+#endif
+
+/* build pcpu_page_first_chunk() iff needed by the arch config */
+#if defined(CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK)
+#define BUILD_PAGE_FIRST_CHUNK
+#endif
+
+/* pcpu_build_alloc_info() is used by both embed and page first chunk */
+#if defined(BUILD_EMBED_FIRST_CHUNK) || defined(BUILD_PAGE_FIRST_CHUNK)
+/**
  * pcpu_build_alloc_info - build alloc_info considering distances between CPUs
  * @reserved_size: the size of reserved percpu area in bytes
  * @dyn_size: minimum free size for dynamic allocation in bytes
@@ -1220,303 +1545,9 @@
 
 	return ai;
 }
+#endif /* BUILD_EMBED_FIRST_CHUNK || BUILD_PAGE_FIRST_CHUNK */
 
-/**
- * pcpu_dump_alloc_info - print out information about pcpu_alloc_info
- * @lvl: loglevel
- * @ai: allocation info to dump
- *
- * Print out information about @ai using loglevel @lvl.
- */
-static void pcpu_dump_alloc_info(const char *lvl,
-				 const struct pcpu_alloc_info *ai)
-{
-	int group_width = 1, cpu_width = 1, width;
-	char empty_str[] = "--------";
-	int alloc = 0, alloc_end = 0;
-	int group, v;
-	int upa, apl;	/* units per alloc, allocs per line */
-
-	v = ai->nr_groups;
-	while (v /= 10)
-		group_width++;
-
-	v = num_possible_cpus();
-	while (v /= 10)
-		cpu_width++;
-	empty_str[min_t(int, cpu_width, sizeof(empty_str) - 1)] = '\0';
-
-	upa = ai->alloc_size / ai->unit_size;
-	width = upa * (cpu_width + 1) + group_width + 3;
-	apl = rounddown_pow_of_two(max(60 / width, 1));
-
-	printk("%spcpu-alloc: s%zu r%zu d%zu u%zu alloc=%zu*%zu",
-	       lvl, ai->static_size, ai->reserved_size, ai->dyn_size,
-	       ai->unit_size, ai->alloc_size / ai->atom_size, ai->atom_size);
-
-	for (group = 0; group < ai->nr_groups; group++) {
-		const struct pcpu_group_info *gi = &ai->groups[group];
-		int unit = 0, unit_end = 0;
-
-		BUG_ON(gi->nr_units % upa);
-		for (alloc_end += gi->nr_units / upa;
-		     alloc < alloc_end; alloc++) {
-			if (!(alloc % apl)) {
-				printk("\n");
-				printk("%spcpu-alloc: ", lvl);
-			}
-			printk("[%0*d] ", group_width, group);
-
-			for (unit_end += upa; unit < unit_end; unit++)
-				if (gi->cpu_map[unit] != NR_CPUS)
-					printk("%0*d ", cpu_width,
-					       gi->cpu_map[unit]);
-				else
-					printk("%s ", empty_str);
-		}
-	}
-	printk("\n");
-}
-
-/**
- * pcpu_setup_first_chunk - initialize the first percpu chunk
- * @ai: pcpu_alloc_info describing how to percpu area is shaped
- * @base_addr: mapped address
- *
- * Initialize the first percpu chunk which contains the kernel static
- * perpcu area.  This function is to be called from arch percpu area
- * setup path.
- *
- * @ai contains all information necessary to initialize the first
- * chunk and prime the dynamic percpu allocator.
- *
- * @ai->static_size is the size of static percpu area.
- *
- * @ai->reserved_size, if non-zero, specifies the amount of bytes to
- * reserve after the static area in the first chunk.  This reserves
- * the first chunk such that it's available only through reserved
- * percpu allocation.  This is primarily used to serve module percpu
- * static areas on architectures where the addressing model has
- * limited offset range for symbol relocations to guarantee module
- * percpu symbols fall inside the relocatable range.
- *
- * @ai->dyn_size determines the number of bytes available for dynamic
- * allocation in the first chunk.  The area between @ai->static_size +
- * @ai->reserved_size + @ai->dyn_size and @ai->unit_size is unused.
- *
- * @ai->unit_size specifies unit size and must be aligned to PAGE_SIZE
- * and equal to or larger than @ai->static_size + @ai->reserved_size +
- * @ai->dyn_size.
- *
- * @ai->atom_size is the allocation atom size and used as alignment
- * for vm areas.
- *
- * @ai->alloc_size is the allocation size and always multiple of
- * @ai->atom_size.  This is larger than @ai->atom_size if
- * @ai->unit_size is larger than @ai->atom_size.
- *
- * @ai->nr_groups and @ai->groups describe virtual memory layout of
- * percpu areas.  Units which should be colocated are put into the
- * same group.  Dynamic VM areas will be allocated according to these
- * groupings.  If @ai->nr_groups is zero, a single group containing
- * all units is assumed.
- *
- * The caller should have mapped the first chunk at @base_addr and
- * copied static data to each unit.
- *
- * If the first chunk ends up with both reserved and dynamic areas, it
- * is served by two chunks - one to serve the core static and reserved
- * areas and the other for the dynamic area.  They share the same vm
- * and page map but uses different area allocation map to stay away
- * from each other.  The latter chunk is circulated in the chunk slots
- * and available for dynamic allocation like any other chunks.
- *
- * RETURNS:
- * 0 on success, -errno on failure.
- */
-int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
-				  void *base_addr)
-{
-	static char cpus_buf[4096] __initdata;
-	static int smap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
-	static int dmap[PERCPU_DYNAMIC_EARLY_SLOTS] __initdata;
-	size_t dyn_size = ai->dyn_size;
-	size_t size_sum = ai->static_size + ai->reserved_size + dyn_size;
-	struct pcpu_chunk *schunk, *dchunk = NULL;
-	unsigned long *group_offsets;
-	size_t *group_sizes;
-	unsigned long *unit_off;
-	unsigned int cpu;
-	int *unit_map;
-	int group, unit, i;
-
-	cpumask_scnprintf(cpus_buf, sizeof(cpus_buf), cpu_possible_mask);
-
-#define PCPU_SETUP_BUG_ON(cond)	do {					\
-	if (unlikely(cond)) {						\
-		pr_emerg("PERCPU: failed to initialize, %s", #cond);	\
-		pr_emerg("PERCPU: cpu_possible_mask=%s\n", cpus_buf);	\
-		pcpu_dump_alloc_info(KERN_EMERG, ai);			\
-		BUG();							\
-	}								\
-} while (0)
-
-	/* sanity checks */
-	PCPU_SETUP_BUG_ON(ai->nr_groups <= 0);
-	PCPU_SETUP_BUG_ON(!ai->static_size);
-	PCPU_SETUP_BUG_ON(!base_addr);
-	PCPU_SETUP_BUG_ON(ai->unit_size < size_sum);
-	PCPU_SETUP_BUG_ON(ai->unit_size & ~PAGE_MASK);
-	PCPU_SETUP_BUG_ON(ai->unit_size < PCPU_MIN_UNIT_SIZE);
-	PCPU_SETUP_BUG_ON(ai->dyn_size < PERCPU_DYNAMIC_EARLY_SIZE);
-	PCPU_SETUP_BUG_ON(pcpu_verify_alloc_info(ai) < 0);
-
-	/* process group information and build config tables accordingly */
-	group_offsets = alloc_bootmem(ai->nr_groups * sizeof(group_offsets[0]));
-	group_sizes = alloc_bootmem(ai->nr_groups * sizeof(group_sizes[0]));
-	unit_map = alloc_bootmem(nr_cpu_ids * sizeof(unit_map[0]));
-	unit_off = alloc_bootmem(nr_cpu_ids * sizeof(unit_off[0]));
-
-	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
-		unit_map[cpu] = UINT_MAX;
-	pcpu_first_unit_cpu = NR_CPUS;
-
-	for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
-		const struct pcpu_group_info *gi = &ai->groups[group];
-
-		group_offsets[group] = gi->base_offset;
-		group_sizes[group] = gi->nr_units * ai->unit_size;
-
-		for (i = 0; i < gi->nr_units; i++) {
-			cpu = gi->cpu_map[i];
-			if (cpu == NR_CPUS)
-				continue;
-
-			PCPU_SETUP_BUG_ON(cpu > nr_cpu_ids);
-			PCPU_SETUP_BUG_ON(!cpu_possible(cpu));
-			PCPU_SETUP_BUG_ON(unit_map[cpu] != UINT_MAX);
-
-			unit_map[cpu] = unit + i;
-			unit_off[cpu] = gi->base_offset + i * ai->unit_size;
-
-			if (pcpu_first_unit_cpu == NR_CPUS)
-				pcpu_first_unit_cpu = cpu;
-			pcpu_last_unit_cpu = cpu;
-		}
-	}
-	pcpu_nr_units = unit;
-
-	for_each_possible_cpu(cpu)
-		PCPU_SETUP_BUG_ON(unit_map[cpu] == UINT_MAX);
-
-	/* we're done parsing the input, undefine BUG macro and dump config */
-#undef PCPU_SETUP_BUG_ON
-	pcpu_dump_alloc_info(KERN_INFO, ai);
-
-	pcpu_nr_groups = ai->nr_groups;
-	pcpu_group_offsets = group_offsets;
-	pcpu_group_sizes = group_sizes;
-	pcpu_unit_map = unit_map;
-	pcpu_unit_offsets = unit_off;
-
-	/* determine basic parameters */
-	pcpu_unit_pages = ai->unit_size >> PAGE_SHIFT;
-	pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT;
-	pcpu_atom_size = ai->atom_size;
-	pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) +
-		BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long);
-
-	/*
-	 * Allocate chunk slots.  The additional last slot is for
-	 * empty chunks.
-	 */
-	pcpu_nr_slots = __pcpu_size_to_slot(pcpu_unit_size) + 2;
-	pcpu_slot = alloc_bootmem(pcpu_nr_slots * sizeof(pcpu_slot[0]));
-	for (i = 0; i < pcpu_nr_slots; i++)
-		INIT_LIST_HEAD(&pcpu_slot[i]);
-
-	/*
-	 * Initialize static chunk.  If reserved_size is zero, the
-	 * static chunk covers static area + dynamic allocation area
-	 * in the first chunk.  If reserved_size is not zero, it
-	 * covers static area + reserved area (mostly used for module
-	 * static percpu allocation).
-	 */
-	schunk = alloc_bootmem(pcpu_chunk_struct_size);
-	INIT_LIST_HEAD(&schunk->list);
-	schunk->base_addr = base_addr;
-	schunk->map = smap;
-	schunk->map_alloc = ARRAY_SIZE(smap);
-	schunk->immutable = true;
-	bitmap_fill(schunk->populated, pcpu_unit_pages);
-
-	if (ai->reserved_size) {
-		schunk->free_size = ai->reserved_size;
-		pcpu_reserved_chunk = schunk;
-		pcpu_reserved_chunk_limit = ai->static_size + ai->reserved_size;
-	} else {
-		schunk->free_size = dyn_size;
-		dyn_size = 0;			/* dynamic area covered */
-	}
-	schunk->contig_hint = schunk->free_size;
-
-	schunk->map[schunk->map_used++] = -ai->static_size;
-	if (schunk->free_size)
-		schunk->map[schunk->map_used++] = schunk->free_size;
-
-	/* init dynamic chunk if necessary */
-	if (dyn_size) {
-		dchunk = alloc_bootmem(pcpu_chunk_struct_size);
-		INIT_LIST_HEAD(&dchunk->list);
-		dchunk->base_addr = base_addr;
-		dchunk->map = dmap;
-		dchunk->map_alloc = ARRAY_SIZE(dmap);
-		dchunk->immutable = true;
-		bitmap_fill(dchunk->populated, pcpu_unit_pages);
-
-		dchunk->contig_hint = dchunk->free_size = dyn_size;
-		dchunk->map[dchunk->map_used++] = -pcpu_reserved_chunk_limit;
-		dchunk->map[dchunk->map_used++] = dchunk->free_size;
-	}
-
-	/* link the first chunk in */
-	pcpu_first_chunk = dchunk ?: schunk;
-	pcpu_chunk_relocate(pcpu_first_chunk, -1);
-
-	/* we're done */
-	pcpu_base_addr = base_addr;
-	return 0;
-}
-
-const char *pcpu_fc_names[PCPU_FC_NR] __initdata = {
-	[PCPU_FC_AUTO]	= "auto",
-	[PCPU_FC_EMBED]	= "embed",
-	[PCPU_FC_PAGE]	= "page",
-};
-
-enum pcpu_fc pcpu_chosen_fc __initdata = PCPU_FC_AUTO;
-
-static int __init percpu_alloc_setup(char *str)
-{
-	if (0)
-		/* nada */;
-#ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK
-	else if (!strcmp(str, "embed"))
-		pcpu_chosen_fc = PCPU_FC_EMBED;
-#endif
-#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
-	else if (!strcmp(str, "page"))
-		pcpu_chosen_fc = PCPU_FC_PAGE;
-#endif
-	else
-		pr_warning("PERCPU: unknown allocator %s specified\n", str);
-
-	return 0;
-}
-early_param("percpu_alloc", percpu_alloc_setup);
-
-#if defined(CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK) || \
-	!defined(CONFIG_HAVE_SETUP_PER_CPU_AREA)
+#if defined(BUILD_EMBED_FIRST_CHUNK)
 /**
  * pcpu_embed_first_chunk - embed the first percpu chunk into bootmem
  * @reserved_size: the size of reserved percpu area in bytes
@@ -1645,10 +1676,9 @@
 		free_bootmem(__pa(areas), areas_size);
 	return rc;
 }
-#endif /* CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK ||
-	  !CONFIG_HAVE_SETUP_PER_CPU_AREA */
+#endif /* BUILD_EMBED_FIRST_CHUNK */
 
-#ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK
+#ifdef BUILD_PAGE_FIRST_CHUNK
 /**
  * pcpu_page_first_chunk - map the first chunk using PAGE_SIZE pages
  * @reserved_size: the size of reserved percpu area in bytes
@@ -1756,10 +1786,11 @@
 	pcpu_free_alloc_info(ai);
 	return rc;
 }
-#endif /* CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK */
+#endif /* BUILD_PAGE_FIRST_CHUNK */
 
+#ifndef	CONFIG_HAVE_SETUP_PER_CPU_AREA
 /*
- * Generic percpu area setup.
+ * Generic SMP percpu area setup.
  *
  * The embedding helper is used because its behavior closely resembles
  * the original non-dynamic generic percpu area setup.  This is
@@ -1770,7 +1801,6 @@
  * on the physical linear memory mapping which uses large page
  * mappings on applicable archs.
  */
-#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
 unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(__per_cpu_offset);
 
@@ -1799,13 +1829,48 @@
 				    PERCPU_DYNAMIC_RESERVE, PAGE_SIZE, NULL,
 				    pcpu_dfl_fc_alloc, pcpu_dfl_fc_free);
 	if (rc < 0)
-		panic("Failed to initialized percpu areas.");
+		panic("Failed to initialize percpu areas.");
 
 	delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
 	for_each_possible_cpu(cpu)
 		__per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu];
 }
-#endif /* CONFIG_HAVE_SETUP_PER_CPU_AREA */
+#endif	/* CONFIG_HAVE_SETUP_PER_CPU_AREA */
+
+#else	/* CONFIG_SMP */
+
+/*
+ * UP percpu area setup.
+ *
+ * UP always uses km-based percpu allocator with identity mapping.
+ * Static percpu variables are indistinguishable from the usual static
+ * variables and don't require any special preparation.
+ */
+void __init setup_per_cpu_areas(void)
+{
+	const size_t unit_size =
+		roundup_pow_of_two(max_t(size_t, PCPU_MIN_UNIT_SIZE,
+					 PERCPU_DYNAMIC_RESERVE));
+	struct pcpu_alloc_info *ai;
+	void *fc;
+
+	ai = pcpu_alloc_alloc_info(1, 1);
+	fc = __alloc_bootmem(unit_size, PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
+	if (!ai || !fc)
+		panic("Failed to allocate memory for percpu areas.");
+
+	ai->dyn_size = unit_size;
+	ai->unit_size = unit_size;
+	ai->atom_size = unit_size;
+	ai->alloc_size = unit_size;
+	ai->groups[0].nr_units = 1;
+	ai->groups[0].cpu_map[0] = 0;
+
+	if (pcpu_setup_first_chunk(ai, fc) < 0)
+		panic("Failed to initialize percpu areas.");
+}
+
+#endif	/* CONFIG_SMP */
 
 /*
  * First and reserved chunks are initialized with temporary allocation
diff --git a/mm/percpu_up.c b/mm/percpu_up.c
deleted file mode 100644
index db884fa..0000000
--- a/mm/percpu_up.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * mm/percpu_up.c - dummy percpu memory allocator implementation for UP
- */
-
-#include <linux/module.h>
-#include <linux/percpu.h>
-#include <linux/slab.h>
-
-void __percpu *__alloc_percpu(size_t size, size_t align)
-{
-	/*
-	 * Can't easily make larger alignment work with kmalloc.  WARN
-	 * on it.  Larger alignment should only be used for module
-	 * percpu sections on SMP for which this path isn't used.
-	 */
-	WARN_ON_ONCE(align > SMP_CACHE_BYTES);
-	return (void __percpu __force *)kzalloc(size, GFP_KERNEL);
-}
-EXPORT_SYMBOL_GPL(__alloc_percpu);
-
-void free_percpu(void __percpu *p)
-{
-	kfree(this_cpu_ptr(p));
-}
-EXPORT_SYMBOL_GPL(free_percpu);
-
-phys_addr_t per_cpu_ptr_to_phys(void *addr)
-{
-	return __pa(addr);
-}
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 7c703ff..9fc7bac 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -139,7 +139,7 @@
 	nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9);
 	if (nr_blocks) {
 		err = blkdev_issue_discard(si->bdev, start_block,
-				nr_blocks, GFP_KERNEL, BLKDEV_IFL_WAIT);
+				nr_blocks, GFP_KERNEL, 0);
 		if (err)
 			return err;
 		cond_resched();
@@ -150,7 +150,7 @@
 		nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9);
 
 		err = blkdev_issue_discard(si->bdev, start_block,
-				nr_blocks, GFP_KERNEL, BLKDEV_IFL_WAIT);
+				nr_blocks, GFP_KERNEL, 0);
 		if (err)
 			break;
 
@@ -189,7 +189,7 @@
 			start_block <<= PAGE_SHIFT - 9;
 			nr_blocks <<= PAGE_SHIFT - 9;
 			if (blkdev_issue_discard(si->bdev, start_block,
-				    nr_blocks, GFP_NOIO, BLKDEV_IFL_WAIT))
+				    nr_blocks, GFP_NOIO, 0))
 				break;
 		}
 
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index d8087f0..9f90962 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2065,6 +2065,7 @@
 }
 EXPORT_SYMBOL_GPL(free_vm_area);
 
+#ifdef CONFIG_SMP
 static struct vmap_area *node_to_va(struct rb_node *n)
 {
 	return n ? rb_entry(n, struct vmap_area, rb_node) : NULL;
@@ -2345,6 +2346,7 @@
 		free_vm_area(vms[i]);
 	kfree(vms);
 }
+#endif	/* CONFIG_SMP */
 
 #ifdef CONFIG_PROC_FS
 static void *s_start(struct seq_file *m, loff_t *pos)
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 6262aea..f85da077 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -38,6 +38,7 @@
 static const struct file_operations proc_atm_dev_ops = {
 	.owner =	THIS_MODULE,
 	.read =		proc_dev_atm_read,
+	.llseek =	noop_llseek,
 };
 
 static void add_stats(struct seq_file *seq, const char *aal,
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index befc3a5..84c2a4d 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -844,10 +844,6 @@
 		BT_DBG("TIOCMIWAIT");
 		break;
 
-	case TIOCGICOUNT:
-		BT_DBG("TIOCGICOUNT");
-		break;
-
 	case TIOCGSERIAL:
 		BT_ERR("TIOCGSERIAL is not supported");
 		return -ENOIOCTLCMD;
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index 078e48d..33d0e62 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -149,6 +149,7 @@
 	.owner	 = THIS_MODULE,
 	.open	 = dccpprobe_open,
 	.read    = dccpprobe_read,
+	.llseek  = noop_llseek,
 };
 
 static __init int dccpprobe_init(void)
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index f8efada..6211e21 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -214,6 +214,7 @@
 	.owner	 = THIS_MODULE,
 	.open	 = tcpprobe_open,
 	.read    = tcpprobe_read,
+	.llseek  = noop_llseek,
 };
 
 static __init int tcpprobe_init(void)
diff --git a/net/ipx/Kconfig b/net/ipx/Kconfig
index e9ad006..02549cb 100644
--- a/net/ipx/Kconfig
+++ b/net/ipx/Kconfig
@@ -3,6 +3,7 @@
 #
 config IPX
 	tristate "The IPX protocol"
+	depends on BKL # should be fixable
 	select LLC
 	---help---
 	  This is support for the Novell networking protocol, IPX, commonly
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index a694c59..b8b0ae7 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -36,6 +36,7 @@
 static const struct file_operations name## _ops = {			\
 	.read = name## _read,						\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 };
 
 #define DEBUGFS_ADD(name)						\
@@ -101,7 +102,8 @@
 static const struct file_operations tsf_ops = {
 	.read = tsf_read,
 	.write = tsf_write,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t reset_write(struct file *file, const char __user *user_buf,
@@ -120,6 +122,7 @@
 static const struct file_operations reset_ops = {
 	.write = reset_write,
 	.open = mac80211_open_file_generic,
+	.llseek = noop_llseek,
 };
 
 static ssize_t noack_read(struct file *file, char __user *user_buf,
@@ -155,7 +158,8 @@
 static const struct file_operations noack_ops = {
 	.read = noack_read,
 	.write = noack_write,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf,
@@ -201,7 +205,8 @@
 static const struct file_operations uapsd_queues_ops = {
 	.read = uapsd_queues_read,
 	.write = uapsd_queues_write,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf,
@@ -247,7 +252,8 @@
 static const struct file_operations uapsd_max_sp_len_ops = {
 	.read = uapsd_max_sp_len_read,
 	.write = uapsd_max_sp_len_write,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t channel_type_read(struct file *file, char __user *user_buf,
@@ -279,7 +285,8 @@
 
 static const struct file_operations channel_type_ops = {
 	.read = channel_type_read,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 static ssize_t queues_read(struct file *file, char __user *user_buf,
@@ -302,7 +309,8 @@
 
 static const struct file_operations queues_ops = {
 	.read = queues_read,
-	.open = mac80211_open_file_generic
+	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 /* statistics stuff */
@@ -346,6 +354,7 @@
 static const struct file_operations stats_ ##name## _ops = {		\
 	.read = stats_ ##name## _read,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 };
 
 #define DEBUGFS_STATS_ADD(name, field)					\
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index fa5e76e..7cd8dd9 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -32,6 +32,7 @@
 static const struct file_operations key_ ##name## _ops = {		\
 	.read = key_##name##_read,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define KEY_FILE(name, format)						\
@@ -46,6 +47,7 @@
 static const struct file_operations key_ ##name## _ops = {		\
 	.read = key_conf_##name##_read,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define KEY_CONF_FILE(name, format)					\
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 20b2998..8ad33ee 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -121,6 +121,7 @@
 	.read = ieee80211_if_read_##name,				\
 	.write = (_write),						\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define __IEEE80211_IF_FILE_W(name)					\
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 76839d4..6a8fdc3 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -36,6 +36,7 @@
 static const struct file_operations sta_ ##name## _ops = {		\
 	.read = sta_##name##_read,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define STA_OPS_RW(name)						\
@@ -43,6 +44,7 @@
 	.read = sta_##name##_read,					\
 	.write = sta_##name##_write,					\
 	.open = mac80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 }
 
 #define STA_FILE(name, field, format)					\
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index be04d461..334cbd3 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -145,6 +145,7 @@
 static const struct file_operations rcname_ops = {
 	.read = rcname_read,
 	.open = mac80211_open_file_generic,
+	.llseek = default_llseek,
 };
 #endif
 
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 241e76f..a290ad23 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -122,6 +122,7 @@
 	.open = minstrel_stats_open,
 	.read = minstrel_stats_read,
 	.release = minstrel_stats_release,
+	.llseek = default_llseek,
 };
 
 void
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 4a5a4b3..cefcb5d 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -90,7 +90,7 @@
 		MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
 	ms->len = p - ms->buf;
 
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 static const struct file_operations minstrel_ht_stat_fops = {
@@ -98,6 +98,7 @@
 	.open = minstrel_ht_stats_open,
 	.read = minstrel_stats_read,
 	.release = minstrel_stats_release,
+	.llseek = no_llseek,
 };
 
 void
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c
index 47438b4..7905f79 100644
--- a/net/mac80211/rc80211_pid_debugfs.c
+++ b/net/mac80211/rc80211_pid_debugfs.c
@@ -206,6 +206,7 @@
 	.poll = rate_control_pid_events_poll,
 	.open = rate_control_pid_events_open,
 	.release = rate_control_pid_events_release,
+	.llseek = noop_llseek,
 };
 
 void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta,
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index 76aec6a..d2ff15a 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -567,6 +567,7 @@
 	.write   = recent_mt_proc_write,
 	.release = seq_release_private,
 	.owner   = THIS_MODULE,
+	.llseek = seq_lseek,
 };
 
 static int __net_init recent_proc_net_init(struct net *net)
diff --git a/net/nonet.c b/net/nonet.c
index 92e7664..b1a73fd 100644
--- a/net/nonet.c
+++ b/net/nonet.c
@@ -22,4 +22,5 @@
 const struct file_operations bad_sock_fops = {
 	.owner = THIS_MODULE,
 	.open = sock_no_open,
+	.llseek = noop_llseek,
 };
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 51875a0..04f5990 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -1241,6 +1241,7 @@
 	.unlocked_ioctl	= rfkill_fop_ioctl,
 	.compat_ioctl	= rfkill_fop_ioctl,
 #endif
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice rfkill_miscdev = {
diff --git a/net/sctp/probe.c b/net/sctp/probe.c
index db3a42b..289b1ba 100644
--- a/net/sctp/probe.c
+++ b/net/sctp/probe.c
@@ -117,6 +117,7 @@
 	.owner	= THIS_MODULE,
 	.open	= sctpprobe_open,
 	.read	= sctpprobe_read,
+	.llseek = noop_llseek,
 };
 
 sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep,
diff --git a/net/socket.c b/net/socket.c
index 2270b94..9eac5c3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -502,6 +502,7 @@
 const struct file_operations bad_sock_fops = {
 	.owner = THIS_MODULE,
 	.open = sock_no_open,
+	.llseek = noop_llseek,
 };
 
 /**
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 2b06410..7dce81a 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -28,7 +28,6 @@
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <asm/ioctls.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/cache.h>
@@ -1348,15 +1347,10 @@
 static long cache_ioctl_procfs(struct file *filp,
 			       unsigned int cmd, unsigned long arg)
 {
-	long ret;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct cache_detail *cd = PDE(inode)->data;
 
-	lock_kernel();
-	ret = cache_ioctl(inode, filp, cmd, arg, cd);
-	unlock_kernel();
-
-	return ret;
+	return cache_ioctl(inode, filp, cmd, arg, cd);
 }
 
 static int cache_open_procfs(struct inode *inode, struct file *filp)
@@ -1441,6 +1435,7 @@
 	.read		= read_flush_procfs,
 	.write		= write_flush_procfs,
 	.release	= release_flush_procfs,
+	.llseek		= no_llseek,
 };
 
 static void remove_cache_proc_entries(struct cache_detail *cd)
@@ -1555,13 +1550,8 @@
 {
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct cache_detail *cd = RPC_I(inode)->private;
-	long ret;
 
-	lock_kernel();
-	ret = cache_ioctl(inode, filp, cmd, arg, cd);
-	unlock_kernel();
-
-	return ret;
+	return cache_ioctl(inode, filp, cmd, arg, cd);
 }
 
 static int cache_open_pipefs(struct inode *inode, struct file *filp)
@@ -1646,6 +1636,7 @@
 	.read		= read_flush_pipefs,
 	.write		= write_flush_pipefs,
 	.release	= release_flush_pipefs,
+	.llseek		= no_llseek,
 };
 
 int sunrpc_cache_register_pipefs(struct dentry *parent,
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 8c8eef2..28bcd52 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -27,7 +27,6 @@
 #include <linux/workqueue.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 #include <linux/sunrpc/cache.h>
-#include <linux/smp_lock.h>
 
 static struct vfsmount *rpc_mount __read_mostly;
 static int rpc_mount_count;
@@ -309,40 +308,33 @@
 	return mask;
 }
 
-static int
-rpc_pipe_ioctl_unlocked(struct file *filp, unsigned int cmd, unsigned long arg)
+static long
+rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
+	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct rpc_inode *rpci = RPC_I(inode);
 	int len;
 
 	switch (cmd) {
 	case FIONREAD:
-		if (rpci->ops == NULL)
+		spin_lock(&inode->i_lock);
+		if (rpci->ops == NULL) {
+			spin_unlock(&inode->i_lock);
 			return -EPIPE;
+		}
 		len = rpci->pipelen;
 		if (filp->private_data) {
 			struct rpc_pipe_msg *msg;
 			msg = (struct rpc_pipe_msg *)filp->private_data;
 			len += msg->len - msg->copied;
 		}
+		spin_unlock(&inode->i_lock);
 		return put_user(len, (int __user *)arg);
 	default:
 		return -EINVAL;
 	}
 }
 
-static long
-rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	long ret;
-
-	lock_kernel();
-	ret = rpc_pipe_ioctl_unlocked(filp, cmd, arg);
-	unlock_kernel();
-
-	return ret;
-}
-
 static const struct file_operations rpc_pipe_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index a4991a3..39765bc 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -34,6 +34,7 @@
 static const struct file_operations name## _ops = {			\
 	.read = name## _read,						\
 	.open = cfg80211_open_file_generic,				\
+	.llseek = generic_file_llseek,					\
 };
 
 DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
@@ -102,6 +103,7 @@
 static const struct file_operations ht40allow_map_ops = {
 	.read = ht40allow_map_read,
 	.open = cfg80211_open_file_generic,
+	.llseek = default_llseek,
 };
 
 #define DEBUGFS_ADD(name)						\
diff --git a/net/x25/Kconfig b/net/x25/Kconfig
index e6759c9..2196e55 100644
--- a/net/x25/Kconfig
+++ b/net/x25/Kconfig
@@ -5,6 +5,7 @@
 config X25
 	tristate "CCITT X.25 Packet Layer (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	depends on BKL # should be fixable
 	---help---
 	  X.25 is a set of standardized network protocols, similar in scope to
 	  frame relay; the one physical line from your box to the X.25 network
diff --git a/samples/kfifo/bytestream-example.c b/samples/kfifo/bytestream-example.c
index 178061e..cfe40ad 100644
--- a/samples/kfifo/bytestream-example.c
+++ b/samples/kfifo/bytestream-example.c
@@ -148,6 +148,7 @@
 	.owner		= THIS_MODULE,
 	.read		= fifo_read,
 	.write		= fifo_write,
+	.llseek		= noop_llseek,
 };
 
 static int __init example_init(void)
diff --git a/samples/kfifo/inttype-example.c b/samples/kfifo/inttype-example.c
index 71b2aab..6f8e79e 100644
--- a/samples/kfifo/inttype-example.c
+++ b/samples/kfifo/inttype-example.c
@@ -141,6 +141,7 @@
 	.owner		= THIS_MODULE,
 	.read		= fifo_read,
 	.write		= fifo_write,
+	.llseek		= noop_llseek,
 };
 
 static int __init example_init(void)
diff --git a/samples/kfifo/record-example.c b/samples/kfifo/record-example.c
index e68bd16..2d7529e 100644
--- a/samples/kfifo/record-example.c
+++ b/samples/kfifo/record-example.c
@@ -155,6 +155,7 @@
 	.owner		= THIS_MODULE,
 	.read		= fifo_read,
 	.write		= fifo_write,
+	.llseek		= noop_llseek,
 };
 
 static int __init example_init(void)
diff --git a/samples/tracepoints/tracepoint-sample.c b/samples/tracepoints/tracepoint-sample.c
index 26fab33..f4d89e0 100644
--- a/samples/tracepoints/tracepoint-sample.c
+++ b/samples/tracepoints/tracepoint-sample.c
@@ -30,6 +30,7 @@
 
 static const struct file_operations mark_ops = {
 	.open = my_open,
+	.llseek = noop_llseek,
 };
 
 static int __init sample_init(void)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 544ff58..0848292 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -88,7 +88,8 @@
 }
 
 static const struct file_operations aa_fs_profile_load = {
-	.write = profile_load
+	.write = profile_load,
+	.llseek = default_llseek,
 };
 
 /* .replace file hook fn to load and/or replace policy */
@@ -109,7 +110,8 @@
 }
 
 static const struct file_operations aa_fs_profile_replace = {
-	.write = profile_replace
+	.write = profile_replace,
+	.llseek = default_llseek,
 };
 
 /* .remove file hook fn to remove loaded policy */
@@ -136,7 +138,8 @@
 }
 
 static const struct file_operations aa_fs_profile_remove = {
-	.write = profile_remove
+	.write = profile_remove,
+	.llseek = default_llseek,
 };
 
 /** Base file system setup **/
diff --git a/security/inode.c b/security/inode.c
index 8c777f0..8883986 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -53,6 +53,7 @@
 	.read =		default_read_file,
 	.write =	default_write_file,
 	.open =		default_open,
+	.llseek =	noop_llseek,
 };
 
 static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index a2b72d7..7512502 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -968,6 +968,7 @@
 static const struct file_operations smk_doi_ops = {
 	.read		= smk_read_doi,
 	.write		= smk_write_doi,
+	.llseek		= default_llseek,
 };
 
 /**
@@ -1031,6 +1032,7 @@
 static const struct file_operations smk_direct_ops = {
 	.read		= smk_read_direct,
 	.write		= smk_write_direct,
+	.llseek		= default_llseek,
 };
 
 /**
@@ -1112,6 +1114,7 @@
 static const struct file_operations smk_ambient_ops = {
 	.read		= smk_read_ambient,
 	.write		= smk_write_ambient,
+	.llseek		= default_llseek,
 };
 
 /**
@@ -1191,6 +1194,7 @@
 static const struct file_operations smk_onlycap_ops = {
 	.read		= smk_read_onlycap,
 	.write		= smk_write_onlycap,
+	.llseek		= default_llseek,
 };
 
 /**
@@ -1255,6 +1259,7 @@
 static const struct file_operations smk_logging_ops = {
 	.read		= smk_read_logging,
 	.write		= smk_write_logging,
+	.llseek		= default_llseek,
 };
 /**
  * smk_fill_super - fill the /smackfs superblock
diff --git a/sound/core/init.c b/sound/core/init.c
index ec4a50c..f7c3df8 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -395,12 +395,10 @@
 		snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
 
 	snd_info_card_disconnect(card);
-#ifndef CONFIG_SYSFS_DEPRECATED
 	if (card->card_dev) {
 		device_unregister(card->card_dev);
 		card->card_dev = NULL;
 	}
-#endif
 #ifdef CONFIG_PM
 	wake_up(&card->power_sleep);
 #endif
@@ -573,7 +571,6 @@
 }
 EXPORT_SYMBOL(snd_card_set_id);
 
-#ifndef CONFIG_SYSFS_DEPRECATED
 static ssize_t
 card_id_show_attr(struct device *dev,
 		  struct device_attribute *attr, char *buf)
@@ -630,7 +627,6 @@
 
 static struct device_attribute card_number_attrs =
 	__ATTR(number, S_IRUGO, card_number_show_attr, NULL);
-#endif /* CONFIG_SYSFS_DEPRECATED */
 
 /**
  *  snd_card_register - register the soundcard
@@ -649,7 +645,7 @@
 
 	if (snd_BUG_ON(!card))
 		return -EINVAL;
-#ifndef CONFIG_SYSFS_DEPRECATED
+
 	if (!card->card_dev) {
 		card->card_dev = device_create(sound_class, card->dev,
 					       MKDEV(0, 0), card,
@@ -657,7 +653,7 @@
 		if (IS_ERR(card->card_dev))
 			card->card_dev = NULL;
 	}
-#endif
+
 	if ((err = snd_device_register_all(card)) < 0)
 		return err;
 	mutex_lock(&snd_card_mutex);
@@ -674,7 +670,6 @@
 	if (snd_mixer_oss_notify_callback)
 		snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
 #endif
-#ifndef CONFIG_SYSFS_DEPRECATED
 	if (card->card_dev) {
 		err = device_create_file(card->card_dev, &card_id_attrs);
 		if (err < 0)
@@ -683,7 +678,7 @@
 		if (err < 0)
 			return err;
 	}
-#endif
+
 	return 0;
 }
 
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index f25e3cc..a1f1a2f 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -220,6 +220,7 @@
 	.poll =		odev_poll,
 	.unlocked_ioctl =	odev_ioctl,
 	.compat_ioctl =	odev_ioctl_compat,
+	.llseek =	noop_llseek,
 };
 
 static int __init
diff --git a/sound/core/sound.c b/sound/core/sound.c
index ac42af4..62a093e 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -184,7 +184,8 @@
 static const struct file_operations snd_fops =
 {
 	.owner =	THIS_MODULE,
-	.open =		snd_open
+	.open =		snd_open,
+	.llseek =	noop_llseek,
 };
 
 #ifdef CONFIG_SND_DYNAMIC_MINORS
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index 2e48b17..ca942f7 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -1117,6 +1117,7 @@
 	.unlocked_ioctl	= dev_ioctl,
 	.open		= dev_open,
 	.release	= dev_release,
+	.llseek		= noop_llseek,
 };
 
 static int reset_dsp(void)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index acc91da..4057d35 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -223,6 +223,7 @@
 	.open = codec_reg_open_file,
 	.read = codec_reg_read_file,
 	.write = codec_reg_write_file,
+	.llseek = default_llseek,
 };
 
 static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 03cb7c0..72a53d0 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1089,6 +1089,7 @@
 static const struct file_operations dapm_widget_power_fops = {
 	.open = dapm_widget_power_open_file,
 	.read = dapm_widget_power_read_file,
+	.llseek = default_llseek,
 };
 
 void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
diff --git a/sound/sound_core.c b/sound/sound_core.c
index cb61317..c03bbae 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -165,6 +165,7 @@
 	/* We must have an owner or the module locking fails */
 	.owner	= THIS_MODULE,
 	.open	= soundcore_open,
+	.llseek = noop_llseek,
 };
 
 /*
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 5186e72..60e5e46 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1305,6 +1305,7 @@
 	.unlocked_ioctl = kvm_vcpu_ioctl,
 	.compat_ioctl   = kvm_vcpu_ioctl,
 	.mmap           = kvm_vcpu_mmap,
+	.llseek		= noop_llseek,
 };
 
 /*
@@ -1774,6 +1775,7 @@
 	.compat_ioctl   = kvm_vm_compat_ioctl,
 #endif
 	.mmap           = kvm_vm_mmap,
+	.llseek		= noop_llseek,
 };
 
 static int kvm_dev_ioctl_create_vm(void)
@@ -1867,6 +1869,7 @@
 static struct file_operations kvm_chardev_ops = {
 	.unlocked_ioctl = kvm_dev_ioctl,
 	.compat_ioctl   = kvm_dev_ioctl,
+	.llseek		= noop_llseek,
 };
 
 static struct miscdevice kvm_dev = {