Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 | 2 | /* |
fa04c281 | 3 | * zfcp device driver |
1da177e4 | 4 | * |
fa04c281 | 5 | * Registration and callback for the s390 common I/O layer. |
1da177e4 | 6 | * |
a53c8fab | 7 | * Copyright IBM Corp. 2002, 2010 |
1da177e4 LT |
8 | */ |
9 | ||
ecf39d42 CS |
10 | #define KMSG_COMPONENT "zfcp" |
11 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
12 | ||
3a4c5d59 | 13 | #include <linux/module.h> |
1da177e4 | 14 | #include "zfcp_ext.h" |
b6bd2fb9 | 15 | #include "zfcp_reqlist.h" |
1da177e4 | 16 | |
6fcf41d1 CS |
17 | #define ZFCP_MODEL_PRIV 0x4 |
18 | ||
de3dc572 SS |
19 | static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock); |
20 | ||
21 | struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *cdev) | |
22 | { | |
23 | struct zfcp_adapter *adapter; | |
24 | unsigned long flags; | |
25 | ||
26 | spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags); | |
27 | adapter = dev_get_drvdata(&cdev->dev); | |
28 | if (adapter) | |
29 | kref_get(&adapter->ref); | |
30 | spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); | |
31 | return adapter; | |
32 | } | |
33 | ||
34 | void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter) | |
35 | { | |
36 | unsigned long flags; | |
37 | ||
38 | spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags); | |
39 | kref_put(&adapter->ref, zfcp_adapter_release); | |
40 | spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); | |
41 | } | |
42 | ||
cb452149 SM |
43 | /** |
44 | * zfcp_ccw_activate - activate adapter and wait for it to finish | |
45 | * @cdev: pointer to belonging ccw device | |
46 | * @clear: Status flags to clear. | |
47 | * @tag: s390dbf trace record tag | |
48 | */ | |
49 | static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag) | |
daa70fa9 | 50 | { |
de3dc572 | 51 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
daa70fa9 | 52 | |
143bb6bf CS |
53 | if (!adapter) |
54 | return 0; | |
55 | ||
cb452149 | 56 | zfcp_erp_clear_adapter_status(adapter, clear); |
edaed859 | 57 | zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); |
daa70fa9 | 58 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
cb452149 | 59 | tag); |
18f87a67 MP |
60 | |
61 | /* | |
62 | * We want to scan ports here, with some random backoff and without | |
63 | * rate limit. Recovery has already scheduled a port scan for us, | |
64 | * but with both random delay and rate limit. Nevertheless we get | |
65 | * what we want here by flushing the scheduled work after sleeping | |
66 | * an equivalent random time. | |
67 | * Let the port scan random delay elapse first. If recovery finishes | |
68 | * up to that point in time, that would be perfect for both recovery | |
69 | * and port scan. If not, i.e. recovery takes ages, there was no | |
70 | * point in waiting a random delay on top of the time consumed by | |
71 | * recovery. | |
72 | */ | |
73 | msleep(zfcp_fc_port_scan_backoff()); | |
daa70fa9 | 74 | zfcp_erp_wait(adapter); |
18f87a67 | 75 | flush_delayed_work(&adapter->scan_work); |
daa70fa9 | 76 | |
de3dc572 SS |
77 | zfcp_ccw_adapter_put(adapter); |
78 | ||
daa70fa9 MP |
79 | return 0; |
80 | } | |
81 | ||
6fcf41d1 CS |
82 | static struct ccw_device_id zfcp_ccw_device_id[] = { |
83 | { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x3) }, | |
84 | { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, ZFCP_MODEL_PRIV) }, | |
85 | {}, | |
86 | }; | |
87 | MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id); | |
88 | ||
1da177e4 LT |
89 | /** |
90 | * zfcp_ccw_probe - probe function of zfcp driver | |
de3dc572 | 91 | * @cdev: pointer to belonging ccw device |
1da177e4 | 92 | * |
143bb6bf CS |
93 | * This function gets called by the common i/o layer for each FCP |
94 | * device found on the current system. This is only a stub to make cio | |
95 | * work: To only allocate adapter resources for devices actually used, | |
96 | * the allocation is deferred to the first call to ccw_set_online. | |
1da177e4 | 97 | */ |
de3dc572 | 98 | static int zfcp_ccw_probe(struct ccw_device *cdev) |
1da177e4 | 99 | { |
143bb6bf | 100 | return 0; |
1da177e4 LT |
101 | } |
102 | ||
103 | /** | |
104 | * zfcp_ccw_remove - remove function of zfcp driver | |
de3dc572 | 105 | * @cdev: pointer to belonging ccw device |
1da177e4 LT |
106 | * |
107 | * This function gets called by the common i/o layer and removes an adapter | |
108 | * from the system. Task of this function is to get rid of all units and | |
109 | * ports that belong to this adapter. And in addition all resources of this | |
110 | * adapter will be freed too. | |
111 | */ | |
de3dc572 | 112 | static void zfcp_ccw_remove(struct ccw_device *cdev) |
1da177e4 LT |
113 | { |
114 | struct zfcp_adapter *adapter; | |
115 | struct zfcp_port *port, *p; | |
116 | struct zfcp_unit *unit, *u; | |
0406289e CS |
117 | LIST_HEAD(unit_remove_lh); |
118 | LIST_HEAD(port_remove_lh); | |
1da177e4 | 119 | |
de3dc572 | 120 | ccw_device_set_offline(cdev); |
f45a5421 | 121 | |
de3dc572 | 122 | adapter = zfcp_ccw_adapter_by_cdev(cdev); |
ecf0c772 SS |
123 | if (!adapter) |
124 | return; | |
125 | ||
ecf0c772 SS |
126 | write_lock_irq(&adapter->port_list_lock); |
127 | list_for_each_entry_safe(port, p, &adapter->port_list, list) { | |
128 | write_lock(&port->unit_list_lock); | |
6b183334 | 129 | list_for_each_entry_safe(unit, u, &port->unit_list, list) |
ecf0c772 | 130 | list_move(&unit->list, &unit_remove_lh); |
ecf0c772 | 131 | write_unlock(&port->unit_list_lock); |
ecf0c772 | 132 | list_move(&port->list, &port_remove_lh); |
1da177e4 | 133 | } |
ecf0c772 | 134 | write_unlock_irq(&adapter->port_list_lock); |
de3dc572 | 135 | zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */ |
1da177e4 | 136 | |
f3450c7b | 137 | list_for_each_entry_safe(unit, u, &unit_remove_lh, list) |
86bdf218 | 138 | device_unregister(&unit->dev); |
f3450c7b SS |
139 | |
140 | list_for_each_entry_safe(port, p, &port_remove_lh, list) | |
83d4e1c3 | 141 | device_unregister(&port->dev); |
f3450c7b | 142 | |
de3dc572 | 143 | zfcp_adapter_unregister(adapter); |
1da177e4 LT |
144 | } |
145 | ||
146 | /** | |
147 | * zfcp_ccw_set_online - set_online function of zfcp driver | |
de3dc572 | 148 | * @cdev: pointer to belonging ccw device |
1da177e4 | 149 | * |
143bb6bf CS |
150 | * This function gets called by the common i/o layer and sets an |
151 | * adapter into state online. The first call will allocate all | |
152 | * adapter resources that will be retained until the device is removed | |
153 | * via zfcp_ccw_remove. | |
154 | * | |
155 | * Setting an fcp device online means that it will be registered with | |
156 | * the SCSI stack, that the QDIO queues will be set up and that the | |
157 | * adapter will be opened. | |
1da177e4 | 158 | */ |
de3dc572 | 159 | static int zfcp_ccw_set_online(struct ccw_device *cdev) |
1da177e4 | 160 | { |
de3dc572 | 161 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
1da177e4 | 162 | |
143bb6bf | 163 | if (!adapter) { |
de3dc572 SS |
164 | adapter = zfcp_adapter_enqueue(cdev); |
165 | ||
166 | if (IS_ERR(adapter)) { | |
167 | dev_err(&cdev->dev, | |
143bb6bf CS |
168 | "Setting up data structures for the " |
169 | "FCP adapter failed\n"); | |
de3dc572 | 170 | return PTR_ERR(adapter); |
143bb6bf | 171 | } |
de3dc572 | 172 | kref_get(&adapter->ref); |
143bb6bf | 173 | } |
1da177e4 | 174 | |
fea9d6c7 | 175 | /* initialize request counter */ |
b6bd2fb9 | 176 | BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); |
fea9d6c7 VS |
177 | adapter->req_no = 0; |
178 | ||
cb452149 | 179 | zfcp_ccw_activate(cdev, 0, "ccsonl1"); |
18f87a67 MP |
180 | |
181 | /* | |
182 | * We want to scan ports here, always, with some random delay and | |
183 | * without rate limit - basically what zfcp_ccw_activate() has | |
184 | * achieved for us. Not quite! That port scan depended on | |
185 | * !no_auto_port_rescan. So let's cover the no_auto_port_rescan | |
186 | * case here to make sure a port scan is done unconditionally. | |
187 | * Since zfcp_ccw_activate() has waited the desired random time, | |
188 | * we can immediately schedule and flush a port scan for the | |
189 | * remaining cases. | |
190 | */ | |
43f60cbd | 191 | zfcp_fc_inverse_conditional_port_scan(adapter); |
18f87a67 | 192 | flush_delayed_work(&adapter->scan_work); |
de3dc572 SS |
193 | zfcp_ccw_adapter_put(adapter); |
194 | return 0; | |
1da177e4 LT |
195 | } |
196 | ||
197 | /** | |
cb452149 | 198 | * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish |
de3dc572 | 199 | * @cdev: pointer to belonging ccw device |
cb452149 SM |
200 | * @set: Status flags to set. |
201 | * @tag: s390dbf trace record tag | |
1da177e4 LT |
202 | * |
203 | * This function gets called by the common i/o layer and sets an adapter | |
9f28745a | 204 | * into state offline. |
1da177e4 | 205 | */ |
cb452149 | 206 | static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag) |
1da177e4 | 207 | { |
de3dc572 SS |
208 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
209 | ||
210 | if (!adapter) | |
211 | return 0; | |
1da177e4 | 212 | |
cb452149 SM |
213 | zfcp_erp_set_adapter_status(adapter, set); |
214 | zfcp_erp_adapter_shutdown(adapter, 0, tag); | |
1da177e4 | 215 | zfcp_erp_wait(adapter); |
de3dc572 SS |
216 | |
217 | zfcp_ccw_adapter_put(adapter); | |
1da177e4 LT |
218 | return 0; |
219 | } | |
220 | ||
cb452149 SM |
221 | /** |
222 | * zfcp_ccw_set_offline - set_offline function of zfcp driver | |
223 | * @cdev: pointer to belonging ccw device | |
224 | * | |
225 | * This function gets called by the common i/o layer and sets an adapter | |
226 | * into state offline. | |
227 | */ | |
228 | static int zfcp_ccw_set_offline(struct ccw_device *cdev) | |
229 | { | |
230 | return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1"); | |
231 | } | |
232 | ||
1da177e4 | 233 | /** |
fa04c281 | 234 | * zfcp_ccw_notify - ccw notify function |
de3dc572 | 235 | * @cdev: pointer to belonging ccw device |
1da177e4 LT |
236 | * @event: indicates if adapter was detached or attached |
237 | * | |
238 | * This function gets called by the common i/o layer if an adapter has gone | |
239 | * or reappeared. | |
240 | */ | |
de3dc572 | 241 | static int zfcp_ccw_notify(struct ccw_device *cdev, int event) |
1da177e4 | 242 | { |
de3dc572 SS |
243 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
244 | ||
245 | if (!adapter) | |
246 | return 1; | |
1da177e4 | 247 | |
1da177e4 LT |
248 | switch (event) { |
249 | case CIO_GONE: | |
cb452149 SM |
250 | if (atomic_read(&adapter->status) & |
251 | ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ | |
252 | zfcp_dbf_hba_basic("ccnigo1", adapter); | |
253 | break; | |
254 | } | |
de3dc572 | 255 | dev_warn(&cdev->dev, "The FCP device has been detached\n"); |
ea4a3a6a | 256 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); |
1da177e4 LT |
257 | break; |
258 | case CIO_NO_PATH: | |
de3dc572 | 259 | dev_warn(&cdev->dev, |
ff3b24fa | 260 | "The CHPID for the FCP device is offline\n"); |
ea4a3a6a | 261 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); |
1da177e4 LT |
262 | break; |
263 | case CIO_OPER: | |
cb452149 SM |
264 | if (atomic_read(&adapter->status) & |
265 | ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ | |
266 | zfcp_dbf_hba_basic("ccniop1", adapter); | |
267 | break; | |
268 | } | |
de3dc572 | 269 | dev_info(&cdev->dev, "The FCP device is operational again\n"); |
edaed859 SS |
270 | zfcp_erp_set_adapter_status(adapter, |
271 | ZFCP_STATUS_COMMON_RUNNING); | |
1f6f7129 | 272 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
ea4a3a6a | 273 | "ccnoti4"); |
1da177e4 | 274 | break; |
47593bfa | 275 | case CIO_BOXED: |
de3dc572 SS |
276 | dev_warn(&cdev->dev, "The FCP device did not respond within " |
277 | "the specified time\n"); | |
ea4a3a6a | 278 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5"); |
47593bfa | 279 | break; |
1da177e4 | 280 | } |
de3dc572 SS |
281 | |
282 | zfcp_ccw_adapter_put(adapter); | |
1da177e4 LT |
283 | return 1; |
284 | } | |
285 | ||
286 | /** | |
fa04c281 CS |
287 | * zfcp_ccw_shutdown - handle shutdown from cio |
288 | * @cdev: device for adapter to shutdown. | |
1da177e4 | 289 | */ |
fa04c281 | 290 | static void zfcp_ccw_shutdown(struct ccw_device *cdev) |
1da177e4 | 291 | { |
de3dc572 | 292 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
1da177e4 | 293 | |
1f99bd4c | 294 | if (!adapter) |
de3dc572 | 295 | return; |
1f99bd4c | 296 | |
ea4a3a6a | 297 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1"); |
1da177e4 | 298 | zfcp_erp_wait(adapter); |
143bb6bf | 299 | zfcp_erp_thread_kill(adapter); |
de3dc572 SS |
300 | |
301 | zfcp_ccw_adapter_put(adapter); | |
1da177e4 LT |
302 | } |
303 | ||
cb452149 SM |
304 | static int zfcp_ccw_suspend(struct ccw_device *cdev) |
305 | { | |
306 | zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1"); | |
307 | return 0; | |
308 | } | |
309 | ||
310 | static int zfcp_ccw_thaw(struct ccw_device *cdev) | |
311 | { | |
312 | /* trace records for thaw and final shutdown during suspend | |
313 | can only be found in system dump until the end of suspend | |
314 | but not after resume because it's based on the memory image | |
315 | right after the very first suspend (freeze) callback */ | |
316 | zfcp_ccw_activate(cdev, 0, "ccthaw1"); | |
317 | return 0; | |
318 | } | |
319 | ||
320 | static int zfcp_ccw_resume(struct ccw_device *cdev) | |
321 | { | |
322 | zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1"); | |
323 | return 0; | |
324 | } | |
325 | ||
c5afd81e | 326 | struct ccw_driver zfcp_ccw_driver = { |
3bda058b SO |
327 | .driver = { |
328 | .owner = THIS_MODULE, | |
329 | .name = "zfcp", | |
330 | }, | |
fa04c281 CS |
331 | .ids = zfcp_ccw_device_id, |
332 | .probe = zfcp_ccw_probe, | |
333 | .remove = zfcp_ccw_remove, | |
334 | .set_online = zfcp_ccw_set_online, | |
335 | .set_offline = zfcp_ccw_set_offline, | |
336 | .notify = zfcp_ccw_notify, | |
337 | .shutdown = zfcp_ccw_shutdown, | |
cb452149 SM |
338 | .freeze = zfcp_ccw_suspend, |
339 | .thaw = zfcp_ccw_thaw, | |
340 | .restore = zfcp_ccw_resume, | |
fa04c281 | 341 | }; |