1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * zfcp device driver |
4 | * |
5 | * Registration and callback for the s390 common I/O layer. |
6 | * |
7 | * Copyright IBM Corp. 2002, 2010 |
8 | */ |
9 | |
10 | #define KMSG_COMPONENT "zfcp" |
11 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
12 | |
13 | #include <linux/module.h> |
14 | #include "zfcp_ext.h" |
15 | #include "zfcp_reqlist.h" |
16 | |
17 | #define ZFCP_MODEL_PRIV 0x4 |
18 | |
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(dev: &cdev->dev); |
28 | if (adapter) |
29 | kref_get(kref: &adapter->ref); |
30 | spin_unlock_irqrestore(lock: &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(kref: &adapter->ref, release: zfcp_adapter_release); |
40 | spin_unlock_irqrestore(lock: &zfcp_ccw_adapter_ref_lock, flags); |
41 | } |
42 | |
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) |
50 | { |
51 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
52 | |
53 | if (!adapter) |
54 | return 0; |
55 | |
56 | zfcp_erp_clear_adapter_status(adapter, clear); |
57 | zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); |
58 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
59 | tag); |
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(msecs: zfcp_fc_port_scan_backoff()); |
74 | zfcp_erp_wait(adapter); |
75 | flush_delayed_work(dwork: &adapter->scan_work); |
76 | |
77 | zfcp_ccw_adapter_put(adapter); |
78 | |
79 | return 0; |
80 | } |
81 | |
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 | |
89 | /** |
90 | * zfcp_ccw_probe - probe function of zfcp driver |
91 | * @cdev: pointer to belonging ccw device |
92 | * |
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. |
97 | */ |
98 | static int zfcp_ccw_probe(struct ccw_device *cdev) |
99 | { |
100 | return 0; |
101 | } |
102 | |
103 | /** |
104 | * zfcp_ccw_remove - remove function of zfcp driver |
105 | * @cdev: pointer to belonging ccw device |
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 | */ |
112 | static void zfcp_ccw_remove(struct ccw_device *cdev) |
113 | { |
114 | struct zfcp_adapter *adapter; |
115 | struct zfcp_port *port, *p; |
116 | struct zfcp_unit *unit, *u; |
117 | LIST_HEAD(unit_remove_lh); |
118 | LIST_HEAD(port_remove_lh); |
119 | |
120 | ccw_device_set_offline(cdev); |
121 | |
122 | adapter = zfcp_ccw_adapter_by_cdev(cdev); |
123 | if (!adapter) |
124 | return; |
125 | |
126 | write_lock_irq(&adapter->port_list_lock); |
127 | list_for_each_entry(port, &adapter->port_list, list) { |
128 | write_lock(&port->unit_list_lock); |
129 | list_splice_init(list: &port->unit_list, head: &unit_remove_lh); |
130 | write_unlock(&port->unit_list_lock); |
131 | } |
132 | list_splice_init(list: &adapter->port_list, head: &port_remove_lh); |
133 | write_unlock_irq(&adapter->port_list_lock); |
134 | zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */ |
135 | |
136 | list_for_each_entry_safe(unit, u, &unit_remove_lh, list) |
137 | device_unregister(dev: &unit->dev); |
138 | |
139 | list_for_each_entry_safe(port, p, &port_remove_lh, list) |
140 | device_unregister(dev: &port->dev); |
141 | |
142 | zfcp_adapter_unregister(adapter); |
143 | } |
144 | |
145 | /** |
146 | * zfcp_ccw_set_online - set_online function of zfcp driver |
147 | * @cdev: pointer to belonging ccw device |
148 | * |
149 | * This function gets called by the common i/o layer and sets an |
150 | * adapter into state online. The first call will allocate all |
151 | * adapter resources that will be retained until the device is removed |
152 | * via zfcp_ccw_remove. |
153 | * |
154 | * Setting an fcp device online means that it will be registered with |
155 | * the SCSI stack, that the QDIO queues will be set up and that the |
156 | * adapter will be opened. |
157 | */ |
158 | static int zfcp_ccw_set_online(struct ccw_device *cdev) |
159 | { |
160 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
161 | |
162 | if (!adapter) { |
163 | adapter = zfcp_adapter_enqueue(cdev); |
164 | |
165 | if (IS_ERR(ptr: adapter)) { |
166 | dev_err(&cdev->dev, |
167 | "Setting up data structures for the " |
168 | "FCP adapter failed\n" ); |
169 | return PTR_ERR(ptr: adapter); |
170 | } |
171 | kref_get(kref: &adapter->ref); |
172 | } |
173 | |
174 | /* initialize request counter */ |
175 | BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); |
176 | adapter->req_no = 0; |
177 | |
178 | zfcp_ccw_activate(cdev, clear: 0, tag: "ccsonl1" ); |
179 | |
180 | /* |
181 | * We want to scan ports here, always, with some random delay and |
182 | * without rate limit - basically what zfcp_ccw_activate() has |
183 | * achieved for us. Not quite! That port scan depended on |
184 | * !no_auto_port_rescan. So let's cover the no_auto_port_rescan |
185 | * case here to make sure a port scan is done unconditionally. |
186 | * Since zfcp_ccw_activate() has waited the desired random time, |
187 | * we can immediately schedule and flush a port scan for the |
188 | * remaining cases. |
189 | */ |
190 | zfcp_fc_inverse_conditional_port_scan(adapter); |
191 | flush_delayed_work(dwork: &adapter->scan_work); |
192 | zfcp_ccw_adapter_put(adapter); |
193 | return 0; |
194 | } |
195 | |
196 | /** |
197 | * zfcp_ccw_set_offline - set_offline function of zfcp driver |
198 | * @cdev: pointer to belonging ccw device |
199 | * |
200 | * This function gets called by the common i/o layer and sets an adapter |
201 | * into state offline. |
202 | */ |
203 | static int zfcp_ccw_set_offline(struct ccw_device *cdev) |
204 | { |
205 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
206 | |
207 | if (!adapter) |
208 | return 0; |
209 | |
210 | zfcp_erp_set_adapter_status(adapter, 0); |
211 | zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1" ); |
212 | zfcp_erp_wait(adapter); |
213 | |
214 | zfcp_ccw_adapter_put(adapter); |
215 | return 0; |
216 | } |
217 | |
218 | /** |
219 | * zfcp_ccw_notify - ccw notify function |
220 | * @cdev: pointer to belonging ccw device |
221 | * @event: indicates if adapter was detached or attached |
222 | * |
223 | * This function gets called by the common i/o layer if an adapter has gone |
224 | * or reappeared. |
225 | */ |
226 | static int zfcp_ccw_notify(struct ccw_device *cdev, int event) |
227 | { |
228 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
229 | |
230 | if (!adapter) |
231 | return 1; |
232 | |
233 | switch (event) { |
234 | case CIO_GONE: |
235 | dev_warn(&cdev->dev, "The FCP device has been detached\n" ); |
236 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1" ); |
237 | break; |
238 | case CIO_NO_PATH: |
239 | dev_warn(&cdev->dev, |
240 | "The CHPID for the FCP device is offline\n" ); |
241 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2" ); |
242 | break; |
243 | case CIO_OPER: |
244 | dev_info(&cdev->dev, "The FCP device is operational again\n" ); |
245 | zfcp_erp_set_adapter_status(adapter, |
246 | ZFCP_STATUS_COMMON_RUNNING); |
247 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
248 | "ccnoti4" ); |
249 | break; |
250 | case CIO_BOXED: |
251 | dev_warn(&cdev->dev, "The FCP device did not respond within " |
252 | "the specified time\n" ); |
253 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5" ); |
254 | break; |
255 | } |
256 | |
257 | zfcp_ccw_adapter_put(adapter); |
258 | return 1; |
259 | } |
260 | |
261 | /** |
262 | * zfcp_ccw_shutdown - handle shutdown from cio |
263 | * @cdev: device for adapter to shutdown. |
264 | */ |
265 | static void zfcp_ccw_shutdown(struct ccw_device *cdev) |
266 | { |
267 | struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); |
268 | |
269 | if (!adapter) |
270 | return; |
271 | |
272 | zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1" ); |
273 | zfcp_erp_wait(adapter); |
274 | zfcp_erp_thread_kill(adapter); |
275 | |
276 | zfcp_ccw_adapter_put(adapter); |
277 | } |
278 | |
279 | struct ccw_driver zfcp_ccw_driver = { |
280 | .driver = { |
281 | .owner = THIS_MODULE, |
282 | .name = "zfcp" , |
283 | }, |
284 | .ids = zfcp_ccw_device_id, |
285 | .probe = zfcp_ccw_probe, |
286 | .remove = zfcp_ccw_remove, |
287 | .set_online = zfcp_ccw_set_online, |
288 | .set_offline = zfcp_ccw_set_offline, |
289 | .notify = zfcp_ccw_notify, |
290 | .shutdown = zfcp_ccw_shutdown, |
291 | }; |
292 | |