diff options
author | Swen Schillig <swen@vnet.ibm.com> | 2009-11-24 10:54:00 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:02:02 -0500 |
commit | de3dc57214a1466034ecc4d4ffb10331d34c09a3 (patch) | |
tree | 63eb490d66f9db2cf032041392fb2f4d5ac4785c /drivers/s390 | |
parent | f3450c7b917201bb49d67032e9f60d5125675d6a (diff) |
[SCSI] zfcp: Remove global config_mutex
The global config_mutex was required for the serialization of a
configuration change within the zfcp driver. This global locking is
now obsolete and can be removed. The requirement of serializing the
access to a zfcp_adapter reference via a ccw_device is realized wth a
static spinlock.
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')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 86 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 138 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_cfdc.c | 25 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 1 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 5 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 3 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_sysfs.c | 132 |
7 files changed, 232 insertions, 158 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 8492ceac140..ed31bd0ff3f 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -80,23 +80,21 @@ int zfcp_reqlist_isempty(struct zfcp_adapter *adapter) | |||
80 | 80 | ||
81 | static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | 81 | static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) |
82 | { | 82 | { |
83 | struct ccw_device *ccwdev; | 83 | struct ccw_device *cdev; |
84 | struct zfcp_adapter *adapter; | 84 | struct zfcp_adapter *adapter; |
85 | struct zfcp_port *port; | 85 | struct zfcp_port *port; |
86 | struct zfcp_unit *unit; | 86 | struct zfcp_unit *unit; |
87 | 87 | ||
88 | ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); | 88 | cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); |
89 | if (!ccwdev) | 89 | if (!cdev) |
90 | return; | 90 | return; |
91 | 91 | ||
92 | if (ccw_device_set_online(ccwdev)) | 92 | if (ccw_device_set_online(cdev)) |
93 | goto out_ccwdev; | 93 | goto out_ccw_device; |
94 | 94 | ||
95 | mutex_lock(&zfcp_data.config_mutex); | 95 | adapter = zfcp_ccw_adapter_by_cdev(cdev); |
96 | adapter = dev_get_drvdata(&ccwdev->dev); | ||
97 | if (!adapter) | 96 | if (!adapter) |
98 | goto out_unlock; | 97 | goto out_ccw_device; |
99 | kref_get(&adapter->ref); | ||
100 | 98 | ||
101 | port = zfcp_get_port_by_wwpn(adapter, wwpn); | 99 | port = zfcp_get_port_by_wwpn(adapter, wwpn); |
102 | if (!port) | 100 | if (!port) |
@@ -105,21 +103,17 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) | |||
105 | unit = zfcp_unit_enqueue(port, lun); | 103 | unit = zfcp_unit_enqueue(port, lun); |
106 | if (IS_ERR(unit)) | 104 | if (IS_ERR(unit)) |
107 | goto out_unit; | 105 | goto out_unit; |
108 | mutex_unlock(&zfcp_data.config_mutex); | ||
109 | 106 | ||
110 | zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL); | 107 | zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL); |
111 | zfcp_erp_wait(adapter); | 108 | zfcp_erp_wait(adapter); |
112 | flush_work(&unit->scsi_work); | 109 | flush_work(&unit->scsi_work); |
113 | 110 | ||
114 | mutex_lock(&zfcp_data.config_mutex); | ||
115 | out_unit: | 111 | out_unit: |
116 | put_device(&port->sysfs_device); | 112 | put_device(&port->sysfs_device); |
117 | out_port: | 113 | out_port: |
118 | kref_put(&adapter->ref, zfcp_adapter_release); | 114 | zfcp_ccw_adapter_put(adapter); |
119 | out_unlock: | 115 | out_ccw_device: |
120 | mutex_unlock(&zfcp_data.config_mutex); | 116 | put_device(&cdev->dev); |
121 | out_ccwdev: | ||
122 | put_device(&ccwdev->dev); | ||
123 | return; | 117 | return; |
124 | } | 118 | } |
125 | 119 | ||
@@ -184,8 +178,6 @@ static int __init zfcp_module_init(void) | |||
184 | if (!zfcp_data.gid_pn_cache) | 178 | if (!zfcp_data.gid_pn_cache) |
185 | goto out_gid_cache; | 179 | goto out_gid_cache; |
186 | 180 | ||
187 | mutex_init(&zfcp_data.config_mutex); | ||
188 | |||
189 | zfcp_data.scsi_transport_template = | 181 | zfcp_data.scsi_transport_template = |
190 | fc_attach_transport(&zfcp_transport_functions); | 182 | fc_attach_transport(&zfcp_transport_functions); |
191 | if (!zfcp_data.scsi_transport_template) | 183 | if (!zfcp_data.scsi_transport_template) |
@@ -296,7 +288,6 @@ static void zfcp_unit_release(struct device *dev) | |||
296 | * @port: pointer to port where unit is added | 288 | * @port: pointer to port where unit is added |
297 | * @fcp_lun: FCP LUN of unit to be enqueued | 289 | * @fcp_lun: FCP LUN of unit to be enqueued |
298 | * Returns: pointer to enqueued unit on success, ERR_PTR on error | 290 | * Returns: pointer to enqueued unit on success, ERR_PTR on error |
299 | * Locks: config_mutex must be held to serialize changes to the unit list | ||
300 | * | 291 | * |
301 | * Sets up some unit internal structures and creates sysfs entry. | 292 | * Sets up some unit internal structures and creates sysfs entry. |
302 | */ | 293 | */ |
@@ -371,7 +362,6 @@ err_out: | |||
371 | 362 | ||
372 | static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) | 363 | static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) |
373 | { | 364 | { |
374 | /* must only be called with zfcp_data.config_mutex taken */ | ||
375 | adapter->pool.erp_req = | 365 | adapter->pool.erp_req = |
376 | mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req)); | 366 | mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req)); |
377 | if (!adapter->pool.erp_req) | 367 | if (!adapter->pool.erp_req) |
@@ -419,7 +409,6 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) | |||
419 | 409 | ||
420 | static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) | 410 | static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) |
421 | { | 411 | { |
422 | /* zfcp_data.config_mutex must be held */ | ||
423 | if (adapter->pool.erp_req) | 412 | if (adapter->pool.erp_req) |
424 | mempool_destroy(adapter->pool.erp_req); | 413 | mempool_destroy(adapter->pool.erp_req); |
425 | if (adapter->pool.scsi_req) | 414 | if (adapter->pool.scsi_req) |
@@ -501,24 +490,22 @@ static void zfcp_destroy_adapter_work_queue(struct zfcp_adapter *adapter) | |||
501 | * zfcp_adapter_enqueue - enqueue a new adapter to the list | 490 | * zfcp_adapter_enqueue - enqueue a new adapter to the list |
502 | * @ccw_device: pointer to the struct cc_device | 491 | * @ccw_device: pointer to the struct cc_device |
503 | * | 492 | * |
504 | * Returns: 0 if a new adapter was successfully enqueued | 493 | * Returns: struct zfcp_adapter* |
505 | * -ENOMEM if alloc failed | ||
506 | * Enqueues an adapter at the end of the adapter list in the driver data. | 494 | * Enqueues an adapter at the end of the adapter list in the driver data. |
507 | * All adapter internal structures are set up. | 495 | * All adapter internal structures are set up. |
508 | * Proc-fs entries are also created. | 496 | * Proc-fs entries are also created. |
509 | * locks: config_mutex must be held to serialize changes to the adapter list | ||
510 | */ | 497 | */ |
511 | int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | 498 | struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) |
512 | { | 499 | { |
513 | struct zfcp_adapter *adapter; | 500 | struct zfcp_adapter *adapter; |
514 | 501 | ||
515 | if (!get_device(&ccw_device->dev)) | 502 | if (!get_device(&ccw_device->dev)) |
516 | return -ENODEV; | 503 | return ERR_PTR(-ENODEV); |
517 | 504 | ||
518 | adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL); | 505 | adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL); |
519 | if (!adapter) { | 506 | if (!adapter) { |
520 | put_device(&ccw_device->dev); | 507 | put_device(&ccw_device->dev); |
521 | return -ENOMEM; | 508 | return ERR_PTR(-ENOMEM); |
522 | } | 509 | } |
523 | 510 | ||
524 | kref_init(&adapter->ref); | 511 | kref_init(&adapter->ref); |
@@ -578,11 +565,30 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
578 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); | 565 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); |
579 | 566 | ||
580 | if (!zfcp_adapter_scsi_register(adapter)) | 567 | if (!zfcp_adapter_scsi_register(adapter)) |
581 | return 0; | 568 | return adapter; |
582 | 569 | ||
583 | failed: | 570 | failed: |
584 | kref_put(&adapter->ref, zfcp_adapter_release); | 571 | zfcp_adapter_unregister(adapter); |
585 | return -ENOMEM; | 572 | return ERR_PTR(-ENOMEM); |
573 | } | ||
574 | |||
575 | void zfcp_adapter_unregister(struct zfcp_adapter *adapter) | ||
576 | { | ||
577 | struct ccw_device *cdev = adapter->ccw_device; | ||
578 | |||
579 | cancel_work_sync(&adapter->scan_work); | ||
580 | cancel_work_sync(&adapter->stat_work); | ||
581 | zfcp_destroy_adapter_work_queue(adapter); | ||
582 | |||
583 | zfcp_fc_wka_ports_force_offline(adapter->gs); | ||
584 | zfcp_adapter_scsi_unregister(adapter); | ||
585 | sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs); | ||
586 | |||
587 | zfcp_erp_thread_kill(adapter); | ||
588 | zfcp_dbf_adapter_unregister(adapter->dbf); | ||
589 | zfcp_qdio_destroy(adapter->qdio); | ||
590 | |||
591 | zfcp_ccw_adapter_put(adapter); /* final put to release */ | ||
586 | } | 592 | } |
587 | 593 | ||
588 | /** | 594 | /** |
@@ -594,27 +600,16 @@ void zfcp_adapter_release(struct kref *ref) | |||
594 | { | 600 | { |
595 | struct zfcp_adapter *adapter = container_of(ref, struct zfcp_adapter, | 601 | struct zfcp_adapter *adapter = container_of(ref, struct zfcp_adapter, |
596 | ref); | 602 | ref); |
597 | struct ccw_device *ccw_device = adapter->ccw_device; | 603 | struct ccw_device *cdev = adapter->ccw_device; |
598 | |||
599 | cancel_work_sync(&adapter->stat_work); | ||
600 | |||
601 | zfcp_fc_wka_ports_force_offline(adapter->gs); | ||
602 | sysfs_remove_group(&ccw_device->dev.kobj, &zfcp_sysfs_adapter_attrs); | ||
603 | |||
604 | dev_set_drvdata(&ccw_device->dev, NULL); | ||
605 | 604 | ||
606 | dev_set_drvdata(&adapter->ccw_device->dev, NULL); | 605 | dev_set_drvdata(&adapter->ccw_device->dev, NULL); |
607 | zfcp_fc_gs_destroy(adapter); | 606 | zfcp_fc_gs_destroy(adapter); |
608 | zfcp_erp_thread_kill(adapter); | ||
609 | zfcp_destroy_adapter_work_queue(adapter); | ||
610 | zfcp_dbf_adapter_unregister(adapter->dbf); | ||
611 | zfcp_free_low_mem_buffers(adapter); | 607 | zfcp_free_low_mem_buffers(adapter); |
612 | zfcp_qdio_destroy(adapter->qdio); | ||
613 | kfree(adapter->req_list); | 608 | kfree(adapter->req_list); |
614 | kfree(adapter->fc_stats); | 609 | kfree(adapter->fc_stats); |
615 | kfree(adapter->stats_reset_data); | 610 | kfree(adapter->stats_reset_data); |
616 | kfree(adapter); | 611 | kfree(adapter); |
617 | put_device(&ccw_device->dev); | 612 | put_device(&cdev->dev); |
618 | } | 613 | } |
619 | 614 | ||
620 | /** | 615 | /** |
@@ -636,7 +631,7 @@ static void zfcp_port_release(struct device *dev) | |||
636 | struct zfcp_port *port = container_of(dev, struct zfcp_port, | 631 | struct zfcp_port *port = container_of(dev, struct zfcp_port, |
637 | sysfs_device); | 632 | sysfs_device); |
638 | 633 | ||
639 | kref_put(&port->adapter->ref, zfcp_adapter_release); | 634 | zfcp_ccw_adapter_put(port->adapter); |
640 | kfree(port); | 635 | kfree(port); |
641 | } | 636 | } |
642 | 637 | ||
@@ -647,7 +642,6 @@ static void zfcp_port_release(struct device *dev) | |||
647 | * @status: initial status for the port | 642 | * @status: initial status for the port |
648 | * @d_id: destination id of the remote port to be enqueued | 643 | * @d_id: destination id of the remote port to be enqueued |
649 | * Returns: pointer to enqueued port on success, ERR_PTR on error | 644 | * Returns: pointer to enqueued port on success, ERR_PTR on error |
650 | * Locks: config_mutex must be held to serialize changes to the port list | ||
651 | * | 645 | * |
652 | * All port internal structures are set up and the sysfs entry is generated. | 646 | * All port internal structures are set up and the sysfs entry is generated. |
653 | * d_id is used to enqueue ports with a well known address like the Directory | 647 | * d_id is used to enqueue ports with a well known address like the Directory |
@@ -718,7 +712,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
718 | err_out_put: | 712 | err_out_put: |
719 | device_unregister(&port->sysfs_device); | 713 | device_unregister(&port->sysfs_device); |
720 | err_out: | 714 | err_out: |
721 | kref_put(&adapter->ref, zfcp_adapter_release); | 715 | zfcp_ccw_adapter_put(adapter); |
722 | return ERR_PTR(retval); | 716 | return ERR_PTR(retval); |
723 | } | 717 | } |
724 | 718 | ||
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index c89dbe25037..2433eaced20 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -13,20 +13,42 @@ | |||
13 | 13 | ||
14 | #define ZFCP_MODEL_PRIV 0x4 | 14 | #define ZFCP_MODEL_PRIV 0x4 |
15 | 15 | ||
16 | static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock); | ||
17 | |||
18 | struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *cdev) | ||
19 | { | ||
20 | struct zfcp_adapter *adapter; | ||
21 | unsigned long flags; | ||
22 | |||
23 | spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags); | ||
24 | adapter = dev_get_drvdata(&cdev->dev); | ||
25 | if (adapter) | ||
26 | kref_get(&adapter->ref); | ||
27 | spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); | ||
28 | return adapter; | ||
29 | } | ||
30 | |||
31 | void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter) | ||
32 | { | ||
33 | unsigned long flags; | ||
34 | |||
35 | spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags); | ||
36 | kref_put(&adapter->ref, zfcp_adapter_release); | ||
37 | spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); | ||
38 | } | ||
39 | |||
16 | static int zfcp_ccw_suspend(struct ccw_device *cdev) | 40 | static int zfcp_ccw_suspend(struct ccw_device *cdev) |
17 | 41 | ||
18 | { | 42 | { |
19 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); | 43 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
20 | 44 | ||
21 | if (!adapter) | 45 | if (!adapter) |
22 | return 0; | 46 | return 0; |
23 | 47 | ||
24 | mutex_lock(&zfcp_data.config_mutex); | ||
25 | |||
26 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL); | 48 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL); |
27 | zfcp_erp_wait(adapter); | 49 | zfcp_erp_wait(adapter); |
28 | 50 | ||
29 | mutex_unlock(&zfcp_data.config_mutex); | 51 | zfcp_ccw_adapter_put(adapter); |
30 | 52 | ||
31 | return 0; | 53 | return 0; |
32 | } | 54 | } |
@@ -34,7 +56,7 @@ static int zfcp_ccw_suspend(struct ccw_device *cdev) | |||
34 | static int zfcp_ccw_activate(struct ccw_device *cdev) | 56 | static int zfcp_ccw_activate(struct ccw_device *cdev) |
35 | 57 | ||
36 | { | 58 | { |
37 | struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev); | 59 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
38 | 60 | ||
39 | if (!adapter) | 61 | if (!adapter) |
40 | return 0; | 62 | return 0; |
@@ -46,6 +68,8 @@ static int zfcp_ccw_activate(struct ccw_device *cdev) | |||
46 | zfcp_erp_wait(adapter); | 68 | zfcp_erp_wait(adapter); |
47 | flush_work(&adapter->scan_work); | 69 | flush_work(&adapter->scan_work); |
48 | 70 | ||
71 | zfcp_ccw_adapter_put(adapter); | ||
72 | |||
49 | return 0; | 73 | return 0; |
50 | } | 74 | } |
51 | 75 | ||
@@ -67,28 +91,28 @@ int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter) | |||
67 | 91 | ||
68 | /** | 92 | /** |
69 | * zfcp_ccw_probe - probe function of zfcp driver | 93 | * zfcp_ccw_probe - probe function of zfcp driver |
70 | * @ccw_device: pointer to belonging ccw device | 94 | * @cdev: pointer to belonging ccw device |
71 | * | 95 | * |
72 | * This function gets called by the common i/o layer for each FCP | 96 | * This function gets called by the common i/o layer for each FCP |
73 | * device found on the current system. This is only a stub to make cio | 97 | * device found on the current system. This is only a stub to make cio |
74 | * work: To only allocate adapter resources for devices actually used, | 98 | * work: To only allocate adapter resources for devices actually used, |
75 | * the allocation is deferred to the first call to ccw_set_online. | 99 | * the allocation is deferred to the first call to ccw_set_online. |
76 | */ | 100 | */ |
77 | static int zfcp_ccw_probe(struct ccw_device *ccw_device) | 101 | static int zfcp_ccw_probe(struct ccw_device *cdev) |
78 | { | 102 | { |
79 | return 0; | 103 | return 0; |
80 | } | 104 | } |
81 | 105 | ||
82 | /** | 106 | /** |
83 | * zfcp_ccw_remove - remove function of zfcp driver | 107 | * zfcp_ccw_remove - remove function of zfcp driver |
84 | * @ccw_device: pointer to belonging ccw device | 108 | * @cdev: pointer to belonging ccw device |
85 | * | 109 | * |
86 | * This function gets called by the common i/o layer and removes an adapter | 110 | * This function gets called by the common i/o layer and removes an adapter |
87 | * from the system. Task of this function is to get rid of all units and | 111 | * from the system. Task of this function is to get rid of all units and |
88 | * ports that belong to this adapter. And in addition all resources of this | 112 | * ports that belong to this adapter. And in addition all resources of this |
89 | * adapter will be freed too. | 113 | * adapter will be freed too. |
90 | */ | 114 | */ |
91 | static void zfcp_ccw_remove(struct ccw_device *ccw_device) | 115 | static void zfcp_ccw_remove(struct ccw_device *cdev) |
92 | { | 116 | { |
93 | struct zfcp_adapter *adapter; | 117 | struct zfcp_adapter *adapter; |
94 | struct zfcp_port *port, *p; | 118 | struct zfcp_port *port, *p; |
@@ -96,22 +120,12 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
96 | LIST_HEAD(unit_remove_lh); | 120 | LIST_HEAD(unit_remove_lh); |
97 | LIST_HEAD(port_remove_lh); | 121 | LIST_HEAD(port_remove_lh); |
98 | 122 | ||
99 | ccw_device_set_offline(ccw_device); | 123 | ccw_device_set_offline(cdev); |
100 | |||
101 | mutex_lock(&zfcp_data.config_mutex); | ||
102 | adapter = dev_get_drvdata(&ccw_device->dev); | ||
103 | mutex_unlock(&zfcp_data.config_mutex); | ||
104 | 124 | ||
125 | adapter = zfcp_ccw_adapter_by_cdev(cdev); | ||
105 | if (!adapter) | 126 | if (!adapter) |
106 | return; | 127 | return; |
107 | 128 | ||
108 | cancel_work_sync(&adapter->scan_work); | ||
109 | |||
110 | mutex_lock(&zfcp_data.config_mutex); | ||
111 | |||
112 | /* this also removes the scsi devices, so call it first */ | ||
113 | zfcp_adapter_scsi_unregister(adapter); | ||
114 | |||
115 | write_lock_irq(&adapter->port_list_lock); | 129 | write_lock_irq(&adapter->port_list_lock); |
116 | list_for_each_entry_safe(port, p, &adapter->port_list, list) { | 130 | list_for_each_entry_safe(port, p, &adapter->port_list, list) { |
117 | write_lock(&port->unit_list_lock); | 131 | write_lock(&port->unit_list_lock); |
@@ -126,7 +140,7 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
126 | } | 140 | } |
127 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); | 141 | atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); |
128 | write_unlock_irq(&adapter->port_list_lock); | 142 | write_unlock_irq(&adapter->port_list_lock); |
129 | mutex_unlock(&zfcp_data.config_mutex); | 143 | zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */ |
130 | 144 | ||
131 | list_for_each_entry_safe(unit, u, &unit_remove_lh, list) | 145 | list_for_each_entry_safe(unit, u, &unit_remove_lh, list) |
132 | zfcp_device_unregister(&unit->sysfs_device, | 146 | zfcp_device_unregister(&unit->sysfs_device, |
@@ -136,12 +150,12 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
136 | zfcp_device_unregister(&port->sysfs_device, | 150 | zfcp_device_unregister(&port->sysfs_device, |
137 | &zfcp_sysfs_port_attrs); | 151 | &zfcp_sysfs_port_attrs); |
138 | 152 | ||
139 | kref_put(&adapter->ref, zfcp_adapter_release); | 153 | zfcp_adapter_unregister(adapter); |
140 | } | 154 | } |
141 | 155 | ||
142 | /** | 156 | /** |
143 | * zfcp_ccw_set_online - set_online function of zfcp driver | 157 | * zfcp_ccw_set_online - set_online function of zfcp driver |
144 | * @ccw_device: pointer to belonging ccw device | 158 | * @cdev: pointer to belonging ccw device |
145 | * | 159 | * |
146 | * This function gets called by the common i/o layer and sets an | 160 | * This function gets called by the common i/o layer and sets an |
147 | * adapter into state online. The first call will allocate all | 161 | * adapter into state online. The first call will allocate all |
@@ -152,23 +166,20 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device) | |||
152 | * the SCSI stack, that the QDIO queues will be set up and that the | 166 | * the SCSI stack, that the QDIO queues will be set up and that the |
153 | * adapter will be opened. | 167 | * adapter will be opened. |
154 | */ | 168 | */ |
155 | static int zfcp_ccw_set_online(struct ccw_device *ccw_device) | 169 | static int zfcp_ccw_set_online(struct ccw_device *cdev) |
156 | { | 170 | { |
157 | struct zfcp_adapter *adapter; | 171 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
158 | int ret = 0; | ||
159 | |||
160 | mutex_lock(&zfcp_data.config_mutex); | ||
161 | adapter = dev_get_drvdata(&ccw_device->dev); | ||
162 | 172 | ||
163 | if (!adapter) { | 173 | if (!adapter) { |
164 | ret = zfcp_adapter_enqueue(ccw_device); | 174 | adapter = zfcp_adapter_enqueue(cdev); |
165 | if (ret) { | 175 | |
166 | dev_err(&ccw_device->dev, | 176 | if (IS_ERR(adapter)) { |
177 | dev_err(&cdev->dev, | ||
167 | "Setting up data structures for the " | 178 | "Setting up data structures for the " |
168 | "FCP adapter failed\n"); | 179 | "FCP adapter failed\n"); |
169 | goto out; | 180 | return PTR_ERR(adapter); |
170 | } | 181 | } |
171 | adapter = dev_get_drvdata(&ccw_device->dev); | 182 | kref_get(&adapter->ref); |
172 | } | 183 | } |
173 | 184 | ||
174 | /* initialize request counter */ | 185 | /* initialize request counter */ |
@@ -180,58 +191,61 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device) | |||
180 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 191 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
181 | "ccsonl2", NULL); | 192 | "ccsonl2", NULL); |
182 | zfcp_erp_wait(adapter); | 193 | zfcp_erp_wait(adapter); |
183 | out: | 194 | |
184 | mutex_unlock(&zfcp_data.config_mutex); | 195 | flush_work(&adapter->scan_work); |
185 | if (!ret) | 196 | |
186 | flush_work(&adapter->scan_work); | 197 | zfcp_ccw_adapter_put(adapter); |
187 | return ret; | 198 | return 0; |
188 | } | 199 | } |
189 | 200 | ||
190 | /** | 201 | /** |
191 | * zfcp_ccw_set_offline - set_offline function of zfcp driver | 202 | * zfcp_ccw_set_offline - set_offline function of zfcp driver |
192 | * @ccw_device: pointer to belonging ccw device | 203 | * @cdev: pointer to belonging ccw device |
193 | * | 204 | * |
194 | * This function gets called by the common i/o layer and sets an adapter | 205 | * This function gets called by the common i/o layer and sets an adapter |
195 | * into state offline. | 206 | * into state offline. |
196 | */ | 207 | */ |
197 | static int zfcp_ccw_set_offline(struct ccw_device *ccw_device) | 208 | static int zfcp_ccw_set_offline(struct ccw_device *cdev) |
198 | { | 209 | { |
199 | struct zfcp_adapter *adapter; | 210 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
211 | |||
212 | if (!adapter) | ||
213 | return 0; | ||
200 | 214 | ||
201 | mutex_lock(&zfcp_data.config_mutex); | ||
202 | adapter = dev_get_drvdata(&ccw_device->dev); | ||
203 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL); | 215 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL); |
204 | zfcp_erp_wait(adapter); | 216 | zfcp_erp_wait(adapter); |
205 | mutex_unlock(&zfcp_data.config_mutex); | 217 | |
218 | zfcp_ccw_adapter_put(adapter); | ||
206 | return 0; | 219 | return 0; |
207 | } | 220 | } |
208 | 221 | ||
209 | /** | 222 | /** |
210 | * zfcp_ccw_notify - ccw notify function | 223 | * zfcp_ccw_notify - ccw notify function |
211 | * @ccw_device: pointer to belonging ccw device | 224 | * @cdev: pointer to belonging ccw device |
212 | * @event: indicates if adapter was detached or attached | 225 | * @event: indicates if adapter was detached or attached |
213 | * | 226 | * |
214 | * This function gets called by the common i/o layer if an adapter has gone | 227 | * This function gets called by the common i/o layer if an adapter has gone |
215 | * or reappeared. | 228 | * or reappeared. |
216 | */ | 229 | */ |
217 | static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) | 230 | static int zfcp_ccw_notify(struct ccw_device *cdev, int event) |
218 | { | 231 | { |
219 | struct zfcp_adapter *adapter = dev_get_drvdata(&ccw_device->dev); | 232 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
233 | |||
234 | if (!adapter) | ||
235 | return 1; | ||
220 | 236 | ||
221 | switch (event) { | 237 | switch (event) { |
222 | case CIO_GONE: | 238 | case CIO_GONE: |
223 | dev_warn(&adapter->ccw_device->dev, | 239 | dev_warn(&cdev->dev, "The FCP device has been detached\n"); |
224 | "The FCP device has been detached\n"); | ||
225 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL); | 240 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL); |
226 | break; | 241 | break; |
227 | case CIO_NO_PATH: | 242 | case CIO_NO_PATH: |
228 | dev_warn(&adapter->ccw_device->dev, | 243 | dev_warn(&cdev->dev, |
229 | "The CHPID for the FCP device is offline\n"); | 244 | "The CHPID for the FCP device is offline\n"); |
230 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL); | 245 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL); |
231 | break; | 246 | break; |
232 | case CIO_OPER: | 247 | case CIO_OPER: |
233 | dev_info(&adapter->ccw_device->dev, | 248 | dev_info(&cdev->dev, "The FCP device is operational again\n"); |
234 | "The FCP device is operational again\n"); | ||
235 | zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL, | 249 | zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL, |
236 | ZFCP_STATUS_COMMON_RUNNING, | 250 | ZFCP_STATUS_COMMON_RUNNING, |
237 | ZFCP_SET); | 251 | ZFCP_SET); |
@@ -239,11 +253,13 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) | |||
239 | "ccnoti4", NULL); | 253 | "ccnoti4", NULL); |
240 | break; | 254 | break; |
241 | case CIO_BOXED: | 255 | case CIO_BOXED: |
242 | dev_warn(&adapter->ccw_device->dev, "The FCP device " | 256 | dev_warn(&cdev->dev, "The FCP device did not respond within " |
243 | "did not respond within the specified time\n"); | 257 | "the specified time\n"); |
244 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL); | 258 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL); |
245 | break; | 259 | break; |
246 | } | 260 | } |
261 | |||
262 | zfcp_ccw_adapter_put(adapter); | ||
247 | return 1; | 263 | return 1; |
248 | } | 264 | } |
249 | 265 | ||
@@ -253,18 +269,16 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) | |||
253 | */ | 269 | */ |
254 | static void zfcp_ccw_shutdown(struct ccw_device *cdev) | 270 | static void zfcp_ccw_shutdown(struct ccw_device *cdev) |
255 | { | 271 | { |
256 | struct zfcp_adapter *adapter; | 272 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
257 | 273 | ||
258 | mutex_lock(&zfcp_data.config_mutex); | ||
259 | adapter = dev_get_drvdata(&cdev->dev); | ||
260 | if (!adapter) | 274 | if (!adapter) |
261 | goto out; | 275 | return; |
262 | 276 | ||
263 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL); | 277 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL); |
264 | zfcp_erp_wait(adapter); | 278 | zfcp_erp_wait(adapter); |
265 | zfcp_erp_thread_kill(adapter); | 279 | zfcp_erp_thread_kill(adapter); |
266 | out: | 280 | |
267 | mutex_unlock(&zfcp_data.config_mutex); | 281 | zfcp_ccw_adapter_put(adapter); |
268 | } | 282 | } |
269 | 283 | ||
270 | struct ccw_driver zfcp_ccw_driver = { | 284 | struct ccw_driver zfcp_ccw_driver = { |
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 856f82dbcb1..f932400e980 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c | |||
@@ -86,22 +86,17 @@ static int zfcp_cfdc_copy_to_user(void __user *user_buffer, | |||
86 | static struct zfcp_adapter *zfcp_cfdc_get_adapter(u32 devno) | 86 | static struct zfcp_adapter *zfcp_cfdc_get_adapter(u32 devno) |
87 | { | 87 | { |
88 | char busid[9]; | 88 | char busid[9]; |
89 | struct ccw_device *ccwdev; | 89 | struct ccw_device *cdev; |
90 | struct zfcp_adapter *adapter = NULL; | 90 | struct zfcp_adapter *adapter; |
91 | 91 | ||
92 | snprintf(busid, sizeof(busid), "0.0.%04x", devno); | 92 | snprintf(busid, sizeof(busid), "0.0.%04x", devno); |
93 | ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); | 93 | cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); |
94 | if (!ccwdev) | 94 | if (!cdev) |
95 | goto out; | 95 | return NULL; |
96 | 96 | ||
97 | adapter = dev_get_drvdata(&ccwdev->dev); | 97 | adapter = zfcp_ccw_adapter_by_cdev(cdev); |
98 | if (!adapter) | 98 | |
99 | goto out_put; | 99 | put_device(&cdev->dev); |
100 | |||
101 | kref_get(&adapter->ref); | ||
102 | out_put: | ||
103 | put_device(&ccwdev->dev); | ||
104 | out: | ||
105 | return adapter; | 100 | return adapter; |
106 | } | 101 | } |
107 | 102 | ||
@@ -244,7 +239,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, | |||
244 | free_sg: | 239 | free_sg: |
245 | zfcp_sg_free_table(fsf_cfdc->sg, ZFCP_CFDC_PAGES); | 240 | zfcp_sg_free_table(fsf_cfdc->sg, ZFCP_CFDC_PAGES); |
246 | adapter_put: | 241 | adapter_put: |
247 | kref_put(&adapter->ref, zfcp_adapter_release); | 242 | zfcp_ccw_adapter_put(adapter); |
248 | free_buffer: | 243 | free_buffer: |
249 | kfree(data); | 244 | kfree(data); |
250 | no_mem_sense: | 245 | no_mem_sense: |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 55dc402c3ae..7e84e1624d1 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -595,7 +595,6 @@ struct zfcp_fsf_req { | |||
595 | struct zfcp_data { | 595 | struct zfcp_data { |
596 | struct scsi_host_template scsi_host_template; | 596 | struct scsi_host_template scsi_host_template; |
597 | struct scsi_transport_template *scsi_transport_template; | 597 | struct scsi_transport_template *scsi_transport_template; |
598 | struct mutex config_mutex; | ||
599 | struct kmem_cache *gpn_ft_cache; | 598 | struct kmem_cache *gpn_ft_cache; |
600 | struct kmem_cache *qtcb_cache; | 599 | struct kmem_cache *qtcb_cache; |
601 | struct kmem_cache *sr_buffer_cache; | 600 | struct kmem_cache *sr_buffer_cache; |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 3106c3be639..1e3ec708505 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -14,7 +14,7 @@ | |||
14 | /* zfcp_aux.c */ | 14 | /* zfcp_aux.c */ |
15 | extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64); | 15 | extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64); |
16 | extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64); | 16 | extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64); |
17 | extern int zfcp_adapter_enqueue(struct ccw_device *); | 17 | extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); |
18 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, | 18 | extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, |
19 | u32); | 19 | u32); |
20 | extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); | 20 | extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); |
@@ -24,11 +24,14 @@ extern int zfcp_sg_setup_table(struct scatterlist *, int); | |||
24 | extern void zfcp_device_unregister(struct device *, | 24 | extern void zfcp_device_unregister(struct device *, |
25 | const struct attribute_group *); | 25 | const struct attribute_group *); |
26 | extern void zfcp_adapter_release(struct kref *); | 26 | extern void zfcp_adapter_release(struct kref *); |
27 | extern void zfcp_adapter_unregister(struct zfcp_adapter *); | ||
27 | 28 | ||
28 | /* zfcp_ccw.c */ | 29 | /* zfcp_ccw.c */ |
29 | extern int zfcp_ccw_register(void); | 30 | extern int zfcp_ccw_register(void); |
30 | extern int zfcp_ccw_priv_sch(struct zfcp_adapter *); | 31 | extern int zfcp_ccw_priv_sch(struct zfcp_adapter *); |
31 | extern struct ccw_driver zfcp_ccw_driver; | 32 | extern struct ccw_driver zfcp_ccw_driver; |
33 | extern struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *); | ||
34 | extern void zfcp_ccw_adapter_put(struct zfcp_adapter *); | ||
32 | 35 | ||
33 | /* zfcp_cfdc.c */ | 36 | /* zfcp_cfdc.c */ |
34 | extern struct miscdevice zfcp_cfdc_misc; | 37 | extern struct miscdevice zfcp_cfdc_misc; |
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 6fa1bcbec0a..3e3e72cc724 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
@@ -622,8 +622,6 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries) | |||
622 | return -E2BIG; | 622 | return -E2BIG; |
623 | } | 623 | } |
624 | 624 | ||
625 | mutex_lock(&zfcp_data.config_mutex); | ||
626 | |||
627 | /* first entry is the header */ | 625 | /* first entry is the header */ |
628 | for (x = 1; x < max_entries && !last; x++) { | 626 | for (x = 1; x < max_entries && !last; x++) { |
629 | if (x % (ZFCP_GPN_FT_ENTRIES + 1)) | 627 | if (x % (ZFCP_GPN_FT_ENTRIES + 1)) |
@@ -655,7 +653,6 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries) | |||
655 | list_for_each_entry_safe(port, tmp, &adapter->port_list, list) | 653 | list_for_each_entry_safe(port, tmp, &adapter->port_list, list) |
656 | zfcp_fc_validate_port(port, &remove_lh); | 654 | zfcp_fc_validate_port(port, &remove_lh); |
657 | write_unlock_irqrestore(&adapter->port_list_lock, flags); | 655 | write_unlock_irqrestore(&adapter->port_list_lock, flags); |
658 | mutex_unlock(&zfcp_data.config_mutex); | ||
659 | 656 | ||
660 | list_for_each_entry_safe(port, tmp, &remove_lh, list) { | 657 | list_for_each_entry_safe(port, tmp, &remove_lh, list) { |
661 | zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL); | 658 | zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL); |
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index b4a7e17932c..181bea0f10f 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c | |||
@@ -26,23 +26,36 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev, \ | |||
26 | static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ | 26 | static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ |
27 | zfcp_sysfs_##_feat##_##_name##_show, NULL); | 27 | zfcp_sysfs_##_feat##_##_name##_show, NULL); |
28 | 28 | ||
29 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n", | 29 | #define ZFCP_DEFINE_A_ATTR(_name, _format, _value) \ |
30 | atomic_read(&adapter->status)); | 30 | static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \ |
31 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n", | 31 | struct device_attribute *at,\ |
32 | (unsigned long long) adapter->peer_wwnn); | 32 | char *buf) \ |
33 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n", | 33 | { \ |
34 | (unsigned long long) adapter->peer_wwpn); | 34 | struct ccw_device *cdev = to_ccwdev(dev); \ |
35 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n", | 35 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); \ |
36 | adapter->peer_d_id); | 36 | int i; \ |
37 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n", | 37 | \ |
38 | adapter->hydra_version); | 38 | if (!adapter) \ |
39 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, lic_version, "0x%08x\n", | 39 | return -ENODEV; \ |
40 | adapter->fsf_lic_version); | 40 | \ |
41 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, hardware_version, "0x%08x\n", | 41 | i = sprintf(buf, _format, _value); \ |
42 | adapter->hardware_version); | 42 | zfcp_ccw_adapter_put(adapter); \ |
43 | ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, in_recovery, "%d\n", | 43 | return i; \ |
44 | (atomic_read(&adapter->status) & | 44 | } \ |
45 | ZFCP_STATUS_COMMON_ERP_INUSE) != 0); | 45 | static ZFCP_DEV_ATTR(adapter, _name, S_IRUGO, \ |
46 | zfcp_sysfs_adapter_##_name##_show, NULL); | ||
47 | |||
48 | ZFCP_DEFINE_A_ATTR(status, "0x%08x\n", atomic_read(&adapter->status)); | ||
49 | ZFCP_DEFINE_A_ATTR(peer_wwnn, "0x%016llx\n", | ||
50 | (unsigned long long) adapter->peer_wwnn); | ||
51 | ZFCP_DEFINE_A_ATTR(peer_wwpn, "0x%016llx\n", | ||
52 | (unsigned long long) adapter->peer_wwpn); | ||
53 | ZFCP_DEFINE_A_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); | ||
54 | ZFCP_DEFINE_A_ATTR(card_version, "0x%04x\n", adapter->hydra_version); | ||
55 | ZFCP_DEFINE_A_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); | ||
56 | ZFCP_DEFINE_A_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version); | ||
57 | ZFCP_DEFINE_A_ATTR(in_recovery, "%d\n", (atomic_read(&adapter->status) & | ||
58 | ZFCP_STATUS_COMMON_ERP_INUSE) != 0); | ||
46 | 59 | ||
47 | ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n", | 60 | ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n", |
48 | atomic_read(&port->status)); | 61 | atomic_read(&port->status)); |
@@ -88,7 +101,6 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \ | |||
88 | unsigned long val; \ | 101 | unsigned long val; \ |
89 | int retval = 0; \ | 102 | int retval = 0; \ |
90 | \ | 103 | \ |
91 | mutex_lock(&zfcp_data.config_mutex); \ | ||
92 | if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) { \ | 104 | if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) { \ |
93 | retval = -EBUSY; \ | 105 | retval = -EBUSY; \ |
94 | goto out; \ | 106 | goto out; \ |
@@ -105,28 +117,89 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \ | |||
105 | _reopen_id, NULL); \ | 117 | _reopen_id, NULL); \ |
106 | zfcp_erp_wait(_adapter); \ | 118 | zfcp_erp_wait(_adapter); \ |
107 | out: \ | 119 | out: \ |
108 | mutex_unlock(&zfcp_data.config_mutex); \ | ||
109 | return retval ? retval : (ssize_t) count; \ | 120 | return retval ? retval : (ssize_t) count; \ |
110 | } \ | 121 | } \ |
111 | static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ | 122 | static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ |
112 | zfcp_sysfs_##_feat##_failed_show, \ | 123 | zfcp_sysfs_##_feat##_failed_show, \ |
113 | zfcp_sysfs_##_feat##_failed_store); | 124 | zfcp_sysfs_##_feat##_failed_store); |
114 | 125 | ||
115 | ZFCP_SYSFS_FAILED(zfcp_adapter, adapter, adapter, "syafai1", "syafai2"); | ||
116 | ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2"); | 126 | ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2"); |
117 | ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2"); | 127 | ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2"); |
118 | 128 | ||
129 | static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev, | ||
130 | struct device_attribute *attr, | ||
131 | char *buf) | ||
132 | { | ||
133 | struct ccw_device *cdev = to_ccwdev(dev); | ||
134 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); | ||
135 | int i; | ||
136 | |||
137 | if (!adapter) | ||
138 | return -ENODEV; | ||
139 | |||
140 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) | ||
141 | i = sprintf(buf, "1\n"); | ||
142 | else | ||
143 | i = sprintf(buf, "0\n"); | ||
144 | |||
145 | zfcp_ccw_adapter_put(adapter); | ||
146 | return i; | ||
147 | } | ||
148 | |||
149 | static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev, | ||
150 | struct device_attribute *attr, | ||
151 | const char *buf, size_t count) | ||
152 | { | ||
153 | struct ccw_device *cdev = to_ccwdev(dev); | ||
154 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); | ||
155 | unsigned long val; | ||
156 | int retval = 0; | ||
157 | |||
158 | if (!adapter) | ||
159 | return -ENODEV; | ||
160 | |||
161 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) { | ||
162 | retval = -EBUSY; | ||
163 | goto out; | ||
164 | } | ||
165 | |||
166 | if (strict_strtoul(buf, 0, &val) || val != 0) { | ||
167 | retval = -EINVAL; | ||
168 | goto out; | ||
169 | } | ||
170 | |||
171 | zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL, | ||
172 | ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); | ||
173 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | ||
174 | "syafai2", NULL); | ||
175 | zfcp_erp_wait(adapter); | ||
176 | out: | ||
177 | zfcp_ccw_adapter_put(adapter); | ||
178 | return retval ? retval : (ssize_t) count; | ||
179 | } | ||
180 | static ZFCP_DEV_ATTR(adapter, failed, S_IWUSR | S_IRUGO, | ||
181 | zfcp_sysfs_adapter_failed_show, | ||
182 | zfcp_sysfs_adapter_failed_store); | ||
183 | |||
119 | static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, | 184 | static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, |
120 | struct device_attribute *attr, | 185 | struct device_attribute *attr, |
121 | const char *buf, size_t count) | 186 | const char *buf, size_t count) |
122 | { | 187 | { |
123 | struct zfcp_adapter *adapter = dev_get_drvdata(dev); | 188 | struct ccw_device *cdev = to_ccwdev(dev); |
189 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); | ||
124 | int ret; | 190 | int ret; |
125 | 191 | ||
126 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) | 192 | if (!adapter) |
127 | return -EBUSY; | 193 | return -ENODEV; |
194 | |||
195 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) { | ||
196 | ret = -EBUSY; | ||
197 | goto out; | ||
198 | } | ||
128 | 199 | ||
129 | ret = zfcp_fc_scan_ports(adapter); | 200 | ret = zfcp_fc_scan_ports(adapter); |
201 | out: | ||
202 | zfcp_ccw_adapter_put(adapter); | ||
130 | return ret ? ret : (ssize_t) count; | 203 | return ret ? ret : (ssize_t) count; |
131 | } | 204 | } |
132 | static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, | 205 | static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, |
@@ -136,12 +209,15 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, | |||
136 | struct device_attribute *attr, | 209 | struct device_attribute *attr, |
137 | const char *buf, size_t count) | 210 | const char *buf, size_t count) |
138 | { | 211 | { |
139 | struct zfcp_adapter *adapter = dev_get_drvdata(dev); | 212 | struct ccw_device *cdev = to_ccwdev(dev); |
213 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); | ||
140 | struct zfcp_port *port; | 214 | struct zfcp_port *port; |
141 | u64 wwpn; | 215 | u64 wwpn; |
142 | int retval = 0; | 216 | int retval = 0; |
143 | 217 | ||
144 | mutex_lock(&zfcp_data.config_mutex); | 218 | if (!adapter) |
219 | return -ENODEV; | ||
220 | |||
145 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) { | 221 | if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) { |
146 | retval = -EBUSY; | 222 | retval = -EBUSY; |
147 | goto out; | 223 | goto out; |
@@ -169,7 +245,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, | |||
169 | zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); | 245 | zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); |
170 | zfcp_device_unregister(&port->sysfs_device, &zfcp_sysfs_port_attrs); | 246 | zfcp_device_unregister(&port->sysfs_device, &zfcp_sysfs_port_attrs); |
171 | out: | 247 | out: |
172 | mutex_unlock(&zfcp_data.config_mutex); | 248 | zfcp_ccw_adapter_put(adapter); |
173 | return retval ? retval : (ssize_t) count; | 249 | return retval ? retval : (ssize_t) count; |
174 | } | 250 | } |
175 | static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL, | 251 | static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL, |
@@ -203,7 +279,6 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, | |||
203 | u64 fcp_lun; | 279 | u64 fcp_lun; |
204 | int retval = -EINVAL; | 280 | int retval = -EINVAL; |
205 | 281 | ||
206 | mutex_lock(&zfcp_data.config_mutex); | ||
207 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { | 282 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { |
208 | retval = -EBUSY; | 283 | retval = -EBUSY; |
209 | goto out; | 284 | goto out; |
@@ -222,7 +297,6 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, | |||
222 | zfcp_erp_wait(unit->port->adapter); | 297 | zfcp_erp_wait(unit->port->adapter); |
223 | flush_work(&unit->scsi_work); | 298 | flush_work(&unit->scsi_work); |
224 | out: | 299 | out: |
225 | mutex_unlock(&zfcp_data.config_mutex); | ||
226 | return retval ? retval : (ssize_t) count; | 300 | return retval ? retval : (ssize_t) count; |
227 | } | 301 | } |
228 | static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); | 302 | static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); |
@@ -236,7 +310,6 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
236 | u64 fcp_lun; | 310 | u64 fcp_lun; |
237 | int retval = 0; | 311 | int retval = 0; |
238 | 312 | ||
239 | mutex_lock(&zfcp_data.config_mutex); | ||
240 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { | 313 | if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) { |
241 | retval = -EBUSY; | 314 | retval = -EBUSY; |
242 | goto out; | 315 | goto out; |
@@ -267,7 +340,6 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, | |||
267 | zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); | 340 | zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL); |
268 | zfcp_device_unregister(&unit->sysfs_device, &zfcp_sysfs_unit_attrs); | 341 | zfcp_device_unregister(&unit->sysfs_device, &zfcp_sysfs_unit_attrs); |
269 | out: | 342 | out: |
270 | mutex_unlock(&zfcp_data.config_mutex); | ||
271 | return retval ? retval : (ssize_t) count; | 343 | return retval ? retval : (ssize_t) count; |
272 | } | 344 | } |
273 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); | 345 | static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); |