--- /dev/null
+From f5832fa2f8dc39adcf3ae348d2d6383163235e79 Mon Sep 17 00:00:00 2001
+From: Brian King <brking@linux.vnet.ibm.com>
+Date: Tue, 20 Apr 2010 14:21:33 -0500
+Subject: [SCSI] ibmvfc: Fix command completion handling
+
+From: Brian King <brking@linux.vnet.ibm.com>
+
+commit f5832fa2f8dc39adcf3ae348d2d6383163235e79 upstream.
+
+Commands which are completed by the VIOS are placed on a CRQ
+in kernel memory for the ibmvfc driver to process. Each CRQ
+entry is 16 bytes. The ibmvfc driver reads the first 8 bytes
+to check if the entry is valid, then reads the next 8 bytes to get
+the handle, which is a pointer the completed command. This fixes
+an issue seen on Power 7 where the processor reordered the
+loads from memory, resulting in processing command completion
+with a stale handle. This could result in command timeouts,
+and also early completion of commands.
+
+Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/ibmvscsi/ibmvfc.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/scsi/ibmvscsi/ibmvfc.c
++++ b/drivers/scsi/ibmvscsi/ibmvfc.c
+@@ -3013,6 +3013,7 @@ static struct ibmvfc_async_crq *ibmvfc_n
+ if (crq->valid & 0x80) {
+ if (++async_crq->cur == async_crq->size)
+ async_crq->cur = 0;
++ rmb();
+ } else
+ crq = NULL;
+
+@@ -3035,6 +3036,7 @@ static struct ibmvfc_crq *ibmvfc_next_cr
+ if (crq->valid & 0x80) {
+ if (++queue->cur == queue->size)
+ queue->cur = 0;
++ rmb();
+ } else
+ crq = NULL;
+
+@@ -3083,12 +3085,14 @@ static void ibmvfc_tasklet(void *data)
+ while ((async = ibmvfc_next_async_crq(vhost)) != NULL) {
+ ibmvfc_handle_async(async, vhost);
+ async->valid = 0;
++ wmb();
+ }
+
+ /* Pull all the valid messages off the CRQ */
+ while ((crq = ibmvfc_next_crq(vhost)) != NULL) {
+ ibmvfc_handle_crq(crq, vhost);
+ crq->valid = 0;
++ wmb();
+ }
+
+ vio_enable_interrupts(vdev);
+@@ -3096,10 +3100,12 @@ static void ibmvfc_tasklet(void *data)
+ vio_disable_interrupts(vdev);
+ ibmvfc_handle_async(async, vhost);
+ async->valid = 0;
++ wmb();
+ } else if ((crq = ibmvfc_next_crq(vhost)) != NULL) {
+ vio_disable_interrupts(vdev);
+ ibmvfc_handle_crq(crq, vhost);
+ crq->valid = 0;
++ wmb();
+ } else
+ done = 1;
+ }
--- /dev/null
+From daa142d1773dd3a986f02a8a4da929608d24daaa Mon Sep 17 00:00:00 2001
+From: Brian King <brking@linux.vnet.ibm.com>
+Date: Tue, 20 Apr 2010 14:21:35 -0500
+Subject: [SCSI] ibmvfc: Reduce error recovery timeout
+
+From: Brian King <brking@linux.vnet.ibm.com>
+
+commit daa142d1773dd3a986f02a8a4da929608d24daaa upstream.
+
+If a command times out resulting in EH getting invoked, we wait for the
+aborted commands to come back after sending the abort. Shorten
+the amount of time we wait for these responses, to ensure we don't
+get stuck in EH for several minutes.
+
+Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/ibmvscsi/ibmvfc.c | 2 +-
+ drivers/scsi/ibmvscsi/ibmvfc.h | 1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/ibmvscsi/ibmvfc.c
++++ b/drivers/scsi/ibmvscsi/ibmvfc.c
+@@ -2245,7 +2245,7 @@ static int ibmvfc_wait_for_ops(struct ib
+ DECLARE_COMPLETION_ONSTACK(comp);
+ int wait;
+ unsigned long flags;
+- signed long timeout = init_timeout * HZ;
++ signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ;
+
+ ENTER;
+ do {
+--- a/drivers/scsi/ibmvscsi/ibmvfc.h
++++ b/drivers/scsi/ibmvscsi/ibmvfc.h
+@@ -38,6 +38,7 @@
+ #define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \
+ (IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT)
+ #define IBMVFC_INIT_TIMEOUT 120
++#define IBMVFC_ABORT_WAIT_TIMEOUT 40
+ #define IBMVFC_MAX_REQUESTS_DEFAULT 100
+
+ #define IBMVFC_DEBUG 0
--- /dev/null
+From e555190d82c0f58e825e3cbd9e6ebe2e7ac713bd Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.de>
+Date: Wed, 31 Mar 2010 11:21:44 +1100
+Subject: md/raid1: delay reads that could overtake behind-writes.
+
+From: NeilBrown <neilb@suse.de>
+
+commit e555190d82c0f58e825e3cbd9e6ebe2e7ac713bd upstream.
+
+When a raid1 array is configured to support write-behind
+on some devices, it normally only reads from other devices.
+If all devices are write-behind (because the rest have failed)
+it is possible for a read request to be serviced before a
+behind-write request, which would appear as data corruption.
+
+So when forced to read from a WriteMostly device, wait for any
+write-behind to complete, and don't start any more behind-writes.
+
+Signed-off-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/bitmap.c | 4 +++-
+ drivers/md/bitmap.h | 1 +
+ drivers/md/raid1.c | 25 ++++++++++++++++++-------
+ 3 files changed, 22 insertions(+), 8 deletions(-)
+
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -1351,7 +1351,8 @@ void bitmap_endwrite(struct bitmap *bitm
+ {
+ if (!bitmap) return;
+ if (behind) {
+- atomic_dec(&bitmap->behind_writes);
++ if (atomic_dec_and_test(&bitmap->behind_writes))
++ wake_up(&bitmap->behind_wait);
+ PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
+ atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+ }
+@@ -1675,6 +1676,7 @@ int bitmap_create(mddev_t *mddev)
+ atomic_set(&bitmap->pending_writes, 0);
+ init_waitqueue_head(&bitmap->write_wait);
+ init_waitqueue_head(&bitmap->overflow_wait);
++ init_waitqueue_head(&bitmap->behind_wait);
+
+ bitmap->mddev = mddev;
+
+--- a/drivers/md/bitmap.h
++++ b/drivers/md/bitmap.h
+@@ -239,6 +239,7 @@ struct bitmap {
+ atomic_t pending_writes; /* pending writes to the bitmap file */
+ wait_queue_head_t write_wait;
+ wait_queue_head_t overflow_wait;
++ wait_queue_head_t behind_wait;
+
+ struct sysfs_dirent *sysfs_can_clear;
+ };
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -866,6 +866,15 @@ static int make_request(struct request_q
+ }
+ mirror = conf->mirrors + rdisk;
+
++ if (test_bit(WriteMostly, &mirror->rdev->flags) &&
++ bitmap) {
++ /* Reading from a write-mostly device must
++ * take care not to over-take any writes
++ * that are 'behind'
++ */
++ wait_event(bitmap->behind_wait,
++ atomic_read(&bitmap->behind_writes) == 0);
++ }
+ r1_bio->read_disk = rdisk;
+
+ read_bio = bio_clone(bio, GFP_NOIO);
+@@ -943,10 +952,14 @@ static int make_request(struct request_q
+ set_bit(R1BIO_Degraded, &r1_bio->state);
+ }
+
+- /* do behind I/O ? */
++ /* do behind I/O ?
++ * Not if there are too many, or cannot allocate memory,
++ * or a reader on WriteMostly is waiting for behind writes
++ * to flush */
+ if (bitmap &&
+ (atomic_read(&bitmap->behind_writes)
+ < mddev->bitmap_info.max_write_behind) &&
++ !waitqueue_active(&bitmap->behind_wait) &&
+ (behind_pages = alloc_behind_pages(bio)) != NULL)
+ set_bit(R1BIO_BehindIO, &r1_bio->state);
+
+@@ -2153,15 +2166,13 @@ static int stop(mddev_t *mddev)
+ {
+ conf_t *conf = mddev->private;
+ struct bitmap *bitmap = mddev->bitmap;
+- int behind_wait = 0;
+
+ /* wait for behind writes to complete */
+- while (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
+- behind_wait++;
+- printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop (%d)\n", mdname(mddev), behind_wait);
+- set_current_state(TASK_UNINTERRUPTIBLE);
+- schedule_timeout(HZ); /* wait a second */
++ if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
++ printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop.\n", mdname(mddev));
+ /* need to kick something here to make sure I/O goes? */
++ wait_event(bitmap->behind_wait,
++ atomic_read(&bitmap->behind_writes) == 0);
+ }
+
+ raise_barrier(conf);