diff options
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 67 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 64 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 241 | ||||
-rw-r--r-- | include/asm-s390/ccwdev.h | 75 | ||||
-rw-r--r-- | include/asm-s390/ccwgroup.h | 32 | ||||
-rw-r--r-- | include/asm-s390/cio.h | 288 |
6 files changed, 575 insertions, 192 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index b0a18f5176aa..9c3b9ea1e66f 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -152,16 +152,24 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) | |||
152 | return 0; | 152 | return 0; |
153 | } | 153 | } |
154 | 154 | ||
155 | /* | 155 | /** |
156 | * try to add a new ccwgroup device for one driver | 156 | * ccwgroup_create() - create and register a ccw group device |
157 | * argc and argv[] are a list of bus_id's of devices | 157 | * @root: parent device for the new device |
158 | * belonging to the driver. | 158 | * @creator_id: identifier of creating driver |
159 | * @cdrv: ccw driver of slave devices | ||
160 | * @argc: number of slave devices | ||
161 | * @argv: bus ids of slave devices | ||
162 | * | ||
163 | * Create and register a new ccw group device as a child of @root. Slave | ||
164 | * devices are obtained from the list of bus ids given in @argv[] and must all | ||
165 | * belong to @cdrv. | ||
166 | * Returns: | ||
167 | * %0 on success and an error code on failure. | ||
168 | * Context: | ||
169 | * non-atomic | ||
159 | */ | 170 | */ |
160 | int | 171 | int ccwgroup_create(struct device *root, unsigned int creator_id, |
161 | ccwgroup_create(struct device *root, | 172 | struct ccw_driver *cdrv, int argc, char *argv[]) |
162 | unsigned int creator_id, | ||
163 | struct ccw_driver *cdrv, | ||
164 | int argc, char *argv[]) | ||
165 | { | 173 | { |
166 | struct ccwgroup_device *gdev; | 174 | struct ccwgroup_device *gdev; |
167 | int i; | 175 | int i; |
@@ -390,8 +398,13 @@ static struct bus_type ccwgroup_bus_type = { | |||
390 | .remove = ccwgroup_remove, | 398 | .remove = ccwgroup_remove, |
391 | }; | 399 | }; |
392 | 400 | ||
393 | int | 401 | /** |
394 | ccwgroup_driver_register (struct ccwgroup_driver *cdriver) | 402 | * ccwgroup_driver_register() - register a ccw group driver |
403 | * @cdriver: driver to be registered | ||
404 | * | ||
405 | * This function is mainly a wrapper around driver_register(). | ||
406 | */ | ||
407 | int ccwgroup_driver_register(struct ccwgroup_driver *cdriver) | ||
395 | { | 408 | { |
396 | /* register our new driver with the core */ | 409 | /* register our new driver with the core */ |
397 | cdriver->driver.bus = &ccwgroup_bus_type; | 410 | cdriver->driver.bus = &ccwgroup_bus_type; |
@@ -406,8 +419,13 @@ __ccwgroup_match_all(struct device *dev, void *data) | |||
406 | return 1; | 419 | return 1; |
407 | } | 420 | } |
408 | 421 | ||
409 | void | 422 | /** |
410 | ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | 423 | * ccwgroup_driver_unregister() - deregister a ccw group driver |
424 | * @cdriver: driver to be deregistered | ||
425 | * | ||
426 | * This function is mainly a wrapper around driver_unregister(). | ||
427 | */ | ||
428 | void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) | ||
411 | { | 429 | { |
412 | struct device *dev; | 430 | struct device *dev; |
413 | 431 | ||
@@ -427,8 +445,16 @@ ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | |||
427 | driver_unregister(&cdriver->driver); | 445 | driver_unregister(&cdriver->driver); |
428 | } | 446 | } |
429 | 447 | ||
430 | int | 448 | /** |
431 | ccwgroup_probe_ccwdev(struct ccw_device *cdev) | 449 | * ccwgroup_probe_ccwdev() - probe function for slave devices |
450 | * @cdev: ccw device to be probed | ||
451 | * | ||
452 | * This is a dummy probe function for ccw devices that are slave devices in | ||
453 | * a ccw group device. | ||
454 | * Returns: | ||
455 | * always %0 | ||
456 | */ | ||
457 | int ccwgroup_probe_ccwdev(struct ccw_device *cdev) | ||
432 | { | 458 | { |
433 | return 0; | 459 | return 0; |
434 | } | 460 | } |
@@ -452,8 +478,15 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev) | |||
452 | return NULL; | 478 | return NULL; |
453 | } | 479 | } |
454 | 480 | ||
455 | void | 481 | /** |
456 | ccwgroup_remove_ccwdev(struct ccw_device *cdev) | 482 | * ccwgroup_remove_ccwdev() - remove function for slave devices |
483 | * @cdev: ccw device to be removed | ||
484 | * | ||
485 | * This is a remove function for ccw devices that are slave devices in a ccw | ||
486 | * group device. It sets the ccw device offline and also deregisters the | ||
487 | * embedding ccw group device. | ||
488 | */ | ||
489 | void ccwgroup_remove_ccwdev(struct ccw_device *cdev) | ||
457 | { | 490 | { |
458 | struct ccwgroup_device *gdev; | 491 | struct ccwgroup_device *gdev; |
459 | 492 | ||
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e44d92eac8e9..3943a4fde22a 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -357,8 +357,18 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) | |||
357 | cdev->private->dev_id.devno); | 357 | cdev->private->dev_id.devno); |
358 | } | 358 | } |
359 | 359 | ||
360 | int | 360 | /** |
361 | ccw_device_set_offline(struct ccw_device *cdev) | 361 | * ccw_device_set_offline() - disable a ccw device for I/O |
362 | * @cdev: target ccw device | ||
363 | * | ||
364 | * This function calls the driver's set_offline() function for @cdev, if | ||
365 | * given, and then disables @cdev. | ||
366 | * Returns: | ||
367 | * %0 on success and a negative error value on failure. | ||
368 | * Context: | ||
369 | * enabled, ccw device lock not held | ||
370 | */ | ||
371 | int ccw_device_set_offline(struct ccw_device *cdev) | ||
362 | { | 372 | { |
363 | int ret; | 373 | int ret; |
364 | 374 | ||
@@ -396,8 +406,19 @@ ccw_device_set_offline(struct ccw_device *cdev) | |||
396 | return ret; | 406 | return ret; |
397 | } | 407 | } |
398 | 408 | ||
399 | int | 409 | /** |
400 | ccw_device_set_online(struct ccw_device *cdev) | 410 | * ccw_device_set_online() - enable a ccw device for I/O |
411 | * @cdev: target ccw device | ||
412 | * | ||
413 | * This function first enables @cdev and then calls the driver's set_online() | ||
414 | * function for @cdev, if given. If set_online() returns an error, @cdev is | ||
415 | * disabled again. | ||
416 | * Returns: | ||
417 | * %0 on success and a negative error value on failure. | ||
418 | * Context: | ||
419 | * enabled, ccw device lock not held | ||
420 | */ | ||
421 | int ccw_device_set_online(struct ccw_device *cdev) | ||
401 | { | 422 | { |
402 | int ret; | 423 | int ret; |
403 | 424 | ||
@@ -1326,8 +1347,19 @@ __ccwdev_check_busid(struct device *dev, void *id) | |||
1326 | } | 1347 | } |
1327 | 1348 | ||
1328 | 1349 | ||
1329 | struct ccw_device * | 1350 | /** |
1330 | get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id) | 1351 | * get_ccwdev_by_busid() - obtain device from a bus id |
1352 | * @cdrv: driver the device is owned by | ||
1353 | * @bus_id: bus id of the device to be searched | ||
1354 | * | ||
1355 | * This function searches all devices owned by @cdrv for a device with a bus | ||
1356 | * id matching @bus_id. | ||
1357 | * Returns: | ||
1358 | * If a match is found, its reference count of the found device is increased | ||
1359 | * and it is returned; else %NULL is returned. | ||
1360 | */ | ||
1361 | struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, | ||
1362 | const char *bus_id) | ||
1331 | { | 1363 | { |
1332 | struct device *dev; | 1364 | struct device *dev; |
1333 | struct device_driver *drv; | 1365 | struct device_driver *drv; |
@@ -1409,8 +1441,15 @@ struct bus_type ccw_bus_type = { | |||
1409 | .remove = ccw_device_remove, | 1441 | .remove = ccw_device_remove, |
1410 | }; | 1442 | }; |
1411 | 1443 | ||
1412 | int | 1444 | /** |
1413 | ccw_driver_register (struct ccw_driver *cdriver) | 1445 | * ccw_driver_register() - register a ccw driver |
1446 | * @cdriver: driver to be registered | ||
1447 | * | ||
1448 | * This function is mainly a wrapper around driver_register(). | ||
1449 | * Returns: | ||
1450 | * %0 on success and a negative error value on failure. | ||
1451 | */ | ||
1452 | int ccw_driver_register(struct ccw_driver *cdriver) | ||
1414 | { | 1453 | { |
1415 | struct device_driver *drv = &cdriver->driver; | 1454 | struct device_driver *drv = &cdriver->driver; |
1416 | 1455 | ||
@@ -1420,8 +1459,13 @@ ccw_driver_register (struct ccw_driver *cdriver) | |||
1420 | return driver_register(drv); | 1459 | return driver_register(drv); |
1421 | } | 1460 | } |
1422 | 1461 | ||
1423 | void | 1462 | /** |
1424 | ccw_driver_unregister (struct ccw_driver *cdriver) | 1463 | * ccw_driver_unregister() - deregister a ccw driver |
1464 | * @cdriver: driver to be deregistered | ||
1465 | * | ||
1466 | * This function is mainly a wrapper around driver_unregister(). | ||
1467 | */ | ||
1468 | void ccw_driver_unregister(struct ccw_driver *cdriver) | ||
1425 | { | 1469 | { |
1426 | driver_unregister(&cdriver->driver); | 1470 | driver_unregister(&cdriver->driver); |
1427 | } | 1471 | } |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 14eba854b155..7fd2dadc3297 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -25,6 +25,16 @@ | |||
25 | #include "device.h" | 25 | #include "device.h" |
26 | #include "chp.h" | 26 | #include "chp.h" |
27 | 27 | ||
28 | /** | ||
29 | * ccw_device_set_options_mask() - set some options and unset the rest | ||
30 | * @cdev: device for which the options are to be set | ||
31 | * @flags: options to be set | ||
32 | * | ||
33 | * All flags specified in @flags are set, all flags not specified in @flags | ||
34 | * are cleared. | ||
35 | * Returns: | ||
36 | * %0 on success, -%EINVAL on an invalid flag combination. | ||
37 | */ | ||
28 | int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) | 38 | int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) |
29 | { | 39 | { |
30 | /* | 40 | /* |
@@ -40,6 +50,15 @@ int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) | |||
40 | return 0; | 50 | return 0; |
41 | } | 51 | } |
42 | 52 | ||
53 | /** | ||
54 | * ccw_device_set_options() - set some options | ||
55 | * @cdev: device for which the options are to be set | ||
56 | * @flags: options to be set | ||
57 | * | ||
58 | * All flags specified in @flags are set, the remainder is left untouched. | ||
59 | * Returns: | ||
60 | * %0 on success, -%EINVAL if an invalid flag combination would ensue. | ||
61 | */ | ||
43 | int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) | 62 | int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) |
44 | { | 63 | { |
45 | /* | 64 | /* |
@@ -59,6 +78,13 @@ int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) | |||
59 | return 0; | 78 | return 0; |
60 | } | 79 | } |
61 | 80 | ||
81 | /** | ||
82 | * ccw_device_clear_options() - clear some options | ||
83 | * @cdev: device for which the options are to be cleared | ||
84 | * @flags: options to be cleared | ||
85 | * | ||
86 | * All flags specified in @flags are cleared, the remainder is left untouched. | ||
87 | */ | ||
62 | void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) | 88 | void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) |
63 | { | 89 | { |
64 | cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0; | 90 | cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0; |
@@ -67,8 +93,22 @@ void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) | |||
67 | cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0; | 93 | cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0; |
68 | } | 94 | } |
69 | 95 | ||
70 | int | 96 | /** |
71 | ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | 97 | * ccw_device_clear() - terminate I/O request processing |
98 | * @cdev: target ccw device | ||
99 | * @intparm: interruption parameter; value is only used if no I/O is | ||
100 | * outstanding, otherwise the intparm associated with the I/O request | ||
101 | * is returned | ||
102 | * | ||
103 | * ccw_device_clear() calls csch on @cdev's subchannel. | ||
104 | * Returns: | ||
105 | * %0 on success, | ||
106 | * -%ENODEV on device not operational, | ||
107 | * -%EINVAL on invalid device state. | ||
108 | * Context: | ||
109 | * Interrupts disabled, ccw device lock held | ||
110 | */ | ||
111 | int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | ||
72 | { | 112 | { |
73 | struct subchannel *sch; | 113 | struct subchannel *sch; |
74 | int ret; | 114 | int ret; |
@@ -89,10 +129,33 @@ ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | |||
89 | return ret; | 129 | return ret; |
90 | } | 130 | } |
91 | 131 | ||
92 | int | 132 | /** |
93 | ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | 133 | * ccw_device_start_key() - start a s390 channel program with key |
94 | unsigned long intparm, __u8 lpm, __u8 key, | 134 | * @cdev: target ccw device |
95 | unsigned long flags) | 135 | * @cpa: logical start address of channel program |
136 | * @intparm: user specific interruption parameter; will be presented back to | ||
137 | * @cdev's interrupt handler. Allows a device driver to associate | ||
138 | * the interrupt with a particular I/O request. | ||
139 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
140 | * value of 0 will make cio use the opm. | ||
141 | * @key: storage key to be used for the I/O | ||
142 | * @flags: additional flags; defines the action to be performed for I/O | ||
143 | * processing. | ||
144 | * | ||
145 | * Start a S/390 channel program. When the interrupt arrives, the | ||
146 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
147 | * or sense required) or never (no IRQ handler registered). | ||
148 | * Returns: | ||
149 | * %0, if the operation was successful; | ||
150 | * -%EBUSY, if the device is busy, or status pending; | ||
151 | * -%EACCES, if no path specified in @lpm is operational; | ||
152 | * -%ENODEV, if the device is not operational. | ||
153 | * Context: | ||
154 | * Interrupts disabled, ccw device lock held | ||
155 | */ | ||
156 | int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | ||
157 | unsigned long intparm, __u8 lpm, __u8 key, | ||
158 | unsigned long flags) | ||
96 | { | 159 | { |
97 | struct subchannel *sch; | 160 | struct subchannel *sch; |
98 | int ret; | 161 | int ret; |
@@ -135,11 +198,38 @@ ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | |||
135 | return ret; | 198 | return ret; |
136 | } | 199 | } |
137 | 200 | ||
138 | 201 | /** | |
139 | int | 202 | * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key |
140 | ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, | 203 | * @cdev: target ccw device |
141 | unsigned long intparm, __u8 lpm, __u8 key, | 204 | * @cpa: logical start address of channel program |
142 | unsigned long flags, int expires) | 205 | * @intparm: user specific interruption parameter; will be presented back to |
206 | * @cdev's interrupt handler. Allows a device driver to associate | ||
207 | * the interrupt with a particular I/O request. | ||
208 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
209 | * value of 0 will make cio use the opm. | ||
210 | * @key: storage key to be used for the I/O | ||
211 | * @flags: additional flags; defines the action to be performed for I/O | ||
212 | * processing. | ||
213 | * @expires: timeout value in jiffies | ||
214 | * | ||
215 | * Start a S/390 channel program. When the interrupt arrives, the | ||
216 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
217 | * or sense required) or never (no IRQ handler registered). | ||
218 | * This function notifies the device driver if the channel program has not | ||
219 | * completed during the time specified by @expires. If a timeout occurs, the | ||
220 | * channel program is terminated via xsch, hsch or csch, and the device's | ||
221 | * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT). | ||
222 | * Returns: | ||
223 | * %0, if the operation was successful; | ||
224 | * -%EBUSY, if the device is busy, or status pending; | ||
225 | * -%EACCES, if no path specified in @lpm is operational; | ||
226 | * -%ENODEV, if the device is not operational. | ||
227 | * Context: | ||
228 | * Interrupts disabled, ccw device lock held | ||
229 | */ | ||
230 | int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, | ||
231 | unsigned long intparm, __u8 lpm, __u8 key, | ||
232 | unsigned long flags, int expires) | ||
143 | { | 233 | { |
144 | int ret; | 234 | int ret; |
145 | 235 | ||
@@ -152,18 +242,67 @@ ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, | |||
152 | return ret; | 242 | return ret; |
153 | } | 243 | } |
154 | 244 | ||
155 | int | 245 | /** |
156 | ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, | 246 | * ccw_device_start() - start a s390 channel program |
157 | unsigned long intparm, __u8 lpm, unsigned long flags) | 247 | * @cdev: target ccw device |
248 | * @cpa: logical start address of channel program | ||
249 | * @intparm: user specific interruption parameter; will be presented back to | ||
250 | * @cdev's interrupt handler. Allows a device driver to associate | ||
251 | * the interrupt with a particular I/O request. | ||
252 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
253 | * value of 0 will make cio use the opm. | ||
254 | * @flags: additional flags; defines the action to be performed for I/O | ||
255 | * processing. | ||
256 | * | ||
257 | * Start a S/390 channel program. When the interrupt arrives, the | ||
258 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
259 | * or sense required) or never (no IRQ handler registered). | ||
260 | * Returns: | ||
261 | * %0, if the operation was successful; | ||
262 | * -%EBUSY, if the device is busy, or status pending; | ||
263 | * -%EACCES, if no path specified in @lpm is operational; | ||
264 | * -%ENODEV, if the device is not operational. | ||
265 | * Context: | ||
266 | * Interrupts disabled, ccw device lock held | ||
267 | */ | ||
268 | int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, | ||
269 | unsigned long intparm, __u8 lpm, unsigned long flags) | ||
158 | { | 270 | { |
159 | return ccw_device_start_key(cdev, cpa, intparm, lpm, | 271 | return ccw_device_start_key(cdev, cpa, intparm, lpm, |
160 | PAGE_DEFAULT_KEY, flags); | 272 | PAGE_DEFAULT_KEY, flags); |
161 | } | 273 | } |
162 | 274 | ||
163 | int | 275 | /** |
164 | ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, | 276 | * ccw_device_start_timeout() - start a s390 channel program with timeout |
165 | unsigned long intparm, __u8 lpm, unsigned long flags, | 277 | * @cdev: target ccw device |
166 | int expires) | 278 | * @cpa: logical start address of channel program |
279 | * @intparm: user specific interruption parameter; will be presented back to | ||
280 | * @cdev's interrupt handler. Allows a device driver to associate | ||
281 | * the interrupt with a particular I/O request. | ||
282 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
283 | * value of 0 will make cio use the opm. | ||
284 | * @flags: additional flags; defines the action to be performed for I/O | ||
285 | * processing. | ||
286 | * @expires: timeout value in jiffies | ||
287 | * | ||
288 | * Start a S/390 channel program. When the interrupt arrives, the | ||
289 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
290 | * or sense required) or never (no IRQ handler registered). | ||
291 | * This function notifies the device driver if the channel program has not | ||
292 | * completed during the time specified by @expires. If a timeout occurs, the | ||
293 | * channel program is terminated via xsch, hsch or csch, and the device's | ||
294 | * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT). | ||
295 | * Returns: | ||
296 | * %0, if the operation was successful; | ||
297 | * -%EBUSY, if the device is busy, or status pending; | ||
298 | * -%EACCES, if no path specified in @lpm is operational; | ||
299 | * -%ENODEV, if the device is not operational. | ||
300 | * Context: | ||
301 | * Interrupts disabled, ccw device lock held | ||
302 | */ | ||
303 | int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, | ||
304 | unsigned long intparm, __u8 lpm, | ||
305 | unsigned long flags, int expires) | ||
167 | { | 306 | { |
168 | return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, | 307 | return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, |
169 | PAGE_DEFAULT_KEY, flags, | 308 | PAGE_DEFAULT_KEY, flags, |
@@ -171,8 +310,23 @@ ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, | |||
171 | } | 310 | } |
172 | 311 | ||
173 | 312 | ||
174 | int | 313 | /** |
175 | ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | 314 | * ccw_device_halt() - halt I/O request processing |
315 | * @cdev: target ccw device | ||
316 | * @intparm: interruption parameter; value is only used if no I/O is | ||
317 | * outstanding, otherwise the intparm associated with the I/O request | ||
318 | * is returned | ||
319 | * | ||
320 | * ccw_device_halt() calls hsch on @cdev's subchannel. | ||
321 | * Returns: | ||
322 | * %0 on success, | ||
323 | * -%ENODEV on device not operational, | ||
324 | * -%EINVAL on invalid device state, | ||
325 | * -%EBUSY on device busy or interrupt pending. | ||
326 | * Context: | ||
327 | * Interrupts disabled, ccw device lock held | ||
328 | */ | ||
329 | int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | ||
176 | { | 330 | { |
177 | struct subchannel *sch; | 331 | struct subchannel *sch; |
178 | int ret; | 332 | int ret; |
@@ -193,8 +347,20 @@ ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | |||
193 | return ret; | 347 | return ret; |
194 | } | 348 | } |
195 | 349 | ||
196 | int | 350 | /** |
197 | ccw_device_resume(struct ccw_device *cdev) | 351 | * ccw_device_resume() - resume channel program execution |
352 | * @cdev: target ccw device | ||
353 | * | ||
354 | * ccw_device_resume() calls rsch on @cdev's subchannel. | ||
355 | * Returns: | ||
356 | * %0 on success, | ||
357 | * -%ENODEV on device not operational, | ||
358 | * -%EINVAL on invalid device state, | ||
359 | * -%EBUSY on device busy or interrupt pending. | ||
360 | * Context: | ||
361 | * Interrupts disabled, ccw device lock held | ||
362 | */ | ||
363 | int ccw_device_resume(struct ccw_device *cdev) | ||
198 | { | 364 | { |
199 | struct subchannel *sch; | 365 | struct subchannel *sch; |
200 | 366 | ||
@@ -260,11 +426,21 @@ ccw_device_call_handler(struct ccw_device *cdev) | |||
260 | return 1; | 426 | return 1; |
261 | } | 427 | } |
262 | 428 | ||
263 | /* | 429 | /** |
264 | * Search for CIW command in extended sense data. | 430 | * ccw_device_get_ciw() - Search for CIW command in extended sense data. |
431 | * @cdev: ccw device to inspect | ||
432 | * @ct: command type to look for | ||
433 | * | ||
434 | * During SenseID, command information words (CIWs) describing special | ||
435 | * commands available to the device may have been stored in the extended | ||
436 | * sense data. This function searches for CIWs of a specified command | ||
437 | * type in the extended sense data. | ||
438 | * Returns: | ||
439 | * %NULL if no extended sense data has been stored or if no CIW of the | ||
440 | * specified command type could be found, | ||
441 | * else a pointer to the CIW of the specified command type. | ||
265 | */ | 442 | */ |
266 | struct ciw * | 443 | struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) |
267 | ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) | ||
268 | { | 444 | { |
269 | int ciw_cnt; | 445 | int ciw_cnt; |
270 | 446 | ||
@@ -276,8 +452,14 @@ ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) | |||
276 | return NULL; | 452 | return NULL; |
277 | } | 453 | } |
278 | 454 | ||
279 | __u8 | 455 | /** |
280 | ccw_device_get_path_mask(struct ccw_device *cdev) | 456 | * ccw_device_get_path_mask() - get currently available paths |
457 | * @cdev: ccw device to be queried | ||
458 | * Returns: | ||
459 | * %0 if no subchannel for the device is available, | ||
460 | * else the mask of currently available paths for the ccw device's subchannel. | ||
461 | */ | ||
462 | __u8 ccw_device_get_path_mask(struct ccw_device *cdev) | ||
281 | { | 463 | { |
282 | struct subchannel *sch; | 464 | struct subchannel *sch; |
283 | 465 | ||
@@ -357,8 +539,7 @@ out_unlock: | |||
357 | return ret; | 539 | return ret; |
358 | } | 540 | } |
359 | 541 | ||
360 | void * | 542 | void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) |
361 | ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) | ||
362 | { | 543 | { |
363 | struct subchannel *sch; | 544 | struct subchannel *sch; |
364 | struct chp_id chpid; | 545 | struct chp_id chpid; |
diff --git a/include/asm-s390/ccwdev.h b/include/asm-s390/ccwdev.h index 1aeda27d5a8b..8e961aa4b394 100644 --- a/include/asm-s390/ccwdev.h +++ b/include/asm-s390/ccwdev.h | |||
@@ -67,36 +67,53 @@ ccw_device_id_match(const struct ccw_device_id *array, | |||
67 | return NULL; | 67 | return NULL; |
68 | } | 68 | } |
69 | 69 | ||
70 | /* The struct ccw device is our replacement for the globally accessible | 70 | /** |
71 | * ioinfo array. ioinfo will mutate into a subchannel device later. | 71 | * struct ccw_device - channel attached device |
72 | * @ccwlock: pointer to device lock | ||
73 | * @id: id of this device | ||
74 | * @drv: ccw driver for this device | ||
75 | * @dev: embedded device structure | ||
76 | * @online: online status of device | ||
77 | * @handler: interrupt handler | ||
72 | * | 78 | * |
73 | * Reference: Documentation/s390/driver-model.txt */ | 79 | * @handler is a member of the device rather than the driver since a driver |
80 | * can have different interrupt handlers for different ccw devices | ||
81 | * (multi-subchannel drivers). | ||
82 | */ | ||
74 | struct ccw_device { | 83 | struct ccw_device { |
75 | spinlock_t *ccwlock; | 84 | spinlock_t *ccwlock; |
85 | /* private: */ | ||
76 | struct ccw_device_private *private; /* cio private information */ | 86 | struct ccw_device_private *private; /* cio private information */ |
77 | struct ccw_device_id id; /* id of this device, driver_info is | 87 | /* public: */ |
78 | set by ccw_find_driver */ | 88 | struct ccw_device_id id; |
79 | struct ccw_driver *drv; /* */ | 89 | struct ccw_driver *drv; |
80 | struct device dev; /* */ | 90 | struct device dev; |
81 | int online; | 91 | int online; |
82 | /* This is sick, but a driver can have different interrupt handlers | ||
83 | for different ccw_devices (multi-subchannel drivers)... */ | ||
84 | void (*handler) (struct ccw_device *, unsigned long, struct irb *); | 92 | void (*handler) (struct ccw_device *, unsigned long, struct irb *); |
85 | }; | 93 | }; |
86 | 94 | ||
87 | 95 | ||
88 | /* Each ccw driver registers with the ccw root bus */ | 96 | /** |
97 | * struct ccw driver - device driver for channel attached devices | ||
98 | * @owner: owning module | ||
99 | * @ids: ids supported by this driver | ||
100 | * @probe: function called on probe | ||
101 | * @remove: function called on remove | ||
102 | * @set_online: called when setting device online | ||
103 | * @set_offline: called when setting device offline | ||
104 | * @notify: notify driver of device state changes | ||
105 | * @driver: embedded device driver structure | ||
106 | * @name: device driver name | ||
107 | */ | ||
89 | struct ccw_driver { | 108 | struct ccw_driver { |
90 | struct module *owner; /* for automatic MOD_INC_USE_COUNT */ | 109 | struct module *owner; |
91 | struct ccw_device_id *ids; /* probe driver with these devs */ | 110 | struct ccw_device_id *ids; |
92 | int (*probe) (struct ccw_device *); /* ask driver to probe dev */ | 111 | int (*probe) (struct ccw_device *); |
93 | void (*remove) (struct ccw_device *); | 112 | void (*remove) (struct ccw_device *); |
94 | /* device is no longer available */ | ||
95 | int (*set_online) (struct ccw_device *); | 113 | int (*set_online) (struct ccw_device *); |
96 | int (*set_offline) (struct ccw_device *); | 114 | int (*set_offline) (struct ccw_device *); |
97 | int (*notify) (struct ccw_device *, int); | 115 | int (*notify) (struct ccw_device *, int); |
98 | struct device_driver driver; /* higher level structure, don't init | 116 | struct device_driver driver; |
99 | this from your driver */ | ||
100 | char *name; | 117 | char *name; |
101 | }; | 118 | }; |
102 | 119 | ||
@@ -124,36 +141,10 @@ extern void ccw_device_clear_options(struct ccw_device *, unsigned long); | |||
124 | /* Allow forced onlining of boxed devices. */ | 141 | /* Allow forced onlining of boxed devices. */ |
125 | #define CCWDEV_ALLOW_FORCE 0x0008 | 142 | #define CCWDEV_ALLOW_FORCE 0x0008 |
126 | 143 | ||
127 | /* | ||
128 | * ccw_device_start() | ||
129 | * | ||
130 | * Start a S/390 channel program. When the interrupt arrives, the | ||
131 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
132 | * or sense required) or never (no IRQ handler registered). | ||
133 | * Depending on the action taken, ccw_device_start() returns: | ||
134 | * 0 - Success | ||
135 | * -EBUSY - Device busy, or status pending | ||
136 | * -ENODEV - Device not operational | ||
137 | * -EINVAL - Device invalid for operation | ||
138 | */ | ||
139 | extern int ccw_device_start(struct ccw_device *, struct ccw1 *, | 144 | extern int ccw_device_start(struct ccw_device *, struct ccw1 *, |
140 | unsigned long, __u8, unsigned long); | 145 | unsigned long, __u8, unsigned long); |
141 | /* | ||
142 | * ccw_device_start_timeout() | ||
143 | * | ||
144 | * This function notifies the device driver if the channel program has not | ||
145 | * completed during the specified time. If a timeout occurs, the channel | ||
146 | * program is terminated via xsch(), hsch() or csch(). | ||
147 | */ | ||
148 | extern int ccw_device_start_timeout(struct ccw_device *, struct ccw1 *, | 146 | extern int ccw_device_start_timeout(struct ccw_device *, struct ccw1 *, |
149 | unsigned long, __u8, unsigned long, int); | 147 | unsigned long, __u8, unsigned long, int); |
150 | /* | ||
151 | * ccw_device_start_key() | ||
152 | * ccw_device_start_key_timeout() | ||
153 | * | ||
154 | * Same as ccw_device_start() and ccw_device_start_timeout(), except a | ||
155 | * storage key != default key can be provided for the I/O. | ||
156 | */ | ||
157 | extern int ccw_device_start_key(struct ccw_device *, struct ccw1 *, | 148 | extern int ccw_device_start_key(struct ccw_device *, struct ccw1 *, |
158 | unsigned long, __u8, __u8, unsigned long); | 149 | unsigned long, __u8, __u8, unsigned long); |
159 | extern int ccw_device_start_timeout_key(struct ccw_device *, struct ccw1 *, | 150 | extern int ccw_device_start_timeout_key(struct ccw_device *, struct ccw1 *, |
diff --git a/include/asm-s390/ccwgroup.h b/include/asm-s390/ccwgroup.h index 925b3ddfa141..7109c7cab87e 100644 --- a/include/asm-s390/ccwgroup.h +++ b/include/asm-s390/ccwgroup.h | |||
@@ -4,19 +4,41 @@ | |||
4 | struct ccw_device; | 4 | struct ccw_device; |
5 | struct ccw_driver; | 5 | struct ccw_driver; |
6 | 6 | ||
7 | /** | ||
8 | * struct ccwgroup_device - ccw group device | ||
9 | * @creator_id: unique number of the driver | ||
10 | * @state: online/offline state | ||
11 | * @count: number of attached slave devices | ||
12 | * @dev: embedded device structure | ||
13 | * @cdev: variable number of slave devices, allocated as needed | ||
14 | */ | ||
7 | struct ccwgroup_device { | 15 | struct ccwgroup_device { |
8 | unsigned long creator_id; /* unique number of the driver */ | 16 | unsigned long creator_id; |
9 | enum { | 17 | enum { |
10 | CCWGROUP_OFFLINE, | 18 | CCWGROUP_OFFLINE, |
11 | CCWGROUP_ONLINE, | 19 | CCWGROUP_ONLINE, |
12 | } state; | 20 | } state; |
21 | /* private: */ | ||
13 | atomic_t onoff; | 22 | atomic_t onoff; |
14 | struct mutex reg_mutex; | 23 | struct mutex reg_mutex; |
15 | unsigned int count; /* number of attached slave devices */ | 24 | /* public: */ |
16 | struct device dev; /* master device */ | 25 | unsigned int count; |
17 | struct ccw_device *cdev[0]; /* variable number, allocate as needed */ | 26 | struct device dev; |
27 | struct ccw_device *cdev[0]; | ||
18 | }; | 28 | }; |
19 | 29 | ||
30 | /** | ||
31 | * struct ccwgroup_driver - driver for ccw group devices | ||
32 | * @owner: driver owner | ||
33 | * @name: driver name | ||
34 | * @max_slaves: maximum number of slave devices | ||
35 | * @driver_id: unique id | ||
36 | * @probe: function called on probe | ||
37 | * @remove: function called on remove | ||
38 | * @set_online: function called when device is set online | ||
39 | * @set_offline: function called when device is set offline | ||
40 | * @driver: embedded driver structure | ||
41 | */ | ||
20 | struct ccwgroup_driver { | 42 | struct ccwgroup_driver { |
21 | struct module *owner; | 43 | struct module *owner; |
22 | char *name; | 44 | char *name; |
@@ -28,7 +50,7 @@ struct ccwgroup_driver { | |||
28 | int (*set_online) (struct ccwgroup_device *); | 50 | int (*set_online) (struct ccwgroup_device *); |
29 | int (*set_offline) (struct ccwgroup_device *); | 51 | int (*set_offline) (struct ccwgroup_device *); |
30 | 52 | ||
31 | struct device_driver driver; /* this driver */ | 53 | struct device_driver driver; |
32 | }; | 54 | }; |
33 | 55 | ||
34 | extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); | 56 | extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); |
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h index 1982fb344164..2f08c16e44ad 100644 --- a/include/asm-s390/cio.h +++ b/include/asm-s390/cio.h | |||
@@ -15,30 +15,50 @@ | |||
15 | #define LPM_ANYPATH 0xff | 15 | #define LPM_ANYPATH 0xff |
16 | #define __MAX_CSSID 0 | 16 | #define __MAX_CSSID 0 |
17 | 17 | ||
18 | /* | 18 | /** |
19 | * subchannel status word | 19 | * struct scsw - subchannel status word |
20 | * @key: subchannel key | ||
21 | * @sctl: suspend control | ||
22 | * @eswf: esw format | ||
23 | * @cc: deferred condition code | ||
24 | * @fmt: format | ||
25 | * @pfch: prefetch | ||
26 | * @isic: initial-status interruption control | ||
27 | * @alcc: adress-limit checking control | ||
28 | * @ssi: supress-suspended interruption | ||
29 | * @zcc: zero condition code | ||
30 | * @ectl: extended control | ||
31 | * @pno: path not operational | ||
32 | * @res: reserved | ||
33 | * @fctl: function control | ||
34 | * @actl: activity control | ||
35 | * @stctl: status control | ||
36 | * @cpa: channel program address | ||
37 | * @dstat: device status | ||
38 | * @cstat: subchannel status | ||
39 | * @count: residual count | ||
20 | */ | 40 | */ |
21 | struct scsw { | 41 | struct scsw { |
22 | __u32 key : 4; /* subchannel key */ | 42 | __u32 key : 4; |
23 | __u32 sctl : 1; /* suspend control */ | 43 | __u32 sctl : 1; |
24 | __u32 eswf : 1; /* ESW format */ | 44 | __u32 eswf : 1; |
25 | __u32 cc : 2; /* deferred condition code */ | 45 | __u32 cc : 2; |
26 | __u32 fmt : 1; /* format */ | 46 | __u32 fmt : 1; |
27 | __u32 pfch : 1; /* prefetch */ | 47 | __u32 pfch : 1; |
28 | __u32 isic : 1; /* initial-status interruption control */ | 48 | __u32 isic : 1; |
29 | __u32 alcc : 1; /* address-limit checking control */ | 49 | __u32 alcc : 1; |
30 | __u32 ssi : 1; /* supress-suspended interruption */ | 50 | __u32 ssi : 1; |
31 | __u32 zcc : 1; /* zero condition code */ | 51 | __u32 zcc : 1; |
32 | __u32 ectl : 1; /* extended control */ | 52 | __u32 ectl : 1; |
33 | __u32 pno : 1; /* path not operational */ | 53 | __u32 pno : 1; |
34 | __u32 res : 1; /* reserved */ | 54 | __u32 res : 1; |
35 | __u32 fctl : 3; /* function control */ | 55 | __u32 fctl : 3; |
36 | __u32 actl : 7; /* activity control */ | 56 | __u32 actl : 7; |
37 | __u32 stctl : 5; /* status control */ | 57 | __u32 stctl : 5; |
38 | __u32 cpa; /* channel program address */ | 58 | __u32 cpa; |
39 | __u32 dstat : 8; /* device status */ | 59 | __u32 dstat : 8; |
40 | __u32 cstat : 8; /* subchannel status */ | 60 | __u32 cstat : 8; |
41 | __u32 count : 16; /* residual count */ | 61 | __u32 count : 16; |
42 | } __attribute__ ((packed)); | 62 | } __attribute__ ((packed)); |
43 | 63 | ||
44 | #define SCSW_FCTL_CLEAR_FUNC 0x1 | 64 | #define SCSW_FCTL_CLEAR_FUNC 0x1 |
@@ -110,11 +130,22 @@ struct scsw { | |||
110 | #define SNS2_ENV_DATA_PRESENT 0x10 | 130 | #define SNS2_ENV_DATA_PRESENT 0x10 |
111 | #define SNS2_INPRECISE_END 0x04 | 131 | #define SNS2_INPRECISE_END 0x04 |
112 | 132 | ||
133 | /** | ||
134 | * struct ccw1 - channel command word | ||
135 | * @cmd_code: command code | ||
136 | * @flags: flags, like IDA adressing, etc. | ||
137 | * @count: byte count | ||
138 | * @cda: data address | ||
139 | * | ||
140 | * The ccw is the basic structure to build channel programs that perform | ||
141 | * operations with the device or the control unit. Only Format-1 channel | ||
142 | * command words are supported. | ||
143 | */ | ||
113 | struct ccw1 { | 144 | struct ccw1 { |
114 | __u8 cmd_code; /* command code */ | 145 | __u8 cmd_code; |
115 | __u8 flags; /* flags, like IDA addressing, etc. */ | 146 | __u8 flags; |
116 | __u16 count; /* byte count */ | 147 | __u16 count; |
117 | __u32 cda; /* data address */ | 148 | __u32 cda; |
118 | } __attribute__ ((packed,aligned(8))); | 149 | } __attribute__ ((packed,aligned(8))); |
119 | 150 | ||
120 | #define CCW_FLAG_DC 0x80 | 151 | #define CCW_FLAG_DC 0x80 |
@@ -140,102 +171,162 @@ struct ccw1 { | |||
140 | 171 | ||
141 | #define SENSE_MAX_COUNT 0x20 | 172 | #define SENSE_MAX_COUNT 0x20 |
142 | 173 | ||
174 | /** | ||
175 | * struct erw - extended report word | ||
176 | * @res0: reserved | ||
177 | * @auth: authorization check | ||
178 | * @pvrf: path-verification-required flag | ||
179 | * @cpt: channel-path timeout | ||
180 | * @fsavf: failing storage address validity flag | ||
181 | * @cons: concurrent sense | ||
182 | * @scavf: secondary ccw address validity flag | ||
183 | * @fsaf: failing storage address format | ||
184 | * @scnt: sense count, if @cons == %1 | ||
185 | * @res16: reserved | ||
186 | */ | ||
143 | struct erw { | 187 | struct erw { |
144 | __u32 res0 : 3; /* reserved */ | 188 | __u32 res0 : 3; |
145 | __u32 auth : 1; /* Authorization check */ | 189 | __u32 auth : 1; |
146 | __u32 pvrf : 1; /* path-verification-required flag */ | 190 | __u32 pvrf : 1; |
147 | __u32 cpt : 1; /* channel-path timeout */ | 191 | __u32 cpt : 1; |
148 | __u32 fsavf : 1; /* Failing storage address validity flag */ | 192 | __u32 fsavf : 1; |
149 | __u32 cons : 1; /* concurrent-sense */ | 193 | __u32 cons : 1; |
150 | __u32 scavf : 1; /* Secondary ccw address validity flag */ | 194 | __u32 scavf : 1; |
151 | __u32 fsaf : 1; /* Failing storage address format */ | 195 | __u32 fsaf : 1; |
152 | __u32 scnt : 6; /* sense count if cons == 1 */ | 196 | __u32 scnt : 6; |
153 | __u32 res16 : 16; /* reserved */ | 197 | __u32 res16 : 16; |
154 | } __attribute__ ((packed)); | 198 | } __attribute__ ((packed)); |
155 | 199 | ||
156 | /* | 200 | /** |
157 | * subchannel logout area | 201 | * struct sublog - subchannel logout area |
202 | * @res0: reserved | ||
203 | * @esf: extended status flags | ||
204 | * @lpum: last path used mask | ||
205 | * @arep: ancillary report | ||
206 | * @fvf: field-validity flags | ||
207 | * @sacc: storage access code | ||
208 | * @termc: termination code | ||
209 | * @devsc: device-status check | ||
210 | * @serr: secondary error | ||
211 | * @ioerr: i/o-error alert | ||
212 | * @seqc: sequence code | ||
158 | */ | 213 | */ |
159 | struct sublog { | 214 | struct sublog { |
160 | __u32 res0 : 1; /* reserved */ | 215 | __u32 res0 : 1; |
161 | __u32 esf : 7; /* extended status flags */ | 216 | __u32 esf : 7; |
162 | __u32 lpum : 8; /* last path used mask */ | 217 | __u32 lpum : 8; |
163 | __u32 arep : 1; /* ancillary report */ | 218 | __u32 arep : 1; |
164 | __u32 fvf : 5; /* field-validity flags */ | 219 | __u32 fvf : 5; |
165 | __u32 sacc : 2; /* storage access code */ | 220 | __u32 sacc : 2; |
166 | __u32 termc : 2; /* termination code */ | 221 | __u32 termc : 2; |
167 | __u32 devsc : 1; /* device-status check */ | 222 | __u32 devsc : 1; |
168 | __u32 serr : 1; /* secondary error */ | 223 | __u32 serr : 1; |
169 | __u32 ioerr : 1; /* i/o-error alert */ | 224 | __u32 ioerr : 1; |
170 | __u32 seqc : 3; /* sequence code */ | 225 | __u32 seqc : 3; |
171 | } __attribute__ ((packed)); | 226 | } __attribute__ ((packed)); |
172 | 227 | ||
173 | /* | 228 | /** |
174 | * Format 0 Extended Status Word (ESW) | 229 | * struct esw0 - Format 0 Extended Status Word (ESW) |
230 | * @sublog: subchannel logout | ||
231 | * @erw: extended report word | ||
232 | * @faddr: failing storage address | ||
233 | * @saddr: secondary ccw address | ||
175 | */ | 234 | */ |
176 | struct esw0 { | 235 | struct esw0 { |
177 | struct sublog sublog; /* subchannel logout */ | 236 | struct sublog sublog; |
178 | struct erw erw; /* extended report word */ | 237 | struct erw erw; |
179 | __u32 faddr[2]; /* failing storage address */ | 238 | __u32 faddr[2]; |
180 | __u32 saddr; /* secondary ccw address */ | 239 | __u32 saddr; |
181 | } __attribute__ ((packed)); | 240 | } __attribute__ ((packed)); |
182 | 241 | ||
183 | /* | 242 | /** |
184 | * Format 1 Extended Status Word (ESW) | 243 | * struct esw1 - Format 1 Extended Status Word (ESW) |
244 | * @zero0: reserved zeros | ||
245 | * @lpum: last path used mask | ||
246 | * @zero16: reserved zeros | ||
247 | * @erw: extended report word | ||
248 | * @zeros: three fullwords of zeros | ||
185 | */ | 249 | */ |
186 | struct esw1 { | 250 | struct esw1 { |
187 | __u8 zero0; /* reserved zeros */ | 251 | __u8 zero0; |
188 | __u8 lpum; /* last path used mask */ | 252 | __u8 lpum; |
189 | __u16 zero16; /* reserved zeros */ | 253 | __u16 zero16; |
190 | struct erw erw; /* extended report word */ | 254 | struct erw erw; |
191 | __u32 zeros[3]; /* 2 fullwords of zeros */ | 255 | __u32 zeros[3]; |
192 | } __attribute__ ((packed)); | 256 | } __attribute__ ((packed)); |
193 | 257 | ||
194 | /* | 258 | /** |
195 | * Format 2 Extended Status Word (ESW) | 259 | * struct esw2 - Format 2 Extended Status Word (ESW) |
260 | * @zero0: reserved zeros | ||
261 | * @lpum: last path used mask | ||
262 | * @dcti: device-connect-time interval | ||
263 | * @erw: extended report word | ||
264 | * @zeros: three fullwords of zeros | ||
196 | */ | 265 | */ |
197 | struct esw2 { | 266 | struct esw2 { |
198 | __u8 zero0; /* reserved zeros */ | 267 | __u8 zero0; |
199 | __u8 lpum; /* last path used mask */ | 268 | __u8 lpum; |
200 | __u16 dcti; /* device-connect-time interval */ | 269 | __u16 dcti; |
201 | struct erw erw; /* extended report word */ | 270 | struct erw erw; |
202 | __u32 zeros[3]; /* 2 fullwords of zeros */ | 271 | __u32 zeros[3]; |
203 | } __attribute__ ((packed)); | 272 | } __attribute__ ((packed)); |
204 | 273 | ||
205 | /* | 274 | /** |
206 | * Format 3 Extended Status Word (ESW) | 275 | * struct esw3 - Format 3 Extended Status Word (ESW) |
276 | * @zero0: reserved zeros | ||
277 | * @lpum: last path used mask | ||
278 | * @res: reserved | ||
279 | * @erw: extended report word | ||
280 | * @zeros: three fullwords of zeros | ||
207 | */ | 281 | */ |
208 | struct esw3 { | 282 | struct esw3 { |
209 | __u8 zero0; /* reserved zeros */ | 283 | __u8 zero0; |
210 | __u8 lpum; /* last path used mask */ | 284 | __u8 lpum; |
211 | __u16 res; /* reserved */ | 285 | __u16 res; |
212 | struct erw erw; /* extended report word */ | 286 | struct erw erw; |
213 | __u32 zeros[3]; /* 2 fullwords of zeros */ | 287 | __u32 zeros[3]; |
214 | } __attribute__ ((packed)); | 288 | } __attribute__ ((packed)); |
215 | 289 | ||
216 | /* | 290 | /** |
217 | * interruption response block | 291 | * struct irb - interruption response block |
292 | * @scsw: subchannel status word | ||
293 | * @esw: extened status word, 4 formats | ||
294 | * @ecw: extended control word | ||
295 | * | ||
296 | * The irb that is handed to the device driver when an interrupt occurs. For | ||
297 | * solicited interrupts, the common I/O layer already performs checks whether | ||
298 | * a field is valid; a field not being valid is always passed as %0. | ||
299 | * If a unit check occured, @ecw may contain sense data; this is retrieved | ||
300 | * by the common I/O layer itself if the device doesn't support concurrent | ||
301 | * sense (so that the device driver never needs to perform basic sene itself). | ||
302 | * For unsolicited interrupts, the irb is passed as-is (expect for sense data, | ||
303 | * if applicable). | ||
218 | */ | 304 | */ |
219 | struct irb { | 305 | struct irb { |
220 | struct scsw scsw; /* subchannel status word */ | 306 | struct scsw scsw; |
221 | union { /* extended status word, 4 formats */ | 307 | union { |
222 | struct esw0 esw0; | 308 | struct esw0 esw0; |
223 | struct esw1 esw1; | 309 | struct esw1 esw1; |
224 | struct esw2 esw2; | 310 | struct esw2 esw2; |
225 | struct esw3 esw3; | 311 | struct esw3 esw3; |
226 | } esw; | 312 | } esw; |
227 | __u8 ecw[32]; /* extended control word */ | 313 | __u8 ecw[32]; |
228 | } __attribute__ ((packed,aligned(4))); | 314 | } __attribute__ ((packed,aligned(4))); |
229 | 315 | ||
230 | /* | 316 | /** |
231 | * command information word (CIW) layout | 317 | * struct ciw - command information word (CIW) layout |
318 | * @et: entry type | ||
319 | * @reserved: reserved bits | ||
320 | * @ct: command type | ||
321 | * @cmd: command code | ||
322 | * @count: command count | ||
232 | */ | 323 | */ |
233 | struct ciw { | 324 | struct ciw { |
234 | __u32 et : 2; /* entry type */ | 325 | __u32 et : 2; |
235 | __u32 reserved : 2; /* reserved */ | 326 | __u32 reserved : 2; |
236 | __u32 ct : 4; /* command type */ | 327 | __u32 ct : 4; |
237 | __u32 cmd : 8; /* command */ | 328 | __u32 cmd : 8; |
238 | __u32 count : 16; /* coun */ | 329 | __u32 count : 16; |
239 | } __attribute__ ((packed)); | 330 | } __attribute__ ((packed)); |
240 | 331 | ||
241 | #define CIW_TYPE_RCD 0x0 /* read configuration data */ | 332 | #define CIW_TYPE_RCD 0x0 /* read configuration data */ |
@@ -258,11 +349,32 @@ struct ciw { | |||
258 | /* Sick revalidation of device. */ | 349 | /* Sick revalidation of device. */ |
259 | #define CIO_REVALIDATE 0x0008 | 350 | #define CIO_REVALIDATE 0x0008 |
260 | 351 | ||
352 | /** | ||
353 | * struct ccw_dev_id - unique identifier for ccw devices | ||
354 | * @ssid: subchannel set id | ||
355 | * @devno: device number | ||
356 | * | ||
357 | * This structure is not directly based on any hardware structure. The | ||
358 | * hardware identifies a device by its device number and its subchannel, | ||
359 | * which is in turn identified by its id. In order to get a unique identifier | ||
360 | * for ccw devices across subchannel sets, @struct ccw_dev_id has been | ||
361 | * introduced. | ||
362 | */ | ||
261 | struct ccw_dev_id { | 363 | struct ccw_dev_id { |
262 | u8 ssid; | 364 | u8 ssid; |
263 | u16 devno; | 365 | u16 devno; |
264 | }; | 366 | }; |
265 | 367 | ||
368 | /** | ||
369 | * ccw_device_id_is_equal() - compare two ccw_dev_ids | ||
370 | * @dev_id1: a ccw_dev_id | ||
371 | * @dev_id2: another ccw_dev_id | ||
372 | * Returns: | ||
373 | * %1 if the two structures are equal field-by-field, | ||
374 | * %0 if not. | ||
375 | * Context: | ||
376 | * any | ||
377 | */ | ||
266 | static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, | 378 | static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, |
267 | struct ccw_dev_id *dev_id2) | 379 | struct ccw_dev_id *dev_id2) |
268 | { | 380 | { |