1 /*
2  * zfcp device driver
3  *
4  * Registration and callback for the s390 common I/O layer.
5  *
6  * Copyright IBM Corporation 2002, 2010
7  */
8 
9 #define KMSG_COMPONENT "zfcp"
10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11 
12 #include <linux/module.h>
13 #include "zfcp_ext.h"
14 #include "zfcp_reqlist.h"
15 
16 #define ZFCP_MODEL_PRIV 0x4
17 
18 static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock);
19 
zfcp_ccw_adapter_by_cdev(struct ccw_device * cdev)20 struct 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 
zfcp_ccw_adapter_put(struct zfcp_adapter * adapter)33 void 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 
42 /**
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  */
zfcp_ccw_activate(struct ccw_device * cdev,int clear,char * tag)48 static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
49 {
50 	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
51 
52 	if (!adapter)
53 		return 0;
54 
55 	zfcp_erp_clear_adapter_status(adapter, clear);
56 	zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
57 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
58 				tag);
59 	zfcp_erp_wait(adapter);
60 	flush_work(&adapter->scan_work);
61 
62 	zfcp_ccw_adapter_put(adapter);
63 
64 	return 0;
65 }
66 
67 static 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 };
72 MODULE_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  */
zfcp_ccw_priv_sch(struct zfcp_adapter * adapter)78 int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter)
79 {
80 	return adapter->ccw_device->id.dev_model == ZFCP_MODEL_PRIV;
81 }
82 
83 /**
84  * zfcp_ccw_probe - probe function of zfcp driver
85  * @cdev: pointer to belonging ccw device
86  *
87  * 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.
91  */
zfcp_ccw_probe(struct ccw_device * cdev)92 static int zfcp_ccw_probe(struct ccw_device *cdev)
93 {
94 	return 0;
95 }
96 
97 /**
98  * zfcp_ccw_remove - remove function of zfcp driver
99  * @cdev: pointer to belonging ccw device
100  *
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  */
zfcp_ccw_remove(struct ccw_device * cdev)106 static void zfcp_ccw_remove(struct ccw_device *cdev)
107 {
108 	struct zfcp_adapter *adapter;
109 	struct zfcp_port *port, *p;
110 	struct zfcp_unit *unit, *u;
111 	LIST_HEAD(unit_remove_lh);
112 	LIST_HEAD(port_remove_lh);
113 
114 	ccw_device_set_offline(cdev);
115 
116 	adapter = zfcp_ccw_adapter_by_cdev(cdev);
117 	if (!adapter)
118 		return;
119 
120 	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);
123 		list_for_each_entry_safe(unit, u, &port->unit_list, list)
124 			list_move(&unit->list, &unit_remove_lh);
125 		write_unlock(&port->unit_list_lock);
126 		list_move(&port->list, &port_remove_lh);
127 	}
128 	write_unlock_irq(&adapter->port_list_lock);
129 	zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */
130 
131 	list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
132 		zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
133 
134 	list_for_each_entry_safe(port, p, &port_remove_lh, list)
135 		zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs);
136 
137 	zfcp_adapter_unregister(adapter);
138 }
139 
140 /**
141  * zfcp_ccw_set_online - set_online function of zfcp driver
142  * @cdev: pointer to belonging ccw device
143  *
144  * 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.
152  */
zfcp_ccw_set_online(struct ccw_device * cdev)153 static int zfcp_ccw_set_online(struct ccw_device *cdev)
154 {
155 	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
156 
157 	if (!adapter) {
158 		adapter = zfcp_adapter_enqueue(cdev);
159 
160 		if (IS_ERR(adapter)) {
161 			dev_err(&cdev->dev,
162 				"Setting up data structures for the "
163 				"FCP adapter failed\n");
164 			return PTR_ERR(adapter);
165 		}
166 		kref_get(&adapter->ref);
167 	}
168 
169 	/* initialize request counter */
170 	BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
171 	adapter->req_no = 0;
172 
173 	zfcp_ccw_activate(cdev, 0, "ccsonl1");
174 	zfcp_ccw_adapter_put(adapter);
175 	return 0;
176 }
177 
178 /**
179  * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish
180  * @cdev: pointer to belonging ccw device
181  * @set: Status flags to set.
182  * @tag: s390dbf trace record tag
183  *
184  * This function gets called by the common i/o layer and sets an adapter
185  * into state offline.
186  */
zfcp_ccw_offline_sync(struct ccw_device * cdev,int set,char * tag)187 static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag)
188 {
189 	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
190 
191 	if (!adapter)
192 		return 0;
193 
194 	zfcp_erp_set_adapter_status(adapter, set);
195 	zfcp_erp_adapter_shutdown(adapter, 0, tag);
196 	zfcp_erp_wait(adapter);
197 
198 	zfcp_ccw_adapter_put(adapter);
199 	return 0;
200 }
201 
202 /**
203  * zfcp_ccw_set_offline - set_offline function of zfcp driver
204  * @cdev: pointer to belonging ccw device
205  *
206  * This function gets called by the common i/o layer and sets an adapter
207  * into state offline.
208  */
zfcp_ccw_set_offline(struct ccw_device * cdev)209 static int zfcp_ccw_set_offline(struct ccw_device *cdev)
210 {
211 	return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1");
212 }
213 
214 /**
215  * zfcp_ccw_notify - ccw notify function
216  * @cdev: pointer to belonging ccw device
217  * @event: indicates if adapter was detached or attached
218  *
219  * This function gets called by the common i/o layer if an adapter has gone
220  * or reappeared.
221  */
zfcp_ccw_notify(struct ccw_device * cdev,int event)222 static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
223 {
224 	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
225 
226 	if (!adapter)
227 		return 1;
228 
229 	switch (event) {
230 	case CIO_GONE:
231 		if (atomic_read(&adapter->status) &
232 		    ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
233 			zfcp_dbf_hba_basic("ccnigo1", adapter);
234 			break;
235 		}
236 		dev_warn(&cdev->dev, "The FCP device has been detached\n");
237 		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
238 		break;
239 	case CIO_NO_PATH:
240 		dev_warn(&cdev->dev,
241 			 "The CHPID for the FCP device is offline\n");
242 		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
243 		break;
244 	case CIO_OPER:
245 		if (atomic_read(&adapter->status) &
246 		    ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
247 			zfcp_dbf_hba_basic("ccniop1", adapter);
248 			break;
249 		}
250 		dev_info(&cdev->dev, "The FCP device is operational again\n");
251 		zfcp_erp_set_adapter_status(adapter,
252 					    ZFCP_STATUS_COMMON_RUNNING);
253 		zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
254 					"ccnoti4");
255 		break;
256 	case CIO_BOXED:
257 		dev_warn(&cdev->dev, "The FCP device did not respond within "
258 				     "the specified time\n");
259 		zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5");
260 		break;
261 	}
262 
263 	zfcp_ccw_adapter_put(adapter);
264 	return 1;
265 }
266 
267 /**
268  * zfcp_ccw_shutdown - handle shutdown from cio
269  * @cdev: device for adapter to shutdown.
270  */
zfcp_ccw_shutdown(struct ccw_device * cdev)271 static void zfcp_ccw_shutdown(struct ccw_device *cdev)
272 {
273 	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
274 
275 	if (!adapter)
276 		return;
277 
278 	zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1");
279 	zfcp_erp_wait(adapter);
280 	zfcp_erp_thread_kill(adapter);
281 
282 	zfcp_ccw_adapter_put(adapter);
283 }
284 
zfcp_ccw_suspend(struct ccw_device * cdev)285 static int zfcp_ccw_suspend(struct ccw_device *cdev)
286 {
287 	zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1");
288 	return 0;
289 }
290 
zfcp_ccw_thaw(struct ccw_device * cdev)291 static int zfcp_ccw_thaw(struct ccw_device *cdev)
292 {
293 	/* trace records for thaw and final shutdown during suspend
294 	   can only be found in system dump until the end of suspend
295 	   but not after resume because it's based on the memory image
296 	   right after the very first suspend (freeze) callback */
297 	zfcp_ccw_activate(cdev, 0, "ccthaw1");
298 	return 0;
299 }
300 
zfcp_ccw_resume(struct ccw_device * cdev)301 static int zfcp_ccw_resume(struct ccw_device *cdev)
302 {
303 	zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1");
304 	return 0;
305 }
306 
307 struct ccw_driver zfcp_ccw_driver = {
308 	.driver = {
309 		.owner	= THIS_MODULE,
310 		.name	= "zfcp",
311 	},
312 	.ids         = zfcp_ccw_device_id,
313 	.probe       = zfcp_ccw_probe,
314 	.remove      = zfcp_ccw_remove,
315 	.set_online  = zfcp_ccw_set_online,
316 	.set_offline = zfcp_ccw_set_offline,
317 	.notify      = zfcp_ccw_notify,
318 	.shutdown    = zfcp_ccw_shutdown,
319 	.freeze      = zfcp_ccw_suspend,
320 	.thaw	     = zfcp_ccw_thaw,
321 	.restore     = zfcp_ccw_resume,
322 };
323