blob: f2dd3a0a39eb04e421437f4eaef1b6d1d1f1f82f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Christof Schmittfa04c282008-06-10 18:20:56 +02002 * zfcp device driver
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Christof Schmittfa04c282008-06-10 18:20:56 +02004 * Registration and callback for the s390 common I/O layer.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Heiko Carstensa53c8fa2012-07-20 11:15:04 +02006 * Copyright IBM Corp. 2002, 2010
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 */
8
Christof Schmittecf39d42008-12-25 13:39:53 +01009#define KMSG_COMPONENT "zfcp"
10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11
Heiko Carstens3a4c5d52011-07-30 09:25:15 +020012#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include "zfcp_ext.h"
Christof Schmittb6bd2fb2010-02-17 11:18:50 +010014#include "zfcp_reqlist.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070015
Christof Schmitt6fcf41d2009-05-15 13:18:21 +020016#define ZFCP_MODEL_PRIV 0x4
17
Swen Schilligde3dc572009-11-24 16:54:00 +010018static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock);
19
20struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *cdev)
21{
22 struct zfcp_adapter *adapter;
23 unsigned long flags;
24
25 spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);
26 adapter = dev_get_drvdata(&cdev->dev);
27 if (adapter)
28 kref_get(&adapter->ref);
29 spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
30 return adapter;
31}
32
33void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
34{
35 unsigned long flags;
36
37 spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);
38 kref_put(&adapter->ref, zfcp_adapter_release);
39 spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
40}
41
Steffen Maiercb452142012-09-04 15:23:32 +020042/**
43 * zfcp_ccw_activate - activate adapter and wait for it to finish
44 * @cdev: pointer to belonging ccw device
45 * @clear: Status flags to clear.
46 * @tag: s390dbf trace record tag
47 */
48static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
Martin Petermanndaa70fa2009-06-16 10:30:34 +020049{
Swen Schilligde3dc572009-11-24 16:54:00 +010050 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
Martin Petermanndaa70fa2009-06-16 10:30:34 +020051
Christof Schmitt143bb6b2009-08-18 15:43:27 +020052 if (!adapter)
53 return 0;
54
Steffen Maiercb452142012-09-04 15:23:32 +020055 zfcp_erp_clear_adapter_status(adapter, clear);
Swen Schilligedaed852010-09-08 14:40:01 +020056 zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
Martin Petermanndaa70fa2009-06-16 10:30:34 +020057 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
Steffen Maiercb452142012-09-04 15:23:32 +020058 tag);
Martin Petermanndaa70fa2009-06-16 10:30:34 +020059 zfcp_erp_wait(adapter);
Steffen Maier43f60cb2012-09-04 15:23:35 +020060 flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
Martin Petermanndaa70fa2009-06-16 10:30:34 +020061
Swen Schilligde3dc572009-11-24 16:54:00 +010062 zfcp_ccw_adapter_put(adapter);
63
Martin Petermanndaa70fa2009-06-16 10:30:34 +020064 return 0;
65}
66
Christof Schmitt6fcf41d2009-05-15 13:18:21 +020067static struct ccw_device_id zfcp_ccw_device_id[] = {
68 { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x3) },
69 { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, ZFCP_MODEL_PRIV) },
70 {},
71};
72MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
73
74/**
75 * zfcp_ccw_priv_sch - check if subchannel is privileged
76 * @adapter: Adapter/Subchannel to check
77 */
78int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter)
79{
80 return adapter->ccw_device->id.dev_model == ZFCP_MODEL_PRIV;
81}
82
Linus Torvalds1da177e2005-04-16 15:20:36 -070083/**
84 * zfcp_ccw_probe - probe function of zfcp driver
Swen Schilligde3dc572009-11-24 16:54:00 +010085 * @cdev: pointer to belonging ccw device
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 *
Christof Schmitt143bb6b2009-08-18 15:43:27 +020087 * This function gets called by the common i/o layer for each FCP
88 * device found on the current system. This is only a stub to make cio
89 * work: To only allocate adapter resources for devices actually used,
90 * the allocation is deferred to the first call to ccw_set_online.
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 */
Swen Schilligde3dc572009-11-24 16:54:00 +010092static int zfcp_ccw_probe(struct ccw_device *cdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070093{
Christof Schmitt143bb6b2009-08-18 15:43:27 +020094 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095}
96
97/**
98 * zfcp_ccw_remove - remove function of zfcp driver
Swen Schilligde3dc572009-11-24 16:54:00 +010099 * @cdev: pointer to belonging ccw device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 *
101 * This function gets called by the common i/o layer and removes an adapter
102 * from the system. Task of this function is to get rid of all units and
103 * ports that belong to this adapter. And in addition all resources of this
104 * adapter will be freed too.
105 */
Swen Schilligde3dc572009-11-24 16:54:00 +0100106static void zfcp_ccw_remove(struct ccw_device *cdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107{
108 struct zfcp_adapter *adapter;
109 struct zfcp_port *port, *p;
110 struct zfcp_unit *unit, *u;
Christof Schmitt04062892008-10-01 12:42:20 +0200111 LIST_HEAD(unit_remove_lh);
112 LIST_HEAD(port_remove_lh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Swen Schilligde3dc572009-11-24 16:54:00 +0100114 ccw_device_set_offline(cdev);
Christof Schmitt143bb6b2009-08-18 15:43:27 +0200115
Swen Schilligde3dc572009-11-24 16:54:00 +0100116 adapter = zfcp_ccw_adapter_by_cdev(cdev);
Swen Schilligecf0c772009-11-24 16:53:58 +0100117 if (!adapter)
118 return;
119
Swen Schilligecf0c772009-11-24 16:53:58 +0100120 write_lock_irq(&adapter->port_list_lock);
121 list_for_each_entry_safe(port, p, &adapter->port_list, list) {
122 write_lock(&port->unit_list_lock);
Swen Schillig6b1833342009-11-24 16:54:05 +0100123 list_for_each_entry_safe(unit, u, &port->unit_list, list)
Swen Schilligecf0c772009-11-24 16:53:58 +0100124 list_move(&unit->list, &unit_remove_lh);
Swen Schilligecf0c772009-11-24 16:53:58 +0100125 write_unlock(&port->unit_list_lock);
Swen Schilligecf0c772009-11-24 16:53:58 +0100126 list_move(&port->list, &port_remove_lh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 }
Swen Schilligecf0c772009-11-24 16:53:58 +0100128 write_unlock_irq(&adapter->port_list_lock);
Swen Schilligde3dc572009-11-24 16:54:00 +0100129 zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
Swen Schilligf3450c72009-11-24 16:53:59 +0100131 list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
Christof Schmitt615f59e2010-02-17 11:18:56 +0100132 zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
Swen Schilligf3450c72009-11-24 16:53:59 +0100133
134 list_for_each_entry_safe(port, p, &port_remove_lh, list)
Christof Schmitt615f59e2010-02-17 11:18:56 +0100135 zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs);
Swen Schilligf3450c72009-11-24 16:53:59 +0100136
Swen Schilligde3dc572009-11-24 16:54:00 +0100137 zfcp_adapter_unregister(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138}
139
140/**
141 * zfcp_ccw_set_online - set_online function of zfcp driver
Swen Schilligde3dc572009-11-24 16:54:00 +0100142 * @cdev: pointer to belonging ccw device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 *
Christof Schmitt143bb6b2009-08-18 15:43:27 +0200144 * This function gets called by the common i/o layer and sets an
145 * adapter into state online. The first call will allocate all
146 * adapter resources that will be retained until the device is removed
147 * via zfcp_ccw_remove.
148 *
149 * Setting an fcp device online means that it will be registered with
150 * the SCSI stack, that the QDIO queues will be set up and that the
151 * adapter will be opened.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 */
Swen Schilligde3dc572009-11-24 16:54:00 +0100153static int zfcp_ccw_set_online(struct ccw_device *cdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154{
Swen Schilligde3dc572009-11-24 16:54:00 +0100155 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
Christof Schmitt143bb6b2009-08-18 15:43:27 +0200157 if (!adapter) {
Swen Schilligde3dc572009-11-24 16:54:00 +0100158 adapter = zfcp_adapter_enqueue(cdev);
159
160 if (IS_ERR(adapter)) {
161 dev_err(&cdev->dev,
Christof Schmitt143bb6b2009-08-18 15:43:27 +0200162 "Setting up data structures for the "
163 "FCP adapter failed\n");
Swen Schilligde3dc572009-11-24 16:54:00 +0100164 return PTR_ERR(adapter);
Christof Schmitt143bb6b2009-08-18 15:43:27 +0200165 }
Swen Schilligde3dc572009-11-24 16:54:00 +0100166 kref_get(&adapter->ref);
Christof Schmitt143bb6b2009-08-18 15:43:27 +0200167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
Volker Sameskefea9d6c2006-08-02 11:05:16 +0200169 /* initialize request counter */
Christof Schmittb6bd2fb2010-02-17 11:18:50 +0100170 BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
Volker Sameskefea9d6c2006-08-02 11:05:16 +0200171 adapter->req_no = 0;
172
Steffen Maiercb452142012-09-04 15:23:32 +0200173 zfcp_ccw_activate(cdev, 0, "ccsonl1");
Steffen Maier43f60cb2012-09-04 15:23:35 +0200174 /* scan for remote ports
175 either at the end of any successful adapter recovery
176 or only after the adapter recovery for setting a device online */
177 zfcp_fc_inverse_conditional_port_scan(adapter);
178 flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
Steffen Maiercb452142012-09-04 15:23:32 +0200179 zfcp_ccw_adapter_put(adapter);
180 return 0;
181}
182
183/**
184 * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish
185 * @cdev: pointer to belonging ccw device
186 * @set: Status flags to set.
187 * @tag: s390dbf trace record tag
188 *
189 * This function gets called by the common i/o layer and sets an adapter
190 * into state offline.
191 */
192static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag)
193{
194 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
195
196 if (!adapter)
197 return 0;
198
199 zfcp_erp_set_adapter_status(adapter, set);
200 zfcp_erp_adapter_shutdown(adapter, 0, tag);
201 zfcp_erp_wait(adapter);
202
Swen Schilligde3dc572009-11-24 16:54:00 +0100203 zfcp_ccw_adapter_put(adapter);
204 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205}
206
207/**
208 * zfcp_ccw_set_offline - set_offline function of zfcp driver
Swen Schilligde3dc572009-11-24 16:54:00 +0100209 * @cdev: pointer to belonging ccw device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 *
211 * This function gets called by the common i/o layer and sets an adapter
Michael Loehr9f287452007-05-09 11:01:24 +0200212 * into state offline.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 */
Swen Schilligde3dc572009-11-24 16:54:00 +0100214static int zfcp_ccw_set_offline(struct ccw_device *cdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215{
Steffen Maiercb452142012-09-04 15:23:32 +0200216 return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217}
218
219/**
Christof Schmittfa04c282008-06-10 18:20:56 +0200220 * zfcp_ccw_notify - ccw notify function
Swen Schilligde3dc572009-11-24 16:54:00 +0100221 * @cdev: pointer to belonging ccw device
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 * @event: indicates if adapter was detached or attached
223 *
224 * This function gets called by the common i/o layer if an adapter has gone
225 * or reappeared.
226 */
Swen Schilligde3dc572009-11-24 16:54:00 +0100227static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228{
Swen Schilligde3dc572009-11-24 16:54:00 +0100229 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
230
231 if (!adapter)
232 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 switch (event) {
235 case CIO_GONE:
Steffen Maiercb452142012-09-04 15:23:32 +0200236 if (atomic_read(&adapter->status) &
237 ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
238 zfcp_dbf_hba_basic("ccnigo1", adapter);
239 break;
240 }
Swen Schilligde3dc572009-11-24 16:54:00 +0100241 dev_warn(&cdev->dev, "The FCP device has been detached\n");
Swen Schilligea4a3a62010-12-02 15:16:16 +0100242 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 break;
244 case CIO_NO_PATH:
Swen Schilligde3dc572009-11-24 16:54:00 +0100245 dev_warn(&cdev->dev,
Christof Schmittff3b24f2008-10-01 12:42:15 +0200246 "The CHPID for the FCP device is offline\n");
Swen Schilligea4a3a62010-12-02 15:16:16 +0100247 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 break;
249 case CIO_OPER:
Steffen Maiercb452142012-09-04 15:23:32 +0200250 if (atomic_read(&adapter->status) &
251 ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
252 zfcp_dbf_hba_basic("ccniop1", adapter);
253 break;
254 }
Swen Schilligde3dc572009-11-24 16:54:00 +0100255 dev_info(&cdev->dev, "The FCP device is operational again\n");
Swen Schilligedaed852010-09-08 14:40:01 +0200256 zfcp_erp_set_adapter_status(adapter,
257 ZFCP_STATUS_COMMON_RUNNING);
Martin Peschke1f6f7122008-04-18 12:51:55 +0200258 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
Swen Schilligea4a3a62010-12-02 15:16:16 +0100259 "ccnoti4");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 break;
Sebastian Ott47593bf2009-03-31 19:16:05 +0200261 case CIO_BOXED:
Swen Schilligde3dc572009-11-24 16:54:00 +0100262 dev_warn(&cdev->dev, "The FCP device did not respond within "
263 "the specified time\n");
Swen Schilligea4a3a62010-12-02 15:16:16 +0100264 zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5");
Sebastian Ott47593bf2009-03-31 19:16:05 +0200265 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 }
Swen Schilligde3dc572009-11-24 16:54:00 +0100267
268 zfcp_ccw_adapter_put(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 return 1;
270}
271
272/**
Christof Schmittfa04c282008-06-10 18:20:56 +0200273 * zfcp_ccw_shutdown - handle shutdown from cio
274 * @cdev: device for adapter to shutdown.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 */
Christof Schmittfa04c282008-06-10 18:20:56 +0200276static void zfcp_ccw_shutdown(struct ccw_device *cdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277{
Swen Schilligde3dc572009-11-24 16:54:00 +0100278 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Christof Schmitt1f99bd42009-09-24 10:23:23 +0200280 if (!adapter)
Swen Schilligde3dc572009-11-24 16:54:00 +0100281 return;
Christof Schmitt1f99bd42009-09-24 10:23:23 +0200282
Swen Schilligea4a3a62010-12-02 15:16:16 +0100283 zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 zfcp_erp_wait(adapter);
Christof Schmitt143bb6b2009-08-18 15:43:27 +0200285 zfcp_erp_thread_kill(adapter);
Swen Schilligde3dc572009-11-24 16:54:00 +0100286
287 zfcp_ccw_adapter_put(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288}
289
Steffen Maiercb452142012-09-04 15:23:32 +0200290static int zfcp_ccw_suspend(struct ccw_device *cdev)
291{
292 zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1");
293 return 0;
294}
295
296static int zfcp_ccw_thaw(struct ccw_device *cdev)
297{
298 /* trace records for thaw and final shutdown during suspend
299 can only be found in system dump until the end of suspend
300 but not after resume because it's based on the memory image
301 right after the very first suspend (freeze) callback */
302 zfcp_ccw_activate(cdev, 0, "ccthaw1");
303 return 0;
304}
305
306static int zfcp_ccw_resume(struct ccw_device *cdev)
307{
308 zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1");
309 return 0;
310}
311
Christof Schmittc5afd812009-09-24 10:23:22 +0200312struct ccw_driver zfcp_ccw_driver = {
Sebastian Ott3bda0582011-03-23 10:16:02 +0100313 .driver = {
314 .owner = THIS_MODULE,
315 .name = "zfcp",
316 },
Christof Schmittfa04c282008-06-10 18:20:56 +0200317 .ids = zfcp_ccw_device_id,
318 .probe = zfcp_ccw_probe,
319 .remove = zfcp_ccw_remove,
320 .set_online = zfcp_ccw_set_online,
321 .set_offline = zfcp_ccw_set_offline,
322 .notify = zfcp_ccw_notify,
323 .shutdown = zfcp_ccw_shutdown,
Steffen Maiercb452142012-09-04 15:23:32 +0200324 .freeze = zfcp_ccw_suspend,
325 .thaw = zfcp_ccw_thaw,
326 .restore = zfcp_ccw_resume,
Christof Schmittfa04c282008-06-10 18:20:56 +0200327};