]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/s390/scsi/zfcp_ccw.c
Revert "x86: blacklist DMAR on Intel G31/G33 chipsets"
[linux-2.6-omap-h63xx.git] / drivers / s390 / scsi / zfcp_ccw.c
1 /*
2  * zfcp device driver
3  *
4  * Registration and callback for the s390 common I/O layer.
5  *
6  * Copyright IBM Corporation 2002, 2008
7  */
8
9 #include "zfcp_ext.h"
10
11 /**
12  * zfcp_ccw_probe - probe function of zfcp driver
13  * @ccw_device: pointer to belonging ccw device
14  *
15  * This function gets called by the common i/o layer and sets up the initial
16  * data structures for each fcp adapter, which was detected by the system.
17  * Also the sysfs files for this adapter will be created by this function.
18  * In addition the nameserver port will be added to the ports of the adapter
19  * and its sysfs representation will be created too.
20  */
21 static int zfcp_ccw_probe(struct ccw_device *ccw_device)
22 {
23         int retval = 0;
24
25         down(&zfcp_data.config_sema);
26         if (zfcp_adapter_enqueue(ccw_device)) {
27                 dev_err(&ccw_device->dev,
28                         "Setting up data structures for the "
29                         "FCP adapter failed\n");
30                 retval = -EINVAL;
31         }
32         up(&zfcp_data.config_sema);
33         return retval;
34 }
35
36 /**
37  * zfcp_ccw_remove - remove function of zfcp driver
38  * @ccw_device: pointer to belonging ccw device
39  *
40  * This function gets called by the common i/o layer and removes an adapter
41  * from the system. Task of this function is to get rid of all units and
42  * ports that belong to this adapter. And in addition all resources of this
43  * adapter will be freed too.
44  */
45 static void zfcp_ccw_remove(struct ccw_device *ccw_device)
46 {
47         struct zfcp_adapter *adapter;
48         struct zfcp_port *port, *p;
49         struct zfcp_unit *unit, *u;
50         LIST_HEAD(unit_remove_lh);
51         LIST_HEAD(port_remove_lh);
52
53         ccw_device_set_offline(ccw_device);
54         down(&zfcp_data.config_sema);
55         adapter = dev_get_drvdata(&ccw_device->dev);
56
57         write_lock_irq(&zfcp_data.config_lock);
58         list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
59                 list_for_each_entry_safe(unit, u, &port->unit_list_head, list) {
60                         list_move(&unit->list, &unit_remove_lh);
61                         atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
62                                         &unit->status);
63                 }
64                 list_move(&port->list, &port_remove_lh);
65                 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
66         }
67         atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
68         write_unlock_irq(&zfcp_data.config_lock);
69
70         list_for_each_entry_safe(port, p, &port_remove_lh, list) {
71                 list_for_each_entry_safe(unit, u, &unit_remove_lh, list) {
72                         if (atomic_read(&unit->status) &
73                             ZFCP_STATUS_UNIT_REGISTERED)
74                                 scsi_remove_device(unit->device);
75                         zfcp_unit_dequeue(unit);
76                 }
77                 zfcp_port_dequeue(port);
78         }
79         wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
80         zfcp_adapter_dequeue(adapter);
81
82         up(&zfcp_data.config_sema);
83 }
84
85 /**
86  * zfcp_ccw_set_online - set_online function of zfcp driver
87  * @ccw_device: pointer to belonging ccw device
88  *
89  * This function gets called by the common i/o layer and sets an adapter
90  * into state online. Setting an fcp device online means that it will be
91  * registered with the SCSI stack, that the QDIO queues will be set up
92  * and that the adapter will be opened (asynchronously).
93  */
94 static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
95 {
96         struct zfcp_adapter *adapter;
97         int retval;
98
99         down(&zfcp_data.config_sema);
100         adapter = dev_get_drvdata(&ccw_device->dev);
101
102         retval = zfcp_erp_thread_setup(adapter);
103         if (retval)
104                 goto out;
105
106         retval = zfcp_adapter_scsi_register(adapter);
107         if (retval)
108                 goto out_scsi_register;
109
110         /* initialize request counter */
111         BUG_ON(!zfcp_reqlist_isempty(adapter));
112         adapter->req_no = 0;
113
114         zfcp_erp_modify_adapter_status(adapter, 10, NULL,
115                                        ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
116         zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85,
117                                 NULL);
118         zfcp_erp_wait(adapter);
119         goto out;
120
121  out_scsi_register:
122         zfcp_erp_thread_kill(adapter);
123  out:
124         up(&zfcp_data.config_sema);
125         return retval;
126 }
127
128 /**
129  * zfcp_ccw_set_offline - set_offline function of zfcp driver
130  * @ccw_device: pointer to belonging ccw device
131  *
132  * This function gets called by the common i/o layer and sets an adapter
133  * into state offline.
134  */
135 static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
136 {
137         struct zfcp_adapter *adapter;
138
139         down(&zfcp_data.config_sema);
140         adapter = dev_get_drvdata(&ccw_device->dev);
141         zfcp_erp_adapter_shutdown(adapter, 0, 86, NULL);
142         zfcp_erp_wait(adapter);
143         zfcp_erp_thread_kill(adapter);
144         up(&zfcp_data.config_sema);
145         return 0;
146 }
147
148 /**
149  * zfcp_ccw_notify - ccw notify function
150  * @ccw_device: pointer to belonging ccw device
151  * @event: indicates if adapter was detached or attached
152  *
153  * This function gets called by the common i/o layer if an adapter has gone
154  * or reappeared.
155  */
156 static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
157 {
158         struct zfcp_adapter *adapter = dev_get_drvdata(&ccw_device->dev);
159
160         switch (event) {
161         case CIO_GONE:
162                 dev_warn(&adapter->ccw_device->dev,
163                          "The FCP device has been detached\n");
164                 zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL);
165                 break;
166         case CIO_NO_PATH:
167                 dev_warn(&adapter->ccw_device->dev,
168                          "The CHPID for the FCP device is offline\n");
169                 zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL);
170                 break;
171         case CIO_OPER:
172                 dev_info(&adapter->ccw_device->dev,
173                          "The FCP device is operational again\n");
174                 zfcp_erp_modify_adapter_status(adapter, 11, NULL,
175                                                ZFCP_STATUS_COMMON_RUNNING,
176                                                ZFCP_SET);
177                 zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
178                                         89, NULL);
179                 break;
180         }
181         return 1;
182 }
183
184 /**
185  * zfcp_ccw_shutdown - handle shutdown from cio
186  * @cdev: device for adapter to shutdown.
187  */
188 static void zfcp_ccw_shutdown(struct ccw_device *cdev)
189 {
190         struct zfcp_adapter *adapter;
191
192         down(&zfcp_data.config_sema);
193         adapter = dev_get_drvdata(&cdev->dev);
194         zfcp_erp_adapter_shutdown(adapter, 0, 90, NULL);
195         zfcp_erp_wait(adapter);
196         up(&zfcp_data.config_sema);
197 }
198
199 static struct ccw_device_id zfcp_ccw_device_id[] = {
200         { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x3) },
201         { CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x4) }, /* priv. */
202         {},
203 };
204
205 MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
206
207 static struct ccw_driver zfcp_ccw_driver = {
208         .owner       = THIS_MODULE,
209         .name        = "zfcp",
210         .ids         = zfcp_ccw_device_id,
211         .probe       = zfcp_ccw_probe,
212         .remove      = zfcp_ccw_remove,
213         .set_online  = zfcp_ccw_set_online,
214         .set_offline = zfcp_ccw_set_offline,
215         .notify      = zfcp_ccw_notify,
216         .shutdown    = zfcp_ccw_shutdown,
217 };
218
219 /**
220  * zfcp_ccw_register - ccw register function
221  *
222  * Registers the driver at the common i/o layer. This function will be called
223  * at module load time/system start.
224  */
225 int __init zfcp_ccw_register(void)
226 {
227         return ccw_driver_register(&zfcp_ccw_driver);
228 }
229
230 /**
231  * zfcp_get_adapter_by_busid - find zfcp_adapter struct
232  * @busid: bus id string of zfcp adapter to find
233  */
234 struct zfcp_adapter *zfcp_get_adapter_by_busid(char *busid)
235 {
236         struct ccw_device *ccw_device;
237         struct zfcp_adapter *adapter = NULL;
238
239         ccw_device = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
240         if (ccw_device) {
241                 adapter = dev_get_drvdata(&ccw_device->dev);
242                 put_device(&ccw_device->dev);
243         }
244         return adapter;
245 }