Lines Matching +full:0 +full:- +full:9 +full:a +full:- +full:z
1 // SPDX-License-Identifier: GPL-2.0
3 * z/VM IUCV hypervisor console (HVC) device driver
6 * z/VM IUCV communication paths.
36 #define MSG_VERSION 0x02 /* Message version */
37 #define MSG_TYPE_ERROR 0x01 /* Error message */
38 #define MSG_TYPE_TERMENV 0x02 /* Terminal environment variable */
39 #define MSG_TYPE_TERMIOS 0x04 /* Terminal IO struct update */
40 #define MSG_TYPE_WINSIZE 0x08 /* Terminal window size update */
41 #define MSG_TYPE_DATA 0x10 /* Terminal data */
46 #define MSG_MAX_DATALEN ((u16)(~0))
53 IUCV_DISCONN = 0,
59 TTY_CLOSED = 0,
102 #define IUCV_HVC_CON_IDX (0)
103 /* List of z/VM user ID filter entries (struct iucv_vmid_filter) */
125 * hvc_iucv_get_private() - Return a struct hvc_iucv_private instance.
139 * alloc_tty_buffer() - Return a new struct iucv_tty_buffer element.
143 * This function allocates a new struct iucv_tty_buffer element and, optionally,
158 memset(bufp, 0, sizeof(*bufp)); in alloc_tty_buffer()
160 if (size > 0) { in alloc_tty_buffer()
161 bufp->msg.length = MSG_SIZE(size); in alloc_tty_buffer()
162 bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA); in alloc_tty_buffer()
163 if (!bufp->mbuf) { in alloc_tty_buffer()
167 bufp->mbuf->version = MSG_VERSION; in alloc_tty_buffer()
168 bufp->mbuf->type = MSG_TYPE_DATA; in alloc_tty_buffer()
169 bufp->mbuf->datalen = (u16) size; in alloc_tty_buffer()
175 * destroy_tty_buffer() - destroy struct iucv_tty_buffer element.
176 * @bufp: Pointer to a struct iucv_tty_buffer element, SHALL NOT be NULL.
180 kfree(bufp->mbuf); in destroy_tty_buffer()
185 * destroy_tty_buffer_list() - call destroy_tty_buffer() for each list element.
193 list_del(&ent->list); in destroy_tty_buffer_list()
199 * hvc_iucv_write() - Receive IUCV message & write data to HVC buffer.
215 * If the IUCV path has been severed, then -EPIPE is returned to cause a
226 if (priv->iucv_state == IUCV_DISCONN) in hvc_iucv_write()
227 return 0; in hvc_iucv_write()
229 /* if the IUCV path has been severed, return -EPIPE to inform the in hvc_iucv_write()
231 if (priv->iucv_state == IUCV_SEVERED) in hvc_iucv_write()
232 return -EPIPE; in hvc_iucv_write()
235 if (list_empty(&priv->tty_inqueue)) in hvc_iucv_write()
236 return 0; in hvc_iucv_write()
239 rb = list_first_entry(&priv->tty_inqueue, struct iucv_tty_buffer, list); in hvc_iucv_write()
241 written = 0; in hvc_iucv_write()
242 if (!rb->mbuf) { /* message not yet received ... */ in hvc_iucv_write()
244 * then leave the buffer on the list and re-try later */ in hvc_iucv_write()
245 rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA); in hvc_iucv_write()
246 if (!rb->mbuf) in hvc_iucv_write()
247 return -ENOMEM; in hvc_iucv_write()
249 rc = __iucv_message_receive(priv->path, &rb->msg, 0, in hvc_iucv_write()
250 rb->mbuf, rb->msg.length, NULL); in hvc_iucv_write()
252 case 0: /* Successful */ in hvc_iucv_write()
255 case 9: /* Message purged */ in hvc_iucv_write()
258 written = -EIO; in hvc_iucv_write()
262 if (rc || (rb->mbuf->version != MSG_VERSION) || in hvc_iucv_write()
263 (rb->msg.length != MSG_SIZE(rb->mbuf->datalen))) in hvc_iucv_write()
267 switch (rb->mbuf->type) { in hvc_iucv_write()
269 written = min_t(int, rb->mbuf->datalen - rb->offset, count); in hvc_iucv_write()
270 memcpy(buf, rb->mbuf->data + rb->offset, written); in hvc_iucv_write()
271 if (written < (rb->mbuf->datalen - rb->offset)) { in hvc_iucv_write()
272 rb->offset += written; in hvc_iucv_write()
279 if (rb->mbuf->datalen != sizeof(struct winsize)) in hvc_iucv_write()
283 __hvc_resize(priv->hvc, *((struct winsize *) rb->mbuf->data)); in hvc_iucv_write()
293 list_del(&rb->list); in hvc_iucv_write()
295 *has_more_data = !list_empty(&priv->tty_inqueue); in hvc_iucv_write()
302 * hvc_iucv_get_chars() - HVC get_chars operation.
304 * @buf: Pointer to a buffer to store data
307 * The HVC thread calls this method to read characters from the back-end.
312 * the routine locks the struct hvc_iucv_private->lock to call
321 if (count <= 0) in hvc_iucv_get_chars()
322 return 0; in hvc_iucv_get_chars()
325 return -ENODEV; in hvc_iucv_get_chars()
327 spin_lock(&priv->lock); in hvc_iucv_get_chars()
328 has_more_data = 0; in hvc_iucv_get_chars()
330 spin_unlock(&priv->lock); in hvc_iucv_get_chars()
340 * hvc_iucv_queue() - Buffer terminal data for sending.
346 * a work queue function is scheduled (with QUEUE_SNDBUF_DELAY).
351 * If the buffer is full, the function returns 0.
352 * If an existing IUCV communicaton path has been severed, -EPIPE is returned
353 * (that can be passed to HVC layer to cause a tty hangup).
360 if (priv->iucv_state == IUCV_DISCONN) in hvc_iucv_queue()
363 if (priv->iucv_state == IUCV_SEVERED) in hvc_iucv_queue()
364 return -EPIPE; in hvc_iucv_queue()
366 len = min_t(size_t, count, SNDBUF_SIZE - priv->sndbuf_len); in hvc_iucv_queue()
368 return 0; in hvc_iucv_queue()
370 memcpy(priv->sndbuf + priv->sndbuf_len, buf, len); in hvc_iucv_queue()
371 priv->sndbuf_len += len; in hvc_iucv_queue()
373 if (priv->iucv_state == IUCV_CONNECTED) in hvc_iucv_queue()
374 schedule_delayed_work(&priv->sndbuf_work, QUEUE_SNDBUF_DELAY); in hvc_iucv_queue()
380 * hvc_iucv_send() - Send an IUCV message containing terminal data.
385 * Returns 0 if there is no established IUCV communication path or
386 * -EPIPE if an existing IUCV communicaton path has been severed.
393 if (priv->iucv_state == IUCV_SEVERED) in hvc_iucv_send()
394 return -EPIPE; in hvc_iucv_send()
396 if (priv->iucv_state == IUCV_DISCONN) in hvc_iucv_send()
397 return -EIO; in hvc_iucv_send()
399 if (!priv->sndbuf_len) in hvc_iucv_send()
400 return 0; in hvc_iucv_send()
404 sb = alloc_tty_buffer(priv->sndbuf_len, GFP_ATOMIC); in hvc_iucv_send()
406 return -ENOMEM; in hvc_iucv_send()
408 memcpy(sb->mbuf->data, priv->sndbuf, priv->sndbuf_len); in hvc_iucv_send()
409 sb->mbuf->datalen = (u16) priv->sndbuf_len; in hvc_iucv_send()
410 sb->msg.length = MSG_SIZE(sb->mbuf->datalen); in hvc_iucv_send()
412 list_add_tail(&sb->list, &priv->tty_outqueue); in hvc_iucv_send()
414 rc = __iucv_message_send(priv->path, &sb->msg, 0, 0, in hvc_iucv_send()
415 (void *) sb->mbuf, sb->msg.length); in hvc_iucv_send()
418 * 0x03 (msg limit reached) by trying again... */ in hvc_iucv_send()
419 list_del(&sb->list); in hvc_iucv_send()
422 len = priv->sndbuf_len; in hvc_iucv_send()
423 priv->sndbuf_len = 0; in hvc_iucv_send()
429 * hvc_iucv_sndbuf_work() - Send buffered data over IUCV
441 spin_lock_bh(&priv->lock); in hvc_iucv_sndbuf_work()
443 spin_unlock_bh(&priv->lock); in hvc_iucv_sndbuf_work()
447 * hvc_iucv_put_chars() - HVC put_chars operation.
452 * The HVC thread calls this method to write characters to the back-end.
456 * locks struct hvc_iucv_private->lock.
464 return 0; in hvc_iucv_put_chars()
467 return -ENODEV; in hvc_iucv_put_chars()
469 spin_lock(&priv->lock); in hvc_iucv_put_chars()
471 spin_unlock(&priv->lock); in hvc_iucv_put_chars()
477 * hvc_iucv_notifier_add() - HVC notifier for opening a TTY for the first time.
483 * instance that is derived from @id. Always returns 0.
485 * Locking: struct hvc_iucv_private->lock, spin_lock_bh
493 return 0; in hvc_iucv_notifier_add()
495 spin_lock_bh(&priv->lock); in hvc_iucv_notifier_add()
496 priv->tty_state = TTY_OPENED; in hvc_iucv_notifier_add()
497 spin_unlock_bh(&priv->lock); in hvc_iucv_notifier_add()
499 return 0; in hvc_iucv_notifier_add()
503 * hvc_iucv_cleanup() - Clean up and reset a z/VM IUCV HVC instance.
508 destroy_tty_buffer_list(&priv->tty_outqueue); in hvc_iucv_cleanup()
509 destroy_tty_buffer_list(&priv->tty_inqueue); in hvc_iucv_cleanup()
511 priv->tty_state = TTY_CLOSED; in hvc_iucv_cleanup()
512 priv->iucv_state = IUCV_DISCONN; in hvc_iucv_cleanup()
514 priv->sndbuf_len = 0; in hvc_iucv_cleanup()
518 * tty_outqueue_empty() - Test if the tty outq is empty
525 spin_lock_bh(&priv->lock); in tty_outqueue_empty()
526 rc = list_empty(&priv->tty_outqueue); in tty_outqueue_empty()
527 spin_unlock_bh(&priv->lock); in tty_outqueue_empty()
533 * flush_sndbuf_sync() - Flush send buffer and wait for completion
536 * The routine cancels a pending sndbuf work, calls hvc_iucv_send()
543 cancel_delayed_work_sync(&priv->sndbuf_work); in flush_sndbuf_sync()
545 spin_lock_bh(&priv->lock); in flush_sndbuf_sync()
547 sync_wait = !list_empty(&priv->tty_outqueue); /* anything queued ? */ in flush_sndbuf_sync()
548 spin_unlock_bh(&priv->lock); in flush_sndbuf_sync()
551 wait_event_timeout(priv->sndbuf_waitq, in flush_sndbuf_sync()
556 * hvc_iucv_hangup() - Sever IUCV path and schedule hvc tty hang up
561 * The hang-up occurs only if an IUCV communication path is established;
564 * The IUCV HVC hang-up is separated into two steps:
568 * IUCV_SEVERED state causes the tty hang-up in the HVC layer.
571 * structure to allow re-connects.
572 * If the tty has been opened, let get_chars() return -EPIPE to signal
576 * Special notes on hanging up a HVC terminal instantiated as console:
577 * Hang-up: 1. do_tty_hangup() replaces file ops (= hung_up_tty_fops)
578 * 2. do_tty_hangup() calls tty->ops->close() for console_filp
582 * Finally, the back-end is not being notified, thus, the tty session is
583 * kept active (TTY_OPEN) to be ready for re-connects.
585 * Locking: spin_lock(&priv->lock) w/o disabling bh
592 spin_lock(&priv->lock); in hvc_iucv_hangup()
593 if (priv->iucv_state == IUCV_CONNECTED) { in hvc_iucv_hangup()
594 path = priv->path; in hvc_iucv_hangup()
595 priv->path = NULL; in hvc_iucv_hangup()
596 priv->iucv_state = IUCV_SEVERED; in hvc_iucv_hangup()
597 if (priv->tty_state == TTY_CLOSED) in hvc_iucv_hangup()
601 if (priv->is_console) { in hvc_iucv_hangup()
603 priv->tty_state = TTY_OPENED; in hvc_iucv_hangup()
607 spin_unlock(&priv->lock); in hvc_iucv_hangup()
609 /* finally sever path (outside of priv->lock due to lock ordering) */ in hvc_iucv_hangup()
617 * hvc_iucv_notifier_hangup() - HVC notifier for TTY hangups.
622 * This routine notifies the HVC back-end that a tty hangup (carrier loss,
624 * The z/VM IUCV HVC device driver ignores virtual hangups (vhangup())
631 * Locking: struct hvc_iucv_private->lock
643 spin_lock_bh(&priv->lock); in hvc_iucv_notifier_hangup()
651 priv->tty_state = TTY_CLOSED; in hvc_iucv_notifier_hangup()
653 if (priv->iucv_state == IUCV_SEVERED) in hvc_iucv_notifier_hangup()
655 spin_unlock_bh(&priv->lock); in hvc_iucv_notifier_hangup()
659 * hvc_iucv_dtr_rts() - HVC notifier for handling DTR/RTS
663 * This routine notifies the HVC back-end to raise or lower DTR/RTS
678 priv = hvc_iucv_get_private(hp->vtermno); in hvc_iucv_dtr_rts()
687 spin_lock_bh(&priv->lock); in hvc_iucv_dtr_rts()
688 path = priv->path; /* save reference to IUCV path */ in hvc_iucv_dtr_rts()
689 priv->path = NULL; in hvc_iucv_dtr_rts()
690 priv->iucv_state = IUCV_DISCONN; in hvc_iucv_dtr_rts()
691 spin_unlock_bh(&priv->lock); in hvc_iucv_dtr_rts()
693 /* Sever IUCV path outside of priv->lock due to lock ordering of: in hvc_iucv_dtr_rts()
694 * priv->lock <--> iucv_table_lock */ in hvc_iucv_dtr_rts()
702 * hvc_iucv_notifier_del() - HVC notifier for closing a TTY for the last time.
707 * This routine notifies the HVC back-end that the last tty device fd has been
708 * closed. The function cleans up tty resources. The clean-up of the IUCV
712 * Locking: struct hvc_iucv_private->lock
724 spin_lock_bh(&priv->lock); in hvc_iucv_notifier_del()
725 destroy_tty_buffer_list(&priv->tty_outqueue); in hvc_iucv_notifier_del()
726 destroy_tty_buffer_list(&priv->tty_inqueue); in hvc_iucv_notifier_del()
727 priv->tty_state = TTY_CLOSED; in hvc_iucv_notifier_del()
728 priv->sndbuf_len = 0; in hvc_iucv_notifier_del()
729 spin_unlock_bh(&priv->lock); in hvc_iucv_notifier_del()
733 * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID
734 * @ipvmid: Originating z/VM user ID (right padded with blanks)
736 * Returns 0 if the z/VM user ID that is specified with @ipvmid is permitted to
737 * connect, otherwise non-zero.
746 return 0; in hvc_iucv_filter_connreq()
748 for (i = 0; i < hvc_iucv_filter_size; i++) { in hvc_iucv_filter_connreq()
751 /* If a filter entry contains the filter wildcard character, in hvc_iucv_filter_connreq()
757 len = (wildcard) ? wildcard - filter_entry : 8; in hvc_iucv_filter_connreq()
758 if (0 == memcmp(ipvmid, filter_entry, len)) in hvc_iucv_filter_connreq()
759 return 0; in hvc_iucv_filter_connreq()
765 * hvc_iucv_path_pending() - IUCV handler to process a connection request.
767 * @ipvmid: z/VM system identifier of originator
772 * to a terminal managed by this device driver.
774 * multiple times (only one connection to a terminal is allowed).
778 * Returns 0 if @path belongs to a terminal managed by the this device driver;
779 * otherwise returns -ENODEV in order to dispatch this path to other handlers.
781 * Locking: struct hvc_iucv_private->lock
787 u8 wildcard[9] = "lnxhvc "; in hvc_iucv_path_pending()
790 u8 vm_user_id[9]; in hvc_iucv_path_pending()
797 * - find a disconnected device if ipuser contains the wildcard in hvc_iucv_path_pending()
798 * - find the device that matches the terminal ID in ipuser in hvc_iucv_path_pending()
801 for (i = 0; i < hvc_iucv_devices; i++) { in hvc_iucv_path_pending()
807 spin_lock(&tmp->lock); in hvc_iucv_path_pending()
808 if (tmp->iucv_state == IUCV_DISCONN) in hvc_iucv_path_pending()
810 spin_unlock(&tmp->lock); in hvc_iucv_path_pending()
812 } else if (!memcmp(tmp->srv_name, ipuser, 8)) in hvc_iucv_path_pending()
818 return -ENODEV; in hvc_iucv_path_pending()
828 vm_user_id[8] = 0; in hvc_iucv_path_pending()
829 pr_info("A connection request from z/VM user ID %s " in hvc_iucv_path_pending()
831 return 0; in hvc_iucv_path_pending()
834 spin_lock(&priv->lock); in hvc_iucv_path_pending()
839 if (priv->iucv_state != IUCV_DISCONN) { in hvc_iucv_path_pending()
848 path->msglim = 0xffff; /* IUCV MSGLIMIT */ in hvc_iucv_path_pending()
849 path->flags &= ~IUCV_IPRMDATA; /* TODO: use IUCV_IPRMDATA */ in hvc_iucv_path_pending()
856 priv->path = path; in hvc_iucv_path_pending()
857 priv->iucv_state = IUCV_CONNECTED; in hvc_iucv_path_pending()
860 memcpy(priv->info_path, ipvmid, 8); in hvc_iucv_path_pending()
861 memcpy(priv->info_path + 8, ipuser + 8, 8); in hvc_iucv_path_pending()
864 schedule_delayed_work(&priv->sndbuf_work, 5); in hvc_iucv_path_pending()
867 spin_unlock(&priv->lock); in hvc_iucv_path_pending()
868 return 0; in hvc_iucv_path_pending()
872 * hvc_iucv_path_severed() - IUCV handler to process a path sever.
880 * Locking: struct hvc_iucv_private->lock
884 struct hvc_iucv_private *priv = path->private; in hvc_iucv_path_severed()
890 * hvc_iucv_msg_pending() - IUCV handler to process an incoming IUCV message.
898 * Locking: struct hvc_iucv_private->lock
903 struct hvc_iucv_private *priv = path->private; in hvc_iucv_msg_pending()
906 /* reject messages that exceed max size of iucv_tty_msg->datalen */ in hvc_iucv_msg_pending()
907 if (msg->length > MSG_SIZE(MSG_MAX_DATALEN)) { in hvc_iucv_msg_pending()
912 spin_lock(&priv->lock); in hvc_iucv_msg_pending()
915 if (priv->tty_state == TTY_CLOSED) { in hvc_iucv_msg_pending()
921 rb = alloc_tty_buffer(0, GFP_ATOMIC); in hvc_iucv_msg_pending()
924 goto unlock_return; /* -ENOMEM */ in hvc_iucv_msg_pending()
926 rb->msg = *msg; in hvc_iucv_msg_pending()
928 list_add_tail(&rb->list, &priv->tty_inqueue); in hvc_iucv_msg_pending()
933 spin_unlock(&priv->lock); in hvc_iucv_msg_pending()
937 * hvc_iucv_msg_complete() - IUCV handler to process message completion
943 * msg->audit: rejected messages (0x040000 (IPADRJCT)), and
944 * purged messages (0x010000 (IPADPGNR)).
946 * Locking: struct hvc_iucv_private->lock
951 struct hvc_iucv_private *priv = path->private; in hvc_iucv_msg_complete()
955 spin_lock(&priv->lock); in hvc_iucv_msg_complete()
956 list_for_each_entry_safe(ent, next, &priv->tty_outqueue, list) in hvc_iucv_msg_complete()
957 if (ent->msg.id == msg->id) { in hvc_iucv_msg_complete()
958 list_move(&ent->list, &list_remove); in hvc_iucv_msg_complete()
961 wake_up(&priv->sndbuf_waitq); in hvc_iucv_msg_complete()
962 spin_unlock(&priv->lock); in hvc_iucv_msg_complete()
973 len = sizeof(priv->srv_name); in hvc_iucv_dev_termid_show()
974 memcpy(buf, priv->srv_name, len); in hvc_iucv_dev_termid_show()
985 return sprintf(buf, "%u:%u\n", priv->iucv_state, priv->tty_state); in hvc_iucv_dev_state_show()
993 char vmid[9], ipuser[9]; in hvc_iucv_dev_peer_show()
995 memset(vmid, 0, sizeof(vmid)); in hvc_iucv_dev_peer_show()
996 memset(ipuser, 0, sizeof(ipuser)); in hvc_iucv_dev_peer_show()
998 spin_lock_bh(&priv->lock); in hvc_iucv_dev_peer_show()
999 if (priv->iucv_state == IUCV_CONNECTED) { in hvc_iucv_dev_peer_show()
1000 memcpy(vmid, priv->info_path, 8); in hvc_iucv_dev_peer_show()
1001 memcpy(ipuser, priv->info_path + 8, 8); in hvc_iucv_dev_peer_show()
1003 spin_unlock_bh(&priv->lock); in hvc_iucv_dev_peer_show()
1040 * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
1044 * This function allocates a new hvc_iucv_private structure and stores
1046 * Returns 0 on success; otherwise non-zero.
1051 char name[9]; in hvc_iucv_alloc()
1056 return -ENOMEM; in hvc_iucv_alloc()
1058 spin_lock_init(&priv->lock); in hvc_iucv_alloc()
1059 INIT_LIST_HEAD(&priv->tty_outqueue); in hvc_iucv_alloc()
1060 INIT_LIST_HEAD(&priv->tty_inqueue); in hvc_iucv_alloc()
1061 INIT_DELAYED_WORK(&priv->sndbuf_work, hvc_iucv_sndbuf_work); in hvc_iucv_alloc()
1062 init_waitqueue_head(&priv->sndbuf_waitq); in hvc_iucv_alloc()
1064 priv->sndbuf = (void *) get_zeroed_page(GFP_KERNEL); in hvc_iucv_alloc()
1065 if (!priv->sndbuf) { in hvc_iucv_alloc()
1067 return -ENOMEM; in hvc_iucv_alloc()
1071 priv->is_console = is_console; in hvc_iucv_alloc()
1074 priv->hvc = hvc_alloc(id, /* PAGE_SIZE */ in hvc_iucv_alloc()
1076 if (IS_ERR(priv->hvc)) { in hvc_iucv_alloc()
1077 rc = PTR_ERR(priv->hvc); in hvc_iucv_alloc()
1082 priv->hvc->irq_requested = 1; in hvc_iucv_alloc()
1085 snprintf(name, 9, "lnxhvc%-2d", id); in hvc_iucv_alloc()
1086 memcpy(priv->srv_name, name, 8); in hvc_iucv_alloc()
1087 ASCEBC(priv->srv_name, 8); in hvc_iucv_alloc()
1090 priv->dev = kzalloc(sizeof(*priv->dev), GFP_KERNEL); in hvc_iucv_alloc()
1091 if (!priv->dev) { in hvc_iucv_alloc()
1092 rc = -ENOMEM; in hvc_iucv_alloc()
1095 dev_set_name(priv->dev, "hvc_iucv%d", id); in hvc_iucv_alloc()
1096 dev_set_drvdata(priv->dev, priv); in hvc_iucv_alloc()
1097 priv->dev->bus = &iucv_bus; in hvc_iucv_alloc()
1098 priv->dev->parent = iucv_root; in hvc_iucv_alloc()
1099 priv->dev->groups = hvc_iucv_dev_attr_groups; in hvc_iucv_alloc()
1100 priv->dev->release = (void (*)(struct device *)) kfree; in hvc_iucv_alloc()
1101 rc = device_register(priv->dev); in hvc_iucv_alloc()
1103 put_device(priv->dev); in hvc_iucv_alloc()
1108 return 0; in hvc_iucv_alloc()
1111 hvc_remove(priv->hvc); in hvc_iucv_alloc()
1113 free_page((unsigned long) priv->sndbuf); in hvc_iucv_alloc()
1120 * hvc_iucv_destroy() - Destroy and free hvc_iucv_private instances
1124 hvc_remove(priv->hvc); in hvc_iucv_destroy()
1125 device_unregister(priv->dev); in hvc_iucv_destroy()
1126 free_page((unsigned long) priv->sndbuf); in hvc_iucv_destroy()
1131 * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID
1132 * @filter: String containing a comma-separated list of z/VM user IDs
1133 * @dest: Location where to store the parsed z/VM user ID
1142 len = nextdelim - filter; in hvc_iucv_parse_filter()
1149 if (len == 0) in hvc_iucv_parse_filter()
1150 return ERR_PTR(-EINVAL); in hvc_iucv_parse_filter()
1153 if (filter[len - 1] == '\n') in hvc_iucv_parse_filter()
1154 len--; in hvc_iucv_parse_filter()
1158 return ERR_PTR(-EINVAL); in hvc_iucv_parse_filter()
1161 return ERR_PTR(-EINVAL); in hvc_iucv_parse_filter()
1165 while (len--) in hvc_iucv_parse_filter()
1171 * hvc_iucv_setup_filter() - Set up z/VM user ID filter
1172 * @filter: String consisting of a comma-separated list of z/VM user IDs
1175 * the list of z/VM user ID filter entries.
1176 * Return code 0 means success, -EINVAL if the filter is syntactically
1177 * incorrect, -ENOMEM if there was not enough memory to allocate the
1178 * filter list array, or -ENOSPC if too many z/VM user IDs have been specified.
1188 if (count == 0 || (count == 1 && val[0] == '\n')) { in hvc_iucv_setup_filter()
1189 size = 0; in hvc_iucv_setup_filter()
1204 return -ENOSPC; in hvc_iucv_setup_filter()
1208 return -ENOMEM; in hvc_iucv_setup_filter()
1214 array + ((size - count) * 8)); in hvc_iucv_setup_filter()
1220 count--; in hvc_iucv_setup_filter()
1231 err = 0; in hvc_iucv_setup_filter()
1237 * param_set_vmidfilter() - Set z/VM user ID filter parameter
1238 * @val: String consisting of a comma-separated list of z/VM user IDs
1241 * The function sets up the z/VM user ID filter specified as comma-separated
1251 return -ENODEV; in param_set_vmidfilter()
1254 return -EINVAL; in param_set_vmidfilter()
1256 rc = 0; in param_set_vmidfilter()
1265 * param_get_vmidfilter() - Get z/VM user ID filter
1266 * @buffer: Buffer to store z/VM user ID filter,
1270 * The function stores the filter as a comma-separated list of z/VM user IDs
1280 return -ENODEV; in param_get_vmidfilter()
1282 rc = 0; in param_get_vmidfilter()
1284 for (index = 0; index < hvc_iucv_filter_size; index++) { in param_get_vmidfilter()
1287 len = (end) ? end - start : 8; in param_get_vmidfilter()
1294 buffer[--rc] = '\0'; /* replace last comma and update rc */ in param_get_vmidfilter()
1306 * hvc_iucv_init() - z/VM IUCV HVC device driver initialization
1314 return -ENODEV; in hvc_iucv_init()
1317 pr_notice("The z/VM IUCV HVC device driver cannot " in hvc_iucv_init()
1318 "be used without z/VM\n"); in hvc_iucv_init()
1319 rc = -ENODEV; in hvc_iucv_init()
1324 pr_err("%lu is not a valid value for the hvc_iucv= " in hvc_iucv_init()
1326 rc = -EINVAL; in hvc_iucv_init()
1330 /* parse hvc_iucv_allow string and create z/VM user ID filter list */ in hvc_iucv_init()
1334 case 0: in hvc_iucv_init()
1336 case -ENOMEM: in hvc_iucv_init()
1340 case -EINVAL: in hvc_iucv_init()
1341 pr_err("hvc_iucv_allow= does not specify a valid " in hvc_iucv_init()
1342 "z/VM user ID list\n"); in hvc_iucv_init()
1344 case -ENOSPC: in hvc_iucv_init()
1346 "z/VM user IDs\n"); in hvc_iucv_init()
1355 0, 0, NULL); in hvc_iucv_init()
1358 rc = -ENOMEM; in hvc_iucv_init()
1367 rc = -ENOMEM; in hvc_iucv_init()
1373 rc = hvc_instantiate(0, IUCV_HVC_CON_IDX, &hvc_iucv_ops); in hvc_iucv_init()
1381 for (i = 0; i < hvc_iucv_devices; i++) { in hvc_iucv_init()
1382 rc = hvc_iucv_alloc(i, (i == IUCV_HVC_CON_IDX) ? 1 : 0); in hvc_iucv_init()
1384 pr_err("Creating a new HVC terminal device " in hvc_iucv_init()
1391 rc = iucv_register(&hvc_iucv_handler, 0); in hvc_iucv_init()
1398 return 0; in hvc_iucv_init()
1401 for (i = 0; i < hvc_iucv_devices; i++) in hvc_iucv_init()
1409 hvc_iucv_devices = 0; /* ensure that we do not provide any device */ in hvc_iucv_init()
1414 * hvc_iucv_config() - Parsing of hvc_iucv= kernel command line parameter