aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
authorSwen Schillig <swen@vnet.ibm.com>2009-11-24 10:53:58 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:02:01 -0500
commitecf0c7721b104c0ce9c8ca534c911f6310cf92a8 (patch)
tree639032b36bcbbe905c98c6f0b3b521dc2f0b1806 /drivers/s390/scsi
parent0a55256d158c18e4821c248a295b7f8f4423660f (diff)
[SCSI] zfcp: Replace global config_lock with local list locks
The global config_lock was used to protect the configuration organized in independent lists. It is not necessary to have a lock on driver level for this purpose. This patch replaces the global config_lock with a set of local list locks. Signed-off-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c80
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c23
-rw-r--r--drivers/s390/scsi/zfcp_def.h9
-rw-r--r--drivers/s390/scsi/zfcp_erp.c116
-rw-r--r--drivers/s390/scsi/zfcp_fc.c49
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c22
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c52
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c48
8 files changed, 199 insertions, 200 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 2889e5f2dfd3..883e13948ace 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -187,7 +187,6 @@ static int __init zfcp_module_init(void)
187 goto out_gid_cache; 187 goto out_gid_cache;
188 188
189 mutex_init(&zfcp_data.config_mutex); 189 mutex_init(&zfcp_data.config_mutex);
190 rwlock_init(&zfcp_data.config_lock);
191 190
192 zfcp_data.scsi_transport_template = 191 zfcp_data.scsi_transport_template =
193 fc_attach_transport(&zfcp_transport_functions); 192 fc_attach_transport(&zfcp_transport_functions);
@@ -238,12 +237,18 @@ module_init(zfcp_module_init);
238 */ 237 */
239struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) 238struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
240{ 239{
240 unsigned long flags;
241 struct zfcp_unit *unit; 241 struct zfcp_unit *unit;
242 242
243 list_for_each_entry(unit, &port->unit_list_head, list) 243 read_lock_irqsave(&port->unit_list_lock, flags);
244 list_for_each_entry(unit, &port->unit_list, list)
244 if ((unit->fcp_lun == fcp_lun) && 245 if ((unit->fcp_lun == fcp_lun) &&
245 !(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_REMOVE)) 246 !(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_REMOVE)) {
246 return unit; 247 zfcp_unit_get(unit);
248 read_unlock_irqrestore(&port->unit_list_lock, flags);
249 return unit;
250 }
251 read_unlock_irqrestore(&port->unit_list_lock, flags);
247 return NULL; 252 return NULL;
248} 253}
249 254
@@ -257,12 +262,18 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
257struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, 262struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
258 u64 wwpn) 263 u64 wwpn)
259{ 264{
265 unsigned long flags;
260 struct zfcp_port *port; 266 struct zfcp_port *port;
261 267
262 list_for_each_entry(port, &adapter->port_list_head, list) 268 read_lock_irqsave(&adapter->port_list_lock, flags);
269 list_for_each_entry(port, &adapter->port_list, list)
263 if ((port->wwpn == wwpn) && 270 if ((port->wwpn == wwpn) &&
264 !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE)) 271 !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE)) {
272 zfcp_port_get(port);
273 read_unlock_irqrestore(&adapter->port_list_lock, flags);
265 return port; 274 return port;
275 }
276 read_unlock_irqrestore(&adapter->port_list_lock, flags);
266 return NULL; 277 return NULL;
267} 278}
268 279
@@ -284,12 +295,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
284{ 295{
285 struct zfcp_unit *unit; 296 struct zfcp_unit *unit;
286 297
287 read_lock_irq(&zfcp_data.config_lock); 298 unit = zfcp_get_unit_by_lun(port, fcp_lun);
288 if (zfcp_get_unit_by_lun(port, fcp_lun)) { 299 if (unit) {
289 read_unlock_irq(&zfcp_data.config_lock); 300 zfcp_unit_put(unit);
290 return ERR_PTR(-EINVAL); 301 return ERR_PTR(-EINVAL);
291 } 302 }
292 read_unlock_irq(&zfcp_data.config_lock);
293 303
294 unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); 304 unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
295 if (!unit) 305 if (!unit)
@@ -335,13 +345,13 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
335 345
336 zfcp_unit_get(unit); 346 zfcp_unit_get(unit);
337 347
338 write_lock_irq(&zfcp_data.config_lock); 348 write_lock_irq(&port->unit_list_lock);
339 list_add_tail(&unit->list, &port->unit_list_head); 349 list_add_tail(&unit->list, &port->unit_list);
350 write_unlock_irq(&port->unit_list_lock);
351
340 atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); 352 atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
341 atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status); 353 atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
342 354
343 write_unlock_irq(&zfcp_data.config_lock);
344
345 zfcp_port_get(port); 355 zfcp_port_get(port);
346 356
347 return unit; 357 return unit;
@@ -356,11 +366,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
356 */ 366 */
357void zfcp_unit_dequeue(struct zfcp_unit *unit) 367void zfcp_unit_dequeue(struct zfcp_unit *unit)
358{ 368{
369 struct zfcp_port *port = unit->port;
370
359 wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0); 371 wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0);
360 write_lock_irq(&zfcp_data.config_lock); 372 list_del(&unit->list); /* no list locking required */
361 list_del(&unit->list); 373 zfcp_port_put(port);
362 write_unlock_irq(&zfcp_data.config_lock);
363 zfcp_port_put(unit->port);
364 sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs); 374 sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs);
365 device_unregister(&unit->sysfs_device); 375 device_unregister(&unit->sysfs_device);
366} 376}
@@ -539,11 +549,13 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
539 if (zfcp_fc_gs_setup(adapter)) 549 if (zfcp_fc_gs_setup(adapter))
540 goto generic_services_failed; 550 goto generic_services_failed;
541 551
552 rwlock_init(&adapter->port_list_lock);
553 INIT_LIST_HEAD(&adapter->port_list);
554
542 init_waitqueue_head(&adapter->remove_wq); 555 init_waitqueue_head(&adapter->remove_wq);
543 init_waitqueue_head(&adapter->erp_ready_wq); 556 init_waitqueue_head(&adapter->erp_ready_wq);
544 init_waitqueue_head(&adapter->erp_done_wqh); 557 init_waitqueue_head(&adapter->erp_done_wqh);
545 558
546 INIT_LIST_HEAD(&adapter->port_list_head);
547 INIT_LIST_HEAD(&adapter->erp_ready_head); 559 INIT_LIST_HEAD(&adapter->erp_ready_head);
548 INIT_LIST_HEAD(&adapter->erp_running_head); 560 INIT_LIST_HEAD(&adapter->erp_running_head);
549 561
@@ -650,19 +662,20 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
650{ 662{
651 struct zfcp_port *port; 663 struct zfcp_port *port;
652 664
653 read_lock_irq(&zfcp_data.config_lock); 665 port = zfcp_get_port_by_wwpn(adapter, wwpn);
654 if (zfcp_get_port_by_wwpn(adapter, wwpn)) { 666 if (port) {
655 read_unlock_irq(&zfcp_data.config_lock); 667 zfcp_port_put(port);
656 return ERR_PTR(-EINVAL); 668 return ERR_PTR(-EEXIST);
657 } 669 }
658 read_unlock_irq(&zfcp_data.config_lock);
659 670
660 port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); 671 port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
661 if (!port) 672 if (!port)
662 return ERR_PTR(-ENOMEM); 673 return ERR_PTR(-ENOMEM);
663 674
675 rwlock_init(&port->unit_list_lock);
676 INIT_LIST_HEAD(&port->unit_list);
677
664 init_waitqueue_head(&port->remove_wq); 678 init_waitqueue_head(&port->remove_wq);
665 INIT_LIST_HEAD(&port->unit_list_head);
666 INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); 679 INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
667 INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); 680 INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
668 INIT_WORK(&port->rport_work, zfcp_scsi_rport_work); 681 INIT_WORK(&port->rport_work, zfcp_scsi_rport_work);
@@ -698,13 +711,13 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
698 711
699 zfcp_port_get(port); 712 zfcp_port_get(port);
700 713
701 write_lock_irq(&zfcp_data.config_lock); 714 write_lock_irq(&adapter->port_list_lock);
702 list_add_tail(&port->list, &adapter->port_list_head); 715 list_add_tail(&port->list, &adapter->port_list);
716 write_unlock_irq(&adapter->port_list_lock);
717
703 atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); 718 atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
704 atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); 719 atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
705 720
706 write_unlock_irq(&zfcp_data.config_lock);
707
708 zfcp_adapter_get(adapter); 721 zfcp_adapter_get(adapter);
709 return port; 722 return port;
710} 723}
@@ -715,12 +728,11 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
715 */ 728 */
716void zfcp_port_dequeue(struct zfcp_port *port) 729void zfcp_port_dequeue(struct zfcp_port *port)
717{ 730{
718 write_lock_irq(&zfcp_data.config_lock); 731 struct zfcp_adapter *adapter = port->adapter;
719 list_del(&port->list); 732
720 write_unlock_irq(&zfcp_data.config_lock); 733 list_del(&port->list); /* no list locking required here */
721 wait_event(port->remove_wq, atomic_read(&port->refcount) == 0); 734 wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
722 cancel_work_sync(&port->rport_work); /* usually not necessary */ 735 zfcp_adapter_put(adapter);
723 zfcp_adapter_put(port->adapter);
724 sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); 736 sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
725 device_unregister(&port->sysfs_device); 737 device_unregister(&port->sysfs_device);
726} 738}
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index e08339428ecf..aca2047dc2d5 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -100,10 +100,11 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
100 100
101 mutex_lock(&zfcp_data.config_mutex); 101 mutex_lock(&zfcp_data.config_mutex);
102 adapter = dev_get_drvdata(&ccw_device->dev); 102 adapter = dev_get_drvdata(&ccw_device->dev);
103 if (!adapter)
104 goto out;
105 mutex_unlock(&zfcp_data.config_mutex); 103 mutex_unlock(&zfcp_data.config_mutex);
106 104
105 if (!adapter)
106 return;
107
107 cancel_work_sync(&adapter->scan_work); 108 cancel_work_sync(&adapter->scan_work);
108 109
109 mutex_lock(&zfcp_data.config_mutex); 110 mutex_lock(&zfcp_data.config_mutex);
@@ -111,18 +112,21 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
111 /* this also removes the scsi devices, so call it first */ 112 /* this also removes the scsi devices, so call it first */
112 zfcp_adapter_scsi_unregister(adapter); 113 zfcp_adapter_scsi_unregister(adapter);
113 114
114 write_lock_irq(&zfcp_data.config_lock); 115 write_lock_irq(&adapter->port_list_lock);
115 list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { 116 list_for_each_entry_safe(port, p, &adapter->port_list, list) {
116 list_for_each_entry_safe(unit, u, &port->unit_list_head, list) { 117 write_lock(&port->unit_list_lock);
117 list_move(&unit->list, &unit_remove_lh); 118 list_for_each_entry_safe(unit, u, &port->unit_list, list) {
118 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, 119 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
119 &unit->status); 120 &unit->status);
121 list_move(&unit->list, &unit_remove_lh);
120 } 122 }
121 list_move(&port->list, &port_remove_lh); 123 write_unlock(&port->unit_list_lock);
122 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); 124 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
125 list_move(&port->list, &port_remove_lh);
123 } 126 }
124 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); 127 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
125 write_unlock_irq(&zfcp_data.config_lock); 128 write_unlock_irq(&adapter->port_list_lock);
129 mutex_unlock(&zfcp_data.config_mutex);
126 130
127 list_for_each_entry_safe(port, p, &port_remove_lh, list) { 131 list_for_each_entry_safe(port, p, &port_remove_lh, list) {
128 list_for_each_entry_safe(unit, u, &unit_remove_lh, list) 132 list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
@@ -131,9 +135,6 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
131 } 135 }
132 wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0); 136 wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
133 zfcp_adapter_dequeue(adapter); 137 zfcp_adapter_dequeue(adapter);
134
135out:
136 mutex_unlock(&zfcp_data.config_mutex);
137} 138}
138 139
139/** 140/**
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 7da2fad8f515..e45a08d6c98e 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -461,7 +461,8 @@ struct zfcp_adapter {
461 u32 hardware_version; /* of FCP channel */ 461 u32 hardware_version; /* of FCP channel */
462 u16 timer_ticks; /* time int for a tick */ 462 u16 timer_ticks; /* time int for a tick */
463 struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ 463 struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
464 struct list_head port_list_head; /* remote port list */ 464 struct list_head port_list; /* remote port list */
465 rwlock_t port_list_lock; /* port list lock */
465 unsigned long req_no; /* unique FSF req number */ 466 unsigned long req_no; /* unique FSF req number */
466 struct list_head *req_list; /* list of pending reqs */ 467 struct list_head *req_list; /* list of pending reqs */
467 spinlock_t req_list_lock; /* request list lock */ 468 spinlock_t req_list_lock; /* request list lock */
@@ -504,7 +505,8 @@ struct zfcp_port {
504 wait_queue_head_t remove_wq; /* can be used to wait for 505 wait_queue_head_t remove_wq; /* can be used to wait for
505 refcount drop to zero */ 506 refcount drop to zero */
506 struct zfcp_adapter *adapter; /* adapter used to access port */ 507 struct zfcp_adapter *adapter; /* adapter used to access port */
507 struct list_head unit_list_head; /* head of logical unit list */ 508 struct list_head unit_list; /* head of logical unit list */
509 rwlock_t unit_list_lock; /* unit list lock */
508 atomic_t status; /* status of this remote port */ 510 atomic_t status; /* status of this remote port */
509 u64 wwnn; /* WWNN if known */ 511 u64 wwnn; /* WWNN if known */
510 u64 wwpn; /* WWPN */ 512 u64 wwpn; /* WWPN */
@@ -601,9 +603,6 @@ struct zfcp_fsf_req {
601struct zfcp_data { 603struct zfcp_data {
602 struct scsi_host_template scsi_host_template; 604 struct scsi_host_template scsi_host_template;
603 struct scsi_transport_template *scsi_transport_template; 605 struct scsi_transport_template *scsi_transport_template;
604 rwlock_t config_lock; /* serialises changes
605 to adapter/port/unit
606 lists */
607 struct mutex config_mutex; 606 struct mutex config_mutex;
608 struct kmem_cache *gpn_ft_cache; 607 struct kmem_cache *gpn_ft_cache;
609 struct kmem_cache *qtcb_cache; 608 struct kmem_cache *qtcb_cache;
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index f73e2180f333..464f0473877a 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -99,9 +99,12 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
99 99
100 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) 100 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
101 zfcp_erp_action_dismiss(&port->erp_action); 101 zfcp_erp_action_dismiss(&port->erp_action);
102 else 102 else {
103 list_for_each_entry(unit, &port->unit_list_head, list) 103 read_lock(&port->unit_list_lock);
104 zfcp_erp_action_dismiss_unit(unit); 104 list_for_each_entry(unit, &port->unit_list, list)
105 zfcp_erp_action_dismiss_unit(unit);
106 read_unlock(&port->unit_list_lock);
107 }
105} 108}
106 109
107static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) 110static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
@@ -110,9 +113,12 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
110 113
111 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE) 114 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_INUSE)
112 zfcp_erp_action_dismiss(&adapter->erp_action); 115 zfcp_erp_action_dismiss(&adapter->erp_action);
113 else 116 else {
114 list_for_each_entry(port, &adapter->port_list_head, list) 117 read_lock(&adapter->port_list_lock);
118 list_for_each_entry(port, &adapter->port_list, list)
115 zfcp_erp_action_dismiss_port(port); 119 zfcp_erp_action_dismiss_port(port);
120 read_unlock(&adapter->port_list_lock);
121 }
116} 122}
117 123
118static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, 124static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
@@ -264,11 +270,16 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear,
264{ 270{
265 unsigned long flags; 271 unsigned long flags;
266 272
267 read_lock_irqsave(&zfcp_data.config_lock, flags); 273 zfcp_erp_adapter_block(adapter, clear);
268 write_lock(&adapter->erp_lock); 274 zfcp_scsi_schedule_rports_block(adapter);
269 _zfcp_erp_adapter_reopen(adapter, clear, id, ref); 275
270 write_unlock(&adapter->erp_lock); 276 write_lock_irqsave(&adapter->erp_lock, flags);
271 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 277 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
278 zfcp_erp_adapter_failed(adapter, "erareo1", NULL);
279 else
280 zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
281 NULL, NULL, id, ref);
282 write_unlock_irqrestore(&adapter->erp_lock, flags);
272} 283}
273 284
274/** 285/**
@@ -345,11 +356,9 @@ void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id,
345 unsigned long flags; 356 unsigned long flags;
346 struct zfcp_adapter *adapter = port->adapter; 357 struct zfcp_adapter *adapter = port->adapter;
347 358
348 read_lock_irqsave(&zfcp_data.config_lock, flags); 359 write_lock_irqsave(&adapter->erp_lock, flags);
349 write_lock(&adapter->erp_lock);
350 _zfcp_erp_port_forced_reopen(port, clear, id, ref); 360 _zfcp_erp_port_forced_reopen(port, clear, id, ref);
351 write_unlock(&adapter->erp_lock); 361 write_unlock_irqrestore(&adapter->erp_lock, flags);
352 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
353} 362}
354 363
355static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, 364static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id,
@@ -377,15 +386,13 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id,
377 */ 386 */
378int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) 387int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref)
379{ 388{
380 unsigned long flags;
381 int retval; 389 int retval;
390 unsigned long flags;
382 struct zfcp_adapter *adapter = port->adapter; 391 struct zfcp_adapter *adapter = port->adapter;
383 392
384 read_lock_irqsave(&zfcp_data.config_lock, flags); 393 write_lock_irqsave(&adapter->erp_lock, flags);
385 write_lock(&adapter->erp_lock);
386 retval = _zfcp_erp_port_reopen(port, clear, id, ref); 394 retval = _zfcp_erp_port_reopen(port, clear, id, ref);
387 write_unlock(&adapter->erp_lock); 395 write_unlock_irqrestore(&adapter->erp_lock, flags);
388 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
389 396
390 return retval; 397 return retval;
391} 398}
@@ -424,11 +431,9 @@ void zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear, char *id,
424 struct zfcp_port *port = unit->port; 431 struct zfcp_port *port = unit->port;
425 struct zfcp_adapter *adapter = port->adapter; 432 struct zfcp_adapter *adapter = port->adapter;
426 433
427 read_lock_irqsave(&zfcp_data.config_lock, flags); 434 write_lock_irqsave(&adapter->erp_lock, flags);
428 write_lock(&adapter->erp_lock);
429 _zfcp_erp_unit_reopen(unit, clear, id, ref); 435 _zfcp_erp_unit_reopen(unit, clear, id, ref);
430 write_unlock(&adapter->erp_lock); 436 write_unlock_irqrestore(&adapter->erp_lock, flags);
431 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
432} 437}
433 438
434static int status_change_set(unsigned long mask, atomic_t *status) 439static int status_change_set(unsigned long mask, atomic_t *status)
@@ -540,8 +545,10 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
540{ 545{
541 struct zfcp_port *port; 546 struct zfcp_port *port;
542 547
543 list_for_each_entry(port, &adapter->port_list_head, list) 548 read_lock(&adapter->port_list_lock);
549 list_for_each_entry(port, &adapter->port_list, list)
544 _zfcp_erp_port_reopen(port, clear, id, ref); 550 _zfcp_erp_port_reopen(port, clear, id, ref);
551 read_unlock(&adapter->port_list_lock);
545} 552}
546 553
547static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, 554static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
@@ -549,8 +556,10 @@ static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
549{ 556{
550 struct zfcp_unit *unit; 557 struct zfcp_unit *unit;
551 558
552 list_for_each_entry(unit, &port->unit_list_head, list) 559 read_lock(&port->unit_list_lock);
560 list_for_each_entry(unit, &port->unit_list, list)
553 _zfcp_erp_unit_reopen(unit, clear, id, ref); 561 _zfcp_erp_unit_reopen(unit, clear, id, ref);
562 read_unlock(&port->unit_list_lock);
554} 563}
555 564
556static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) 565static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
@@ -590,16 +599,14 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter)
590{ 599{
591 unsigned long flags; 600 unsigned long flags;
592 601
593 read_lock_irqsave(&zfcp_data.config_lock, flags); 602 read_lock_irqsave(&adapter->erp_lock, flags);
594 read_lock(&adapter->erp_lock);
595 if (list_empty(&adapter->erp_ready_head) && 603 if (list_empty(&adapter->erp_ready_head) &&
596 list_empty(&adapter->erp_running_head)) { 604 list_empty(&adapter->erp_running_head)) {
597 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, 605 atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
598 &adapter->status); 606 &adapter->status);
599 wake_up(&adapter->erp_done_wqh); 607 wake_up(&adapter->erp_done_wqh);
600 } 608 }
601 read_unlock(&adapter->erp_lock); 609 read_unlock_irqrestore(&adapter->erp_lock, flags);
602 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
603} 610}
604 611
605static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act) 612static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act)
@@ -1214,11 +1221,10 @@ static int zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
1214static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) 1221static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
1215{ 1222{
1216 int retval; 1223 int retval;
1217 struct zfcp_adapter *adapter = erp_action->adapter;
1218 unsigned long flags; 1224 unsigned long flags;
1225 struct zfcp_adapter *adapter = erp_action->adapter;
1219 1226
1220 read_lock_irqsave(&zfcp_data.config_lock, flags); 1227 write_lock_irqsave(&adapter->erp_lock, flags);
1221 write_lock(&adapter->erp_lock);
1222 1228
1223 zfcp_erp_strategy_check_fsfreq(erp_action); 1229 zfcp_erp_strategy_check_fsfreq(erp_action);
1224 1230
@@ -1231,11 +1237,9 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
1231 zfcp_erp_action_to_running(erp_action); 1237 zfcp_erp_action_to_running(erp_action);
1232 1238
1233 /* no lock to allow for blocking operations */ 1239 /* no lock to allow for blocking operations */
1234 write_unlock(&adapter->erp_lock); 1240 write_unlock_irqrestore(&adapter->erp_lock, flags);
1235 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1236 retval = zfcp_erp_strategy_do_action(erp_action); 1241 retval = zfcp_erp_strategy_do_action(erp_action);
1237 read_lock_irqsave(&zfcp_data.config_lock, flags); 1242 write_lock_irqsave(&adapter->erp_lock, flags);
1238 write_lock(&adapter->erp_lock);
1239 1243
1240 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED) 1244 if (erp_action->status & ZFCP_STATUS_ERP_DISMISSED)
1241 retval = ZFCP_ERP_CONTINUES; 1245 retval = ZFCP_ERP_CONTINUES;
@@ -1273,8 +1277,7 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
1273 zfcp_erp_strategy_followup_failed(erp_action); 1277 zfcp_erp_strategy_followup_failed(erp_action);
1274 1278
1275 unlock: 1279 unlock:
1276 write_unlock(&adapter->erp_lock); 1280 write_unlock_irqrestore(&adapter->erp_lock, flags);
1277 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1278 1281
1279 if (retval != ZFCP_ERP_CONTINUES) 1282 if (retval != ZFCP_ERP_CONTINUES)
1280 zfcp_erp_action_cleanup(erp_action, retval); 1283 zfcp_erp_action_cleanup(erp_action, retval);
@@ -1415,6 +1418,7 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
1415 void *ref, u32 mask, int set_or_clear) 1418 void *ref, u32 mask, int set_or_clear)
1416{ 1419{
1417 struct zfcp_port *port; 1420 struct zfcp_port *port;
1421 unsigned long flags;
1418 u32 common_mask = mask & ZFCP_COMMON_FLAGS; 1422 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1419 1423
1420 if (set_or_clear == ZFCP_SET) { 1424 if (set_or_clear == ZFCP_SET) {
@@ -1429,10 +1433,13 @@ void zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter, char *id,
1429 atomic_set(&adapter->erp_counter, 0); 1433 atomic_set(&adapter->erp_counter, 0);
1430 } 1434 }
1431 1435
1432 if (common_mask) 1436 if (common_mask) {
1433 list_for_each_entry(port, &adapter->port_list_head, list) 1437 read_lock_irqsave(&adapter->port_list_lock, flags);
1438 list_for_each_entry(port, &adapter->port_list, list)
1434 zfcp_erp_modify_port_status(port, id, ref, common_mask, 1439 zfcp_erp_modify_port_status(port, id, ref, common_mask,
1435 set_or_clear); 1440 set_or_clear);
1441 read_unlock_irqrestore(&adapter->port_list_lock, flags);
1442 }
1436} 1443}
1437 1444
1438/** 1445/**
@@ -1449,6 +1456,7 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
1449 u32 mask, int set_or_clear) 1456 u32 mask, int set_or_clear)
1450{ 1457{
1451 struct zfcp_unit *unit; 1458 struct zfcp_unit *unit;
1459 unsigned long flags;
1452 u32 common_mask = mask & ZFCP_COMMON_FLAGS; 1460 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
1453 1461
1454 if (set_or_clear == ZFCP_SET) { 1462 if (set_or_clear == ZFCP_SET) {
@@ -1463,10 +1471,13 @@ void zfcp_erp_modify_port_status(struct zfcp_port *port, char *id, void *ref,
1463 atomic_set(&port->erp_counter, 0); 1471 atomic_set(&port->erp_counter, 0);
1464 } 1472 }
1465 1473
1466 if (common_mask) 1474 if (common_mask) {
1467 list_for_each_entry(unit, &port->unit_list_head, list) 1475 read_lock_irqsave(&port->unit_list_lock, flags);
1476 list_for_each_entry(unit, &port->unit_list, list)
1468 zfcp_erp_modify_unit_status(unit, id, ref, common_mask, 1477 zfcp_erp_modify_unit_status(unit, id, ref, common_mask,
1469 set_or_clear); 1478 set_or_clear);
1479 read_unlock_irqrestore(&port->unit_list_lock, flags);
1480 }
1470} 1481}
1471 1482
1472/** 1483/**
@@ -1502,12 +1513,8 @@ void zfcp_erp_modify_unit_status(struct zfcp_unit *unit, char *id, void *ref,
1502 */ 1513 */
1503void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref) 1514void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref)
1504{ 1515{
1505 unsigned long flags;
1506
1507 read_lock_irqsave(&zfcp_data.config_lock, flags);
1508 zfcp_erp_modify_port_status(port, id, ref, 1516 zfcp_erp_modify_port_status(port, id, ref,
1509 ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET); 1517 ZFCP_STATUS_COMMON_ACCESS_BOXED, ZFCP_SET);
1510 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1511 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref); 1518 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, id, ref);
1512} 1519}
1513 1520
@@ -1535,13 +1542,9 @@ void zfcp_erp_unit_boxed(struct zfcp_unit *unit, char *id, void *ref)
1535 */ 1542 */
1536void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref) 1543void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref)
1537{ 1544{
1538 unsigned long flags;
1539
1540 read_lock_irqsave(&zfcp_data.config_lock, flags);
1541 zfcp_erp_modify_port_status(port, id, ref, 1545 zfcp_erp_modify_port_status(port, id, ref,
1542 ZFCP_STATUS_COMMON_ERP_FAILED | 1546 ZFCP_STATUS_COMMON_ERP_FAILED |
1543 ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET); 1547 ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
1544 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
1545} 1548}
1546 1549
1547/** 1550/**
@@ -1574,12 +1577,15 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id,
1574 void *ref) 1577 void *ref)
1575{ 1578{
1576 struct zfcp_unit *unit; 1579 struct zfcp_unit *unit;
1580 unsigned long flags;
1577 int status = atomic_read(&port->status); 1581 int status = atomic_read(&port->status);
1578 1582
1579 if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED | 1583 if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
1580 ZFCP_STATUS_COMMON_ACCESS_BOXED))) { 1584 ZFCP_STATUS_COMMON_ACCESS_BOXED))) {
1581 list_for_each_entry(unit, &port->unit_list_head, list) 1585 read_lock_irqsave(&port->unit_list_lock, flags);
1586 list_for_each_entry(unit, &port->unit_list, list)
1582 zfcp_erp_unit_access_changed(unit, id, ref); 1587 zfcp_erp_unit_access_changed(unit, id, ref);
1588 read_unlock_irqrestore(&port->unit_list_lock, flags);
1583 return; 1589 return;
1584 } 1590 }
1585 1591
@@ -1595,14 +1601,14 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, char *id,
1595void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id, 1601void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id,
1596 void *ref) 1602 void *ref)
1597{ 1603{
1598 struct zfcp_port *port;
1599 unsigned long flags; 1604 unsigned long flags;
1605 struct zfcp_port *port;
1600 1606
1601 if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) 1607 if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
1602 return; 1608 return;
1603 1609
1604 read_lock_irqsave(&zfcp_data.config_lock, flags); 1610 read_lock_irqsave(&adapter->port_list_lock, flags);
1605 list_for_each_entry(port, &adapter->port_list_head, list) 1611 list_for_each_entry(port, &adapter->port_list, list)
1606 zfcp_erp_port_access_changed(port, id, ref); 1612 zfcp_erp_port_access_changed(port, id, ref);
1607 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 1613 read_unlock_irqrestore(&adapter->port_list_lock, flags);
1608} 1614}
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index df23bcead23d..c7efdc51df63 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -145,10 +145,11 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
145 struct fcp_rscn_element *elem) 145 struct fcp_rscn_element *elem)
146{ 146{
147 unsigned long flags; 147 unsigned long flags;
148 struct zfcp_adapter *adapter = fsf_req->adapter;
148 struct zfcp_port *port; 149 struct zfcp_port *port;
149 150
150 read_lock_irqsave(&zfcp_data.config_lock, flags); 151 read_lock_irqsave(&adapter->port_list_lock, flags);
151 list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) { 152 list_for_each_entry(port, &adapter->port_list, list) {
152 if ((port->d_id & range) == (elem->nport_did & range)) 153 if ((port->d_id & range) == (elem->nport_did & range))
153 zfcp_fc_test_link(port); 154 zfcp_fc_test_link(port);
154 if (!port->d_id) 155 if (!port->d_id)
@@ -156,8 +157,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
156 ZFCP_STATUS_COMMON_ERP_FAILED, 157 ZFCP_STATUS_COMMON_ERP_FAILED,
157 "fcrscn1", NULL); 158 "fcrscn1", NULL);
158 } 159 }
159 160 read_unlock_irqrestore(&adapter->port_list_lock, flags);
160 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
161} 161}
162 162
163static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) 163static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
@@ -187,18 +187,17 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
187 187
188static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) 188static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn)
189{ 189{
190 unsigned long flags;
190 struct zfcp_adapter *adapter = req->adapter; 191 struct zfcp_adapter *adapter = req->adapter;
191 struct zfcp_port *port; 192 struct zfcp_port *port;
192 unsigned long flags;
193 193
194 read_lock_irqsave(&zfcp_data.config_lock, flags); 194 read_lock_irqsave(&adapter->port_list_lock, flags);
195 list_for_each_entry(port, &adapter->port_list_head, list) 195 list_for_each_entry(port, &adapter->port_list, list)
196 if (port->wwpn == wwpn) 196 if (port->wwpn == wwpn) {
197 zfcp_erp_port_forced_reopen(port, 0, "fciwwp1", req);
197 break; 198 break;
198 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 199 }
199 200 read_unlock_irqrestore(&adapter->port_list_lock, flags);
200 if (port && (port->wwpn == wwpn))
201 zfcp_erp_port_forced_reopen(port, 0, "fciwwp1", req);
202} 201}
203 202
204static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req) 203static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req)
@@ -579,20 +578,17 @@ static int zfcp_fc_send_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
579 578
580static void zfcp_fc_validate_port(struct zfcp_port *port) 579static void zfcp_fc_validate_port(struct zfcp_port *port)
581{ 580{
582 struct zfcp_adapter *adapter = port->adapter;
583
584 if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC)) 581 if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC))
585 return; 582 return;
586 583
587 atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); 584 atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status);
588 585
589 if ((port->supported_classes != 0) || 586 if ((port->supported_classes != 0) ||
590 !list_empty(&port->unit_list_head)) { 587 !list_empty(&port->unit_list)) {
591 zfcp_port_put(port); 588 zfcp_port_put(port);
592 return; 589 return;
593 } 590 }
594 zfcp_erp_port_shutdown(port, 0, "fcpval1", NULL); 591 zfcp_erp_port_shutdown(port, 0, "fcpval1", NULL);
595 zfcp_erp_wait(adapter);
596 zfcp_port_put(port); 592 zfcp_port_put(port);
597 zfcp_port_dequeue(port); 593 zfcp_port_dequeue(port);
598} 594}
@@ -605,6 +601,7 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
605 struct gpn_ft_resp_acc *acc = sg_virt(sg); 601 struct gpn_ft_resp_acc *acc = sg_virt(sg);
606 struct zfcp_adapter *adapter = ct->wka_port->adapter; 602 struct zfcp_adapter *adapter = ct->wka_port->adapter;
607 struct zfcp_port *port, *tmp; 603 struct zfcp_port *port, *tmp;
604 unsigned long flags;
608 u32 d_id; 605 u32 d_id;
609 int ret = 0, x, last = 0; 606 int ret = 0, x, last = 0;
610 607
@@ -643,21 +640,20 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
643 /* skip the adapter's port and known remote ports */ 640 /* skip the adapter's port and known remote ports */
644 if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) 641 if (acc->wwpn == fc_host_port_name(adapter->scsi_host))
645 continue; 642 continue;
646 port = zfcp_get_port_by_wwpn(adapter, acc->wwpn);
647 if (port)
648 continue;
649 643
650 port = zfcp_port_enqueue(adapter, acc->wwpn, 644 port = zfcp_port_enqueue(adapter, acc->wwpn,
651 ZFCP_STATUS_COMMON_NOESC, d_id); 645 ZFCP_STATUS_COMMON_NOESC, d_id);
652 if (IS_ERR(port)) 646 if (!IS_ERR(port))
653 ret = PTR_ERR(port);
654 else
655 zfcp_erp_port_reopen(port, 0, "fcegpf1", NULL); 647 zfcp_erp_port_reopen(port, 0, "fcegpf1", NULL);
648 else if (PTR_ERR(port) != -EEXIST)
649 ret = PTR_ERR(port);
656 } 650 }
657 651
658 zfcp_erp_wait(adapter); 652 zfcp_erp_wait(adapter);
659 list_for_each_entry_safe(port, tmp, &adapter->port_list_head, list) 653 write_lock_irqsave(&adapter->port_list_lock, flags);
654 list_for_each_entry_safe(port, tmp, &adapter->port_list, list)
660 zfcp_fc_validate_port(port); 655 zfcp_fc_validate_port(port);
656 write_unlock_irqrestore(&adapter->port_list_lock, flags);
661 mutex_unlock(&zfcp_data.config_mutex); 657 mutex_unlock(&zfcp_data.config_mutex);
662 return ret; 658 return ret;
663} 659}
@@ -760,15 +756,14 @@ int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *job)
760 756
761 els_fc_job->els.adapter = adapter; 757 els_fc_job->els.adapter = adapter;
762 if (rport) { 758 if (rport) {
763 read_lock_irq(&zfcp_data.config_lock);
764 port = zfcp_get_port_by_wwpn(adapter, rport->port_name); 759 port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
765 if (port)
766 els_fc_job->els.d_id = port->d_id;
767 read_unlock_irq(&zfcp_data.config_lock);
768 if (!port) { 760 if (!port) {
769 kfree(els_fc_job); 761 kfree(els_fc_job);
770 return -EINVAL; 762 return -EINVAL;
771 } 763 }
764
765 els_fc_job->els.d_id = port->d_id;
766 zfcp_port_put(port);
772 } else { 767 } else {
773 port_did = job->request->rqst_data.h_els.port_id; 768 port_did = job->request->rqst_data.h_els.port_id;
774 els_fc_job->els.d_id = (port_did[0] << 16) + 769 els_fc_job->els.d_id = (port_did[0] << 16) +
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 4e41baa0c141..9df62f686812 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -122,36 +122,32 @@ void zfcp_fsf_req_free(struct zfcp_fsf_req *req)
122 122
123static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) 123static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
124{ 124{
125 unsigned long flags;
125 struct fsf_status_read_buffer *sr_buf = req->data; 126 struct fsf_status_read_buffer *sr_buf = req->data;
126 struct zfcp_adapter *adapter = req->adapter; 127 struct zfcp_adapter *adapter = req->adapter;
127 struct zfcp_port *port; 128 struct zfcp_port *port;
128 int d_id = sr_buf->d_id & ZFCP_DID_MASK; 129 int d_id = sr_buf->d_id & ZFCP_DID_MASK;
129 unsigned long flags;
130 130
131 read_lock_irqsave(&zfcp_data.config_lock, flags); 131 read_lock_irqsave(&adapter->port_list_lock, flags);
132 list_for_each_entry(port, &adapter->port_list_head, list) 132 list_for_each_entry(port, &adapter->port_list, list)
133 if (port->d_id == d_id) { 133 if (port->d_id == d_id) {
134 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
135 zfcp_erp_port_reopen(port, 0, "fssrpc1", req); 134 zfcp_erp_port_reopen(port, 0, "fssrpc1", req);
136 return; 135 break;
137 } 136 }
138 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 137 read_unlock_irqrestore(&adapter->port_list_lock, flags);
139} 138}
140 139
141static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id, 140static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id,
142 struct fsf_link_down_info *link_down) 141 struct fsf_link_down_info *link_down)
143{ 142{
144 struct zfcp_adapter *adapter = req->adapter; 143 struct zfcp_adapter *adapter = req->adapter;
145 unsigned long flags;
146 144
147 if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED) 145 if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
148 return; 146 return;
149 147
150 atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); 148 atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
151 149
152 read_lock_irqsave(&zfcp_data.config_lock, flags);
153 zfcp_scsi_schedule_rports_block(adapter); 150 zfcp_scsi_schedule_rports_block(adapter);
154 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
155 151
156 if (!link_down) 152 if (!link_down)
157 goto out; 153 goto out;
@@ -1765,9 +1761,11 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
1765 /* can't use generic zfcp_erp_modify_port_status because 1761 /* can't use generic zfcp_erp_modify_port_status because
1766 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */ 1762 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
1767 atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 1763 atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1768 list_for_each_entry(unit, &port->unit_list_head, list) 1764 read_lock(&port->unit_list_lock);
1765 list_for_each_entry(unit, &port->unit_list, list)
1769 atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, 1766 atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
1770 &unit->status); 1767 &unit->status);
1768 read_unlock(&port->unit_list_lock);
1771 zfcp_erp_port_boxed(port, "fscpph2", req); 1769 zfcp_erp_port_boxed(port, "fscpph2", req);
1772 req->status |= ZFCP_STATUS_FSFREQ_ERROR | 1770 req->status |= ZFCP_STATUS_FSFREQ_ERROR |
1773 ZFCP_STATUS_FSFREQ_RETRY; 1771 ZFCP_STATUS_FSFREQ_RETRY;
@@ -1787,9 +1785,11 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
1787 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port 1785 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
1788 */ 1786 */
1789 atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status); 1787 atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1790 list_for_each_entry(unit, &port->unit_list_head, list) 1788 read_lock(&port->unit_list_lock);
1789 list_for_each_entry(unit, &port->unit_list, list)
1791 atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, 1790 atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
1792 &unit->status); 1791 &unit->status);
1792 read_unlock(&port->unit_list_lock);
1793 break; 1793 break;
1794 } 1794 }
1795} 1795}
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index f54655998bd5..6feece3b2e36 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -128,49 +128,44 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
128} 128}
129 129
130static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter, 130static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter,
131 int channel, unsigned int id, 131 unsigned int id, u64 lun)
132 unsigned int lun)
133{ 132{
133 unsigned long flags;
134 struct zfcp_port *port; 134 struct zfcp_port *port;
135 struct zfcp_unit *unit; 135 struct zfcp_unit *unit = NULL;
136 int scsi_lun;
137 136
138 list_for_each_entry(port, &adapter->port_list_head, list) { 137 read_lock_irqsave(&adapter->port_list_lock, flags);
138 list_for_each_entry(port, &adapter->port_list, list) {
139 if (!port->rport || (id != port->rport->scsi_target_id)) 139 if (!port->rport || (id != port->rport->scsi_target_id))
140 continue; 140 continue;
141 list_for_each_entry(unit, &port->unit_list_head, list) { 141 unit = zfcp_get_unit_by_lun(port, lun);
142 scsi_lun = scsilun_to_int( 142 if (unit)
143 (struct scsi_lun *)&unit->fcp_lun); 143 break;
144 if (lun == scsi_lun)
145 return unit;
146 }
147 } 144 }
145 read_unlock_irqrestore(&adapter->port_list_lock, flags);
148 146
149 return NULL; 147 return unit;
150} 148}
151 149
152static int zfcp_scsi_slave_alloc(struct scsi_device *sdp) 150static int zfcp_scsi_slave_alloc(struct scsi_device *sdp)
153{ 151{
154 struct zfcp_adapter *adapter; 152 struct zfcp_adapter *adapter;
155 struct zfcp_unit *unit; 153 struct zfcp_unit *unit;
156 unsigned long flags; 154 u64 lun;
157 int retval = -ENXIO;
158 155
159 adapter = (struct zfcp_adapter *) sdp->host->hostdata[0]; 156 adapter = (struct zfcp_adapter *) sdp->host->hostdata[0];
160 if (!adapter) 157 if (!adapter)
161 goto out; 158 goto out;
162 159
163 read_lock_irqsave(&zfcp_data.config_lock, flags); 160 int_to_scsilun(sdp->lun, (struct scsi_lun *)&lun);
164 unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun); 161 unit = zfcp_unit_lookup(adapter, sdp->id, lun);
165 if (unit) { 162 if (unit) {
166 sdp->hostdata = unit; 163 sdp->hostdata = unit;
167 unit->device = sdp; 164 unit->device = sdp;
168 zfcp_unit_get(unit); 165 return 0;
169 retval = 0;
170 } 166 }
171 read_unlock_irqrestore(&zfcp_data.config_lock, flags);
172out: 167out:
173 return retval; 168 return -ENXIO;
174} 169}
175 170
176static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) 171static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
@@ -338,12 +333,12 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
338 if (!shost) 333 if (!shost)
339 return; 334 return;
340 335
341 read_lock_irq(&zfcp_data.config_lock); 336 read_lock_irq(&adapter->port_list_lock);
342 list_for_each_entry(port, &adapter->port_list_head, list) 337 list_for_each_entry(port, &adapter->port_list, list)
343 if (port->rport) 338 if (port->rport)
344 port->rport = NULL; 339 port->rport = NULL;
340 read_unlock_irq(&adapter->port_list_lock);
345 341
346 read_unlock_irq(&zfcp_data.config_lock);
347 fc_remove_host(shost); 342 fc_remove_host(shost);
348 scsi_remove_host(shost); 343 scsi_remove_host(shost);
349 scsi_host_put(shost); 344 scsi_host_put(shost);
@@ -508,7 +503,7 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
508 * @rport: The FC rport where to teminate I/O 503 * @rport: The FC rport where to teminate I/O
509 * 504 *
510 * Abort all pending SCSI commands for a port by closing the 505 * Abort all pending SCSI commands for a port by closing the
511 * port. Using a reopen for avoids a conflict with a shutdown 506 * port. Using a reopen avoiding a conflict with a shutdown
512 * overwriting a reopen. 507 * overwriting a reopen.
513 */ 508 */
514static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) 509static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
@@ -518,11 +513,7 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
518 struct zfcp_adapter *adapter = 513 struct zfcp_adapter *adapter =
519 (struct zfcp_adapter *)shost->hostdata[0]; 514 (struct zfcp_adapter *)shost->hostdata[0];
520 515
521 write_lock_irq(&zfcp_data.config_lock);
522 port = zfcp_get_port_by_wwpn(adapter, rport->port_name); 516 port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
523 if (port)
524 zfcp_port_get(port);
525 write_unlock_irq(&zfcp_data.config_lock);
526 517
527 if (port) { 518 if (port) {
528 zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); 519 zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
@@ -589,10 +580,13 @@ void zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
589 580
590void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter) 581void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
591{ 582{
583 unsigned long flags;
592 struct zfcp_port *port; 584 struct zfcp_port *port;
593 585
594 list_for_each_entry(port, &adapter->port_list_head, list) 586 read_lock_irqsave(&adapter->port_list_lock, flags);
587 list_for_each_entry(port, &adapter->port_list, list)
595 zfcp_scsi_schedule_rport_block(port); 588 zfcp_scsi_schedule_rport_block(port);
589 read_unlock_irqrestore(&adapter->port_list_lock, flags);
596} 590}
597 591
598void zfcp_scsi_rport_work(struct work_struct *work) 592void zfcp_scsi_rport_work(struct work_struct *work)
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index d31000886ca8..8430b518357e 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -153,15 +153,14 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
153 goto out; 153 goto out;
154 } 154 }
155 155
156 write_lock_irq(&zfcp_data.config_lock);
157 port = zfcp_get_port_by_wwpn(adapter, wwpn); 156 port = zfcp_get_port_by_wwpn(adapter, wwpn);
158 if (port && (atomic_read(&port->refcount) == 0)) { 157 if (port && (atomic_read(&port->refcount) == 1)) {
159 zfcp_port_get(port);
160 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); 158 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
159 write_lock_irq(&adapter->port_list_lock);
161 list_move(&port->list, &port_remove_lh); 160 list_move(&port->list, &port_remove_lh);
161 write_unlock_irq(&adapter->port_list_lock);
162 } else 162 } else
163 port = NULL; 163 port = NULL;
164 write_unlock_irq(&zfcp_data.config_lock);
165 164
166 if (!port) { 165 if (!port) {
167 retval = -ENXIO; 166 retval = -ENXIO;
@@ -253,35 +252,28 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
253 goto out; 252 goto out;
254 } 253 }
255 254
256 write_lock_irq(&zfcp_data.config_lock);
257 unit = zfcp_get_unit_by_lun(port, fcp_lun); 255 unit = zfcp_get_unit_by_lun(port, fcp_lun);
258 if (unit) {
259 write_unlock_irq(&zfcp_data.config_lock);
260 /* wait for possible timeout during SCSI probe */
261 flush_work(&unit->scsi_work);
262 write_lock_irq(&zfcp_data.config_lock);
263
264 if (atomic_read(&unit->refcount) == 0) {
265 zfcp_unit_get(unit);
266 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
267 &unit->status);
268 list_move(&unit->list, &unit_remove_lh);
269 } else {
270 unit = NULL;
271 }
272 }
273
274 write_unlock_irq(&zfcp_data.config_lock);
275
276 if (!unit) { 256 if (!unit) {
277 retval = -ENXIO; 257 retval = -EINVAL;
278 goto out; 258 goto out;
279 } 259 }
280 260
281 zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); 261 /* wait for possible timeout during SCSI probe */
282 zfcp_erp_wait(unit->port->adapter); 262 flush_work(&unit->scsi_work);
283 zfcp_unit_put(unit); 263
284 zfcp_unit_dequeue(unit); 264 if (atomic_read(&unit->refcount) == 1) {
265 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
266
267 write_lock_irq(&port->unit_list_lock);
268 list_move(&unit->list, &unit_remove_lh);
269 write_unlock_irq(&port->unit_list_lock);
270
271 zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
272 zfcp_erp_wait(unit->port->adapter);
273 zfcp_unit_put(unit);
274 zfcp_unit_dequeue(unit);
275 } else
276 zfcp_unit_put(unit);
285out: 277out:
286 mutex_unlock(&zfcp_data.config_mutex); 278 mutex_unlock(&zfcp_data.config_mutex);
287 return retval ? retval : (ssize_t) count; 279 return retval ? retval : (ssize_t) count;