]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Aug 2013 18:56:32 +0000 (11:56 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Aug 2013 18:56:32 +0000 (11:56 -0700)
added patches:
hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch
libata-apply-behavioral-quirks-to-sil3826-pmp.patch
scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch
x86-xen-do-not-identity-map-unusable-regions-in-the-machine-e820.patch
zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch

queue-3.4/hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch [new file with mode: 0644]
queue-3.4/libata-apply-behavioral-quirks-to-sil3826-pmp.patch [new file with mode: 0644]
queue-3.4/scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/x86-xen-do-not-identity-map-unusable-regions-in-the-machine-e820.patch [new file with mode: 0644]
queue-3.4/zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch [new file with mode: 0644]

diff --git a/queue-3.4/hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch b/queue-3.4/hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch
new file mode 100644 (file)
index 0000000..4d8a7c3
--- /dev/null
@@ -0,0 +1,34 @@
+From 909bd5926d474e275599094acad986af79671ac9 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Fri, 9 Aug 2013 12:52:31 +0300
+Subject: Hostap: copying wrong data prism2_ioctl_giwaplist()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 909bd5926d474e275599094acad986af79671ac9 upstream.
+
+We want the data stored in "addr" and "qual", but the extra ampersands
+mean we are copying stack data instead.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/hostap/hostap_ioctl.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/hostap/hostap_ioctl.c
++++ b/drivers/net/wireless/hostap/hostap_ioctl.c
+@@ -522,9 +522,9 @@ static int prism2_ioctl_giwaplist(struct
+       data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1);
+-      memcpy(extra, &addr, sizeof(struct sockaddr) * data->length);
++      memcpy(extra, addr, sizeof(struct sockaddr) * data->length);
+       data->flags = 1; /* has quality information */
+-      memcpy(extra + sizeof(struct sockaddr) * data->length, &qual,
++      memcpy(extra + sizeof(struct sockaddr) * data->length, qual,
+              sizeof(struct iw_quality) * data->length);
+       kfree(addr);
diff --git a/queue-3.4/libata-apply-behavioral-quirks-to-sil3826-pmp.patch b/queue-3.4/libata-apply-behavioral-quirks-to-sil3826-pmp.patch
new file mode 100644 (file)
index 0000000..508ac18
--- /dev/null
@@ -0,0 +1,66 @@
+From 8ffff94d20b7eb446e848e0046107d51b17a20a8 Mon Sep 17 00:00:00 2001
+From: Terry Suereth <terry.suereth@gmail.com>
+Date: Sat, 17 Aug 2013 15:53:12 -0400
+Subject: libata: apply behavioral quirks to sil3826 PMP
+
+From: Terry Suereth <terry.suereth@gmail.com>
+
+commit 8ffff94d20b7eb446e848e0046107d51b17a20a8 upstream.
+
+Fixing support for the Silicon Image 3826 port multiplier, by applying
+to it the same quirks applied to the Silicon Image 3726.  Specifically
+fixes the repeated timeout/reset process which previously afflicted
+the 3726, as described from line 290.  Slightly based on notes from:
+
+https://bugzilla.redhat.com/show_bug.cgi?id=890237
+
+Signed-off-by: Terry Suereth <terry.suereth@gmail.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/ata/libata-pmp.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/ata/libata-pmp.c
++++ b/drivers/ata/libata-pmp.c
+@@ -289,24 +289,24 @@ static int sata_pmp_configure(struct ata
+       /* Disable sending Early R_OK.
+        * With "cached read" HDD testing and multiple ports busy on a SATA
+-       * host controller, 3726 PMP will very rarely drop a deferred
++       * host controller, 3x26 PMP will very rarely drop a deferred
+        * R_OK that was intended for the host. Symptom will be all
+        * 5 drives under test will timeout, get reset, and recover.
+        */
+-      if (vendor == 0x1095 && devid == 0x3726) {
++      if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
+               u32 reg;
+               err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, &reg);
+               if (err_mask) {
+                       rc = -EIO;
+-                      reason = "failed to read Sil3726 Private Register";
++                      reason = "failed to read Sil3x26 Private Register";
+                       goto fail;
+               }
+               reg &= ~0x1;
+               err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
+               if (err_mask) {
+                       rc = -EIO;
+-                      reason = "failed to write Sil3726 Private Register";
++                      reason = "failed to write Sil3x26 Private Register";
+                       goto fail;
+               }
+       }
+@@ -383,8 +383,8 @@ static void sata_pmp_quirks(struct ata_p
+       u16 devid = sata_pmp_gscr_devid(gscr);
+       struct ata_link *link;
+-      if (vendor == 0x1095 && devid == 0x3726) {
+-              /* sil3726 quirks */
++      if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
++              /* sil3x26 quirks */
+               ata_for_each_link(link, ap, EDGE) {
+                       /* link reports offline after LPM */
+                       link->flags |= ATA_LFLAG_NO_LPM;
diff --git a/queue-3.4/scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch b/queue-3.4/scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch
new file mode 100644 (file)
index 0000000..31419bb
--- /dev/null
@@ -0,0 +1,158 @@
+From d79ff142624e1be080ad8d09101f7004d79c36e1 Mon Sep 17 00:00:00 2001
+From: Martin Peschke <mpeschke@linux.vnet.ibm.com>
+Date: Thu, 22 Aug 2013 17:45:36 +0200
+Subject: SCSI: zfcp: fix lock imbalance by reworking request queue locking
+
+From: Martin Peschke <mpeschke@linux.vnet.ibm.com>
+
+commit d79ff142624e1be080ad8d09101f7004d79c36e1 upstream.
+
+This patch adds wait_event_interruptible_lock_irq_timeout(), which is a
+straight-forward descendant of wait_event_interruptible_timeout() and
+wait_event_interruptible_lock_irq().
+
+The zfcp driver used to call wait_event_interruptible_timeout()
+in combination with some intricate and error-prone locking. Using
+wait_event_interruptible_lock_irq_timeout() as a replacement
+nicely cleans up that locking.
+
+This rework removes a situation that resulted in a locking imbalance
+in zfcp_qdio_sbal_get():
+
+BUG: workqueue leaked lock or atomic: events/1/0xffffff00/10
+    last function: zfcp_fc_wka_port_offline+0x0/0xa0 [zfcp]
+
+It was introduced by commit c2af7545aaff3495d9bf9a7608c52f0af86fb194
+"[SCSI] zfcp: Do not wait for SBALs on stopped queue", which had a new
+code path related to ZFCP_STATUS_ADAPTER_QDIOUP that took an early exit
+without a required lock being held. The problem occured when a
+special, non-SCSI I/O request was being submitted in process context,
+when the adapter's queues had been torn down. In this case the bug
+surfaced when the Fibre Channel port connection for a well-known address
+was closed during a concurrent adapter shut-down procedure, which is a
+rare constellation.
+
+This patch also fixes these warnings from the sparse tool (make C=1):
+
+drivers/s390/scsi/zfcp_qdio.c:224:12: warning: context imbalance in
+ 'zfcp_qdio_sbal_check' - wrong count at exit
+drivers/s390/scsi/zfcp_qdio.c:244:5: warning: context imbalance in
+ 'zfcp_qdio_sbal_get' - unexpected unlock
+
+Last but not least, we get rid of that crappy lock-unlock-lock
+sequence at the beginning of the critical section.
+
+It is okay to call zfcp_erp_adapter_reopen() with req_q_lock held.
+
+Reported-by: Mikulas Patocka <mpatocka@redhat.com>
+Reported-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+Signed-off-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
+Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/s390/scsi/zfcp_qdio.c |    8 +----
+ include/linux/wait.h          |   57 ++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 59 insertions(+), 6 deletions(-)
+
+--- a/drivers/s390/scsi/zfcp_qdio.c
++++ b/drivers/s390/scsi/zfcp_qdio.c
+@@ -224,11 +224,9 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_
+ static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio)
+ {
+-      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_irq(&qdio->req_q_lock);
+       return 0;
+ }
+@@ -246,9 +244,8 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio
+ {
+       long ret;
+-      spin_unlock_irq(&qdio->req_q_lock);
+-      ret = wait_event_interruptible_timeout(qdio->req_q_wq,
+-                             zfcp_qdio_sbal_check(qdio), 5 * HZ);
++      ret = wait_event_interruptible_lock_irq_timeout(qdio->req_q_wq,
++                     zfcp_qdio_sbal_check(qdio), qdio->req_q_lock, 5 * HZ);
+       if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
+               return -EIO;
+@@ -262,7 +259,6 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio
+               zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1");
+       }
+-      spin_lock_irq(&qdio->req_q_lock);
+       return -EIO;
+ }
+--- a/include/linux/wait.h
++++ b/include/linux/wait.h
+@@ -530,6 +530,63 @@ do {                                                                      \
+        ? 0 : __wait_event_interruptible_locked(wq, condition, 1, 1))
++#define __wait_event_interruptible_lock_irq_timeout(wq, condition,    \
++                                                  lock, ret)          \
++do {                                                                  \
++      DEFINE_WAIT(__wait);                                            \
++                                                                      \
++      for (;;) {                                                      \
++              prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);      \
++              if (condition)                                          \
++                      break;                                          \
++              if (signal_pending(current)) {                          \
++                      ret = -ERESTARTSYS;                             \
++                      break;                                          \
++              }                                                       \
++              spin_unlock_irq(&lock);                                 \
++              ret = schedule_timeout(ret);                            \
++              spin_lock_irq(&lock);                                   \
++              if (!ret)                                               \
++                      break;                                          \
++      }                                                               \
++      finish_wait(&wq, &__wait);                                      \
++} while (0)
++
++/**
++ * wait_event_interruptible_lock_irq_timeout - sleep until a condition gets true or a timeout elapses.
++ *            The condition is checked under the lock. This is expected
++ *            to be called with the lock taken.
++ * @wq: the waitqueue to wait on
++ * @condition: a C expression for the event to wait for
++ * @lock: a locked spinlock_t, which will be released before schedule()
++ *      and reacquired afterwards.
++ * @timeout: timeout, in jiffies
++ *
++ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
++ * @condition evaluates to true or signal is received. The @condition is
++ * checked each time the waitqueue @wq is woken up.
++ *
++ * wake_up() has to be called after changing any variable that could
++ * change the result of the wait condition.
++ *
++ * This is supposed to be called while holding the lock. The lock is
++ * dropped before going to sleep and is reacquired afterwards.
++ *
++ * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
++ * was interrupted by a signal, and the remaining jiffies otherwise
++ * if the condition evaluated to true before the timeout elapsed.
++ */
++#define wait_event_interruptible_lock_irq_timeout(wq, condition, lock,        \
++                                                timeout)              \
++({                                                                    \
++      int __ret = timeout;                                            \
++                                                                      \
++      if (!(condition))                                               \
++              __wait_event_interruptible_lock_irq_timeout(            \
++                                      wq, condition, lock, __ret);    \
++      __ret;                                                          \
++})
++
+ #define __wait_event_killable(wq, condition, ret)                     \
+ do {                                                                  \
index 2d290bccd655908f0b8e6c47767e6b63a3d20980..9a4cca004832fadc40951b53bddbe55e86014874 100644 (file)
@@ -6,3 +6,8 @@ drm-i915-invalidate-tlbs-for-the-rings-after-a-reset.patch
 of-fdt-fix-memory-initialization-for-expanded-dt.patch
 nilfs2-remove-double-bio_put-in-nilfs_end_bio_write-for-bio_eopnotsupp-error.patch
 nilfs2-fix-issue-with-counting-number-of-bio-requests-for-bio_eopnotsupp-error-detection.patch
+hostap-copying-wrong-data-prism2_ioctl_giwaplist.patch
+libata-apply-behavioral-quirks-to-sil3826-pmp.patch
+scsi-zfcp-fix-lock-imbalance-by-reworking-request-queue-locking.patch
+zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch
+x86-xen-do-not-identity-map-unusable-regions-in-the-machine-e820.patch
diff --git a/queue-3.4/x86-xen-do-not-identity-map-unusable-regions-in-the-machine-e820.patch b/queue-3.4/x86-xen-do-not-identity-map-unusable-regions-in-the-machine-e820.patch
new file mode 100644 (file)
index 0000000..aaf59ed
--- /dev/null
@@ -0,0 +1,90 @@
+From 3bc38cbceb85881a8eb789ee1aa56678038b1909 Mon Sep 17 00:00:00 2001
+From: David Vrabel <david.vrabel@citrix.com>
+Date: Fri, 16 Aug 2013 15:42:55 +0100
+Subject: x86/xen: do not identity map UNUSABLE regions in the machine E820
+
+From: David Vrabel <david.vrabel@citrix.com>
+
+commit 3bc38cbceb85881a8eb789ee1aa56678038b1909 upstream.
+
+If there are UNUSABLE regions in the machine memory map, dom0 will
+attempt to map them 1:1 which is not permitted by Xen and the kernel
+will crash.
+
+There isn't anything interesting in the UNUSABLE region that the dom0
+kernel needs access to so we can avoid making the 1:1 mapping and
+treat it as RAM.
+
+We only do this for dom0, as that is where tboot case shows up.
+A PV domU could have an UNUSABLE region in its pseudo-physical map
+and would need to be handled in another patch.
+
+This fixes a boot failure on hosts with tboot.
+
+tboot marks a region in the e820 map as unusable and the dom0 kernel
+would attempt to map this region and Xen does not permit unusable
+regions to be mapped by guests.
+
+  (XEN)  0000000000000000 - 0000000000060000 (usable)
+  (XEN)  0000000000060000 - 0000000000068000 (reserved)
+  (XEN)  0000000000068000 - 000000000009e000 (usable)
+  (XEN)  0000000000100000 - 0000000000800000 (usable)
+  (XEN)  0000000000800000 - 0000000000972000 (unusable)
+
+tboot marked this region as unusable.
+
+  (XEN)  0000000000972000 - 00000000cf200000 (usable)
+  (XEN)  00000000cf200000 - 00000000cf38f000 (reserved)
+  (XEN)  00000000cf38f000 - 00000000cf3ce000 (ACPI data)
+  (XEN)  00000000cf3ce000 - 00000000d0000000 (reserved)
+  (XEN)  00000000e0000000 - 00000000f0000000 (reserved)
+  (XEN)  00000000fe000000 - 0000000100000000 (reserved)
+  (XEN)  0000000100000000 - 0000000630000000 (usable)
+
+Signed-off-by: David Vrabel <david.vrabel@citrix.com>
+[v1: Altered the patch and description with domU's with UNUSABLE regions]
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/xen/setup.c |   22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+--- a/arch/x86/xen/setup.c
++++ b/arch/x86/xen/setup.c
+@@ -213,6 +213,17 @@ static void xen_align_and_add_e820_regio
+       e820_add_region(start, end - start, type);
+ }
++void xen_ignore_unusable(struct e820entry *list, size_t map_size)
++{
++      struct e820entry *entry;
++      unsigned int i;
++
++      for (i = 0, entry = list; i < map_size; i++, entry++) {
++              if (entry->type == E820_UNUSABLE)
++                      entry->type = E820_RAM;
++      }
++}
++
+ /**
+  * machine_specific_memory_setup - Hook for machine specific memory setup.
+  **/
+@@ -251,6 +262,17 @@ char * __init xen_memory_setup(void)
+       }
+       BUG_ON(rc);
++      /*
++       * Xen won't allow a 1:1 mapping to be created to UNUSABLE
++       * regions, so if we're using the machine memory map leave the
++       * region as RAM as it is in the pseudo-physical map.
++       *
++       * UNUSABLE regions in domUs are not handled and will need
++       * a patch in the future.
++       */
++      if (xen_initial_domain())
++              xen_ignore_unusable(map, memmap.nr_entries);
++
+       /* Make sure the Xen-supplied memory map is well-ordered. */
+       sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
diff --git a/queue-3.4/zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch b/queue-3.4/zfcp-fix-schedule-inside-lock-in-scsi_device-list-loops.patch
new file mode 100644 (file)
index 0000000..4abbbab
--- /dev/null
@@ -0,0 +1,170 @@
+From 924dd584b198a58aa7cb3efefd8a03326550ce8f Mon Sep 17 00:00:00 2001
+From: Martin Peschke <mpeschke@linux.vnet.ibm.com>
+Date: Thu, 22 Aug 2013 17:45:37 +0200
+Subject: SCSI: zfcp: fix schedule-inside-lock in scsi_device list loops
+
+From: Martin Peschke <mpeschke@linux.vnet.ibm.com>
+
+commit 924dd584b198a58aa7cb3efefd8a03326550ce8f upstream.
+
+BUG: sleeping function called from invalid context at kernel/workqueue.c:2752
+in_atomic(): 1, irqs_disabled(): 1, pid: 360, name: zfcperp0.0.1700
+CPU: 1 Not tainted 3.9.3+ #69
+Process zfcperp0.0.1700 (pid: 360, task: 0000000075b7e080, ksp: 000000007476bc30)
+<snip>
+Call Trace:
+([<00000000001165de>] show_trace+0x106/0x154)
+ [<00000000001166a0>] show_stack+0x74/0xf4
+ [<00000000006ff646>] dump_stack+0xc6/0xd4
+ [<000000000017f3a0>] __might_sleep+0x128/0x148
+ [<000000000015ece8>] flush_work+0x54/0x1f8
+ [<00000000001630de>] __cancel_work_timer+0xc6/0x128
+ [<00000000005067ac>] scsi_device_dev_release_usercontext+0x164/0x23c
+ [<0000000000161816>] execute_in_process_context+0x96/0xa8
+ [<00000000004d33d8>] device_release+0x60/0xc0
+ [<000000000048af48>] kobject_release+0xa8/0x1c4
+ [<00000000004f4bf2>] __scsi_iterate_devices+0xfa/0x130
+ [<000003ff801b307a>] zfcp_erp_strategy+0x4da/0x1014 [zfcp]
+ [<000003ff801b3caa>] zfcp_erp_thread+0xf6/0x2b0 [zfcp]
+ [<000000000016b75a>] kthread+0xf2/0xfc
+ [<000000000070c9de>] kernel_thread_starter+0x6/0xc
+ [<000000000070c9d8>] kernel_thread_starter+0x0/0xc
+
+Apparently, the ref_count for some scsi_device drops down to zero,
+triggering device removal through execute_in_process_context(), while
+the lldd error recovery thread iterates through a scsi device list.
+Unfortunately, execute_in_process_context() decides to immediately
+execute that device removal function, instead of scheduling asynchronous
+execution, since it detects process context and thinks it is safe to do
+so. But almost all calls to shost_for_each_device() in our lldd are
+inside spin_lock_irq, even in thread context. Obviously, schedule()
+inside spin_lock_irq sections is a bad idea.
+
+Change the lldd to use the proper iterator function,
+__shost_for_each_device(), in combination with required locking.
+
+Occurences that need to be changed include all calls in zfcp_erp.c,
+since those might be executed in zfcp error recovery thread context
+with a lock held.
+
+Other occurences of shost_for_each_device() in zfcp_fsf.c do not
+need to be changed (no process context, no surrounding locking).
+
+The problem was introduced in Linux 2.6.37 by commit
+b62a8d9b45b971a67a0f8413338c230e3117dff5
+"[SCSI] zfcp: Use SCSI device data zfcp_scsi_dev instead of zfcp_unit".
+
+Reported-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Signed-off-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
+Signed-off-by: Steffen Maier <maier@linux.vnet.ibm.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/s390/scsi/zfcp_erp.c |   29 ++++++++++++++++++++++-------
+ 1 file changed, 22 insertions(+), 7 deletions(-)
+
+--- a/drivers/s390/scsi/zfcp_erp.c
++++ b/drivers/s390/scsi/zfcp_erp.c
+@@ -102,10 +102,13 @@ static void zfcp_erp_action_dismiss_port
+       if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
+               zfcp_erp_action_dismiss(&port->erp_action);
+-      else
+-              shost_for_each_device(sdev, port->adapter->scsi_host)
++      else {
++              spin_lock(port->adapter->scsi_host->host_lock);
++              __shost_for_each_device(sdev, port->adapter->scsi_host)
+                       if (sdev_to_zfcp(sdev)->port == port)
+                               zfcp_erp_action_dismiss_lun(sdev);
++              spin_unlock(port->adapter->scsi_host->host_lock);
++      }
+ }
+ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
+@@ -592,9 +595,11 @@ static void _zfcp_erp_lun_reopen_all(str
+ {
+       struct scsi_device *sdev;
+-      shost_for_each_device(sdev, port->adapter->scsi_host)
++      spin_lock(port->adapter->scsi_host->host_lock);
++      __shost_for_each_device(sdev, port->adapter->scsi_host)
+               if (sdev_to_zfcp(sdev)->port == port)
+                       _zfcp_erp_lun_reopen(sdev, clear, id, 0);
++      spin_unlock(port->adapter->scsi_host->host_lock);
+ }
+ static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
+@@ -1435,8 +1440,10 @@ void zfcp_erp_set_adapter_status(struct
+               atomic_set_mask(common_mask, &port->status);
+       read_unlock_irqrestore(&adapter->port_list_lock, flags);
+-      shost_for_each_device(sdev, adapter->scsi_host)
++      spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
++      __shost_for_each_device(sdev, adapter->scsi_host)
+               atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
++      spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
+ }
+ /**
+@@ -1470,11 +1477,13 @@ void zfcp_erp_clear_adapter_status(struc
+       }
+       read_unlock_irqrestore(&adapter->port_list_lock, flags);
+-      shost_for_each_device(sdev, adapter->scsi_host) {
++      spin_lock_irqsave(adapter->scsi_host->host_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);
+       }
++      spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
+ }
+ /**
+@@ -1488,16 +1497,19 @@ void zfcp_erp_set_port_status(struct zfc
+ {
+       struct scsi_device *sdev;
+       u32 common_mask = mask & ZFCP_COMMON_FLAGS;
++      unsigned long flags;
+       atomic_set_mask(mask, &port->status);
+       if (!common_mask)
+               return;
+-      shost_for_each_device(sdev, port->adapter->scsi_host)
++      spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
++      __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);
++      spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
+ }
+ /**
+@@ -1512,6 +1524,7 @@ void zfcp_erp_clear_port_status(struct z
+       struct scsi_device *sdev;
+       u32 common_mask = mask & ZFCP_COMMON_FLAGS;
+       u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
++      unsigned long flags;
+       atomic_clear_mask(mask, &port->status);
+@@ -1521,13 +1534,15 @@ void zfcp_erp_clear_port_status(struct z
+       if (clear_counter)
+               atomic_set(&port->erp_counter, 0);
+-      shost_for_each_device(sdev, port->adapter->scsi_host)
++      spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
++      __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);
+               }
++      spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
+ }
+ /**