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
)
425 * we allow for the device action handler if .
426 * - we received ending status
427 * - the action handler requested to see all interrupts
428 * - we received an intermediate status
429 * - fast notification was requested (primary status)
430 * - unsolicited interrupts
432 stctl
= scsw_stctl(&cdev
->private->irb
.scsw
);
433 ending_status
= (stctl
& SCSW_STCTL_SEC_STATUS
) ||
434 (stctl
== (SCSW_STCTL_ALERT_STATUS
| SCSW_STCTL_STATUS_PEND
)) ||
435 (stctl
== SCSW_STCTL_STATUS_PEND
);
436 if (!ending_status
&&
437 !cdev
->private->options
.repall
&&
438 !(stctl
& SCSW_STCTL_INTER_STATUS
) &&
439 !(cdev
->private->options
.fast
&&
440 (stctl
& SCSW_STCTL_PRIM_STATUS
)))
443 /* Clear pending timers for device driver initiated I/O. */
445 ccw_device_set_timeout(cdev
, 0);
447 * Now we are ready to call the device driver interrupt handler.
450 cdev
->handler(cdev
, cdev
->private->intparm
,
451 &cdev
->private->irb
);
454 * Clear the old and now useless interrupt response block.
456 memset(&cdev
->private->irb
, 0, sizeof(struct irb
));
462 * ccw_device_get_ciw() - Search for CIW command in extended sense data.
463 * @cdev: ccw device to inspect
464 * @ct: command type to look for
466 * During SenseID, command information words (CIWs) describing special
467 * commands available to the device may have been stored in the extended
468 * sense data. This function searches for CIWs of a specified command
469 * type in the extended sense data.
471 * %NULL if no extended sense data has been stored or if no CIW of the
472 * specified command type could be found,
473 * else a pointer to the CIW of the specified command type.
475 struct ciw
*ccw_device_get_ciw(struct ccw_device
*cdev
, __u32 ct
)
479 if (cdev
->private->flags
.esid
== 0)
481 for (ciw_cnt
= 0; ciw_cnt
< MAX_CIWS
; ciw_cnt
++)
482 if (cdev
->private->senseid
.ciw
[ciw_cnt
].ct
== ct
)
483 return cdev
->private->senseid
.ciw
+ ciw_cnt
;
488 * ccw_device_get_path_mask() - get currently available paths
489 * @cdev: ccw device to be queried
491 * %0 if no subchannel for the device is available,
492 * else the mask of currently available paths for the ccw device's subchannel.
494 __u8
ccw_device_get_path_mask(struct ccw_device
*cdev
)
496 struct subchannel
*sch
;
498 if (!cdev
->dev
.parent
)
501 sch
= to_subchannel(cdev
->dev
.parent
);
506 struct completion done
;
510 void ccw_device_stlck_done(struct ccw_device
*cdev
, void *data
, int rc
)
512 struct stlck_data
*sdata
= data
;
515 complete(&sdata
->done
);
519 * Perform unconditional reserve + release.
521 int ccw_device_stlck(struct ccw_device
*cdev
)
523 struct subchannel
*sch
= to_subchannel(cdev
->dev
.parent
);
524 struct stlck_data data
;
528 /* Check if steal lock operation is valid for this device. */
530 if (!cdev
->private->options
.force
)
533 buffer
= kzalloc(64, GFP_DMA
| GFP_KERNEL
);
536 init_completion(&data
.done
);
538 spin_lock_irq(sch
->lock
);
539 rc
= cio_enable_subchannel(sch
, (u32
) (addr_t
) sch
);
542 /* Perform operation. */
543 cdev
->private->state
= DEV_STATE_STEAL_LOCK
,
544 ccw_device_stlck_start(cdev
, &data
, &buffer
[0], &buffer
[32]);
545 spin_unlock_irq(sch
->lock
);
546 /* Wait for operation to finish. */
547 if (wait_for_completion_interruptible(&data
.done
)) {
549 spin_lock_irq(sch
->lock
);
550 ccw_request_cancel(cdev
);
551 spin_unlock_irq(sch
->lock
);
552 wait_for_completion(&data
.done
);
556 spin_lock_irq(sch
->lock
);
557 cio_disable_subchannel(sch
);
558 cdev
->private->state
= DEV_STATE_BOXED
;
560 spin_unlock_irq(sch
->lock
);
566 void *ccw_device_get_chp_desc(struct ccw_device
*cdev
, int chp_no
)
568 struct subchannel
*sch
;
571 sch
= to_subchannel(cdev
->dev
.parent
);
573 chpid
.id
= sch
->schib
.pmcw
.chpid
[chp_no
];
574 return chp_get_chp_desc(chpid
);
578 * ccw_device_get_id - obtain a ccw device id
579 * @cdev: device to obtain the id for
580 * @dev_id: where to fill in the values
582 void ccw_device_get_id(struct ccw_device
*cdev
, struct ccw_dev_id
*dev_id
)
584 *dev_id
= cdev
->private->dev_id
;
586 EXPORT_SYMBOL(ccw_device_get_id
);
589 * ccw_device_tm_start_key - perform start function
590 * @cdev: ccw device on which to perform the start function
591 * @tcw: transport-command word to be started
592 * @intparm: user defined parameter to be passed to the interrupt handler
593 * @lpm: mask of paths to use
594 * @key: storage key to use for storage access
596 * Start the tcw on the given ccw device. Return zero on success, non-zero
599 int ccw_device_tm_start_key(struct ccw_device
*cdev
, struct tcw
*tcw
,
600 unsigned long intparm
, u8 lpm
, u8 key
)
602 struct subchannel
*sch
;
605 sch
= to_subchannel(cdev
->dev
.parent
);
606 if (!sch
->schib
.pmcw
.ena
)
608 if (cdev
->private->state
!= DEV_STATE_ONLINE
)
610 /* Adjust requested path mask to excluded varied off paths. */
616 rc
= cio_tm_start_key(sch
, tcw
, lpm
, key
);
618 cdev
->private->intparm
= intparm
;
621 EXPORT_SYMBOL(ccw_device_tm_start_key
);
624 * ccw_device_tm_start_timeout_key - perform start function
625 * @cdev: ccw device on which to perform the start function
626 * @tcw: transport-command word to be started
627 * @intparm: user defined parameter to be passed to the interrupt handler
628 * @lpm: mask of paths to use
629 * @key: storage key to use for storage access
630 * @expires: time span in jiffies after which to abort request
632 * Start the tcw on the given ccw device. Return zero on success, non-zero
635 int ccw_device_tm_start_timeout_key(struct ccw_device
*cdev
, struct tcw
*tcw
,
636 unsigned long intparm
, u8 lpm
, u8 key
,
641 ccw_device_set_timeout(cdev
, expires
);
642 ret
= ccw_device_tm_start_key(cdev
, tcw
, intparm
, lpm
, key
);
644 ccw_device_set_timeout(cdev
, 0);
647 EXPORT_SYMBOL(ccw_device_tm_start_timeout_key
);
650 * ccw_device_tm_start - perform start function
651 * @cdev: ccw device on which to perform the start function
652 * @tcw: transport-command word to be started
653 * @intparm: user defined parameter to be passed to the interrupt handler
654 * @lpm: mask of paths to use
656 * Start the tcw on the given ccw device. Return zero on success, non-zero
659 int ccw_device_tm_start(struct ccw_device
*cdev
, struct tcw
*tcw
,
660 unsigned long intparm
, u8 lpm
)
662 return ccw_device_tm_start_key(cdev
, tcw
, intparm
, lpm
,
665 EXPORT_SYMBOL(ccw_device_tm_start
);
668 * ccw_device_tm_start_timeout - perform start function
669 * @cdev: ccw device on which to perform the start function
670 * @tcw: transport-command word to be started
671 * @intparm: user defined parameter to be passed to the interrupt handler
672 * @lpm: mask of paths to use
673 * @expires: time span in jiffies after which to abort request
675 * Start the tcw on the given ccw device. Return zero on success, non-zero
678 int ccw_device_tm_start_timeout(struct ccw_device
*cdev
, struct tcw
*tcw
,
679 unsigned long intparm
, u8 lpm
, int expires
)
681 return ccw_device_tm_start_timeout_key(cdev
, tcw
, intparm
, lpm
,
682 PAGE_DEFAULT_KEY
, expires
);
684 EXPORT_SYMBOL(ccw_device_tm_start_timeout
);
687 * ccw_device_get_mdc - accumulate max data count
688 * @cdev: ccw device for which the max data count is accumulated
689 * @mask: mask of paths to use
691 * Return the number of 64K-bytes blocks all paths at least support
692 * for a transport command. Return values <= 0 indicate failures.
694 int ccw_device_get_mdc(struct ccw_device
*cdev
, u8 mask
)
696 struct subchannel
*sch
= to_subchannel(cdev
->dev
.parent
);
697 struct channel_path_desc_fmt1 desc
;
701 /* Adjust requested path mask to excluded varied off paths. */
708 for (i
= 0; i
< 8; i
++) {
709 if (!(mask
& (0x80 >> i
)))
711 chpid
.id
= sch
->schib
.pmcw
.chpid
[i
];
712 ret
= chsc_determine_fmt1_channel_path_desc(chpid
, &desc
);
719 mdc
= mdc
? min(mdc
, (int)desc
.mdc
) : desc
.mdc
;
724 EXPORT_SYMBOL(ccw_device_get_mdc
);
727 * ccw_device_tm_intrg - perform interrogate function
728 * @cdev: ccw device on which to perform the interrogate function
730 * Perform an interrogate function on the given ccw device. Return zero on
731 * success, non-zero otherwise.
733 int ccw_device_tm_intrg(struct ccw_device
*cdev
)
735 struct subchannel
*sch
= to_subchannel(cdev
->dev
.parent
);
737 if (!sch
->schib
.pmcw
.ena
)
739 if (cdev
->private->state
!= DEV_STATE_ONLINE
)
741 if (!scsw_is_tm(&sch
->schib
.scsw
) ||
742 !(scsw_actl(&sch
->schib
.scsw
) & SCSW_ACTL_START_PEND
))
744 return cio_tm_intrg(sch
);
746 EXPORT_SYMBOL(ccw_device_tm_intrg
);
748 // FIXME: these have to go:
751 _ccw_device_get_subchannel_number(struct ccw_device
*cdev
)
753 return cdev
->private->schid
.sch_no
;
757 MODULE_LICENSE("GPL");
758 EXPORT_SYMBOL(ccw_device_set_options_mask
);
759 EXPORT_SYMBOL(ccw_device_set_options
);
760 EXPORT_SYMBOL(ccw_device_clear_options
);
761 EXPORT_SYMBOL(ccw_device_clear
);
762 EXPORT_SYMBOL(ccw_device_halt
);
763 EXPORT_SYMBOL(ccw_device_resume
);
764 EXPORT_SYMBOL(ccw_device_start_timeout
);
765 EXPORT_SYMBOL(ccw_device_start
);
766 EXPORT_SYMBOL(ccw_device_start_timeout_key
);
767 EXPORT_SYMBOL(ccw_device_start_key
);
768 EXPORT_SYMBOL(ccw_device_get_ciw
);
769 EXPORT_SYMBOL(ccw_device_get_path_mask
);
770 EXPORT_SYMBOL(_ccw_device_get_subchannel_number
);
771 EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc
);