xref: /openbmc/linux/drivers/s390/scsi/zfcp_ccw.c (revision 384740dc)
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 }
246