diff options
Diffstat (limited to 'drivers/char/hvc_iucv.c')
-rw-r--r-- | drivers/char/hvc_iucv.c | 176 |
1 files changed, 75 insertions, 101 deletions
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index a23f7e8fba86..ce1a25f779ce 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -1,14 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * hvc_iucv.c - z/VM IUCV back-end for the Hypervisor Console (HVC) | 2 | * hvc_iucv.c - z/VM IUCV hypervisor console (HVC) device driver |
3 | * | 3 | * |
4 | * This back-end for HVC provides terminal access via | 4 | * This HVC device driver provides terminal access using |
5 | * z/VM IUCV communication paths. | 5 | * z/VM IUCV communication paths. |
6 | * | 6 | * |
7 | * Copyright IBM Corp. 2008. | 7 | * Copyright IBM Corp. 2008 |
8 | * | 8 | * |
9 | * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 9 | * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> |
10 | */ | 10 | */ |
11 | #define KMSG_COMPONENT "hvc_iucv" | 11 | #define KMSG_COMPONENT "hvc_iucv" |
12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
12 | 13 | ||
13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
14 | #include <asm/ebcdic.h> | 15 | #include <asm/ebcdic.h> |
@@ -22,7 +23,7 @@ | |||
22 | #include "hvc_console.h" | 23 | #include "hvc_console.h" |
23 | 24 | ||
24 | 25 | ||
25 | /* HVC backend for z/VM IUCV */ | 26 | /* General device driver settings */ |
26 | #define HVC_IUCV_MAGIC 0xc9e4c3e5 | 27 | #define HVC_IUCV_MAGIC 0xc9e4c3e5 |
27 | #define MAX_HVC_IUCV_LINES HVC_ALLOC_TTY_ADAPTERS | 28 | #define MAX_HVC_IUCV_LINES HVC_ALLOC_TTY_ADAPTERS |
28 | #define MEMPOOL_MIN_NR (PAGE_SIZE / sizeof(struct iucv_tty_buffer)/4) | 29 | #define MEMPOOL_MIN_NR (PAGE_SIZE / sizeof(struct iucv_tty_buffer)/4) |
@@ -35,7 +36,6 @@ | |||
35 | #define MSG_TYPE_WINSIZE 0x08 /* Terminal window size update */ | 36 | #define MSG_TYPE_WINSIZE 0x08 /* Terminal window size update */ |
36 | #define MSG_TYPE_DATA 0x10 /* Terminal data */ | 37 | #define MSG_TYPE_DATA 0x10 /* Terminal data */ |
37 | 38 | ||
38 | #define MSG_SIZE(s) ((s) + offsetof(struct iucv_tty_msg, data)) | ||
39 | struct iucv_tty_msg { | 39 | struct iucv_tty_msg { |
40 | u8 version; /* Message version */ | 40 | u8 version; /* Message version */ |
41 | u8 type; /* Message type */ | 41 | u8 type; /* Message type */ |
@@ -43,6 +43,7 @@ struct iucv_tty_msg { | |||
43 | u16 datalen; /* Payload length */ | 43 | u16 datalen; /* Payload length */ |
44 | u8 data[]; /* Payload buffer */ | 44 | u8 data[]; /* Payload buffer */ |
45 | } __attribute__((packed)); | 45 | } __attribute__((packed)); |
46 | #define MSG_SIZE(s) ((s) + offsetof(struct iucv_tty_msg, data)) | ||
46 | 47 | ||
47 | enum iucv_state_t { | 48 | enum iucv_state_t { |
48 | IUCV_DISCONN = 0, | 49 | IUCV_DISCONN = 0, |
@@ -56,7 +57,7 @@ enum tty_state_t { | |||
56 | }; | 57 | }; |
57 | 58 | ||
58 | struct hvc_iucv_private { | 59 | struct hvc_iucv_private { |
59 | struct hvc_struct *hvc; /* HVC console struct reference */ | 60 | struct hvc_struct *hvc; /* HVC struct reference */ |
60 | u8 srv_name[8]; /* IUCV service name (ebcdic) */ | 61 | u8 srv_name[8]; /* IUCV service name (ebcdic) */ |
61 | enum iucv_state_t iucv_state; /* IUCV connection status */ | 62 | enum iucv_state_t iucv_state; /* IUCV connection status */ |
62 | enum tty_state_t tty_state; /* TTY status */ | 63 | enum tty_state_t tty_state; /* TTY status */ |
@@ -74,7 +75,7 @@ struct hvc_iucv_private { | |||
74 | 75 | ||
75 | struct iucv_tty_buffer { | 76 | struct iucv_tty_buffer { |
76 | struct list_head list; /* list pointer */ | 77 | struct list_head list; /* list pointer */ |
77 | struct iucv_message msg; /* store an incoming IUCV message */ | 78 | struct iucv_message msg; /* store an IUCV message */ |
78 | size_t offset; /* data buffer offset */ | 79 | size_t offset; /* data buffer offset */ |
79 | struct iucv_tty_msg *mbuf; /* buffer to store input/output data */ | 80 | struct iucv_tty_msg *mbuf; /* buffer to store input/output data */ |
80 | }; | 81 | }; |
@@ -120,7 +121,7 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) | |||
120 | } | 121 | } |
121 | 122 | ||
122 | /** | 123 | /** |
123 | * alloc_tty_buffer() - Returns a new struct iucv_tty_buffer element. | 124 | * alloc_tty_buffer() - Return a new struct iucv_tty_buffer element. |
124 | * @size: Size of the internal buffer used to store data. | 125 | * @size: Size of the internal buffer used to store data. |
125 | * @flags: Memory allocation flags passed to mempool. | 126 | * @flags: Memory allocation flags passed to mempool. |
126 | * | 127 | * |
@@ -128,7 +129,6 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) | |||
128 | * allocates an internal data buffer with the specified size @size. | 129 | * allocates an internal data buffer with the specified size @size. |
129 | * Note: The total message size arises from the internal buffer size and the | 130 | * Note: The total message size arises from the internal buffer size and the |
130 | * members of the iucv_tty_msg structure. | 131 | * members of the iucv_tty_msg structure. |
131 | * | ||
132 | * The function returns NULL if memory allocation has failed. | 132 | * The function returns NULL if memory allocation has failed. |
133 | */ | 133 | */ |
134 | static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) | 134 | static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) |
@@ -157,9 +157,6 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) | |||
157 | /** | 157 | /** |
158 | * destroy_tty_buffer() - destroy struct iucv_tty_buffer element. | 158 | * destroy_tty_buffer() - destroy struct iucv_tty_buffer element. |
159 | * @bufp: Pointer to a struct iucv_tty_buffer element, SHALL NOT be NULL. | 159 | * @bufp: Pointer to a struct iucv_tty_buffer element, SHALL NOT be NULL. |
160 | * | ||
161 | * The destroy_tty_buffer() function frees the internal data buffer and returns | ||
162 | * the struct iucv_tty_buffer element back to the mempool for freeing. | ||
163 | */ | 160 | */ |
164 | static void destroy_tty_buffer(struct iucv_tty_buffer *bufp) | 161 | static void destroy_tty_buffer(struct iucv_tty_buffer *bufp) |
165 | { | 162 | { |
@@ -169,11 +166,7 @@ static void destroy_tty_buffer(struct iucv_tty_buffer *bufp) | |||
169 | 166 | ||
170 | /** | 167 | /** |
171 | * destroy_tty_buffer_list() - call destroy_tty_buffer() for each list element. | 168 | * destroy_tty_buffer_list() - call destroy_tty_buffer() for each list element. |
172 | * @list: List head pointer to a list containing struct iucv_tty_buffer | 169 | * @list: List containing struct iucv_tty_buffer elements. |
173 | * elements. | ||
174 | * | ||
175 | * Calls destroy_tty_buffer() for each struct iucv_tty_buffer element in the | ||
176 | * list @list. | ||
177 | */ | 170 | */ |
178 | static void destroy_tty_buffer_list(struct list_head *list) | 171 | static void destroy_tty_buffer_list(struct list_head *list) |
179 | { | 172 | { |
@@ -186,24 +179,24 @@ static void destroy_tty_buffer_list(struct list_head *list) | |||
186 | } | 179 | } |
187 | 180 | ||
188 | /** | 181 | /** |
189 | * hvc_iucv_write() - Receive IUCV message write data to HVC console buffer. | 182 | * hvc_iucv_write() - Receive IUCV message & write data to HVC buffer. |
190 | * @priv: Pointer to hvc_iucv_private structure. | 183 | * @priv: Pointer to struct hvc_iucv_private |
191 | * @buf: HVC console buffer for writing received terminal data. | 184 | * @buf: HVC buffer for writing received terminal data. |
192 | * @count: HVC console buffer size. | 185 | * @count: HVC buffer size. |
193 | * @has_more_data: Pointer to an int variable. | 186 | * @has_more_data: Pointer to an int variable. |
194 | * | 187 | * |
195 | * The function picks up pending messages from the input queue and receives | 188 | * The function picks up pending messages from the input queue and receives |
196 | * the message data that is then written to the specified buffer @buf. | 189 | * the message data that is then written to the specified buffer @buf. |
197 | * If the buffer size @count is less than the data message size, then the | 190 | * If the buffer size @count is less than the data message size, the |
198 | * message is kept on the input queue and @has_more_data is set to 1. | 191 | * message is kept on the input queue and @has_more_data is set to 1. |
199 | * If the message data has been entirely written, the message is removed from | 192 | * If all message data has been written, the message is removed from |
200 | * the input queue. | 193 | * the input queue. |
201 | * | 194 | * |
202 | * The function returns the number of bytes written to the terminal, zero if | 195 | * The function returns the number of bytes written to the terminal, zero if |
203 | * there are no pending data messages available or if there is no established | 196 | * there are no pending data messages available or if there is no established |
204 | * IUCV path. | 197 | * IUCV path. |
205 | * If the IUCV path has been severed, then -EPIPE is returned to cause a | 198 | * If the IUCV path has been severed, then -EPIPE is returned to cause a |
206 | * hang up (that is issued by the HVC console layer). | 199 | * hang up (that is issued by the HVC layer). |
207 | */ | 200 | */ |
208 | static int hvc_iucv_write(struct hvc_iucv_private *priv, | 201 | static int hvc_iucv_write(struct hvc_iucv_private *priv, |
209 | char *buf, int count, int *has_more_data) | 202 | char *buf, int count, int *has_more_data) |
@@ -212,12 +205,12 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, | |||
212 | int written; | 205 | int written; |
213 | int rc; | 206 | int rc; |
214 | 207 | ||
215 | /* Immediately return if there is no IUCV connection */ | 208 | /* immediately return if there is no IUCV connection */ |
216 | if (priv->iucv_state == IUCV_DISCONN) | 209 | if (priv->iucv_state == IUCV_DISCONN) |
217 | return 0; | 210 | return 0; |
218 | 211 | ||
219 | /* If the IUCV path has been severed, return -EPIPE to inform the | 212 | /* if the IUCV path has been severed, return -EPIPE to inform the |
220 | * hvc console layer to hang up the tty device. */ | 213 | * HVC layer to hang up the tty device. */ |
221 | if (priv->iucv_state == IUCV_SEVERED) | 214 | if (priv->iucv_state == IUCV_SEVERED) |
222 | return -EPIPE; | 215 | return -EPIPE; |
223 | 216 | ||
@@ -225,7 +218,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, | |||
225 | if (list_empty(&priv->tty_inqueue)) | 218 | if (list_empty(&priv->tty_inqueue)) |
226 | return 0; | 219 | return 0; |
227 | 220 | ||
228 | /* receive a iucv message and flip data to the tty (ldisc) */ | 221 | /* receive an iucv message and flip data to the tty (ldisc) */ |
229 | rb = list_first_entry(&priv->tty_inqueue, struct iucv_tty_buffer, list); | 222 | rb = list_first_entry(&priv->tty_inqueue, struct iucv_tty_buffer, list); |
230 | 223 | ||
231 | written = 0; | 224 | written = 0; |
@@ -268,7 +261,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, | |||
268 | case MSG_TYPE_WINSIZE: | 261 | case MSG_TYPE_WINSIZE: |
269 | if (rb->mbuf->datalen != sizeof(struct winsize)) | 262 | if (rb->mbuf->datalen != sizeof(struct winsize)) |
270 | break; | 263 | break; |
271 | hvc_resize(priv->hvc, *((struct winsize *)rb->mbuf->data)); | 264 | hvc_resize(priv->hvc, *((struct winsize *) rb->mbuf->data)); |
272 | break; | 265 | break; |
273 | 266 | ||
274 | case MSG_TYPE_ERROR: /* ignored ... */ | 267 | case MSG_TYPE_ERROR: /* ignored ... */ |
@@ -292,10 +285,9 @@ out_written: | |||
292 | * @buf: Pointer to a buffer to store data | 285 | * @buf: Pointer to a buffer to store data |
293 | * @count: Size of buffer available for writing | 286 | * @count: Size of buffer available for writing |
294 | * | 287 | * |
295 | * The hvc_console thread calls this method to read characters from | 288 | * The HVC thread calls this method to read characters from the back-end. |
296 | * the terminal backend. If an IUCV communication path has been established, | 289 | * If an IUCV communication path has been established, pending IUCV messages |
297 | * pending IUCV messages are received and data is copied into buffer @buf | 290 | * are received and data is copied into buffer @buf up to @count bytes. |
298 | * up to @count bytes. | ||
299 | * | 291 | * |
300 | * Locking: The routine gets called under an irqsave() spinlock; and | 292 | * Locking: The routine gets called under an irqsave() spinlock; and |
301 | * the routine locks the struct hvc_iucv_private->lock to call | 293 | * the routine locks the struct hvc_iucv_private->lock to call |
@@ -332,17 +324,17 @@ static int hvc_iucv_get_chars(uint32_t vtermno, char *buf, int count) | |||
332 | * @count: Size of buffer and amount of data to send. | 324 | * @count: Size of buffer and amount of data to send. |
333 | * | 325 | * |
334 | * The function queues data for sending. To actually send the buffered data, | 326 | * The function queues data for sending. To actually send the buffered data, |
335 | * a work queue function is * scheduled (with QUEUE_SNDBUF_DELAY). | 327 | * a work queue function is scheduled (with QUEUE_SNDBUF_DELAY). |
336 | * The function returns the number of data bytes that has been buffered. | 328 | * The function returns the number of data bytes that has been buffered. |
337 | * | 329 | * |
338 | * If the device is not connected, data is ignored and the function returns | 330 | * If the device is not connected, data is ignored and the function returns |
339 | * @count. | 331 | * @count. |
340 | * If the buffer is full, the function returns 0. | 332 | * If the buffer is full, the function returns 0. |
341 | * If an existing IUCV communicaton path has been severed, the function returns | 333 | * If an existing IUCV communicaton path has been severed, -EPIPE is returned |
342 | * -EPIPE (can be passed to HVC layer to cause a tty hangup). | 334 | * (that can be passed to HVC layer to cause a tty hangup). |
343 | */ | 335 | */ |
344 | static int hvc_iucv_queue(struct hvc_iucv_private *priv, const char *buf, | 336 | static int hvc_iucv_queue(struct hvc_iucv_private *priv, const char *buf, |
345 | int count) | 337 | int count) |
346 | { | 338 | { |
347 | size_t len; | 339 | size_t len; |
348 | 340 | ||
@@ -369,12 +361,10 @@ static int hvc_iucv_queue(struct hvc_iucv_private *priv, const char *buf, | |||
369 | * hvc_iucv_send() - Send an IUCV message containing terminal data. | 361 | * hvc_iucv_send() - Send an IUCV message containing terminal data. |
370 | * @priv: Pointer to struct hvc_iucv_private instance. | 362 | * @priv: Pointer to struct hvc_iucv_private instance. |
371 | * | 363 | * |
372 | * If an IUCV communication path has been established, the queued data | 364 | * If an IUCV communication path has been established, the buffered output data |
373 | * for output are sent via an IUCV message. | 365 | * is sent via an IUCV message and the number of bytes sent is returned. |
374 | * | 366 | * Returns 0 if there is no established IUCV communication path or |
375 | * If there is no IUCV communication path established, the function returns 0. | 367 | * -EPIPE if an existing IUCV communicaton path has been severed. |
376 | * If an existing IUCV communicaton path has been severed, the function returns | ||
377 | * -EPIPE. | ||
378 | */ | 368 | */ |
379 | static int hvc_iucv_send(struct hvc_iucv_private *priv) | 369 | static int hvc_iucv_send(struct hvc_iucv_private *priv) |
380 | { | 370 | { |
@@ -420,15 +410,14 @@ static int hvc_iucv_send(struct hvc_iucv_private *priv) | |||
420 | * hvc_iucv_sndbuf_work() - Send buffered data over IUCV | 410 | * hvc_iucv_sndbuf_work() - Send buffered data over IUCV |
421 | * @work: Work structure. | 411 | * @work: Work structure. |
422 | * | 412 | * |
423 | * The function sends buffered output data over IUCV and, if necessary, | 413 | * This work queue function sends buffered output data over IUCV and, |
424 | * reschedules itself if not all buffered data could be sent. | 414 | * if not all buffered data could be sent, reschedules itself. |
425 | */ | 415 | */ |
426 | static void hvc_iucv_sndbuf_work(struct work_struct *work) | 416 | static void hvc_iucv_sndbuf_work(struct work_struct *work) |
427 | { | 417 | { |
428 | struct hvc_iucv_private *priv; | 418 | struct hvc_iucv_private *priv; |
429 | 419 | ||
430 | priv = container_of(work, struct hvc_iucv_private, sndbuf_work.work); | 420 | priv = container_of(work, struct hvc_iucv_private, sndbuf_work.work); |
431 | |||
432 | if (!priv) | 421 | if (!priv) |
433 | return; | 422 | return; |
434 | 423 | ||
@@ -443,10 +432,8 @@ static void hvc_iucv_sndbuf_work(struct work_struct *work) | |||
443 | * @buf: Pointer to an buffer to read data from | 432 | * @buf: Pointer to an buffer to read data from |
444 | * @count: Size of buffer available for reading | 433 | * @count: Size of buffer available for reading |
445 | * | 434 | * |
446 | * The hvc_console thread calls this method to write characters from | 435 | * The HVC thread calls this method to write characters to the back-end. |
447 | * to the terminal backend. | 436 | * The function calls hvc_iucv_queue() to queue terminal data for sending. |
448 | * The function calls hvc_iucv_send() under the lock of the | ||
449 | * struct hvc_iucv_private instance that corresponds to the tty @vtermno. | ||
450 | * | 437 | * |
451 | * Locking: The method gets called under an irqsave() spinlock; and | 438 | * Locking: The method gets called under an irqsave() spinlock; and |
452 | * locks struct hvc_iucv_private->lock. | 439 | * locks struct hvc_iucv_private->lock. |
@@ -496,12 +483,8 @@ static int hvc_iucv_notifier_add(struct hvc_struct *hp, int id) | |||
496 | } | 483 | } |
497 | 484 | ||
498 | /** | 485 | /** |
499 | * hvc_iucv_cleanup() - Clean up function if the tty portion is finally closed. | 486 | * hvc_iucv_cleanup() - Clean up and reset a z/VM IUCV HVC instance. |
500 | * @priv: Pointer to the struct hvc_iucv_private instance. | 487 | * @priv: Pointer to the struct hvc_iucv_private instance. |
501 | * | ||
502 | * The functions severs the established IUCV communication path (if any), and | ||
503 | * destroy struct iucv_tty_buffer elements from the in- and outqueue. Finally, | ||
504 | * the functions resets the states to TTY_CLOSED and IUCV_DISCONN. | ||
505 | */ | 488 | */ |
506 | static void hvc_iucv_cleanup(struct hvc_iucv_private *priv) | 489 | static void hvc_iucv_cleanup(struct hvc_iucv_private *priv) |
507 | { | 490 | { |
@@ -553,22 +536,19 @@ static void flush_sndbuf_sync(struct hvc_iucv_private *priv) | |||
553 | } | 536 | } |
554 | 537 | ||
555 | /** | 538 | /** |
556 | * hvc_iucv_notifier_hangup() - HVC notifier for tty hangups. | 539 | * hvc_iucv_notifier_hangup() - HVC notifier for TTY hangups. |
557 | * @hp: Pointer to the HVC device (struct hvc_struct) | 540 | * @hp: Pointer to the HVC device (struct hvc_struct) |
558 | * @id: Additional data (originally passed to hvc_alloc): the index of an struct | 541 | * @id: Additional data (originally passed to hvc_alloc): |
559 | * hvc_iucv_private instance. | 542 | * the index of an struct hvc_iucv_private instance. |
560 | * | 543 | * |
561 | * This routine notifies the HVC backend that a tty hangup (carrier loss, | 544 | * This routine notifies the HVC back-end that a tty hangup (carrier loss, |
562 | * virtual or otherwise) has occured. | 545 | * virtual or otherwise) has occured. |
563 | * | 546 | * The z/VM IUCV HVC device driver ignores virtual hangups (vhangup()) |
564 | * The HVC backend for z/VM IUCV ignores virtual hangups (vhangup()), to keep | 547 | * to keep an existing IUCV communication path established. |
565 | * an existing IUCV communication path established. | ||
566 | * (Background: vhangup() is called from user space (by getty or login) to | 548 | * (Background: vhangup() is called from user space (by getty or login) to |
567 | * disable writing to the tty by other applications). | 549 | * disable writing to the tty by other applications). |
568 | * | 550 | * If the tty has been opened and an established IUCV path has been severed |
569 | * If the tty has been opened (e.g. getty) and an established IUCV path has been | 551 | * (we caused the tty hangup), the function calls hvc_iucv_cleanup(). |
570 | * severed (we caused the tty hangup in that case), then the functions invokes | ||
571 | * hvc_iucv_cleanup() to clean up. | ||
572 | * | 552 | * |
573 | * Locking: struct hvc_iucv_private->lock | 553 | * Locking: struct hvc_iucv_private->lock |
574 | */ | 554 | */ |
@@ -584,10 +564,8 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id) | |||
584 | 564 | ||
585 | spin_lock_bh(&priv->lock); | 565 | spin_lock_bh(&priv->lock); |
586 | /* NOTE: If the hangup was scheduled by ourself (from the iucv | 566 | /* NOTE: If the hangup was scheduled by ourself (from the iucv |
587 | * path_servered callback [IUCV_SEVERED]), then we have to | 567 | * path_servered callback [IUCV_SEVERED]), we have to clean up |
588 | * finally clean up the tty backend structure and set state to | 568 | * our structure and to set state to TTY_CLOSED. |
589 | * TTY_CLOSED. | ||
590 | * | ||
591 | * If the tty was hung up otherwise (e.g. vhangup()), then we | 569 | * If the tty was hung up otherwise (e.g. vhangup()), then we |
592 | * ignore this hangup and keep an established IUCV path open... | 570 | * ignore this hangup and keep an established IUCV path open... |
593 | * (...the reason is that we are not able to connect back to the | 571 | * (...the reason is that we are not able to connect back to the |
@@ -605,10 +583,9 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id) | |||
605 | * @id: Additional data (originally passed to hvc_alloc): | 583 | * @id: Additional data (originally passed to hvc_alloc): |
606 | * the index of an struct hvc_iucv_private instance. | 584 | * the index of an struct hvc_iucv_private instance. |
607 | * | 585 | * |
608 | * This routine notifies the HVC backend that the last tty device file | 586 | * This routine notifies the HVC back-end that the last tty device fd has been |
609 | * descriptor has been closed. | 587 | * closed. The function calls hvc_iucv_cleanup() to clean up the struct |
610 | * The function calls hvc_iucv_cleanup() to clean up the struct hvc_iucv_private | 588 | * hvc_iucv_private instance. |
611 | * instance. | ||
612 | * | 589 | * |
613 | * Locking: struct hvc_iucv_private->lock | 590 | * Locking: struct hvc_iucv_private->lock |
614 | */ | 591 | */ |
@@ -640,20 +617,18 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) | |||
640 | /** | 617 | /** |
641 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. | 618 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. |
642 | * @path: Pending path (struct iucv_path) | 619 | * @path: Pending path (struct iucv_path) |
643 | * @ipvmid: Originator z/VM system identifier | 620 | * @ipvmid: z/VM system identifier of originator |
644 | * @ipuser: User specified data for this path | 621 | * @ipuser: User specified data for this path |
645 | * (AF_IUCV: port/service name and originator port) | 622 | * (AF_IUCV: port/service name and originator port) |
646 | * | 623 | * |
647 | * The function uses the @ipuser data to check to determine if the pending | 624 | * The function uses the @ipuser data to determine if the pending path belongs |
648 | * path belongs to a terminal managed by this HVC backend. | 625 | * to a terminal managed by this device driver. |
649 | * If the check is successful, then an additional check is done to ensure | 626 | * If the path belongs to this driver, ensure that the terminal is not accessed |
650 | * that a terminal cannot be accessed multiple times (only one connection | 627 | * multiple times (only one connection to a terminal is allowed). |
651 | * to a terminal is allowed). In that particular case, the pending path is | 628 | * If the terminal is not yet connected, the pending path is accepted and is |
652 | * severed. If it is the first connection, the pending path is accepted and | 629 | * associated to the appropriate struct hvc_iucv_private instance. |
653 | * associated to the struct hvc_iucv_private. The iucv state is updated to | ||
654 | * reflect that a communication path has been established. | ||
655 | * | 630 | * |
656 | * Returns 0 if the path belongs to a terminal managed by the this HVC backend; | 631 | * Returns 0 if @path belongs to a terminal managed by the this device driver; |
657 | * otherwise returns -ENODEV in order to dispatch this path to other handlers. | 632 | * otherwise returns -ENODEV in order to dispatch this path to other handlers. |
658 | * | 633 | * |
659 | * Locking: struct hvc_iucv_private->lock | 634 | * Locking: struct hvc_iucv_private->lock |
@@ -672,7 +647,6 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
672 | priv = hvc_iucv_table[i]; | 647 | priv = hvc_iucv_table[i]; |
673 | break; | 648 | break; |
674 | } | 649 | } |
675 | |||
676 | if (!priv) | 650 | if (!priv) |
677 | return -ENODEV; | 651 | return -ENODEV; |
678 | 652 | ||
@@ -719,8 +693,7 @@ out_path_handled: | |||
719 | * sets the iucv state to IUCV_SEVERED for the associated struct | 693 | * sets the iucv state to IUCV_SEVERED for the associated struct |
720 | * hvc_iucv_private instance. Later, the IUCV_SEVERED state triggers a tty | 694 | * hvc_iucv_private instance. Later, the IUCV_SEVERED state triggers a tty |
721 | * hangup (hvc_iucv_get_chars() / hvc_iucv_write()). | 695 | * hangup (hvc_iucv_get_chars() / hvc_iucv_write()). |
722 | * | 696 | * If tty portion of the HVC is closed, clean up the outqueue. |
723 | * If tty portion of the HVC is closed then clean up the outqueue in addition. | ||
724 | * | 697 | * |
725 | * Locking: struct hvc_iucv_private->lock | 698 | * Locking: struct hvc_iucv_private->lock |
726 | */ | 699 | */ |
@@ -755,9 +728,9 @@ static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16]) | |||
755 | * @path: Pending path (struct iucv_path) | 728 | * @path: Pending path (struct iucv_path) |
756 | * @msg: Pointer to the IUCV message | 729 | * @msg: Pointer to the IUCV message |
757 | * | 730 | * |
758 | * The function stores an incoming message on the input queue for later | 731 | * The function puts an incoming message on the input queue for later |
759 | * processing (by hvc_iucv_get_chars() / hvc_iucv_write()). | 732 | * processing (by hvc_iucv_get_chars() / hvc_iucv_write()). |
760 | * However, if the tty has not yet been opened, the message is rejected. | 733 | * If the tty has not yet been opened, the message is rejected. |
761 | * | 734 | * |
762 | * Locking: struct hvc_iucv_private->lock | 735 | * Locking: struct hvc_iucv_private->lock |
763 | */ | 736 | */ |
@@ -773,6 +746,7 @@ static void hvc_iucv_msg_pending(struct iucv_path *path, | |||
773 | return; | 746 | return; |
774 | } | 747 | } |
775 | 748 | ||
749 | |||
776 | spin_lock(&priv->lock); | 750 | spin_lock(&priv->lock); |
777 | 751 | ||
778 | /* reject messages if tty has not yet been opened */ | 752 | /* reject messages if tty has not yet been opened */ |
@@ -791,7 +765,7 @@ static void hvc_iucv_msg_pending(struct iucv_path *path, | |||
791 | 765 | ||
792 | list_add_tail(&rb->list, &priv->tty_inqueue); | 766 | list_add_tail(&rb->list, &priv->tty_inqueue); |
793 | 767 | ||
794 | hvc_kick(); /* wake up hvc console thread */ | 768 | hvc_kick(); /* wake up hvc thread */ |
795 | 769 | ||
796 | unlock_return: | 770 | unlock_return: |
797 | spin_unlock(&priv->lock); | 771 | spin_unlock(&priv->lock); |
@@ -802,10 +776,10 @@ unlock_return: | |||
802 | * @path: Pending path (struct iucv_path) | 776 | * @path: Pending path (struct iucv_path) |
803 | * @msg: Pointer to the IUCV message | 777 | * @msg: Pointer to the IUCV message |
804 | * | 778 | * |
805 | * The function is called upon completion of message delivery and the | 779 | * The function is called upon completion of message delivery to remove the |
806 | * message is removed from the outqueue. Additional delivery information | 780 | * message from the outqueue. Additional delivery information can be found |
807 | * can be found in msg->audit: rejected messages (0x040000 (IPADRJCT)) and | 781 | * msg->audit: rejected messages (0x040000 (IPADRJCT)), and |
808 | * purged messages (0x010000 (IPADPGNR)). | 782 | * purged messages (0x010000 (IPADPGNR)). |
809 | * | 783 | * |
810 | * Locking: struct hvc_iucv_private->lock | 784 | * Locking: struct hvc_iucv_private->lock |
811 | */ | 785 | */ |
@@ -841,8 +815,8 @@ static struct hv_ops hvc_iucv_ops = { | |||
841 | * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance | 815 | * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance |
842 | * @id: hvc_iucv_table index | 816 | * @id: hvc_iucv_table index |
843 | * | 817 | * |
844 | * This function allocates a new hvc_iucv_private struct and put the | 818 | * This function allocates a new hvc_iucv_private structure and stores |
845 | * instance into hvc_iucv_table at index @id. | 819 | * the instance in hvc_iucv_table at index @id. |
846 | * Returns 0 on success; otherwise non-zero. | 820 | * Returns 0 on success; otherwise non-zero. |
847 | */ | 821 | */ |
848 | static int __init hvc_iucv_alloc(int id) | 822 | static int __init hvc_iucv_alloc(int id) |
@@ -867,7 +841,7 @@ static int __init hvc_iucv_alloc(int id) | |||
867 | return -ENOMEM; | 841 | return -ENOMEM; |
868 | } | 842 | } |
869 | 843 | ||
870 | /* Finally allocate hvc */ | 844 | /* finally allocate hvc */ |
871 | priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, /* PAGE_SIZE */ | 845 | priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, /* PAGE_SIZE */ |
872 | HVC_IUCV_MAGIC + id, &hvc_iucv_ops, 256); | 846 | HVC_IUCV_MAGIC + id, &hvc_iucv_ops, 256); |
873 | if (IS_ERR(priv->hvc)) { | 847 | if (IS_ERR(priv->hvc)) { |
@@ -877,7 +851,7 @@ static int __init hvc_iucv_alloc(int id) | |||
877 | return rc; | 851 | return rc; |
878 | } | 852 | } |
879 | 853 | ||
880 | /* kick khvcd thread; instead of using polling */ | 854 | /* notify HVC thread instead of using polling */ |
881 | priv->hvc->irq_requested = 1; | 855 | priv->hvc->irq_requested = 1; |
882 | 856 | ||
883 | /* setup iucv related information */ | 857 | /* setup iucv related information */ |
@@ -890,7 +864,7 @@ static int __init hvc_iucv_alloc(int id) | |||
890 | } | 864 | } |
891 | 865 | ||
892 | /** | 866 | /** |
893 | * hvc_iucv_init() - Initialization of HVC backend for z/VM IUCV | 867 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization |
894 | */ | 868 | */ |
895 | static int __init hvc_iucv_init(void) | 869 | static int __init hvc_iucv_init(void) |
896 | { | 870 | { |
@@ -929,7 +903,7 @@ static int __init hvc_iucv_init(void) | |||
929 | rc = hvc_iucv_alloc(i); | 903 | rc = hvc_iucv_alloc(i); |
930 | if (rc) { | 904 | if (rc) { |
931 | pr_err("Creating a new HVC terminal device " | 905 | pr_err("Creating a new HVC terminal device " |
932 | "failed with error code=%d\n", rc); | 906 | "failed with error code=%d\n", rc); |
933 | goto out_error_hvc; | 907 | goto out_error_hvc; |
934 | } | 908 | } |
935 | } | 909 | } |