aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorSwen Schillig <swen@vnet.ibm.com>2009-11-24 10:54:00 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:02:02 -0500
commitde3dc57214a1466034ecc4d4ffb10331d34c09a3 (patch)
tree63eb490d66f9db2cf032041392fb2f4d5ac4785c /drivers/s390
parentf3450c7b917201bb49d67032e9f60d5125675d6a (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.c86
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c138
-rw-r--r--drivers/s390/scsi/zfcp_cfdc.c25
-rw-r--r--drivers/s390/scsi/zfcp_def.h1
-rw-r--r--drivers/s390/scsi/zfcp_ext.h5
-rw-r--r--drivers/s390/scsi/zfcp_fc.c3
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c132
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
81static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) 81static 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);
115out_unit: 111out_unit:
116 put_device(&port->sysfs_device); 112 put_device(&port->sysfs_device);
117out_port: 113out_port:
118 kref_put(&adapter->ref, zfcp_adapter_release); 114 zfcp_ccw_adapter_put(adapter);
119out_unlock: 115out_ccw_device:
120 mutex_unlock(&zfcp_data.config_mutex); 116 put_device(&cdev->dev);
121out_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
372static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) 363static 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
420static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) 410static 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 */
511int zfcp_adapter_enqueue(struct ccw_device *ccw_device) 498struct 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
583failed: 570failed:
584 kref_put(&adapter->ref, zfcp_adapter_release); 571 zfcp_adapter_unregister(adapter);
585 return -ENOMEM; 572 return ERR_PTR(-ENOMEM);
573}
574
575void 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,
718err_out_put: 712err_out_put:
719 device_unregister(&port->sysfs_device); 713 device_unregister(&port->sysfs_device);
720err_out: 714err_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
16static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock);
17
18struct 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
31void 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
16static int zfcp_ccw_suspend(struct ccw_device *cdev) 40static 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)
34static int zfcp_ccw_activate(struct ccw_device *cdev) 56static 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 */
77static int zfcp_ccw_probe(struct ccw_device *ccw_device) 101static 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 */
91static void zfcp_ccw_remove(struct ccw_device *ccw_device) 115static 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 */
155static int zfcp_ccw_set_online(struct ccw_device *ccw_device) 169static 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);
183out: 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 */
197static int zfcp_ccw_set_offline(struct ccw_device *ccw_device) 208static 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 */
217static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) 230static 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 */
254static void zfcp_ccw_shutdown(struct ccw_device *cdev) 270static 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);
266out: 280
267 mutex_unlock(&zfcp_data.config_mutex); 281 zfcp_ccw_adapter_put(adapter);
268} 282}
269 283
270struct ccw_driver zfcp_ccw_driver = { 284struct 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,
86static struct zfcp_adapter *zfcp_cfdc_get_adapter(u32 devno) 86static 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);
102out_put:
103 put_device(&ccwdev->dev);
104out:
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 {
595struct zfcp_data { 595struct 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 */
15extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64); 15extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64);
16extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64); 16extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64);
17extern int zfcp_adapter_enqueue(struct ccw_device *); 17extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
18extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, 18extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
19 u32); 19 u32);
20extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64); 20extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
@@ -24,11 +24,14 @@ extern int zfcp_sg_setup_table(struct scatterlist *, int);
24extern void zfcp_device_unregister(struct device *, 24extern void zfcp_device_unregister(struct device *,
25 const struct attribute_group *); 25 const struct attribute_group *);
26extern void zfcp_adapter_release(struct kref *); 26extern void zfcp_adapter_release(struct kref *);
27extern void zfcp_adapter_unregister(struct zfcp_adapter *);
27 28
28/* zfcp_ccw.c */ 29/* zfcp_ccw.c */
29extern int zfcp_ccw_register(void); 30extern int zfcp_ccw_register(void);
30extern int zfcp_ccw_priv_sch(struct zfcp_adapter *); 31extern int zfcp_ccw_priv_sch(struct zfcp_adapter *);
31extern struct ccw_driver zfcp_ccw_driver; 32extern struct ccw_driver zfcp_ccw_driver;
33extern struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *);
34extern void zfcp_ccw_adapter_put(struct zfcp_adapter *);
32 35
33/* zfcp_cfdc.c */ 36/* zfcp_cfdc.c */
34extern struct miscdevice zfcp_cfdc_misc; 37extern 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, \
26static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \ 26static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \
27 zfcp_sysfs_##_feat##_##_name##_show, NULL); 27 zfcp_sysfs_##_feat##_##_name##_show, NULL);
28 28
29ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n", 29#define ZFCP_DEFINE_A_ATTR(_name, _format, _value) \
30 atomic_read(&adapter->status)); 30static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \
31ZFCP_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) \
33ZFCP_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); \
35ZFCP_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; \
37ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n", 37 \
38 adapter->hydra_version); 38 if (!adapter) \
39ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, lic_version, "0x%08x\n", 39 return -ENODEV; \
40 adapter->fsf_lic_version); 40 \
41ZFCP_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); \
43ZFCP_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); 45static ZFCP_DEV_ATTR(adapter, _name, S_IRUGO, \
46 zfcp_sysfs_adapter_##_name##_show, NULL);
47
48ZFCP_DEFINE_A_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
49ZFCP_DEFINE_A_ATTR(peer_wwnn, "0x%016llx\n",
50 (unsigned long long) adapter->peer_wwnn);
51ZFCP_DEFINE_A_ATTR(peer_wwpn, "0x%016llx\n",
52 (unsigned long long) adapter->peer_wwpn);
53ZFCP_DEFINE_A_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
54ZFCP_DEFINE_A_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
55ZFCP_DEFINE_A_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
56ZFCP_DEFINE_A_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version);
57ZFCP_DEFINE_A_ATTR(in_recovery, "%d\n", (atomic_read(&adapter->status) &
58 ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
46 59
47ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n", 60ZFCP_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); \
107out: \ 119out: \
108 mutex_unlock(&zfcp_data.config_mutex); \
109 return retval ? retval : (ssize_t) count; \ 120 return retval ? retval : (ssize_t) count; \
110} \ 121} \
111static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \ 122static 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
115ZFCP_SYSFS_FAILED(zfcp_adapter, adapter, adapter, "syafai1", "syafai2");
116ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2"); 126ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
117ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2"); 127ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
118 128
129static 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
149static 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);
176out:
177 zfcp_ccw_adapter_put(adapter);
178 return retval ? retval : (ssize_t) count;
179}
180static ZFCP_DEV_ATTR(adapter, failed, S_IWUSR | S_IRUGO,
181 zfcp_sysfs_adapter_failed_show,
182 zfcp_sysfs_adapter_failed_store);
183
119static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, 184static 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);
201out:
202 zfcp_ccw_adapter_put(adapter);
130 return ret ? ret : (ssize_t) count; 203 return ret ? ret : (ssize_t) count;
131} 204}
132static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, 205static 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}
175static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL, 251static 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);
224out: 299out:
225 mutex_unlock(&zfcp_data.config_mutex);
226 return retval ? retval : (ssize_t) count; 300 return retval ? retval : (ssize_t) count;
227} 301}
228static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); 302static 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);
269out: 342out:
270 mutex_unlock(&zfcp_data.config_mutex);
271 return retval ? retval : (ssize_t) count; 343 return retval ? retval : (ssize_t) count;
272} 344}
273static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); 345static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);