← Documents Documentation/arch/s390/cds.rst GitHub 원문 ↗

Linux 6.18.37 · Architecture

Linux for S/390 and zSeries Common Device Support

S/390 CDS의 ccw_device I/O 시작·재개·중단·clear API, 상태 비트, 잠금과 중첩 I/O 규칙을 설명합니다.

Source pathDocumentation/arch/s390/cds.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

cds.rst:1-530

ESA/390의 채널 서브시스템은 서로 다른 주변 장치를 `ccw_device`와 CCW 채널 프로그램이라는 공통 모델로 다룹니다. 드라이버는 하드웨어 명령을 직접 발행하지 않고 `ccw_device_start()` 계열을 사용해야 하며, `struct irb`의 sense·서브채널·장치 상태를 판독해 완료와 오류를 처리합니다.

핵심 안전 규칙은 인터럽트를 비활성화하고 `ccw_device` 잠금을 보유한 상태에서 start, halt, clear를 호출하는 것입니다. 중간 상태 보고, 조기 통지, suspend, 무한 TIC 프로그램은 처리량을 높일 수 있지만 채널 점유와 교착 상태를 피하도록 원문의 조건을 지켜야 합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ===========================
2 Linux for S/390 and zSeries
3 ===========================
4
5 Common Device Support (CDS)
6 Device Driver I/O Support Routines
7
8 Authors:
9 - Ingo Adlung
10 - Cornelia Huck
11
12 Copyright, IBM Corp. 1999-2002
13
14 Introduction
15 ============
16
17 This document describes the common device support routines for Linux/390.
18 Different than other hardware architectures, ESA/390 has defined a unified
19 I/O access method. This gives relief to the device drivers as they don't
20 have to deal with different bus types, polling versus interrupt
21 processing, shared versus non-shared interrupt processing, DMA versus port
22 I/O (PIO), and other hardware features more. However, this implies that
23 either every single device driver needs to implement the hardware I/O
24 attachment functionality itself, or the operating system provides for a
25 unified method to access the hardware, providing all the functionality that
26 every single device driver would have to provide itself.
27
28 The document does not intend to explain the ESA/390 hardware architecture in
29 every detail.This information can be obtained from the ESA/390 Principles of
30 Operation manual (IBM Form. No. SA22-7201).
31
32 In order to build common device support for ESA/390 I/O interfaces, a
33 functional layer was introduced that provides generic I/O access methods to
34 the hardware.
35
36 The common device support layer comprises the I/O support routines defined
37 below. Some of them implement common Linux device driver interfaces, while
38 some of them are ESA/390 platform specific.
39
40 Note:
41 In order to write a driver for S/390, you also need to look into the interface
42 described in Documentation/arch/s390/driver-model.rst.
43
44 Note for porting drivers from 2.4:
45
46 The major changes are:
47
48 * The functions use a ccw_device instead of an irq (subchannel).
49 * All drivers must define a ccw_driver (see driver-model.txt) and the associated
50 functions.
51 * request_irq() and free_irq() are no longer done by the driver.
52 * The oper_handler is (kindof) replaced by the probe() and set_online() functions
53 of the ccw_driver.
54 * The not_oper_handler is (kindof) replaced by the remove() and set_offline()
55 functions of the ccw_driver.
56 * The channel device layer is gone.
57 * The interrupt handlers must be adapted to use a ccw_device as argument.
58 Moreover, they don't return a devstat, but an irb.
59 * Before initiating an io, the options must be set via ccw_device_set_options().
60 * Instead of calling read_dev_chars()/read_conf_data(), the driver issues
61 the channel program and handles the interrupt itself.
62
63 ccw_device_get_ciw()
64 get commands from extended sense data.
65
66 ccw_device_start(), ccw_device_start_timeout(), ccw_device_start_key(), ccw_device_start_key_timeout()
67 initiate an I/O request.
68
69 ccw_device_resume()
70 resume channel program execution.
71
72 ccw_device_halt()
73 terminate the current I/O request processed on the device.
74
75 do_IRQ()
76 generic interrupt routine. This function is called by the interrupt entry
77 routine whenever an I/O interrupt is presented to the system. The do_IRQ()
78 routine determines the interrupt status and calls the device specific
79 interrupt handler according to the rules (flags) defined during I/O request
80 initiation with do_IO().
81
82 The next chapters describe the functions other than do_IRQ() in more details.
83 The do_IRQ() interface is not described, as it is called from the Linux/390
84 first level interrupt handler only and does not comprise a device driver
85 callable interface. Instead, the functional description of do_IO() also
86 describes the input to the device specific interrupt handler.
87
88 Note:
89 All explanations apply also to the 64 bit architecture s390x.
90
91
92 Common Device Support (CDS) for Linux/390 Device Drivers
93 ========================================================
94
95 General Information
96 -------------------
97
98 The following chapters describe the I/O related interface routines the
99 Linux/390 common device support (CDS) provides to allow for device specific
100 driver implementations on the IBM ESA/390 hardware platform. Those interfaces
101 intend to provide the functionality required by every device driver
102 implementation to allow to drive a specific hardware device on the ESA/390
103 platform. Some of the interface routines are specific to Linux/390 and some
104 of them can be found on other Linux platforms implementations too.
105 Miscellaneous function prototypes, data declarations, and macro definitions
106 can be found in the architecture specific C header file
107 linux/arch/s390/include/asm/irq.h.
108
109 Overview of CDS interface concepts
110 ----------------------------------
111
112 Different to other hardware platforms, the ESA/390 architecture doesn't define
113 interrupt lines managed by a specific interrupt controller and bus systems
114 that may or may not allow for shared interrupts, DMA processing, etc.. Instead,
115 the ESA/390 architecture has implemented a so called channel subsystem, that
116 provides a unified view of the devices physically attached to the systems.
117 Though the ESA/390 hardware platform knows about a huge variety of different
118 peripheral attachments like disk devices (aka. DASDs), tapes, communication
119 controllers, etc. they can all be accessed by a well defined access method and
120 they are presenting I/O completion a unified way : I/O interruptions. Every
121 single device is uniquely identified to the system by a so called subchannel,
122 where the ESA/390 architecture allows for 64k devices be attached.
123
124 Linux, however, was first built on the Intel PC architecture, with its two
125 cascaded 8259 programmable interrupt controllers (PICs), that allow for a
126 maximum of 15 different interrupt lines. All devices attached to such a system
127 share those 15 interrupt levels. Devices attached to the ISA bus system must
128 not share interrupt levels (aka. IRQs), as the ISA bus bases on edge triggered
129 interrupts. MCA, EISA, PCI and other bus systems base on level triggered
130 interrupts, and therewith allow for shared IRQs. However, if multiple devices
131 present their hardware status by the same (shared) IRQ, the operating system
132 has to call every single device driver registered on this IRQ in order to
133 determine the device driver owning the device that raised the interrupt.
134
135 Up to kernel 2.4, Linux/390 used to provide interfaces via the IRQ (subchannel).
136 For internal use of the common I/O layer, these are still there. However,
137 device drivers should use the new calling interface via the ccw_device only.
138
139 During its startup the Linux/390 system checks for peripheral devices. Each
140 of those devices is uniquely defined by a so called subchannel by the ESA/390
141 channel subsystem. While the subchannel numbers are system generated, each
142 subchannel also takes a user defined attribute, the so called device number.
143 Both subchannel number and device number cannot exceed 65535. During sysfs
144 initialisation, the information about control unit type and device types that
145 imply specific I/O commands (channel command words - CCWs) in order to operate
146 the device are gathered. Device drivers can retrieve this set of hardware
147 information during their initialization step to recognize the devices they
148 support using the information saved in the struct ccw_device given to them.
149 This methods implies that Linux/390 doesn't require to probe for free (not
150 armed) interrupt request lines (IRQs) to drive its devices with. Where
151 applicable, the device drivers can use issue the READ DEVICE CHARACTERISTICS
152 ccw to retrieve device characteristics in its online routine.
153
154 In order to allow for easy I/O initiation the CDS layer provides a
155 ccw_device_start() interface that takes a device specific channel program (one
156 or more CCWs) as input sets up the required architecture specific control blocks
157 and initiates an I/O request on behalf of the device driver. The
158 ccw_device_start() routine allows to specify whether it expects the CDS layer
159 to notify the device driver for every interrupt it observes, or with final status
160 only. See ccw_device_start() for more details. A device driver must never issue
161 ESA/390 I/O commands itself, but must use the Linux/390 CDS interfaces instead.
162
163 For long running I/O request to be canceled, the CDS layer provides the
164 ccw_device_halt() function. Some devices require to initially issue a HALT
165 SUBCHANNEL (HSCH) command without having pending I/O requests. This function is
166 also covered by ccw_device_halt().
167
168
169 get_ciw() - get command information word
170
171 This call enables a device driver to get information about supported commands
172 from the extended SenseID data.
173
174 ::
175
176 struct ciw *
177 ccw_device_get_ciw(struct ccw_device *cdev, __u32 cmd);
178
179 ==== ========================================================
180 cdev The ccw_device for which the command is to be retrieved.
181 cmd The command type to be retrieved.
182 ==== ========================================================
183
184 ccw_device_get_ciw() returns:
185
186 ===== ================================================================
187 NULL No extended data available, invalid device or command not found.
188 !NULL The command requested.
189 ===== ================================================================
190
191 ::
192
193 ccw_device_start() - Initiate I/O Request
194
195 The ccw_device_start() routines is the I/O request front-end processor. All
196 device driver I/O requests must be issued using this routine. A device driver
197 must not issue ESA/390 I/O commands itself. Instead the ccw_device_start()
198 routine provides all interfaces required to drive arbitrary devices.
199
200 This description also covers the status information passed to the device
201 driver's interrupt handler as this is related to the rules (flags) defined
202 with the associated I/O request when calling ccw_device_start().
203
204 ::
205
206 int ccw_device_start(struct ccw_device *cdev,
207 struct ccw1 *cpa,
208 unsigned long intparm,
209 __u8 lpm,
210 unsigned long flags);
211 int ccw_device_start_timeout(struct ccw_device *cdev,
212 struct ccw1 *cpa,
213 unsigned long intparm,
214 __u8 lpm,
215 unsigned long flags,
216 int expires);
217 int ccw_device_start_key(struct ccw_device *cdev,
218 struct ccw1 *cpa,
219 unsigned long intparm,
220 __u8 lpm,
221 __u8 key,
222 unsigned long flags);
223 int ccw_device_start_key_timeout(struct ccw_device *cdev,
224 struct ccw1 *cpa,
225 unsigned long intparm,
226 __u8 lpm,
227 __u8 key,
228 unsigned long flags,
229 int expires);
230
231 ============= =============================================================
232 cdev ccw_device the I/O is destined for
233 cpa logical start address of channel program
234 user_intparm user specific interrupt information; will be presented
235 back to the device driver's interrupt handler. Allows a
236 device driver to associate the interrupt with a
237 particular I/O request.
238 lpm defines the channel path to be used for a specific I/O
239 request. A value of 0 will make cio use the opm.
240 key the storage key to use for the I/O (useful for operating on a
241 storage with a storage key != default key)
242 flag defines the action to be performed for I/O processing
243 expires timeout value in jiffies. The common I/O layer will terminate
244 the running program after this and call the interrupt handler
245 with ERR_PTR(-ETIMEDOUT) as irb.
246 ============= =============================================================
247
248 Possible flag values are:
249
250 ========================= =============================================
251 DOIO_ALLOW_SUSPEND channel program may become suspended
252 DOIO_DENY_PREFETCH don't allow for CCW prefetch; usually
253 this implies the channel program might
254 become modified
255 DOIO_SUPPRESS_INTER don't call the handler on intermediate status
256 ========================= =============================================
257
258 The cpa parameter points to the first format 1 CCW of a channel program::
259
260 struct ccw1 {
261 __u8 cmd_code;/* command code */
262 __u8 flags; /* flags, like IDA addressing, etc. */
263 __u16 count; /* byte count */
264 __u32 cda; /* data address */
265 } __attribute__ ((packed,aligned(8)));
266
267 with the following CCW flags values defined:
268
269 =================== =========================
270 CCW_FLAG_DC data chaining
271 CCW_FLAG_CC command chaining
272 CCW_FLAG_SLI suppress incorrect length
273 CCW_FLAG_SKIP skip
274 CCW_FLAG_PCI PCI
275 CCW_FLAG_IDA indirect addressing
276 CCW_FLAG_SUSPEND suspend
277 =================== =========================
278
279
280 Via ccw_device_set_options(), the device driver may specify the following
281 options for the device:
282
283 ========================= ======================================
284 DOIO_EARLY_NOTIFICATION allow for early interrupt notification
285 DOIO_REPORT_ALL report all interrupt conditions
286 ========================= ======================================
287
288
289 The ccw_device_start() function returns:
290
291 ======== ======================================================================
292 0 successful completion or request successfully initiated
293 -EBUSY The device is currently processing a previous I/O request, or there is
294 a status pending at the device.
295 -ENODEV cdev is invalid, the device is not operational or the ccw_device is
296 not online.
297 ======== ======================================================================
298
299 When the I/O request completes, the CDS first level interrupt handler will
300 accumulate the status in a struct irb and then call the device interrupt handler.
301 The intparm field will contain the value the device driver has associated with a
302 particular I/O request. If a pending device status was recognized,
303 intparm will be set to 0 (zero). This may happen during I/O initiation or delayed
304 by an alert status notification. In any case this status is not related to the
305 current (last) I/O request. In case of a delayed status notification no special
306 interrupt will be presented to indicate I/O completion as the I/O request was
307 never started, even though ccw_device_start() returned with successful completion.
308
309 The irb may contain an error value, and the device driver should check for this
310 first:
311
312 ========== =================================================================
313 -ETIMEDOUT the common I/O layer terminated the request after the specified
314 timeout value
315 -EIO the common I/O layer terminated the request due to an error state
316 ========== =================================================================
317
318 If the concurrent sense flag in the extended status word (esw) in the irb is
319 set, the field erw.scnt in the esw describes the number of device specific
320 sense bytes available in the extended control word irb->scsw.ecw[]. No device
321 sensing by the device driver itself is required.
322
323 The device interrupt handler can use the following definitions to investigate
324 the primary unit check source coded in sense byte 0 :
325
326 ======================= ====
327 SNS0_CMD_REJECT 0x80
328 SNS0_INTERVENTION_REQ 0x40
329 SNS0_BUS_OUT_CHECK 0x20
330 SNS0_EQUIPMENT_CHECK 0x10
331 SNS0_DATA_CHECK 0x08
332 SNS0_OVERRUN 0x04
333 SNS0_INCOMPL_DOMAIN 0x01
334 ======================= ====
335
336 Depending on the device status, multiple of those values may be set together.
337 Please refer to the device specific documentation for details.
338
339 The irb->scsw.cstat field provides the (accumulated) subchannel status :
340
341 ========================= ============================
342 SCHN_STAT_PCI program controlled interrupt
343 SCHN_STAT_INCORR_LEN incorrect length
344 SCHN_STAT_PROG_CHECK program check
345 SCHN_STAT_PROT_CHECK protection check
346 SCHN_STAT_CHN_DATA_CHK channel data check
347 SCHN_STAT_CHN_CTRL_CHK channel control check
348 SCHN_STAT_INTF_CTRL_CHK interface control check
349 SCHN_STAT_CHAIN_CHECK chaining check
350 ========================= ============================
351
352 The irb->scsw.dstat field provides the (accumulated) device status :
353
354 ===================== =================
355 DEV_STAT_ATTENTION attention
356 DEV_STAT_STAT_MOD status modifier
357 DEV_STAT_CU_END control unit end
358 DEV_STAT_BUSY busy
359 DEV_STAT_CHN_END channel end
360 DEV_STAT_DEV_END device end
361 DEV_STAT_UNIT_CHECK unit check
362 DEV_STAT_UNIT_EXCEP unit exception
363 ===================== =================
364
365 Please see the ESA/390 Principles of Operation manual for details on the
366 individual flag meanings.
367
368 Usage Notes:
369
370 ccw_device_start() must be called disabled and with the ccw device lock held.
371
372 The device driver is allowed to issue the next ccw_device_start() call from
373 within its interrupt handler already. It is not required to schedule a
374 bottom-half, unless a non deterministically long running error recovery procedure
375 or similar needs to be scheduled. During I/O processing the Linux/390 generic
376 I/O device driver support has already obtained the IRQ lock, i.e. the handler
377 must not try to obtain it again when calling ccw_device_start() or we end in a
378 deadlock situation!
379
380 If a device driver relies on an I/O request to be completed prior to start the
381 next it can reduce I/O processing overhead by chaining a NoOp I/O command
382 CCW_CMD_NOOP to the end of the submitted CCW chain. This will force Channel-End
383 and Device-End status to be presented together, with a single interrupt.
384 However, this should be used with care as it implies the channel will remain
385 busy, not being able to process I/O requests for other devices on the same
386 channel. Therefore e.g. read commands should never use this technique, as the
387 result will be presented by a single interrupt anyway.
388
389 In order to minimize I/O overhead, a device driver should use the
390 DOIO_REPORT_ALL only if the device can report intermediate interrupt
391 information prior to device-end the device driver urgently relies on. In this
392 case all I/O interruptions are presented to the device driver until final
393 status is recognized.
394
395 If a device is able to recover from asynchronously presented I/O errors, it can
396 perform overlapping I/O using the DOIO_EARLY_NOTIFICATION flag. While some
397 devices always report channel-end and device-end together, with a single
398 interrupt, others present primary status (channel-end) when the channel is
399 ready for the next I/O request and secondary status (device-end) when the data
400 transmission has been completed at the device.
401
402 Above flag allows to exploit this feature, e.g. for communication devices that
403 can handle lost data on the network to allow for enhanced I/O processing.
404
405 Unless the channel subsystem at any time presents a secondary status interrupt,
406 exploiting this feature will cause only primary status interrupts to be
407 presented to the device driver while overlapping I/O is performed. When a
408 secondary status without error (alert status) is presented, this indicates
409 successful completion for all overlapping ccw_device_start() requests that have
410 been issued since the last secondary (final) status.
411
412 Channel programs that intend to set the suspend flag on a channel command word
413 (CCW) must start the I/O operation with the DOIO_ALLOW_SUSPEND option or the
414 suspend flag will cause a channel program check. At the time the channel program
415 becomes suspended an intermediate interrupt will be generated by the channel
416 subsystem.
417
418 ccw_device_resume() - Resume Channel Program Execution
419
420 If a device driver chooses to suspend the current channel program execution by
421 setting the CCW suspend flag on a particular CCW, the channel program execution
422 is suspended. In order to resume channel program execution the CIO layer
423 provides the ccw_device_resume() routine.
424
425 ::
426
427 int ccw_device_resume(struct ccw_device *cdev);
428
429 ==== ================================================
430 cdev ccw_device the resume operation is requested for
431 ==== ================================================
432
433 The ccw_device_resume() function returns:
434
435 ========= ==============================================
436 0 suspended channel program is resumed
437 -EBUSY status pending
438 -ENODEV cdev invalid or not-operational subchannel
439 -EINVAL resume function not applicable
440 -ENOTCONN there is no I/O request pending for completion
441 ========= ==============================================
442
443 Usage Notes:
444
445 Please have a look at the ccw_device_start() usage notes for more details on
446 suspended channel programs.
447
448 ccw_device_halt() - Halt I/O Request Processing
449
450 Sometimes a device driver might need a possibility to stop the processing of
451 a long-running channel program or the device might require to initially issue
452 a halt subchannel (HSCH) I/O command. For those purposes the ccw_device_halt()
453 command is provided.
454
455 ccw_device_halt() must be called disabled and with the ccw device lock held.
456
457 ::
458
459 int ccw_device_halt(struct ccw_device *cdev,
460 unsigned long intparm);
461
462 ======= =====================================================
463 cdev ccw_device the halt operation is requested for
464 intparm interruption parameter; value is only used if no I/O
465 is outstanding, otherwise the intparm associated with
466 the I/O request is returned
467 ======= =====================================================
468
469 The ccw_device_halt() function returns:
470
471 ======= ==============================================================
472 0 request successfully initiated
473 -EBUSY the device is currently busy, or status pending.
474 -ENODEV cdev invalid.
475 -EINVAL The device is not operational or the ccw device is not online.
476 ======= ==============================================================
477
478 Usage Notes:
479
480 A device driver may write a never-ending channel program by writing a channel
481 program that at its end loops back to its beginning by means of a transfer in
482 channel (TIC) command (CCW_CMD_TIC). Usually this is performed by network
483 device drivers by setting the PCI CCW flag (CCW_FLAG_PCI). Once this CCW is
484 executed a program controlled interrupt (PCI) is generated. The device driver
485 can then perform an appropriate action. Prior to interrupt of an outstanding
486 read to a network device (with or without PCI flag) a ccw_device_halt()
487 is required to end the pending operation.
488
489 ::
490
491 ccw_device_clear() - Terminage I/O Request Processing
492
493 In order to terminate all I/O processing at the subchannel, the clear subchannel
494 (CSCH) command is used. It can be issued via ccw_device_clear().
495
496 ccw_device_clear() must be called disabled and with the ccw device lock held.
497
498 ::
499
500 int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm);
501
502 ======= ===============================================
503 cdev ccw_device the clear operation is requested for
504 intparm interruption parameter (see ccw_device_halt())
505 ======= ===============================================
506
507 The ccw_device_clear() function returns:
508
509 ======= ==============================================================
510 0 request successfully initiated
511 -ENODEV cdev invalid
512 -EINVAL The device is not operational or the ccw device is not online.
513 ======= ==============================================================
514
515 Miscellaneous Support Routines
516 ------------------------------
517
518 This chapter describes various routines to be used in a Linux/390 device
519 driver programming environment.
520
521 get_ccwdev_lock()
522
523 Get the address of the device specific lock. This is then used in
524 spin_lock() / spin_unlock() calls.
525
526 ::
527
528 __u8 ccw_device_get_path_mask(struct ccw_device *cdev);
529
530 Get the mask of the path currently available for cdev.
531

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Linux for S/390 및 zSeries

1-12

이 문서는 공통 장치 지원(Common Device Support, CDS)의 장치 드라이버 I/O 지원 루틴을 설명합니다. 저자는 Ingo Adlung과 Cornelia Huck이며, 저작권은 IBM Corp. 1999-2002에 있습니다.

소개

13-43

이 문서는 Linux/390의 공통 장치 지원 루틴을 설명합니다. 다른 하드웨어 아키텍처와 달리 ESA/390은 통합 I/O 접근 방식을 정의합니다. 따라서 장치 드라이버는 버스 유형의 차이, 폴링과 인터럽트 처리, 공유와 비공유 인터럽트, DMA와 포트 I/O(PIO) 같은 하드웨어 차이를 각각 다룰 필요가 없습니다.

이 통합 방식이 없다면 각 드라이버가 하드웨어 I/O 연결 기능을 직접 구현해야 합니다. 대신 운영체제가 모든 드라이버에 필요한 기능을 제공하는 하나의 하드웨어 접근 방식을 마련할 수 있습니다.

이 문서는 ESA/390 하드웨어 아키텍처의 모든 세부 사항을 설명하려는 것이 아닙니다. 자세한 내용은 ESA/390 Principles of Operation 매뉴얼(IBM 문서 번호 SA22-7201)을 참조하십시오.

ESA/390 I/O 인터페이스에 대한 공통 장치 지원을 구축하기 위해 하드웨어에 일반적인 I/O 접근 방식을 제공하는 기능 계층이 도입됐습니다. CDS 계층은 아래에 정의된 I/O 지원 루틴으로 구성되며, 일부는 일반 Linux 장치 드라이버 인터페이스를 구현하고 일부는 ESA/390 플랫폼 전용입니다.

S/390 드라이버를 작성하려면 `Documentation/arch/s390/driver-model.rst`에 설명된 인터페이스도 함께 확인해야 합니다.

Linux 2.4 드라이버 포팅 변경점

44-61

Linux 2.4 드라이버를 포팅할 때의 주요 변경 사항은 다음과 같습니다.

  • 함수는 IRQ(서브채널) 대신 `ccw_device`를 사용합니다.
  • 모든 드라이버는 `ccw_driver`와 관련 함수를 정의해야 합니다. 원문은 `driver-model.txt`를 참조합니다.
  • 드라이버가 더 이상 `request_irq()`와 `free_irq()`를 호출하지 않습니다.
  • `oper_handler`는 대체로 `ccw_driver`의 `probe()`와 `set_online()` 함수로 대체됩니다.
  • `not_oper_handler`는 대체로 `remove()`와 `set_offline()` 함수로 대체됩니다.
  • 채널 장치 계층은 제거됐습니다.
  • 인터럽트 핸들러는 `ccw_device`를 인수로 받도록 바꿔야 하며, `devstat` 대신 `irb`를 받습니다.
  • I/O를 시작하기 전에 `ccw_device_set_options()`로 옵션을 설정해야 합니다.
  • `read_dev_chars()` 또는 `read_conf_data()`를 호출하는 대신 드라이버가 채널 프로그램을 발행하고 인터럽트를 직접 처리합니다.

CDS 루틴 개요

62-90
루틴역할
`ccw_device_get_ciw()`확장 sense 데이터에서 명령 정보를 얻습니다.
`ccw_device_start()` 계열`ccw_device_start_timeout()`, `ccw_device_start_key()`, `ccw_device_start_key_timeout()`을 포함해 I/O 요청을 시작합니다.
`ccw_device_resume()`채널 프로그램 실행을 재개합니다.
`ccw_device_halt()`장치에서 처리 중인 현재 I/O 요청을 종료합니다.
`do_IRQ()`I/O 인터럽트 상태를 판별하고 I/O 시작 시 `do_IO()`에 지정한 규칙에 따라 장치별 핸들러를 호출하는 일반 인터럽트 루틴입니다.

이후 절에서는 `do_IRQ()` 이외의 함수를 자세히 설명합니다. `do_IRQ()`는 Linux/390 1단계 인터럽트 핸들러에서만 호출되며 장치 드라이버가 호출할 수 있는 인터페이스가 아니므로 별도로 설명하지 않습니다. 대신 `do_IO()`의 기능 설명이 장치별 인터럽트 핸들러에 전달되는 입력도 설명합니다.

모든 설명은 64비트 아키텍처인 s390x에도 적용됩니다.

일반 정보

91-110

다음 절은 IBM ESA/390 플랫폼에서 장치별 드라이버를 구현할 수 있도록 Linux/390 CDS가 제공하는 I/O 관련 인터페이스를 설명합니다. 이 인터페이스는 ESA/390의 특정 하드웨어 장치를 구동하는 모든 드라이버에 필요한 기능을 제공하려는 것입니다.

일부 인터페이스는 Linux/390 전용이고 일부는 다른 Linux 플랫폼에도 존재합니다. 기타 함수 원형, 데이터 선언, 매크로 정의는 아키텍처 전용 C 헤더 `linux/arch/s390/include/asm/irq.h`에서 찾을 수 있습니다.

CDS 인터페이스 개념

111-168

ESA/390은 전용 인터럽트 컨트롤러가 관리하는 인터럽트 선이나 공유 인터럽트와 DMA 지원 여부가 제각각인 버스 체계를 정의하지 않습니다. 대신 물리적으로 연결된 장치를 통합된 관점으로 제공하는 채널 서브시스템을 구현합니다.

디스크(DASD), 테이프, 통신 컨트롤러 등 매우 다양한 주변 장치가 존재하지만 모두 잘 정의된 방식으로 접근하며, I/O 완료도 I/O 인터럽트라는 통합 방식으로 보고합니다. 각 장치는 서브채널로 고유하게 식별되며 ESA/390은 최대 64K 장치 연결을 허용합니다.

반면 초기 Linux의 Intel PC 구조는 계단식 8259 PIC 두 개와 최대 15개 인터럽트 선을 사용했습니다. ISA 장치는 에지 트리거 인터럽트 때문에 IRQ를 공유할 수 없지만 MCA, EISA, PCI 같은 레벨 트리거 버스는 공유할 수 있습니다. 여러 장치가 하나의 IRQ를 공유하면 운영체제는 그 IRQ에 등록된 모든 드라이버를 호출해 실제 인터럽트를 발생시킨 장치를 찾아야 합니다.

커널 2.4까지 Linux/390은 IRQ, 즉 서브채널을 통한 인터페이스를 제공했습니다. 공통 I/O 계층 내부에는 여전히 남아 있지만 장치 드라이버는 이제 `ccw_device`를 통한 호출 인터페이스만 사용해야 합니다.

부팅 중 Linux/390은 주변 장치를 검사합니다. 각 장치는 ESA/390 채널 서브시스템이 생성한 서브채널 번호와 사용자가 정의한 장치 번호를 가지며 두 값은 모두 65535를 넘을 수 없습니다. sysfs 초기화 중에는 장치 운용에 필요한 채널 명령어(CCW)를 암시하는 제어 장치 유형과 장치 유형 정보가 수집됩니다.

드라이버는 초기화 단계에서 전달받은 `struct ccw_device`의 하드웨어 정보를 사용해 자신이 지원하는 장치를 식별합니다. 따라서 Linux/390은 장치 구동을 위해 비어 있는 IRQ를 탐색할 필요가 없습니다. 필요하면 드라이버의 온라인 루틴에서 `READ DEVICE CHARACTERISTICS` CCW를 발행해 장치 특성을 읽을 수 있습니다.

CDS의 `ccw_device_start()`는 하나 이상의 CCW로 된 장치별 채널 프로그램을 받아 아키텍처별 제어 블록을 설정하고 드라이버 대신 I/O 요청을 시작합니다. 드라이버는 모든 인터럽트마다 알림을 받을지 최종 상태에서만 받을지 지정할 수 있습니다. 드라이버가 ESA/390 I/O 명령을 직접 발행해서는 안 되며 반드시 Linux/390 CDS 인터페이스를 사용해야 합니다.

장시간 실행되는 I/O 요청을 취소하려면 `ccw_device_halt()`를 사용합니다. 대기 중인 I/O 요청 없이 먼저 HALT SUBCHANNEL(HSCH)을 발행해야 하는 장치도 이 함수로 처리합니다.

ESA/390 공통 I/O 경로
`ccw_device` 장치 정보장치 드라이버CCW 채널 프로그램
`ccw_device_start()`채널 서브시스템장치 I/O
I/O 인터럽트`struct irb` 상태드라이버 핸들러

장치 식별부터 채널 프로그램 실행과 완료 통지까지의 CDS 경로입니다.

ccw_device_get_ciw()

169-190

`ccw_device_get_ciw()`는 확장 SenseID 데이터에서 장치가 지원하는 명령 정보를 가져옵니다.

struct ciw *
ccw_device_get_ciw(struct ccw_device *cdev, __u32 cmd);
매개변수설명
`cdev`명령을 조회할 `ccw_device`
`cmd`조회할 명령 유형
반환값의미
`NULL`확장 데이터가 없거나 장치가 유효하지 않거나 명령을 찾지 못했습니다.
`!NULL`요청한 명령 정보입니다.

ccw_device_start() 계열

191-230

`ccw_device_start()` 계열은 I/O 요청의 프런트엔드 처리기입니다. 모든 장치 드라이버 I/O 요청은 이 루틴을 통해 발행해야 하며, 드라이버가 ESA/390 I/O 명령을 직접 발행해서는 안 됩니다. 이 계열은 임의의 장치를 구동하는 데 필요한 인터페이스를 제공합니다.

이 설명에는 드라이버 인터럽트 핸들러로 전달되는 상태 정보도 포함됩니다. 그 정보는 `ccw_device_start()` 호출 시 I/O 요청에 지정한 규칙과 플래그에 연결되기 때문입니다.

int ccw_device_start(struct ccw_device *cdev,
                     struct ccw1 *cpa,
                     unsigned long intparm,
                     __u8 lpm,
                     unsigned long flags);
int ccw_device_start_timeout(struct ccw_device *cdev,
                             struct ccw1 *cpa,
                             unsigned long intparm,
                             __u8 lpm,
                             unsigned long flags,
                             int expires);
int ccw_device_start_key(struct ccw_device *cdev,
                         struct ccw1 *cpa,
                         unsigned long intparm,
                         __u8 lpm,
                         __u8 key,
                         unsigned long flags);
int ccw_device_start_key_timeout(struct ccw_device *cdev,
                                 struct ccw1 *cpa,
                                 unsigned long intparm,
                                 __u8 lpm,
                                 __u8 key,
                                 unsigned long flags,
                                 int expires);

시작 인수, 플래그, CCW 구조

231-288
매개변수설명
`cdev`I/O 대상 `ccw_device`
`cpa`채널 프로그램의 논리 시작 주소
`user_intparm`드라이버별 인터럽트 정보입니다. 인터럽트 핸들러로 되돌려 전달되어 특정 I/O 요청과 인터럽트를 연결할 수 있습니다.
`lpm`특정 I/O 요청에 사용할 채널 경로를 정의합니다. 0이면 CIO가 `opm`을 사용합니다.
`key`I/O에 사용할 저장소 키입니다. 기본 키와 다른 저장소에서 작업할 때 유용합니다.
`flag`I/O 처리에서 수행할 동작을 정의합니다.
`expires`jiffies 단위 시간 제한입니다. 시간이 지나면 공통 I/O 계층이 프로그램을 종료하고 `ERR_PTR(-ETIMEDOUT)`을 `irb`로 전달해 인터럽트 핸들러를 호출합니다.

가능한 시작 플래그는 다음과 같습니다.

플래그의미
`DOIO_ALLOW_SUSPEND`채널 프로그램의 일시 중단을 허용합니다.
`DOIO_DENY_PREFETCH`CCW 프리페치를 허용하지 않습니다. 보통 채널 프로그램이 수정될 수 있음을 뜻합니다.
`DOIO_SUPPRESS_INTER`중간 상태에서 핸들러를 호출하지 않습니다.

`cpa`는 채널 프로그램의 첫 번째 format-1 CCW를 가리킵니다.

struct ccw1 {
      __u8  cmd_code;/* command code */
      __u8  flags;   /* flags, like IDA addressing, etc. */
      __u16 count;   /* byte count */
      __u32 cda;     /* data address */
} __attribute__ ((packed,aligned(8)));
CCW 플래그의미
`CCW_FLAG_DC`데이터 체이닝
`CCW_FLAG_CC`명령 체이닝
`CCW_FLAG_SLI`잘못된 길이 억제
`CCW_FLAG_SKIP`건너뛰기
`CCW_FLAG_PCI`PCI
`CCW_FLAG_IDA`간접 주소 지정
`CCW_FLAG_SUSPEND`일시 중단

드라이버는 `ccw_device_set_options()`로 다음 장치 옵션을 지정할 수 있습니다.

옵션의미
`DOIO_EARLY_NOTIFICATION`조기 인터럽트 통지를 허용합니다.
`DOIO_REPORT_ALL`모든 인터럽트 조건을 보고합니다.

시작 결과와 IRB 오류

289-337

`ccw_device_start()`의 반환값은 다음과 같습니다.

반환값의미
`0`성공적으로 완료됐거나 요청이 성공적으로 시작됐습니다.
`-EBUSY`장치가 이전 I/O 요청을 처리 중이거나 장치에 대기 상태가 있습니다.
`-ENODEV``cdev`가 유효하지 않거나 장치가 작동하지 않거나 `ccw_device`가 온라인이 아닙니다.

I/O 요청이 끝나면 CDS 1단계 인터럽트 핸들러가 상태를 `struct irb`에 누적한 뒤 장치 인터럽트 핸들러를 호출합니다. `intparm`에는 드라이버가 해당 요청과 연결한 값이 들어갑니다. 대기 중 장치 상태를 인식하면 `intparm`은 0이 됩니다.

대기 상태는 I/O 시작 도중 또는 alert status 통지가 지연되어 발생할 수 있으며 현재의 마지막 I/O 요청과 관계가 없습니다. 지연된 상태 통지의 경우 `ccw_device_start()`가 성공을 반환했더라도 요청이 실제로 시작되지 않았으므로 I/O 완료를 알리는 별도 인터럽트가 오지 않습니다.

`irb`에는 오류 값이 들어갈 수 있으므로 드라이버는 이를 가장 먼저 검사해야 합니다.

오류의미
`-ETIMEDOUT`공통 I/O 계층이 지정한 시간 제한 뒤 요청을 종료했습니다.
`-EIO`공통 I/O 계층이 오류 상태 때문에 요청을 종료했습니다.

`irb`의 확장 상태어 `esw`에 concurrent sense 플래그가 설정되면 `esw`의 `erw.scnt`는 확장 제어어 `irb->scsw.ecw[]`에 들어 있는 장치별 sense 바이트 수를 나타냅니다. 장치 드라이버가 별도로 device sense를 수행할 필요는 없습니다.

인터럽트 핸들러는 sense byte 0에 기록된 주 unit-check 원인을 다음 정의로 조사합니다. 장치 상태에 따라 여러 비트가 함께 설정될 수 있으므로 세부 내용은 장치별 문서를 참조하십시오.

정의
`SNS0_CMD_REJECT``0x80`
`SNS0_INTERVENTION_REQ``0x40`
`SNS0_BUS_OUT_CHECK``0x20`
`SNS0_EQUIPMENT_CHECK``0x10`
`SNS0_DATA_CHECK``0x08`
`SNS0_OVERRUN``0x04`
`SNS0_INCOMPL_DOMAIN``0x01`

누적 서브채널 및 장치 상태

338-367

`irb->scsw.cstat` 필드는 누적 서브채널 상태를 제공합니다.

서브채널 상태의미
`SCHN_STAT_PCI`프로그램 제어 인터럽트
`SCHN_STAT_INCORR_LEN`잘못된 길이
`SCHN_STAT_PROG_CHECK`프로그램 검사
`SCHN_STAT_PROT_CHECK`보호 검사
`SCHN_STAT_CHN_DATA_CHK`채널 데이터 검사
`SCHN_STAT_CHN_CTRL_CHK`채널 제어 검사
`SCHN_STAT_INTF_CTRL_CHK`인터페이스 제어 검사
`SCHN_STAT_CHAIN_CHECK`체이닝 검사

`irb->scsw.dstat` 필드는 누적 장치 상태를 제공합니다.

장치 상태의미
`DEV_STAT_ATTENTION`attention
`DEV_STAT_STAT_MOD`상태 수정자
`DEV_STAT_CU_END`제어 장치 종료
`DEV_STAT_BUSY`사용 중
`DEV_STAT_CHN_END`채널 종료
`DEV_STAT_DEV_END`장치 종료
`DEV_STAT_UNIT_CHECK`장치 검사
`DEV_STAT_UNIT_EXCEP`장치 예외

개별 플래그의 정확한 의미는 ESA/390 Principles of Operation 매뉴얼을 참조하십시오.

ccw_device_start() 사용 시 주의점

368-417

`ccw_device_start()`는 인터럽트가 비활성화된 상태에서 `ccw_device` 잠금을 보유한 채 호출해야 합니다.

드라이버는 인터럽트 핸들러 안에서 다음 `ccw_device_start()`를 바로 발행할 수 있습니다. 실행 시간이 비결정적으로 긴 오류 복구 같은 작업이 아니라면 bottom half를 예약할 필요가 없습니다. 일반 I/O 지원 계층은 이미 IRQ 잠금을 획득했으므로 핸들러가 다시 잠금을 얻으려 하면 교착 상태가 발생합니다.

다음 요청 전에 현재 I/O 완료를 반드시 기다리는 드라이버는 CCW 체인의 끝에 NoOp 명령 `CCW_CMD_NOOP`을 연결해 처리 오버헤드를 줄일 수 있습니다. 그러면 Channel-End와 Device-End가 하나의 인터럽트로 함께 전달됩니다. 그러나 그동안 채널이 계속 사용 중이어서 같은 채널의 다른 장치 요청을 처리할 수 없으므로 주의해야 합니다. 읽기 명령은 어차피 결과가 하나의 인터럽트로 전달되므로 이 기법을 사용하면 안 됩니다.

I/O 오버헤드를 줄이려면 장치가 Device-End 전에 반드시 필요한 중간 인터럽트 정보를 보고할 수 있을 때만 `DOIO_REPORT_ALL`을 사용하십시오. 이 경우 최종 상태를 인식할 때까지 모든 I/O 인터럽트가 드라이버에 전달됩니다.

장치가 비동기 I/O 오류에서 복구할 수 있다면 `DOIO_EARLY_NOTIFICATION`으로 I/O를 중첩할 수 있습니다. 일부 장치는 Channel-End와 Device-End를 한 인터럽트로 함께 보고하지만, 다른 장치는 채널이 다음 요청을 받을 준비가 되면 1차 상태인 Channel-End를, 장치 데이터 전송이 끝나면 2차 상태인 Device-End를 보고합니다.

이 옵션은 네트워크의 데이터 손실을 처리할 수 있는 통신 장치 같은 경우에 더 높은 I/O 처리량을 얻는 데 활용할 수 있습니다. 중첩 I/O 중에는 채널 서브시스템이 2차 상태 인터럽트를 보내기 전까지 1차 상태만 드라이버에 전달됩니다. 오류 없는 2차 alert status가 오면 마지막 2차 최종 상태 이후 발행한 모든 중첩 `ccw_device_start()` 요청이 성공적으로 완료됐음을 뜻합니다.

CCW에 suspend 플래그를 설정하려는 채널 프로그램은 `DOIO_ALLOW_SUSPEND` 옵션으로 I/O를 시작해야 합니다. 그렇지 않으면 suspend 플래그가 채널 프로그램 검사를 일으킵니다. 채널 프로그램이 중단되는 시점에는 채널 서브시스템이 중간 인터럽트를 생성합니다.

중첩 I/O 상태 통지
I/O 요청 시작Channel-End 1차 상태다음 요청 중첩
장치 전송 완료Device-End 2차 상태중첩 요청 완료 확정

조기 통지 옵션에서 1차 상태와 최종 상태가 드라이버에 전달되는 관계입니다.

ccw_device_resume()

418-447

드라이버가 특정 CCW에 suspend 플래그를 설정하면 현재 채널 프로그램 실행이 중단됩니다. CIO 계층은 실행을 재개하기 위해 `ccw_device_resume()`을 제공합니다.

int ccw_device_resume(struct ccw_device *cdev);
매개변수설명
`cdev`재개 작업을 요청할 `ccw_device`
반환값의미
`0`중단된 채널 프로그램을 재개했습니다.
`-EBUSY`대기 중인 상태가 있습니다.
`-ENODEV``cdev`가 유효하지 않거나 서브채널이 작동하지 않습니다.
`-EINVAL`재개 기능을 적용할 수 없습니다.
`-ENOTCONN`완료를 기다리는 I/O 요청이 없습니다.

중단된 채널 프로그램에 관한 자세한 내용은 `ccw_device_start()` 사용 시 주의점을 참조하십시오.

ccw_device_halt()

448-488

드라이버가 장시간 실행되는 채널 프로그램을 멈춰야 하거나 장치가 처음에 HALT SUBCHANNEL(HSCH) I/O 명령을 요구할 때 `ccw_device_halt()`를 사용합니다. 이 함수는 인터럽트가 비활성화된 상태에서 `ccw_device` 잠금을 보유한 채 호출해야 합니다.

int ccw_device_halt(struct ccw_device *cdev,
                    unsigned long intparm);
매개변수설명
`cdev`중단 작업을 요청할 `ccw_device`
`intparm`인터럽트 매개변수입니다. 진행 중 I/O가 없을 때만 이 값을 사용하며, I/O가 있으면 그 요청에 연결된 `intparm`을 반환합니다.
반환값의미
`0`요청을 성공적으로 시작했습니다.
`-EBUSY`장치가 사용 중이거나 상태가 대기 중입니다.
`-ENODEV``cdev`가 유효하지 않습니다.
`-EINVAL`장치가 작동하지 않거나 `ccw_device`가 온라인이 아닙니다.

드라이버는 채널 내 전송(TIC) 명령 `CCW_CMD_TIC`으로 끝에서 처음으로 되돌아가는 무한 채널 프로그램을 만들 수 있습니다. 네트워크 드라이버는 보통 PCI CCW 플래그 `CCW_FLAG_PCI`와 함께 사용하며, 해당 CCW가 실행되면 프로그램 제어 인터럽트(PCI)가 발생합니다.

네트워크 장치에 대기 중인 읽기 작업을 중단하려면 PCI 플래그 사용 여부와 관계없이 먼저 `ccw_device_halt()`로 대기 작업을 끝내야 합니다.

ccw_device_clear()

489-514

서브채널의 모든 I/O 처리를 끝내려면 clear subchannel(CSCH) 명령을 사용하며 `ccw_device_clear()`로 발행합니다. 이 함수도 인터럽트가 비활성화된 상태에서 `ccw_device` 잠금을 보유한 채 호출해야 합니다.

int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm);
매개변수설명
`cdev`clear 작업을 요청할 `ccw_device`
`intparm``ccw_device_halt()`와 같은 인터럽트 매개변수
반환값의미
`0`요청을 성공적으로 시작했습니다.
`-ENODEV``cdev`가 유효하지 않습니다.
`-EINVAL`장치가 작동하지 않거나 `ccw_device`가 온라인이 아닙니다.

기타 지원 루틴

515-530

이 절은 Linux/390 장치 드라이버 프로그래밍 환경에서 사용하는 기타 루틴을 설명합니다. 원문의 `get_ccwdev_lock()` 설명은 장치별 잠금의 주소를 얻어 `spin_lock()`과 `spin_unlock()` 호출에 사용한다고 밝힙니다.

이어지는 선언 `ccw_device_get_path_mask()`는 현재 `cdev`에 사용할 수 있는 경로의 마스크를 반환합니다.

__u8 ccw_device_get_path_mask(struct ccw_device *cdev);