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.
32 #define HVC_IUCV_MAGIC 0xc9e4c3e5
37 #define MSG_VERSION 0x02 /* Message version */
38 #define MSG_TYPE_ERROR 0x01 /* Error message */
39 #define MSG_TYPE_TERMENV 0x02 /* Terminal environment variable */
40 #define MSG_TYPE_TERMIOS 0x04 /* Terminal IO struct update */
41 #define MSG_TYPE_WINSIZE 0x08 /* Terminal window size update */
42 #define MSG_TYPE_DATA 0x10 /* Terminal data */
47 #define MSG_MAX_DATALEN ((u16)(~0))
54 IUCV_DISCONN = 0,
60 TTY_CLOSED = 0,
103 #define IUCV_HVC_CON_IDX (0)
104 /* List of z/VM user ID filter entries (struct iucv_vmid_filter) */
126 * hvc_iucv_get_private() - Return a struct hvc_iucv_private instance.
134 if ((num < HVC_IUCV_MAGIC) || (num - HVC_IUCV_MAGIC > hvc_iucv_devices)) in hvc_iucv_get_private()
136 return hvc_iucv_table[num - HVC_IUCV_MAGIC]; in hvc_iucv_get_private()
140 * alloc_tty_buffer() - Return a new struct iucv_tty_buffer element.
144 * This function allocates a new struct iucv_tty_buffer element and, optionally,
159 memset(bufp, 0, sizeof(*bufp)); in alloc_tty_buffer()
161 if (size > 0) { in alloc_tty_buffer()
162 bufp->msg.length = MSG_SIZE(size); in alloc_tty_buffer()
163 bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA); in alloc_tty_buffer()
164 if (!bufp->mbuf) { in alloc_tty_buffer()
168 bufp->mbuf->version = MSG_VERSION; in alloc_tty_buffer()
169 bufp->mbuf->type = MSG_TYPE_DATA; in alloc_tty_buffer()
170 bufp->mbuf->datalen = (u16) size; in alloc_tty_buffer()
176 * destroy_tty_buffer() - destroy struct iucv_tty_buffer element.
177 * @bufp: Pointer to a struct iucv_tty_buffer element, SHALL NOT be NULL.
181 kfree(bufp->mbuf); in destroy_tty_buffer()
186 * destroy_tty_buffer_list() - call destroy_tty_buffer() for each list element.
194 list_del(&ent->list); in destroy_tty_buffer_list()
200 * hvc_iucv_write() - Receive IUCV message & write data to HVC buffer.
216 * If the IUCV path has been severed, then -EPIPE is returned to cause a
227 if (priv->iucv_state == IUCV_DISCONN) in hvc_iucv_write()
228 return 0; in hvc_iucv_write()
230 /* if the IUCV path has been severed, return -EPIPE to inform the in hvc_iucv_write()
232 if (priv->iucv_state == IUCV_SEVERED) in hvc_iucv_write()
233 return -EPIPE; in hvc_iucv_write()
236 if (list_empty(&priv->tty_inqueue)) in hvc_iucv_write()
237 return 0; in hvc_iucv_write()
240 rb = list_first_entry(&priv->tty_inqueue, struct iucv_tty_buffer, list); in hvc_iucv_write()
242 written = 0; in hvc_iucv_write()
243 if (!rb->mbuf) { /* message not yet received ... */ in hvc_iucv_write()
245 * then leave the buffer on the list and re-try later */ in hvc_iucv_write()
246 rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA); in hvc_iucv_write()
247 if (!rb->mbuf) in hvc_iucv_write()
248 return -ENOMEM; in hvc_iucv_write()
250 rc = __iucv_message_receive(priv->path, &rb->msg, 0, in hvc_iucv_write()
251 rb->mbuf, rb->msg.length, NULL); in hvc_iucv_write()
253 case 0: /* Successful */ in hvc_iucv_write()
256 case 9: /* Message purged */ in hvc_iucv_write()
259 written = -EIO; in hvc_iucv_write()
263 if (rc || (rb->mbuf->version != MSG_VERSION) || in hvc_iucv_write()
264 (rb->msg.length != MSG_SIZE(rb->mbuf->datalen))) in hvc_iucv_write()
268 switch (rb->mbuf->type) { in hvc_iucv_write()
270 written = min_t(int, rb->mbuf->datalen - rb->offset, count); in hvc_iucv_write()
271 memcpy(buf, rb->mbuf->data + rb->offset, written); in hvc_iucv_write()
272 if (written < (rb->mbuf->datalen - rb->offset)) { in hvc_iucv_write()
273 rb->offset += written; in hvc_iucv_write()
280 if (rb->mbuf->datalen != sizeof(struct winsize)) in hvc_iucv_write()
284 __hvc_resize(priv->hvc, *((struct winsize *) rb->mbuf->data)); in hvc_iucv_write()
294 list_del(&rb->list); in hvc_iucv_write()
296 *has_more_data = !list_empty(&priv->tty_inqueue); in hvc_iucv_write()
303 * hvc_iucv_get_chars() - HVC get_chars operation.
305 * @buf: Pointer to a buffer to store data
308 * The HVC thread calls this method to read characters from the back-end.
313 * the routine locks the struct hvc_iucv_private->lock to call
322 if (count <= 0) in hvc_iucv_get_chars()
323 return 0; in hvc_iucv_get_chars()
326 return -ENODEV; in hvc_iucv_get_chars()
328 spin_lock(&priv->lock); in hvc_iucv_get_chars()
329 has_more_data = 0; in hvc_iucv_get_chars()
331 spin_unlock(&priv->lock); in hvc_iucv_get_chars()
341 * hvc_iucv_queue() - Buffer terminal data for sending.
347 * a work queue function is scheduled (with QUEUE_SNDBUF_DELAY).
352 * If the buffer is full, the function returns 0.
353 * If an existing IUCV communicaton path has been severed, -EPIPE is returned
354 * (that can be passed to HVC layer to cause a tty hangup).
361 if (priv->iucv_state == IUCV_DISCONN) in hvc_iucv_queue()
364 if (priv->iucv_state == IUCV_SEVERED) in hvc_iucv_queue()
365 return -EPIPE; in hvc_iucv_queue()
367 len = min_t(size_t, count, SNDBUF_SIZE - priv->sndbuf_len); in hvc_iucv_queue()
369 return 0; in hvc_iucv_queue()
371 memcpy(priv->sndbuf + priv->sndbuf_len, buf, len); in hvc_iucv_queue()
372 priv->sndbuf_len += len; in hvc_iucv_queue()
374 if (priv->iucv_state == IUCV_CONNECTED) in hvc_iucv_queue()
375 schedule_delayed_work(&priv->sndbuf_work, QUEUE_SNDBUF_DELAY); in hvc_iucv_queue()
381 * hvc_iucv_send() - Send an IUCV message containing terminal data.
386 * Returns 0 if there is no established IUCV communication path or
387 * -EPIPE if an existing IUCV communicaton path has been severed.
394 if (priv->iucv_state == IUCV_SEVERED) in hvc_iucv_send()
395 return -EPIPE; in hvc_iucv_send()
397 if (priv->iucv_state == IUCV_DISCONN) in hvc_iucv_send()
398 return -EIO; in hvc_iucv_send()
400 if (!priv->sndbuf_len) in hvc_iucv_send()
401 return 0; in hvc_iucv_send()
405 sb = alloc_tty_buffer(priv->sndbuf_len, GFP_ATOMIC); in hvc_iucv_send()
407 return -ENOMEM; in hvc_iucv_send()
409 memcpy(sb->mbuf->data, priv->sndbuf, priv->sndbuf_len); in hvc_iucv_send()
410 sb->mbuf->datalen = (u16) priv->sndbuf_len; in hvc_iucv_send()
411 sb->msg.length = MSG_SIZE(sb->mbuf->datalen); in hvc_iucv_send()
413 list_add_tail(&sb->list, &priv->tty_outqueue); in hvc_iucv_send()
415 rc = __iucv_message_send(priv->path, &sb->msg, 0, 0, in hvc_iucv_send()
416 (void *) sb->mbuf, sb->msg.length); in hvc_iucv_send()
419 * 0x03 (msg limit reached) by trying again... */ in hvc_iucv_send()
420 list_del(&sb->list); in hvc_iucv_send()
423 len = priv->sndbuf_len; in hvc_iucv_send()
424 priv->sndbuf_len = 0; in hvc_iucv_send()
430 * hvc_iucv_sndbuf_work() - Send buffered data over IUCV
444 spin_lock_bh(&priv->lock); in hvc_iucv_sndbuf_work()
446 spin_unlock_bh(&priv->lock); in hvc_iucv_sndbuf_work()
450 * hvc_iucv_put_chars() - HVC put_chars operation.
455 * The HVC thread calls this method to write characters to the back-end.
459 * locks struct hvc_iucv_private->lock.
466 if (count <= 0) in hvc_iucv_put_chars()
467 return 0; in hvc_iucv_put_chars()
470 return -ENODEV; in hvc_iucv_put_chars()
472 spin_lock(&priv->lock); in hvc_iucv_put_chars()
474 spin_unlock(&priv->lock); in hvc_iucv_put_chars()
480 * hvc_iucv_notifier_add() - HVC notifier for opening a TTY for the first time.
486 * instance that is derived from @id. Always returns 0.
488 * Locking: struct hvc_iucv_private->lock, spin_lock_bh
496 return 0; in hvc_iucv_notifier_add()
498 spin_lock_bh(&priv->lock); in hvc_iucv_notifier_add()
499 priv->tty_state = TTY_OPENED; in hvc_iucv_notifier_add()
500 spin_unlock_bh(&priv->lock); in hvc_iucv_notifier_add()
502 return 0; in hvc_iucv_notifier_add()
506 * hvc_iucv_cleanup() - Clean up and reset a z/VM IUCV HVC instance.
511 destroy_tty_buffer_list(&priv->tty_outqueue); in hvc_iucv_cleanup()
512 destroy_tty_buffer_list(&priv->tty_inqueue); in hvc_iucv_cleanup()
514 priv->tty_state = TTY_CLOSED; in hvc_iucv_cleanup()
515 priv->iucv_state = IUCV_DISCONN; in hvc_iucv_cleanup()
517 priv->sndbuf_len = 0; in hvc_iucv_cleanup()
521 * tty_outqueue_empty() - Test if the tty outq is empty
528 spin_lock_bh(&priv->lock); in tty_outqueue_empty()
529 rc = list_empty(&priv->tty_outqueue); in tty_outqueue_empty()
530 spin_unlock_bh(&priv->lock); in tty_outqueue_empty()
536 * flush_sndbuf_sync() - Flush send buffer and wait for completion
539 * The routine cancels a pending sndbuf work, calls hvc_iucv_send()
546 cancel_delayed_work_sync(&priv->sndbuf_work); in flush_sndbuf_sync()
548 spin_lock_bh(&priv->lock); in flush_sndbuf_sync()
550 sync_wait = !list_empty(&priv->tty_outqueue); /* anything queued ? */ in flush_sndbuf_sync()
551 spin_unlock_bh(&priv->lock); in flush_sndbuf_sync()
554 wait_event_timeout(priv->sndbuf_waitq, in flush_sndbuf_sync()
559 * hvc_iucv_hangup() - Sever IUCV path and schedule hvc tty hang up
564 * The hang-up occurs only if an IUCV communication path is established;
567 * The IUCV HVC hang-up is separated into two steps:
571 * IUCV_SEVERED state causes the tty hang-up in the HVC layer.
574 * structure to allow re-connects.
575 * If the tty has been opened, let get_chars() return -EPIPE to signal
579 * Special notes on hanging up a HVC terminal instantiated as console:
580 * Hang-up: 1. do_tty_hangup() replaces file ops (= hung_up_tty_fops)
581 * 2. do_tty_hangup() calls tty->ops->close() for console_filp
585 * Finally, the back-end is not being notified, thus, the tty session is
586 * kept active (TTY_OPEN) to be ready for re-connects.
588 * Locking: spin_lock(&priv->lock) w/o disabling bh
595 spin_lock(&priv->lock); in hvc_iucv_hangup()
596 if (priv->iucv_state == IUCV_CONNECTED) { in hvc_iucv_hangup()
597 path = priv->path; in hvc_iucv_hangup()
598 priv->path = NULL; in hvc_iucv_hangup()
599 priv->iucv_state = IUCV_SEVERED; in hvc_iucv_hangup()
600 if (priv->tty_state == TTY_CLOSED) in hvc_iucv_hangup()
604 if (priv->is_console) { in hvc_iucv_hangup()
606 priv->tty_state = TTY_OPENED; in hvc_iucv_hangup()
610 spin_unlock(&priv->lock); in hvc_iucv_hangup()
612 /* finally sever path (outside of priv->lock due to lock ordering) */ in hvc_iucv_hangup()
620 * hvc_iucv_notifier_hangup() - HVC notifier for TTY hangups.
625 * This routine notifies the HVC back-end that a tty hangup (carrier loss,
627 * The z/VM IUCV HVC device driver ignores virtual hangups (vhangup())
634 * Locking: struct hvc_iucv_private->lock
646 spin_lock_bh(&priv->lock); in hvc_iucv_notifier_hangup()
654 priv->tty_state = TTY_CLOSED; in hvc_iucv_notifier_hangup()
656 if (priv->iucv_state == IUCV_SEVERED) in hvc_iucv_notifier_hangup()
658 spin_unlock_bh(&priv->lock); in hvc_iucv_notifier_hangup()
662 * hvc_iucv_dtr_rts() - HVC notifier for handling DTR/RTS
664 * @raise: Non-zero to raise or zero to lower DTR/RTS lines
666 * This routine notifies the HVC back-end to raise or lower DTR/RTS
681 priv = hvc_iucv_get_private(hp->vtermno); in hvc_iucv_dtr_rts()
690 spin_lock_bh(&priv->lock); in hvc_iucv_dtr_rts()
691 path = priv->path; /* save reference to IUCV path */ in hvc_iucv_dtr_rts()
692 priv->path = NULL; in hvc_iucv_dtr_rts()
693 priv->iucv_state = IUCV_DISCONN; in hvc_iucv_dtr_rts()
694 spin_unlock_bh(&priv->lock); in hvc_iucv_dtr_rts()
696 /* Sever IUCV path outside of priv->lock due to lock ordering of: in hvc_iucv_dtr_rts()
697 * priv->lock <--> iucv_table_lock */ in hvc_iucv_dtr_rts()
705 * hvc_iucv_notifier_del() - HVC notifier for closing a TTY for the last time.
710 * This routine notifies the HVC back-end that the last tty device fd has been
711 * closed. The function cleans up tty resources. The clean-up of the IUCV
715 * Locking: struct hvc_iucv_private->lock
727 spin_lock_bh(&priv->lock); in hvc_iucv_notifier_del()
728 destroy_tty_buffer_list(&priv->tty_outqueue); in hvc_iucv_notifier_del()
729 destroy_tty_buffer_list(&priv->tty_inqueue); in hvc_iucv_notifier_del()
730 priv->tty_state = TTY_CLOSED; in hvc_iucv_notifier_del()
731 priv->sndbuf_len = 0; in hvc_iucv_notifier_del()
732 spin_unlock_bh(&priv->lock); in hvc_iucv_notifier_del()
736 * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID
737 * @ipvmid: Originating z/VM user ID (right padded with blanks)
739 * Returns 0 if the z/VM user ID that is specified with @ipvmid is permitted to
740 * connect, otherwise non-zero.
749 return 0; in hvc_iucv_filter_connreq()
751 for (i = 0; i < hvc_iucv_filter_size; i++) { in hvc_iucv_filter_connreq()
754 /* If a filter entry contains the filter wildcard character, in hvc_iucv_filter_connreq()
760 len = (wildcard) ? wildcard - filter_entry : 8; in hvc_iucv_filter_connreq()
761 if (0 == memcmp(ipvmid, filter_entry, len)) in hvc_iucv_filter_connreq()
762 return 0; in hvc_iucv_filter_connreq()
768 * hvc_iucv_path_pending() - IUCV handler to process a connection request.
770 * @ipvmid: z/VM system identifier of originator
775 * to a terminal managed by this device driver.
777 * multiple times (only one connection to a terminal is allowed).
781 * Returns 0 if @path belongs to a terminal managed by the this device driver;
782 * otherwise returns -ENODEV in order to dispatch this path to other handlers.
784 * Locking: struct hvc_iucv_private->lock
790 u8 wildcard[9] = "lnxhvc "; in hvc_iucv_path_pending()
793 u8 vm_user_id[9]; in hvc_iucv_path_pending()
800 * - find a disconnected device if ipuser contains the wildcard in hvc_iucv_path_pending()
801 * - find the device that matches the terminal ID in ipuser in hvc_iucv_path_pending()
804 for (i = 0; i < hvc_iucv_devices; i++) { in hvc_iucv_path_pending()
810 spin_lock(&tmp->lock); in hvc_iucv_path_pending()
811 if (tmp->iucv_state == IUCV_DISCONN) in hvc_iucv_path_pending()
813 spin_unlock(&tmp->lock); in hvc_iucv_path_pending()
815 } else if (!memcmp(tmp->srv_name, ipuser, 8)) in hvc_iucv_path_pending()
821 return -ENODEV; in hvc_iucv_path_pending()
831 vm_user_id[8] = 0; in hvc_iucv_path_pending()
832 pr_info("A connection request from z/VM user ID %s " in hvc_iucv_path_pending()
834 return 0; in hvc_iucv_path_pending()
837 spin_lock(&priv->lock); in hvc_iucv_path_pending()
842 if (priv->iucv_state != IUCV_DISCONN) { in hvc_iucv_path_pending()
851 path->msglim = 0xffff; /* IUCV MSGLIMIT */ in hvc_iucv_path_pending()
852 path->flags &= ~IUCV_IPRMDATA; /* TODO: use IUCV_IPRMDATA */ in hvc_iucv_path_pending()
859 priv->path = path; in hvc_iucv_path_pending()
860 priv->iucv_state = IUCV_CONNECTED; in hvc_iucv_path_pending()
863 memcpy(priv->info_path, ipvmid, 8); in hvc_iucv_path_pending()
864 memcpy(priv->info_path + 8, ipuser + 8, 8); in hvc_iucv_path_pending()
867 schedule_delayed_work(&priv->sndbuf_work, 5); in hvc_iucv_path_pending()
870 spin_unlock(&priv->lock); in hvc_iucv_path_pending()
871 return 0; in hvc_iucv_path_pending()
875 * hvc_iucv_path_severed() - IUCV handler to process a path sever.
883 * Locking: struct hvc_iucv_private->lock
887 struct hvc_iucv_private *priv = path->private; in hvc_iucv_path_severed()
893 * hvc_iucv_msg_pending() - IUCV handler to process an incoming IUCV message.
901 * Locking: struct hvc_iucv_private->lock
906 struct hvc_iucv_private *priv = path->private; in hvc_iucv_msg_pending()
909 /* reject messages that exceed max size of iucv_tty_msg->datalen */ in hvc_iucv_msg_pending()
910 if (msg->length > MSG_SIZE(MSG_MAX_DATALEN)) { in hvc_iucv_msg_pending()
915 spin_lock(&priv->lock); in hvc_iucv_msg_pending()
918 if (priv->tty_state == TTY_CLOSED) { in hvc_iucv_msg_pending()
924 rb = alloc_tty_buffer(0, GFP_ATOMIC); in hvc_iucv_msg_pending()
927 goto unlock_return; /* -ENOMEM */ in hvc_iucv_msg_pending()
929 rb->msg = *msg; in hvc_iucv_msg_pending()
931 list_add_tail(&rb->list, &priv->tty_inqueue); in hvc_iucv_msg_pending()
936 spin_unlock(&priv->lock); in hvc_iucv_msg_pending()
940 * hvc_iucv_msg_complete() - IUCV handler to process message completion
946 * msg->audit: rejected messages (0x040000 (IPADRJCT)), and
947 * purged messages (0x010000 (IPADPGNR)).
949 * Locking: struct hvc_iucv_private->lock
954 struct hvc_iucv_private *priv = path->private; in hvc_iucv_msg_complete()
958 spin_lock(&priv->lock); in hvc_iucv_msg_complete()
959 list_for_each_entry_safe(ent, next, &priv->tty_outqueue, list) in hvc_iucv_msg_complete()
960 if (ent->msg.id == msg->id) { in hvc_iucv_msg_complete()
961 list_move(&ent->list, &list_remove); in hvc_iucv_msg_complete()
964 wake_up(&priv->sndbuf_waitq); in hvc_iucv_msg_complete()
965 spin_unlock(&priv->lock); in hvc_iucv_msg_complete()
970 * hvc_iucv_pm_freeze() - Freeze PM callback
974 * trigger a hang-up of the underlying HVC terminal.
984 return 0; in hvc_iucv_pm_freeze()
988 * hvc_iucv_pm_restore_thaw() - Thaw and restore PM callback
991 * Wake up the HVC thread to trigger hang-up and respective
992 * HVC back-end notifier invocations.
997 return 0; in hvc_iucv_pm_restore_thaw()
1007 len = sizeof(priv->srv_name); in hvc_iucv_dev_termid_show()
1008 memcpy(buf, priv->srv_name, len); in hvc_iucv_dev_termid_show()
1019 return sprintf(buf, "%u:%u\n", priv->iucv_state, priv->tty_state); in hvc_iucv_dev_state_show()
1027 char vmid[9], ipuser[9]; in hvc_iucv_dev_peer_show()
1029 memset(vmid, 0, sizeof(vmid)); in hvc_iucv_dev_peer_show()
1030 memset(ipuser, 0, sizeof(ipuser)); in hvc_iucv_dev_peer_show()
1032 spin_lock_bh(&priv->lock); in hvc_iucv_dev_peer_show()
1033 if (priv->iucv_state == IUCV_CONNECTED) { in hvc_iucv_dev_peer_show()
1034 memcpy(vmid, priv->info_path, 8); in hvc_iucv_dev_peer_show()
1035 memcpy(ipuser, priv->info_path + 8, 8); in hvc_iucv_dev_peer_show()
1037 spin_unlock_bh(&priv->lock); in hvc_iucv_dev_peer_show()
1088 * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
1092 * This function allocates a new hvc_iucv_private structure and stores
1094 * Returns 0 on success; otherwise non-zero.
1099 char name[9]; in hvc_iucv_alloc()
1104 return -ENOMEM; in hvc_iucv_alloc()
1106 spin_lock_init(&priv->lock); in hvc_iucv_alloc()
1107 INIT_LIST_HEAD(&priv->tty_outqueue); in hvc_iucv_alloc()
1108 INIT_LIST_HEAD(&priv->tty_inqueue); in hvc_iucv_alloc()
1109 INIT_DELAYED_WORK(&priv->sndbuf_work, hvc_iucv_sndbuf_work); in hvc_iucv_alloc()
1110 init_waitqueue_head(&priv->sndbuf_waitq); in hvc_iucv_alloc()
1112 priv->sndbuf = (void *) get_zeroed_page(GFP_KERNEL); in hvc_iucv_alloc()
1113 if (!priv->sndbuf) { in hvc_iucv_alloc()
1115 return -ENOMEM; in hvc_iucv_alloc()
1119 priv->is_console = is_console; in hvc_iucv_alloc()
1122 priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, /* PAGE_SIZE */ in hvc_iucv_alloc()
1124 if (IS_ERR(priv->hvc)) { in hvc_iucv_alloc()
1125 rc = PTR_ERR(priv->hvc); in hvc_iucv_alloc()
1130 priv->hvc->irq_requested = 1; in hvc_iucv_alloc()
1133 snprintf(name, 9, "lnxhvc%-2d", id); in hvc_iucv_alloc()
1134 memcpy(priv->srv_name, name, 8); in hvc_iucv_alloc()
1135 ASCEBC(priv->srv_name, 8); in hvc_iucv_alloc()
1138 priv->dev = kzalloc(sizeof(*priv->dev), GFP_KERNEL); in hvc_iucv_alloc()
1139 if (!priv->dev) { in hvc_iucv_alloc()
1140 rc = -ENOMEM; in hvc_iucv_alloc()
1143 dev_set_name(priv->dev, "hvc_iucv%d", id); in hvc_iucv_alloc()
1144 dev_set_drvdata(priv->dev, priv); in hvc_iucv_alloc()
1145 priv->dev->bus = &iucv_bus; in hvc_iucv_alloc()
1146 priv->dev->parent = iucv_root; in hvc_iucv_alloc()
1147 priv->dev->driver = &hvc_iucv_driver; in hvc_iucv_alloc()
1148 priv->dev->groups = hvc_iucv_dev_attr_groups; in hvc_iucv_alloc()
1149 priv->dev->release = (void (*)(struct device *)) kfree; in hvc_iucv_alloc()
1150 rc = device_register(priv->dev); in hvc_iucv_alloc()
1152 put_device(priv->dev); in hvc_iucv_alloc()
1157 return 0; in hvc_iucv_alloc()
1160 hvc_remove(priv->hvc); in hvc_iucv_alloc()
1162 free_page((unsigned long) priv->sndbuf); in hvc_iucv_alloc()
1169 * hvc_iucv_destroy() - Destroy and free hvc_iucv_private instances
1173 hvc_remove(priv->hvc); in hvc_iucv_destroy()
1174 device_unregister(priv->dev); in hvc_iucv_destroy()
1175 free_page((unsigned long) priv->sndbuf); in hvc_iucv_destroy()
1180 * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID
1181 * @filter: String containing a comma-separated list of z/VM user IDs
1182 * @dest: Location where to store the parsed z/VM user ID
1191 len = nextdelim - filter; in hvc_iucv_parse_filter()
1198 if (len == 0) in hvc_iucv_parse_filter()
1199 return ERR_PTR(-EINVAL); in hvc_iucv_parse_filter()
1202 if (filter[len - 1] == '\n') in hvc_iucv_parse_filter()
1203 len--; in hvc_iucv_parse_filter()
1207 return ERR_PTR(-EINVAL); in hvc_iucv_parse_filter()
1210 return ERR_PTR(-EINVAL); in hvc_iucv_parse_filter()
1214 while (len--) in hvc_iucv_parse_filter()
1220 * hvc_iucv_setup_filter() - Set up z/VM user ID filter
1221 * @filter: String consisting of a comma-separated list of z/VM user IDs
1224 * the list of z/VM user ID filter entries.
1225 * Return code 0 means success, -EINVAL if the filter is syntactically
1226 * incorrect, -ENOMEM if there was not enough memory to allocate the
1227 * filter list array, or -ENOSPC if too many z/VM user IDs have been specified.
1237 if (count == 0 || (count == 1 && val[0] == '\n')) { in hvc_iucv_setup_filter()
1238 size = 0; in hvc_iucv_setup_filter()
1253 return -ENOSPC; in hvc_iucv_setup_filter()
1257 return -ENOMEM; in hvc_iucv_setup_filter()
1263 array + ((size - count) * 8)); in hvc_iucv_setup_filter()
1269 count--; in hvc_iucv_setup_filter()
1280 err = 0; in hvc_iucv_setup_filter()
1286 * param_set_vmidfilter() - Set z/VM user ID filter parameter
1287 * @val: String consisting of a comma-separated list of z/VM user IDs
1290 * The function sets up the z/VM user ID filter specified as comma-separated
1300 return -ENODEV; in param_set_vmidfilter()
1303 return -EINVAL; in param_set_vmidfilter()
1305 rc = 0; in param_set_vmidfilter()
1314 * param_get_vmidfilter() - Get z/VM user ID filter
1315 * @buffer: Buffer to store z/VM user ID filter,
1319 * The function stores the filter as a comma-separated list of z/VM user IDs
1329 return -ENODEV; in param_get_vmidfilter()
1331 rc = 0; in param_get_vmidfilter()
1333 for (index = 0; index < hvc_iucv_filter_size; index++) { in param_get_vmidfilter()
1336 len = (end) ? end - start : 8; in param_get_vmidfilter()
1343 buffer[--rc] = '\0'; /* replace last comma and update rc */ in param_get_vmidfilter()
1355 * hvc_iucv_init() - z/VM IUCV HVC device driver initialization
1363 return -ENODEV; in hvc_iucv_init()
1366 pr_notice("The z/VM IUCV HVC device driver cannot " in hvc_iucv_init()
1367 "be used without z/VM\n"); in hvc_iucv_init()
1368 rc = -ENODEV; in hvc_iucv_init()
1373 pr_err("%lu is not a valid value for the hvc_iucv= " in hvc_iucv_init()
1375 rc = -EINVAL; in hvc_iucv_init()
1384 /* parse hvc_iucv_allow string and create z/VM user ID filter list */ in hvc_iucv_init()
1388 case 0: in hvc_iucv_init()
1390 case -ENOMEM: in hvc_iucv_init()
1394 case -EINVAL: in hvc_iucv_init()
1395 pr_err("hvc_iucv_allow= does not specify a valid " in hvc_iucv_init()
1396 "z/VM user ID list\n"); in hvc_iucv_init()
1398 case -ENOSPC: in hvc_iucv_init()
1400 "z/VM user IDs\n"); in hvc_iucv_init()
1409 0, 0, NULL); in hvc_iucv_init()
1412 rc = -ENOMEM; in hvc_iucv_init()
1421 rc = -ENOMEM; in hvc_iucv_init()
1435 for (i = 0; i < hvc_iucv_devices; i++) { in hvc_iucv_init()
1436 rc = hvc_iucv_alloc(i, (i == IUCV_HVC_CON_IDX) ? 1 : 0); in hvc_iucv_init()
1438 pr_err("Creating a new HVC terminal device " in hvc_iucv_init()
1445 rc = iucv_register(&hvc_iucv_handler, 0); in hvc_iucv_init()
1452 return 0; in hvc_iucv_init()
1455 for (i = 0; i < hvc_iucv_devices; i++) in hvc_iucv_init()
1463 hvc_iucv_devices = 0; /* ensure that we do not provide any device */ in hvc_iucv_init()
1468 * hvc_iucv_config() - Parsing of hvc_iucv= kernel command line parameter