initial commit with v3.6.7
[linux-3.6.7-moxart.git] / drivers / s390 / scsi / zfcp_ccw.c
blob9646766360d3d5acf5052e4b21b5d2ce04114764
1 /*
2 * zfcp device driver
4 * Registration and callback for the s390 common I/O layer.
6 * Copyright IBM Corp. 2002, 2010
7 */
9 #define KMSG_COMPONENT "zfcp"
10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12 #include <linux/module.h>
13 #include "zfcp_ext.h"
14 #include "zfcp_reqlist.h"
16 #define ZFCP_MODEL_PRIV 0x4
18 static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock);
20 struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *cdev)
22 struct zfcp_adapter *adapter;
23 unsigned long flags;
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;
33 void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
35 unsigned long flags;
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);
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
48 static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
50 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
52 if (!adapter)
53 return 0;
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);
62 zfcp_ccw_adapter_put(adapter);
64 return 0;
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 {},
72 MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
74 /**
75 * zfcp_ccw_priv_sch - check if subchannel is privileged
76 * @adapter: Adapter/Subchannel to check
78 int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter)
80 return adapter->ccw_device->id.dev_model == ZFCP_MODEL_PRIV;
83 /**
84 * zfcp_ccw_probe - probe function of zfcp driver
85 * @cdev: pointer to belonging ccw device
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.
92 static int zfcp_ccw_probe(struct ccw_device *cdev)
94 return 0;
97 /**
98 * zfcp_ccw_remove - remove function of zfcp driver
99 * @cdev: pointer to belonging ccw device
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.
106 static void zfcp_ccw_remove(struct ccw_device *cdev)
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);
114 ccw_device_set_offline(cdev);
116 adapter = zfcp_ccw_adapter_by_cdev(cdev);
117 if (!adapter)
118 return;
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);
128 write_unlock_irq(&adapter->port_list_lock);
129 zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */
131 list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
132 zfcp_device_unregister(&unit->dev, &zfcp_sysfs_unit_attrs);
134 list_for_each_entry_safe(port, p, &port_remove_lh, list)
135 zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs);
137 zfcp_adapter_unregister(adapter);
141 * zfcp_ccw_set_online - set_online function of zfcp driver
142 * @cdev: pointer to belonging ccw device
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.
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.
153 static int zfcp_ccw_set_online(struct ccw_device *cdev)
155 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
157 if (!adapter) {
158 adapter = zfcp_adapter_enqueue(cdev);
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);
166 kref_get(&adapter->ref);
169 /* initialize request counter */
170 BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
171 adapter->req_no = 0;
173 zfcp_ccw_activate(cdev, 0, "ccsonl1");
174 zfcp_ccw_adapter_put(adapter);
175 return 0;
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
184 * This function gets called by the common i/o layer and sets an adapter
185 * into state offline.
187 static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag)
189 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
191 if (!adapter)
192 return 0;
194 zfcp_erp_set_adapter_status(adapter, set);
195 zfcp_erp_adapter_shutdown(adapter, 0, tag);
196 zfcp_erp_wait(adapter);
198 zfcp_ccw_adapter_put(adapter);
199 return 0;
203 * zfcp_ccw_set_offline - set_offline function of zfcp driver
204 * @cdev: pointer to belonging ccw device
206 * This function gets called by the common i/o layer and sets an adapter
207 * into state offline.
209 static int zfcp_ccw_set_offline(struct ccw_device *cdev)
211 return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1");
215 * zfcp_ccw_notify - ccw notify function
216 * @cdev: pointer to belonging ccw device
217 * @event: indicates if adapter was detached or attached
219 * This function gets called by the common i/o layer if an adapter has gone
220 * or reappeared.
222 static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
224 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
226 if (!adapter)
227 return 1;
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;
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;
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;
263 zfcp_ccw_adapter_put(adapter);
264 return 1;
268 * zfcp_ccw_shutdown - handle shutdown from cio
269 * @cdev: device for adapter to shutdown.
271 static void zfcp_ccw_shutdown(struct ccw_device *cdev)
273 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
275 if (!adapter)
276 return;
278 zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1");
279 zfcp_erp_wait(adapter);
280 zfcp_erp_thread_kill(adapter);
282 zfcp_ccw_adapter_put(adapter);
285 static int zfcp_ccw_suspend(struct ccw_device *cdev)
287 zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1");
288 return 0;
291 static int zfcp_ccw_thaw(struct ccw_device *cdev)
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;
301 static int zfcp_ccw_resume(struct ccw_device *cdev)
303 zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1");
304 return 0;
307 struct ccw_driver zfcp_ccw_driver = {
308 .driver = {
309 .owner = THIS_MODULE,
310 .name = "zfcp",
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,