diff options
| -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 | } |
