2 * Copyright IBM Corp. 2002, 2009
4 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
5 * Cornelia Huck (cornelia.huck@de.ibm.com)
7 #include <linux/module.h>
8 #include <linux/init.h>
9 #include <linux/errno.h>
10 #include <linux/slab.h>
11 #include <linux/list.h>
12 #include <linux/device.h>
13 #include <linux/delay.h>
14 #include <linux/completion.h>
16 #include <asm/ccwdev.h>
17 #include <asm/idals.h>
18 #include <asm/chpid.h>
22 #include "cio_debug.h"
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
33 * All flags specified in @flags are set, all flags not specified in @flags
36 * %0 on success, -%EINVAL on an invalid flag combination.
38 int ccw_device_set_options_mask(struct ccw_device
*cdev
, unsigned long flags
)
41 * The flag usage is mutal exclusive ...
43 if ((flags
& CCWDEV_EARLY_NOTIFICATION
) &&
44 (flags
& CCWDEV_REPORT_ALL
))
46 cdev
->private->options
.fast
= (flags
& CCWDEV_EARLY_NOTIFICATION
) != 0;
47 cdev
->private->options
.repall
= (flags
& CCWDEV_REPORT_ALL
) != 0;
48 cdev
->private->options
.pgroup
= (flags
& CCWDEV_DO_PATHGROUP
) != 0;
49 cdev
->private->options
.force
= (flags
& CCWDEV_ALLOW_FORCE
) != 0;
50 cdev
->private->options
.mpath
= (flags
& CCWDEV_DO_MULTIPATH
) != 0;
55 * ccw_device_set_options() - set some options
56 * @cdev: device for which the options are to be set
57 * @flags: options to be set
59 * All flags specified in @flags are set, the remainder is left untouched.
61 * %0 on success, -%EINVAL if an invalid flag combination would ensue.
63 int ccw_device_set_options(struct ccw_device
*cdev
, unsigned long flags
)
66 * The flag usage is mutal exclusive ...
68 if (((flags
& CCWDEV_EARLY_NOTIFICATION
) &&
69 (flags
& CCWDEV_REPORT_ALL
)) ||
70 ((flags
& CCWDEV_EARLY_NOTIFICATION
) &&
71 cdev
->private->options
.repall
) ||
72 ((flags
& CCWDEV_REPORT_ALL
) &&
73 cdev
->private->options
.fast
))
75 cdev
->private->options
.fast
|= (flags
& CCWDEV_EARLY_NOTIFICATION
) != 0;
76 cdev
->private->options
.repall
|= (flags
& CCWDEV_REPORT_ALL
) != 0;
77 cdev
->private->options
.pgroup
|= (flags
& CCWDEV_DO_PATHGROUP
) != 0;
78 cdev
->private->options
.force
|= (flags
& CCWDEV_ALLOW_FORCE
) != 0;
79 cdev
->private->options
.mpath
|= (flags
& CCWDEV_DO_MULTIPATH
) != 0;
84 * ccw_device_clear_options() - clear some options
85 * @cdev: device for which the options are to be cleared
86 * @flags: options to be cleared
88 * All flags specified in @flags are cleared, the remainder is left untouched.
90 void ccw_device_clear_options(struct ccw_device
*cdev
, unsigned long flags
)
92 cdev
->private->options
.fast
&= (flags
& CCWDEV_EARLY_NOTIFICATION
) == 0;
93 cdev
->private->options
.repall
&= (flags
& CCWDEV_REPORT_ALL
) == 0;
94 cdev
->private->options
.pgroup
&= (flags
& CCWDEV_DO_PATHGROUP
) == 0;
95 cdev
->private->options
.force
&= (flags
& CCWDEV_ALLOW_FORCE
) == 0;
96 cdev
->private->options
.mpath
&= (flags
& CCWDEV_DO_MULTIPATH
) == 0;
100 * ccw_device_is_pathgroup - determine if paths to this device are grouped
103 * Return non-zero if there is a path group, zero otherwise.
105 int ccw_device_is_pathgroup(struct ccw_device
*cdev
)
107 return cdev
->private->flags
.pgroup
;
109 EXPORT_SYMBOL(ccw_device_is_pathgroup
);
112 * ccw_device_is_multipath - determine if device is operating in multipath mode
115 * Return non-zero if device is operating in multipath mode, zero otherwise.
117 int ccw_device_is_multipath(struct ccw_device
*cdev
)
119 return cdev
->private->flags
.mpath
;
121 EXPORT_SYMBOL(ccw_device_is_multipath
);
124 * ccw_device_clear() - terminate I/O request processing
125 * @cdev: target ccw device
126 * @intparm: interruption parameter; value is only used if no I/O is
127 * outstanding, otherwise the intparm associated with the I/O request
130 * ccw_device_clear() calls csch on @cdev's subchannel.
133 * -%ENODEV on device not operational,
134 * -%EINVAL on invalid device state.
136 * Interrupts disabled, ccw device lock held
138 int ccw_device_clear(struct ccw_device
*cdev
, unsigned long intparm
)
140 struct subchannel
*sch
;
143 if (!cdev
|| !cdev
->dev
.parent
)
145 sch
= to_subchannel(cdev
->dev
.parent
);
146 if (!sch
->schib
.pmcw
.ena
)
148 if (cdev
->private->state
== DEV_STATE_NOT_OPER
)
150 if (cdev
->private->state
!= DEV_STATE_ONLINE
&&
151 cdev
->private->state
!= DEV_STATE_W4SENSE
)
154 ret
= cio_clear(sch
);
156 cdev
->private->intparm
= intparm
;
161 * ccw_device_start_key() - start a s390 channel program with key
162 * @cdev: target ccw device
163 * @cpa: logical start address of channel program
164 * @intparm: user specific interruption parameter; will be presented back to
165 * @cdev's interrupt handler. Allows a device driver to associate
166 * the interrupt with a particular I/O request.
167 * @lpm: defines the channel path to be used for a specific I/O request. A
168 * value of 0 will make cio use the opm.
169 * @key: storage key to be used for the I/O
170 * @flags: additional flags; defines the action to be performed for I/O
173 * Start a S/390 channel program. When the interrupt arrives, the
174 * IRQ handler is called, either immediately, delayed (dev-end missing,
175 * or sense required) or never (no IRQ handler registered).
177 * %0, if the operation was successful;
178 * -%EBUSY, if the device is busy, or status pending;
179 * -%EACCES, if no path specified in @lpm is operational;
180 * -%ENODEV, if the device is not operational.
182 * Interrupts disabled, ccw device lock held
184 int ccw_device_start_key(struct ccw_device
*cdev
, struct ccw1
*cpa
,
185 unsigned long intparm
, __u8 lpm
, __u8 key
,
188 struct subchannel
*sch
;
191 if (!cdev
|| !cdev
->dev
.parent
)
193 sch
= to_subchannel(cdev
->dev
.parent
);
194 if (!sch
->schib
.pmcw
.ena
)
196 if (cdev
->private->state
== DEV_STATE_NOT_OPER
)
198 if (cdev
->private->state
== DEV_STATE_VERIFY
) {
199 /* Remember to fake irb when finished. */
200 if (!cdev
->private->flags
.fake_irb
) {
201 cdev
->private->flags
.fake_irb
= 1;
202 cdev
->private->intparm
= intparm
;
205 /* There's already a fake I/O around. */
208 if (cdev
->private->state
!= DEV_STATE_ONLINE
||
209 ((sch
->schib
.scsw
.cmd
.stctl
& SCSW_STCTL_PRIM_STATUS
) &&
210 !(sch
->schib
.scsw
.cmd
.stctl
& SCSW_STCTL_SEC_STATUS
)) ||
211 cdev
->private->flags
.doverify
)
213 ret
= cio_set_options (sch
, flags
);
216 /* Adjust requested path mask to excluded varied off paths. */
222 ret
= cio_start_key (sch
, cpa
, lpm
, key
);
225 cdev
->private->intparm
= intparm
;
229 dev_fsm_event(cdev
, DEV_EVENT_VERIFY
);
236 * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key
237 * @cdev: target ccw device
238 * @cpa: logical start address of channel program
239 * @intparm: user specific interruption parameter; will be presented back to
240 * @cdev's interrupt handler. Allows a device driver to associate
241 * the interrupt with a particular I/O request.
242 * @lpm: defines the channel path to be used for a specific I/O request. A
243 * value of 0 will make cio use the opm.
244 * @key: storage key to be used for the I/O
245 * @flags: additional flags; defines the action to be performed for I/O
247 * @expires: timeout value in jiffies
249 * Start a S/390 channel program. When the interrupt arrives, the
250 * IRQ handler is called, either immediately, delayed (dev-end missing,
251 * or sense required) or never (no IRQ handler registered).
252 * This function notifies the device driver if the channel program has not
253 * completed during the time specified by @expires. If a timeout occurs, the
254 * channel program is terminated via xsch, hsch or csch, and the device's
255 * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
257 * %0, if the operation was successful;
258 * -%EBUSY, if the device is busy, or status pending;
259 * -%EACCES, if no path specified in @lpm is operational;
260 * -%ENODEV, if the device is not operational.
262 * Interrupts disabled, ccw device lock held
264 int ccw_device_start_timeout_key(struct ccw_device
*cdev
, struct ccw1
*cpa
,
265 unsigned long intparm
, __u8 lpm
, __u8 key
,
266 unsigned long flags
, int expires
)
272 ccw_device_set_timeout(cdev
, expires
);
273 ret
= ccw_device_start_key(cdev
, cpa
, intparm
, lpm
, key
, flags
);
275 ccw_device_set_timeout(cdev
, 0);
280 * ccw_device_start() - start a s390 channel program
281 * @cdev: target ccw device
282 * @cpa: logical start address of channel program
283 * @intparm: user specific interruption parameter; will be presented back to
284 * @cdev's interrupt handler. Allows a device driver to associate
285 * the interrupt with a particular I/O request.
286 * @lpm: defines the channel path to be used for a specific I/O request. A
287 * value of 0 will make cio use the opm.
288 * @flags: additional flags; defines the action to be performed for I/O
291 * Start a S/390 channel program. When the interrupt arrives, the
292 * IRQ handler is called, either immediately, delayed (dev-end missing,
293 * or sense required) or never (no IRQ handler registered).
295 * %0, if the operation was successful;
296 * -%EBUSY, if the device is busy, or status pending;
297 * -%EACCES, if no path specified in @lpm is operational;
298 * -%ENODEV, if the device is not operational.
300 * Interrupts disabled, ccw device lock held
302 int ccw_device_start(struct ccw_device
*cdev
, struct ccw1
*cpa
,
303 unsigned long intparm
, __u8 lpm
, unsigned long flags
)
305 return ccw_device_start_key(cdev
, cpa
, intparm
, lpm
,
306 PAGE_DEFAULT_KEY
, flags
);
310 * ccw_device_start_timeout() - start a s390 channel program with timeout
311 * @cdev: target ccw device
312 * @cpa: logical start address of channel program
313 * @intparm: user specific interruption parameter; will be presented back to
314 * @cdev's interrupt handler. Allows a device driver to associate
315 * the interrupt with a particular I/O request.
316 * @lpm: defines the channel path to be used for a specific I/O request. A
317 * value of 0 will make cio use the opm.
318 * @flags: additional flags; defines the action to be performed for I/O
320 * @expires: timeout value in jiffies
322 * Start a S/390 channel program. When the interrupt arrives, the
323 * IRQ handler is called, either immediately, delayed (dev-end missing,
324 * or sense required) or never (no IRQ handler registered).
325 * This function notifies the device driver if the channel program has not
326 * completed during the time specified by @expires. If a timeout occurs, the
327 * channel program is terminated via xsch, hsch or csch, and the device's
328 * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT).
330 * %0, if the operation was successful;
331 * -%EBUSY, if the device is busy, or status pending;
332 * -%EACCES, if no path specified in @lpm is operational;
333 * -%ENODEV, if the device is not operational.
335 * Interrupts disabled, ccw device lock held
337 int ccw_device_start_timeout(struct ccw_device
*cdev
, struct ccw1
*cpa
,
338 unsigned long intparm
, __u8 lpm
,
339 unsigned long flags
, int expires
)
341 return ccw_device_start_timeout_key(cdev
, cpa
, intparm
, lpm
,
342 PAGE_DEFAULT_KEY
, flags
,
348 * ccw_device_halt() - halt I/O request processing
349 * @cdev: target ccw device
350 * @intparm: interruption parameter; value is only used if no I/O is
351 * outstanding, otherwise the intparm associated with the I/O request
354 * ccw_device_halt() calls hsch on @cdev's subchannel.
357 * -%ENODEV on device not operational,
358 * -%EINVAL on invalid device state,
359 * -%EBUSY on device busy or interrupt pending.
361 * Interrupts disabled, ccw device lock held
363 int ccw_device_halt(struct ccw_device
*cdev
, unsigned long intparm
)
365 struct subchannel
*sch
;
368 if (!cdev
|| !cdev
->dev
.parent
)
370 sch
= to_subchannel(cdev
->dev
.parent
);
371 if (!sch
->schib
.pmcw
.ena
)
373 if (cdev
->private->state
== DEV_STATE_NOT_OPER
)
375 if (cdev
->private->state
!= DEV_STATE_ONLINE
&&
376 cdev
->private->state
!= DEV_STATE_W4SENSE
)
381 cdev
->private->intparm
= intparm
;
386 * ccw_device_resume() - resume channel program execution
387 * @cdev: target ccw device
389 * ccw_device_resume() calls rsch on @cdev's subchannel.
392 * -%ENODEV on device not operational,
393 * -%EINVAL on invalid device state,
394 * -%EBUSY on device busy or interrupt pending.
396 * Interrupts disabled, ccw device lock held
398 int ccw_device_resume(struct ccw_device
*cdev
)
400 struct subchannel
*sch
;
402 if (!cdev
|| !cdev
->dev
.parent
)
404 sch
= to_subchannel(cdev
->dev
.parent
);
405 if (!sch
->schib
.pmcw
.ena
)
407 if (cdev
->private->state
== DEV_STATE_NOT_OPER
)
409 if (cdev
->private->state
!= DEV_STATE_ONLINE
||
410 !(sch
->schib
.scsw
.cmd
.actl
& SCSW_ACTL_SUSPENDED
))
412 return cio_resume(sch
);
416 * Pass interrupt to device driver.
419 ccw_device_call_handler(struct ccw_device
*cdev
)
421 struct subchannel
*sch
;
425 sch
= to_subchannel(cdev
->dev
.parent
);
428 * we allow for the device action handler if .
429 * - we received ending status
430 * - the action handler requested to see all interrupts
431 * - we received an intermediate status
432 * - fast notification was requested (primary status)
433 * - unsolicited interrupts
435 stctl
= scsw_stctl(&cdev
->private->irb
.scsw
);
436 ending_status
= (stctl
& SCSW_STCTL_SEC_STATUS
) ||
437 (stctl
== (SCSW_STCTL_ALERT_STATUS
| SCSW_STCTL_STATUS_PEND
)) ||
438 (stctl
== SCSW_STCTL_STATUS_PEND
);
439 if (!ending_status
&&
440 !cdev
->private->options
.repall
&&
441 !(stctl
& SCSW_STCTL_INTER_STATUS
) &&
442 !(cdev
->private->options
.fast
&&
443 (stctl
& SCSW_STCTL_PRIM_STATUS
)))
446 /* Clear pending timers for device driver initiated I/O. */
448 ccw_device_set_timeout(cdev
, 0);
450 * Now we are ready to call the device driver interrupt handler.
453 cdev
->handler(cdev
, cdev
->private->intparm
,
454 &cdev
->private->irb
);
457 * Clear the old and now useless interrupt response block.
459 memset(&cdev
->private->irb
, 0, sizeof(struct irb
));
465 * ccw_device_get_ciw() - Search for CIW command in extended sense data.
466 * @cdev: ccw device to inspect
467 * @ct: command type to look for
469 * During SenseID, command information words (CIWs) describing special
470 * commands available to the device may have been stored in the extended
471 * sense data. This function searches for CIWs of a specified command
472 * type in the extended sense data.
474 * %NULL if no extended sense data has been stored or if no CIW of the
475 * specified command type could be found,
476 * else a pointer to the CIW of the specified command type.
478 struct ciw
*ccw_device_get_ciw(struct ccw_device
*cdev
, __u32 ct
)
482 if (cdev
->private->flags
.esid
== 0)
484 for (ciw_cnt
= 0; ciw_cnt
< MAX_CIWS
; ciw_cnt
++)
485 if (cdev
->private->senseid
.ciw
[ciw_cnt
].ct
== ct
)
486 return cdev
->private->senseid
.ciw
+ ciw_cnt
;
491 * ccw_device_get_path_mask() - get currently available paths
492 * @cdev: ccw device to be queried
494 * %0 if no subchannel for the device is available,
495 * else the mask of currently available paths for the ccw device's subchannel.
497 __u8
ccw_device_get_path_mask(struct ccw_device
*cdev
)
499 struct subchannel
*sch
;
501 if (!cdev
->dev
.parent
)
504 sch
= to_subchannel(cdev
->dev
.parent
);
509 struct completion done
;
513 void ccw_device_stlck_done(struct ccw_device
*cdev
, void *data
, int rc
)
515 struct stlck_data
*sdata
= data
;
518 complete(&sdata
->done
);
522 * Perform unconditional reserve + release.
524 int ccw_device_stlck(struct ccw_device
*cdev
)
526 struct subchannel
*sch
= to_subchannel(cdev
->dev
.parent
);
527 struct stlck_data data
;
531 /* Check if steal lock operation is valid for this device. */
533 if (!cdev
->private->options
.force
)
536 buffer
= kzalloc(64, GFP_DMA
| GFP_KERNEL
);
539 init_completion(&data
.done
);
541 spin_lock_irq(sch
->lock
);
542 rc
= cio_enable_subchannel(sch
, (u32
) (addr_t
) sch
);
545 /* Perform operation. */
546 cdev
->private->state
= DEV_STATE_STEAL_LOCK
,
547 ccw_device_stlck_start(cdev
, &data
, &buffer
[0], &buffer
[32]);
548 spin_unlock_irq(sch
->lock
);
549 /* Wait for operation to finish. */
550 if (wait_for_completion_interruptible(&data
.done
)) {
552 spin_lock_irq(sch
->lock
);
553 ccw_request_cancel(cdev
);
554 spin_unlock_irq(sch
->lock
);
555 wait_for_completion(&data
.done
);
559 spin_lock_irq(sch
->lock
);
560 cio_disable_subchannel(sch
);
561 cdev
->private->state
= DEV_STATE_BOXED
;
563 spin_unlock_irq(sch
->lock
);
569 void *ccw_device_get_chp_desc(struct ccw_device
*cdev
, int chp_no
)
571 struct subchannel
*sch
;
574 sch
= to_subchannel(cdev
->dev
.parent
);
576 chpid
.id
= sch
->schib
.pmcw
.chpid
[chp_no
];
577 return chp_get_chp_desc(chpid
);
581 * ccw_device_get_id - obtain a ccw device id
582 * @cdev: device to obtain the id for
583 * @dev_id: where to fill in the values
585 void ccw_device_get_id(struct ccw_device
*cdev
, struct ccw_dev_id
*dev_id
)
587 *dev_id
= cdev
->private->dev_id
;
589 EXPORT_SYMBOL(ccw_device_get_id
);
592 * ccw_device_tm_start_key - perform start function
593 * @cdev: ccw device on which to perform the start function
594 * @tcw: transport-command word to be started
595 * @intparm: user defined parameter to be passed to the interrupt handler
596 * @lpm: mask of paths to use
597 * @key: storage key to use for storage access
599 * Start the tcw on the given ccw device. Return zero on success, non-zero
602 int ccw_device_tm_start_key(struct ccw_device
*cdev
, struct tcw
*tcw
,
603 unsigned long intparm
, u8 lpm
, u8 key
)
605 struct subchannel
*sch
;
608 sch
= to_subchannel(cdev
->dev
.parent
);
609 if (!sch
->schib
.pmcw
.ena
)
611 if (cdev
->private->state
!= DEV_STATE_ONLINE
)
613 /* Adjust requested path mask to excluded varied off paths. */
619 rc
= cio_tm_start_key(sch
, tcw
, lpm
, key
);
621 cdev
->private->intparm
= intparm
;
624 EXPORT_SYMBOL(ccw_device_tm_start_key
);
627 * ccw_device_tm_start_timeout_key - perform start function
628 * @cdev: ccw device on which to perform the start function
629 * @tcw: transport-command word to be started
630 * @intparm: user defined parameter to be passed to the interrupt handler
631 * @lpm: mask of paths to use
632 * @key: storage key to use for storage access
633 * @expires: time span in jiffies after which to abort request
635 * Start the tcw on the given ccw device. Return zero on success, non-zero
638 int ccw_device_tm_start_timeout_key(struct ccw_device
*cdev
, struct tcw
*tcw
,
639 unsigned long intparm
, u8 lpm
, u8 key
,
644 ccw_device_set_timeout(cdev
, expires
);
645 ret
= ccw_device_tm_start_key(cdev
, tcw
, intparm
, lpm
, key
);
647 ccw_device_set_timeout(cdev
, 0);
650 EXPORT_SYMBOL(ccw_device_tm_start_timeout_key
);
653 * ccw_device_tm_start - perform start function
654 * @cdev: ccw device on which to perform the start function
655 * @tcw: transport-command word to be started
656 * @intparm: user defined parameter to be passed to the interrupt handler
657 * @lpm: mask of paths to use
659 * Start the tcw on the given ccw device. Return zero on success, non-zero
662 int ccw_device_tm_start(struct ccw_device
*cdev
, struct tcw
*tcw
,
663 unsigned long intparm
, u8 lpm
)
665 return ccw_device_tm_start_key(cdev
, tcw
, intparm
, lpm
,
668 EXPORT_SYMBOL(ccw_device_tm_start
);
671 * ccw_device_tm_start_timeout - perform start function
672 * @cdev: ccw device on which to perform the start function
673 * @tcw: transport-command word to be started
674 * @intparm: user defined parameter to be passed to the interrupt handler
675 * @lpm: mask of paths to use
676 * @expires: time span in jiffies after which to abort request
678 * Start the tcw on the given ccw device. Return zero on success, non-zero
681 int ccw_device_tm_start_timeout(struct ccw_device
*cdev
, struct tcw
*tcw
,
682 unsigned long intparm
, u8 lpm
, int expires
)
684 return ccw_device_tm_start_timeout_key(cdev
, tcw
, intparm
, lpm
,
685 PAGE_DEFAULT_KEY
, expires
);
687 EXPORT_SYMBOL(ccw_device_tm_start_timeout
);
690 * ccw_device_tm_intrg - perform interrogate function
691 * @cdev: ccw device on which to perform the interrogate function
693 * Perform an interrogate function on the given ccw device. Return zero on
694 * success, non-zero otherwise.
696 int ccw_device_tm_intrg(struct ccw_device
*cdev
)
698 struct subchannel
*sch
= to_subchannel(cdev
->dev
.parent
);
700 if (!sch
->schib
.pmcw
.ena
)
702 if (cdev
->private->state
!= DEV_STATE_ONLINE
)
704 if (!scsw_is_tm(&sch
->schib
.scsw
) ||
705 !(scsw_actl(&sch
->schib
.scsw
) & SCSW_ACTL_START_PEND
))
707 return cio_tm_intrg(sch
);
709 EXPORT_SYMBOL(ccw_device_tm_intrg
);
711 // FIXME: these have to go:
714 _ccw_device_get_subchannel_number(struct ccw_device
*cdev
)
716 return cdev
->private->schid
.sch_no
;
720 MODULE_LICENSE("GPL");
721 EXPORT_SYMBOL(ccw_device_set_options_mask
);
722 EXPORT_SYMBOL(ccw_device_set_options
);
723 EXPORT_SYMBOL(ccw_device_clear_options
);
724 EXPORT_SYMBOL(ccw_device_clear
);
725 EXPORT_SYMBOL(ccw_device_halt
);
726 EXPORT_SYMBOL(ccw_device_resume
);
727 EXPORT_SYMBOL(ccw_device_start_timeout
);
728 EXPORT_SYMBOL(ccw_device_start
);
729 EXPORT_SYMBOL(ccw_device_start_timeout_key
);
730 EXPORT_SYMBOL(ccw_device_start_key
);
731 EXPORT_SYMBOL(ccw_device_get_ciw
);
732 EXPORT_SYMBOL(ccw_device_get_path_mask
);
733 EXPORT_SYMBOL(_ccw_device_get_subchannel_number
);
734 EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc
);