i2c: aspeed: Fix initial values of master and slave state
[linux/fpc-iii.git] / drivers / s390 / scsi / zfcp_ccw.c
blob49eda141ea431f8a92afe70786fc165e24b9372e
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * zfcp device driver
5 * Registration and callback for the s390 common I/O layer.
7 * Copyright IBM Corp. 2002, 2010
8 */
10 #define KMSG_COMPONENT "zfcp"
11 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
13 #include <linux/module.h>
14 #include "zfcp_ext.h"
15 #include "zfcp_reqlist.h"
17 #define ZFCP_MODEL_PRIV 0x4
19 static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock);
21 struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *cdev)
23 struct zfcp_adapter *adapter;
24 unsigned long flags;
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;
34 void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
36 unsigned long flags;
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);
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
49 static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
51 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
53 if (!adapter)
54 return 0;
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);
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.
73 msleep(zfcp_fc_port_scan_backoff());
74 zfcp_erp_wait(adapter);
75 flush_delayed_work(&adapter->scan_work);
77 zfcp_ccw_adapter_put(adapter);
79 return 0;
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 {},
87 MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
89 /**
90 * zfcp_ccw_probe - probe function of zfcp driver
91 * @cdev: pointer to belonging ccw device
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.
98 static int zfcp_ccw_probe(struct ccw_device *cdev)
100 return 0;
104 * zfcp_ccw_remove - remove function of zfcp driver
105 * @cdev: pointer to belonging ccw device
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.
112 static void zfcp_ccw_remove(struct ccw_device *cdev)
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);
120 ccw_device_set_offline(cdev);
122 adapter = zfcp_ccw_adapter_by_cdev(cdev);
123 if (!adapter)
124 return;
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);
129 list_for_each_entry_safe(unit, u, &port->unit_list, list)
130 list_move(&unit->list, &unit_remove_lh);
131 write_unlock(&port->unit_list_lock);
132 list_move(&port->list, &port_remove_lh);
134 write_unlock_irq(&adapter->port_list_lock);
135 zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */
137 list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
138 device_unregister(&unit->dev);
140 list_for_each_entry_safe(port, p, &port_remove_lh, list)
141 device_unregister(&port->dev);
143 zfcp_adapter_unregister(adapter);
147 * zfcp_ccw_set_online - set_online function of zfcp driver
148 * @cdev: pointer to belonging ccw device
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.
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.
159 static int zfcp_ccw_set_online(struct ccw_device *cdev)
161 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
163 if (!adapter) {
164 adapter = zfcp_adapter_enqueue(cdev);
166 if (IS_ERR(adapter)) {
167 dev_err(&cdev->dev,
168 "Setting up data structures for the "
169 "FCP adapter failed\n");
170 return PTR_ERR(adapter);
172 kref_get(&adapter->ref);
175 /* initialize request counter */
176 BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
177 adapter->req_no = 0;
179 zfcp_ccw_activate(cdev, 0, "ccsonl1");
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.
191 zfcp_fc_inverse_conditional_port_scan(adapter);
192 flush_delayed_work(&adapter->scan_work);
193 zfcp_ccw_adapter_put(adapter);
194 return 0;
198 * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish
199 * @cdev: pointer to belonging ccw device
200 * @set: Status flags to set.
201 * @tag: s390dbf trace record tag
203 * This function gets called by the common i/o layer and sets an adapter
204 * into state offline.
206 static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag)
208 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
210 if (!adapter)
211 return 0;
213 zfcp_erp_set_adapter_status(adapter, set);
214 zfcp_erp_adapter_shutdown(adapter, 0, tag);
215 zfcp_erp_wait(adapter);
217 zfcp_ccw_adapter_put(adapter);
218 return 0;
222 * zfcp_ccw_set_offline - set_offline function of zfcp driver
223 * @cdev: pointer to belonging ccw device
225 * This function gets called by the common i/o layer and sets an adapter
226 * into state offline.
228 static int zfcp_ccw_set_offline(struct ccw_device *cdev)
230 return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1");
234 * zfcp_ccw_notify - ccw notify function
235 * @cdev: pointer to belonging ccw device
236 * @event: indicates if adapter was detached or attached
238 * This function gets called by the common i/o layer if an adapter has gone
239 * or reappeared.
241 static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
243 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
245 if (!adapter)
246 return 1;
248 switch (event) {
249 case CIO_GONE:
250 if (atomic_read(&adapter->status) &
251 ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
252 zfcp_dbf_hba_basic("ccnigo1", adapter);
253 break;
255 dev_warn(&cdev->dev, "The FCP device has been detached\n");
256 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
257 break;
258 case CIO_NO_PATH:
259 dev_warn(&cdev->dev,
260 "The CHPID for the FCP device is offline\n");
261 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
262 break;
263 case CIO_OPER:
264 if (atomic_read(&adapter->status) &
265 ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
266 zfcp_dbf_hba_basic("ccniop1", adapter);
267 break;
269 dev_info(&cdev->dev, "The FCP device is operational again\n");
270 zfcp_erp_set_adapter_status(adapter,
271 ZFCP_STATUS_COMMON_RUNNING);
272 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
273 "ccnoti4");
274 break;
275 case CIO_BOXED:
276 dev_warn(&cdev->dev, "The FCP device did not respond within "
277 "the specified time\n");
278 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5");
279 break;
282 zfcp_ccw_adapter_put(adapter);
283 return 1;
287 * zfcp_ccw_shutdown - handle shutdown from cio
288 * @cdev: device for adapter to shutdown.
290 static void zfcp_ccw_shutdown(struct ccw_device *cdev)
292 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
294 if (!adapter)
295 return;
297 zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1");
298 zfcp_erp_wait(adapter);
299 zfcp_erp_thread_kill(adapter);
301 zfcp_ccw_adapter_put(adapter);
304 static int zfcp_ccw_suspend(struct ccw_device *cdev)
306 zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1");
307 return 0;
310 static int zfcp_ccw_thaw(struct ccw_device *cdev)
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;
320 static int zfcp_ccw_resume(struct ccw_device *cdev)
322 zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1");
323 return 0;
326 struct ccw_driver zfcp_ccw_driver = {
327 .driver = {
328 .owner = THIS_MODULE,
329 .name = "zfcp",
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,
338 .freeze = zfcp_ccw_suspend,
339 .thaw = zfcp_ccw_thaw,
340 .restore = zfcp_ccw_resume,