diff options
author | Swen Schillig <swen@vnet.ibm.com> | 2009-11-24 10:53:58 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:02:01 -0500 |
commit | ecf0c7721b104c0ce9c8ca534c911f6310cf92a8 (patch) | |
tree | 639032b36bcbbe905c98c6f0b3b521dc2f0b1806 | |
parent | 0a55256d158c18e4821c248a295b7f8f4423660f (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>
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 80 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 23 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 9 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 116 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 49 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 22 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 52 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_sysfs.c | 48 |
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 | */ |
239 | struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) | 238 | struct 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) | |||
257 | struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, | 262 | struct 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 | */ |
357 | void zfcp_unit_dequeue(struct zfcp_unit *unit) | 367 | void 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 | */ |
716 | void zfcp_port_dequeue(struct zfcp_port *port) | 729 | void 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 | |||
135 | out: | ||
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 { | |||
601 | struct zfcp_data { | 603 | struct 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 | ||
107 | static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | 110 | static 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 | ||
118 | static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter, | 124 | static 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 | ||
355 | static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, | 364 | static 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 | */ |
378 | int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id, void *ref) | 387 | int 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 | ||
434 | static int status_change_set(unsigned long mask, atomic_t *status) | 439 | static 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 | ||
547 | static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, | 554 | static 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 | ||
556 | static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) | 565 | static 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 | ||
605 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *act) | 612 | static 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) | |||
1214 | static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action) | 1221 | static 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 | */ |
1503 | void zfcp_erp_port_boxed(struct zfcp_port *port, char *id, void *ref) | 1514 | void 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 | */ |
1536 | void zfcp_erp_port_access_denied(struct zfcp_port *port, char *id, void *ref) | 1543 | void 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, | |||
1595 | void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, char *id, | 1601 | void 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 | ||
163 | static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) | 163 | static 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 | ||
188 | static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) | 188 | static 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 | ||
204 | static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req) | 203 | static 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 | ||
580 | static void zfcp_fc_validate_port(struct zfcp_port *port) | 579 | static 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 | ||
123 | static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req) | 123 | static 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 | ||
141 | static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id, | 140 | static 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 | ||
130 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter, | 130 | static 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 | ||
152 | static int zfcp_scsi_slave_alloc(struct scsi_device *sdp) | 150 | static 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); | ||
172 | out: | 167 | out: |
173 | return retval; | 168 | return -ENXIO; |
174 | } | 169 | } |
175 | 170 | ||
176 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | 171 | static 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 | */ |
514 | static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) | 509 | static 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 | ||
590 | void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter) | 581 | void 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 | ||
598 | void zfcp_scsi_rport_work(struct work_struct *work) | 592 | void 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); | ||
285 | out: | 277 | out: |
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; |