aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_aux.c
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/zfcp_aux.c
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/zfcp_aux.c')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c80
1 files changed, 46 insertions, 34 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}