aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_ccw.c
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/scsi/zfcp_ccw.c
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/scsi/zfcp_ccw.c')
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c138
1 files changed, 76 insertions, 62 deletions
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index c89dbe250377..2433eaced20c 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 = {