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/scsi/zfcp_ccw.c | |
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/scsi/zfcp_ccw.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 138 |
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 | ||
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 = { |