brintos

brintos / linux-shallow public Read only

0
0
Text · 42.9 KiB · f57fd90 Raw
1547 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * IBM eServer Hypervisor Virtual Console Server Device Driver4 * Copyright (C) 2003, 2004 IBM Corp.5 *  Ryan S. Arnold (rsa@us.ibm.com)6 *7 * Author(s) :  Ryan S. Arnold <rsa@us.ibm.com>8 *9 * This is the device driver for the IBM Hypervisor Virtual Console Server,10 * "hvcs".  The IBM hvcs provides a tty driver interface to allow Linux11 * user space applications access to the system consoles of logically12 * partitioned operating systems, e.g. Linux, running on the same partitioned13 * Power5 ppc64 system.  Physical hardware consoles per partition are not14 * practical on this hardware so system consoles are accessed by this driver15 * using inter-partition firmware interfaces to virtual terminal devices.16 *17 * A vty is known to the HMC as a "virtual serial server adapter".  It is a18 * virtual terminal device that is created by firmware upon partition creation19 * to act as a partitioned OS's console device.20 *21 * Firmware dynamically (via hotplug) exposes vty-servers to a running ppc6422 * Linux system upon their creation by the HMC or their exposure during boot.23 * The non-user interactive backend of this driver is implemented as a vio24 * device driver so that it can receive notification of vty-server lifetimes25 * after it registers with the vio bus to handle vty-server probe and remove26 * callbacks.27 *28 * Many vty-servers can be configured to connect to one vty, but a vty can29 * only be actively connected to by a single vty-server, in any manner, at one30 * time.  If the HMC is currently hosting the console for a target Linux31 * partition; attempts to open the tty device to the partition's console using32 * the hvcs on any partition will return -EBUSY with every open attempt until33 * the HMC frees the connection between its vty-server and the desired34 * partition's vty device.  Conversely, a vty-server may only be connected to35 * a single vty at one time even though it may have several configured vty36 * partner possibilities.37 *38 * Firmware does not provide notification of vty partner changes to this39 * driver.  This means that an HMC Super Admin may add or remove partner vtys40 * from a vty-server's partner list but the changes will not be signaled to41 * the vty-server.  Firmware only notifies the driver when a vty-server is42 * added or removed from the system.  To compensate for this deficiency, this43 * driver implements a sysfs update attribute which provides a method for44 * rescanning partner information upon a user's request.45 *46 * Each vty-server, prior to being exposed to this driver is reference counted47 * using the 2.6 Linux kernel kref construct.48 *49 * For direction on installation and usage of this driver please reference50 * Documentation/arch/powerpc/hvcs.rst.51 */52 53#include <linux/device.h>54#include <linux/init.h>55#include <linux/completion.h>56#include <linux/interrupt.h>57#include <linux/kernel.h>58#include <linux/kref.h>59#include <linux/kthread.h>60#include <linux/list.h>61#include <linux/major.h>62#include <linux/module.h>63#include <linux/moduleparam.h>64#include <linux/sched.h>65#include <linux/slab.h>66#include <linux/spinlock.h>67#include <linux/stat.h>68#include <linux/tty.h>69#include <linux/tty_flip.h>70#include <asm/hvconsole.h>71#include <asm/hvcserver.h>72#include <linux/uaccess.h>73#include <linux/termios_internal.h>74#include <asm/vio.h>75 76/*77 * 1.3.0 -> 1.3.1 In hvcs_open memset(..,0x00,..) instead of memset(..,0x3F,00).78 * Removed braces around single statements following conditionals.  Removed '=79 * 0' after static int declarations since these default to zero.  Removed80 * list_for_each_safe() and replaced with list_for_each_entry() in81 * hvcs_get_by_index().  The 'safe' version is un-needed now that the driver is82 * using spinlocks.  Changed spin_lock_irqsave() to spin_lock() when locking83 * hvcs_structs_lock and hvcs_pi_lock since these are not touched in an int84 * handler.  Initialized hvcs_structs_lock and hvcs_pi_lock to85 * SPIN_LOCK_UNLOCKED at declaration time rather than in hvcs_module_init().86 * Added spin_lock around list_del() in destroy_hvcs_struct() to protect the87 * list traversals from a deletion.  Removed '= NULL' from pointer declaration88 * statements since they are initialized NULL by default.  Removed wmb()89 * instances from hvcs_try_write().  They probably aren't needed with locking in90 * place.  Added check and cleanup for hvcs_pi_buff = kmalloc() in91 * hvcs_module_init().  Exposed hvcs_struct.index via a sysfs attribute so that92 * the coupling between /dev/hvcs* and a vty-server can be automatically93 * determined.  Moved kobject_put() in hvcs_open outside of the94 * spin_unlock_irqrestore().95 *96 * 1.3.1 -> 1.3.2 Changed method for determining hvcs_struct->index and had it97 * align with how the tty layer always assigns the lowest index available.  This98 * change resulted in a list of ints that denotes which indexes are available.99 * Device additions and removals use the new hvcs_get_index() and100 * hvcs_return_index() helper functions.  The list is created with101 * hvsc_alloc_index_list() and it is destroyed with hvcs_free_index_list().102 * Without these fixes hotplug vty-server adapter support goes crazy with this103 * driver if the user removes a vty-server adapter.  Moved free_irq() outside of104 * the hvcs_final_close() function in order to get it out of the spinlock.105 * Rearranged hvcs_close().  Cleaned up some printks and did some housekeeping106 * on the changelog.  Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from107 * arch/powerepc/include/asm/hvcserver.h108 *109 * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to110 * prevent possible lockup with realtime scheduling as similarly pointed out by111 * akpm in hvc_console.  Changed resulted in the removal of hvcs_final_close()112 * to reorder cleanup operations and prevent discarding of pending data during113 * an hvcs_close().  Removed spinlock protection of hvcs_struct data members in114 * hvcs_write_room() and hvcs_chars_in_buffer() because they aren't needed.115 */116 117#define HVCS_DRIVER_VERSION "1.3.3"118 119MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");120MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver");121MODULE_LICENSE("GPL");122MODULE_VERSION(HVCS_DRIVER_VERSION);123 124/*125 * Wait this long per iteration while trying to push buffered data to the126 * hypervisor before allowing the tty to complete a close operation.127 */128#define HVCS_CLOSE_WAIT (HZ/100) /* 1/10 of a second */129 130/*131 * Since the Linux TTY code does not currently (2-04-2004) support dynamic132 * addition of tty derived devices and we shouldn't allocate thousands of133 * tty_device pointers when the number of vty-server & vty partner connections134 * will most often be much lower than this, we'll arbitrarily allocate135 * HVCS_DEFAULT_SERVER_ADAPTERS tty_structs and cdev's by default when we136 * register the tty_driver. This can be overridden using an insmod parameter.137 */138#define HVCS_DEFAULT_SERVER_ADAPTERS	64139 140/*141 * The user can't insmod with more than HVCS_MAX_SERVER_ADAPTERS hvcs device142 * nodes as a sanity check.  Theoretically there can be over 1 Billion143 * vty-server & vty partner connections.144 */145#define HVCS_MAX_SERVER_ADAPTERS	1024146 147/*148 * We let Linux assign us a major number and we start the minors at zero.  There149 * is no intuitive mapping between minor number and the target vty-server150 * adapter except that each new vty-server adapter is always assigned to the151 * smallest minor number available.152 */153#define HVCS_MINOR_START	0154 155/*156 * The hcall interface involves putting 8 chars into each of two registers.157 * We load up those 2 registers (in arch/powerpc/platforms/pseries/hvconsole.c)158 * by casting char[16] to long[2].  It would work without __ALIGNED__, but a 159 * little (tiny) bit slower because an unaligned load is slower than aligned 160 * load.161 */162#define __ALIGNED__	__attribute__((__aligned__(8)))163 164/*165 * How much data can firmware send with each hvc_put_chars()?  Maybe this166 * should be moved into an architecture specific area.167 */168#define HVCS_BUFF_LEN	16169 170/*171 * This is the maximum amount of data we'll let the user send us (hvcs_write) at172 * once in a chunk as a sanity check.173 */174#define HVCS_MAX_FROM_USER	4096175 176/*177 * Be careful when adding flags to this line discipline.  Don't add anything178 * that will cause echoing or we'll go into recursive loop echoing chars back179 * and forth with the console drivers.180 */181static const struct ktermios hvcs_tty_termios = {182	.c_iflag = IGNBRK | IGNPAR,183	.c_oflag = OPOST,184	.c_cflag = B38400 | CS8 | CREAD | HUPCL,185	.c_cc = INIT_C_CC,186	.c_ispeed = 38400,187	.c_ospeed = 38400188};189 190/*191 * This value is used to take the place of a command line parameter when the192 * module is inserted.  It starts as -1 and stays as such if the user doesn't193 * specify a module insmod parameter.  If they DO specify one then it is set to194 * the value of the integer passed in.195 */196static int hvcs_parm_num_devs = -1;197module_param(hvcs_parm_num_devs, int, 0);198 199static const char hvcs_driver_name[] = "hvcs";200static const char hvcs_device_node[] = "hvcs";201 202/* Status of partner info rescan triggered via sysfs. */203static int hvcs_rescan_status;204 205static struct tty_driver *hvcs_tty_driver;206 207/*208 * In order to be somewhat sane this driver always associates the hvcs_struct209 * index element with the numerically equal tty->index.  This means that a210 * hotplugged vty-server adapter will always map to the lowest index valued211 * device node.  If vty-servers were hotplug removed from the system and then212 * new ones added the new vty-server may have the largest slot number of all213 * the vty-server adapters in the partition but it may have the lowest dev node214 * index of all the adapters due to the hole left by the hotplug removed215 * adapter.  There are a set of functions provided to get the lowest index for216 * a new device as well as return the index to the list.  This list is allocated217 * with a number of elements equal to the number of device nodes requested when218 * the module was inserted.219 */220static int *hvcs_index_list;221 222/*223 * How large is the list?  This is kept for traversal since the list is224 * dynamically created.225 */226static int hvcs_index_count;227 228/*229 * Used by the khvcsd to pick up I/O operations when the kernel_thread is230 * already awake but potentially shifted to TASK_INTERRUPTIBLE state.231 */232static int hvcs_kicked;233 234/*235 * Use by the kthread construct for task operations like waking the sleeping236 * thread and stopping the kthread.237 */238static struct task_struct *hvcs_task;239 240/*241 * We allocate this for the use of all of the hvcs_structs when they fetch242 * partner info.243 */244static unsigned long *hvcs_pi_buff;245 246/* Only allow one hvcs_struct to use the hvcs_pi_buff at a time. */247static DEFINE_SPINLOCK(hvcs_pi_lock);248 249/* One vty-server per hvcs_struct */250struct hvcs_struct {251	struct tty_port port;252	spinlock_t lock;253 254	/*255	 * This index identifies this hvcs device as the complement to a256	 * specific tty index.257	 */258	unsigned int index;259 260	/*261	 * Used to tell the driver kernel_thread what operations need to take262	 * place upon this hvcs_struct instance.263	 */264	int todo_mask;265 266	/*267	 * This buffer is required so that when hvcs_write_room() reports that268	 * it can send HVCS_BUFF_LEN characters that it will buffer the full269	 * HVCS_BUFF_LEN characters if need be.  This is essential for opost270	 * writes since they do not do high level buffering and expect to be271	 * able to send what the driver commits to sending buffering272	 * [e.g. tab to space conversions in n_tty.c opost()].273	 */274	char buffer[HVCS_BUFF_LEN];275	int chars_in_buffer;276 277	/*278	 * Any variable below is valid before a tty is connected and279	 * stays valid after the tty is disconnected.  These shouldn't be280	 * whacked until the kobject refcount reaches zero though some entries281	 * may be changed via sysfs initiatives.282	 */283	int connected; /* is the vty-server currently connected to a vty? */284	uint32_t p_unit_address; /* partner unit address */285	uint32_t p_partition_ID; /* partner partition ID */286	char p_location_code[HVCS_CLC_LENGTH + 1]; /* CLC + Null Term */287	struct list_head next; /* list management */288	struct vio_dev *vdev;289	struct completion *destroyed;290};291 292static LIST_HEAD(hvcs_structs);293static DEFINE_SPINLOCK(hvcs_structs_lock);294static DEFINE_MUTEX(hvcs_init_mutex);295 296static int hvcs_get_pi(struct hvcs_struct *hvcsd);297static int hvcs_rescan_devices_list(void);298 299static void hvcs_partner_free(struct hvcs_struct *hvcsd);300 301static int hvcs_initialize(void);302 303#define HVCS_SCHED_READ	0x00000001304#define HVCS_QUICK_READ	0x00000002305#define HVCS_TRY_WRITE	0x00000004306#define HVCS_READ_MASK	(HVCS_SCHED_READ | HVCS_QUICK_READ)307 308static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)309{310	return dev_get_drvdata(&viod->dev);311}312/* The sysfs interface for the driver and devices */313 314static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)315{316	struct vio_dev *viod = to_vio_dev(dev);317	struct hvcs_struct *hvcsd = from_vio_dev(viod);318	unsigned long flags;319	int retval;320 321	spin_lock_irqsave(&hvcsd->lock, flags);322	retval = sprintf(buf, "%X\n", hvcsd->p_unit_address);323	spin_unlock_irqrestore(&hvcsd->lock, flags);324	return retval;325}326static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);327 328static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)329{330	struct vio_dev *viod = to_vio_dev(dev);331	struct hvcs_struct *hvcsd = from_vio_dev(viod);332	unsigned long flags;333	int retval;334 335	spin_lock_irqsave(&hvcsd->lock, flags);336	retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);337	spin_unlock_irqrestore(&hvcsd->lock, flags);338	return retval;339}340static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);341 342static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,343		size_t count)344{345	/*346	 * Don't need this feature at the present time because firmware doesn't347	 * yet support multiple partners.348	 */349	printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n");350	return -EPERM;351}352 353static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)354{355	struct vio_dev *viod = to_vio_dev(dev);356	struct hvcs_struct *hvcsd = from_vio_dev(viod);357	unsigned long flags;358	int retval;359 360	spin_lock_irqsave(&hvcsd->lock, flags);361	retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]);362	spin_unlock_irqrestore(&hvcsd->lock, flags);363	return retval;364}365 366static DEVICE_ATTR(current_vty,367	S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);368 369static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,370		size_t count)371{372	struct vio_dev *viod = to_vio_dev(dev);373	struct hvcs_struct *hvcsd = from_vio_dev(viod);374	unsigned long flags;375 376	/* writing a '0' to this sysfs entry will result in the disconnect. */377	if (simple_strtol(buf, NULL, 0) != 0)378		return -EINVAL;379 380	spin_lock_irqsave(&hvcsd->lock, flags);381 382	if (hvcsd->port.count > 0) {383		spin_unlock_irqrestore(&hvcsd->lock, flags);384		printk(KERN_INFO "HVCS: vterm state unchanged.  "385				"The hvcs device node is still in use.\n");386		return -EPERM;387	}388 389	if (hvcsd->connected == 0) {390		spin_unlock_irqrestore(&hvcsd->lock, flags);391		printk(KERN_INFO "HVCS: vterm state unchanged. The"392				" vty-server is not connected to a vty.\n");393		return -EPERM;394	}395 396	hvcs_partner_free(hvcsd);397	printk(KERN_INFO "HVCS: Closed vty-server@%X and"398			" partner vty@%X:%d connection.\n",399			hvcsd->vdev->unit_address,400			hvcsd->p_unit_address,401			(uint32_t)hvcsd->p_partition_ID);402 403	spin_unlock_irqrestore(&hvcsd->lock, flags);404	return count;405}406 407static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)408{409	struct vio_dev *viod = to_vio_dev(dev);410	struct hvcs_struct *hvcsd = from_vio_dev(viod);411	unsigned long flags;412	int retval;413 414	spin_lock_irqsave(&hvcsd->lock, flags);415	retval = sprintf(buf, "%d\n", hvcsd->connected);416	spin_unlock_irqrestore(&hvcsd->lock, flags);417	return retval;418}419static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,420		hvcs_vterm_state_show, hvcs_vterm_state_store);421 422static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)423{424	struct vio_dev *viod = to_vio_dev(dev);425	struct hvcs_struct *hvcsd = from_vio_dev(viod);426	unsigned long flags;427	int retval;428 429	spin_lock_irqsave(&hvcsd->lock, flags);430	retval = sprintf(buf, "%d\n", hvcsd->index);431	spin_unlock_irqrestore(&hvcsd->lock, flags);432	return retval;433}434 435static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);436 437static struct attribute *hvcs_dev_attrs[] = {438	&dev_attr_partner_vtys.attr,439	&dev_attr_partner_clcs.attr,440	&dev_attr_current_vty.attr,441	&dev_attr_vterm_state.attr,442	&dev_attr_index.attr,443	NULL,444};445 446ATTRIBUTE_GROUPS(hvcs_dev);447 448static ssize_t rescan_show(struct device_driver *ddp, char *buf)449{450	/* A 1 means it is updating, a 0 means it is done updating */451	return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status);452}453 454static ssize_t rescan_store(struct device_driver *ddp, const char * buf,455		size_t count)456{457	if ((simple_strtol(buf, NULL, 0) != 1)458		&& (hvcs_rescan_status != 0))459		return -EINVAL;460 461	hvcs_rescan_status = 1;462	printk(KERN_INFO "HVCS: rescanning partner info for all"463		" vty-servers.\n");464	hvcs_rescan_devices_list();465	hvcs_rescan_status = 0;466	return count;467}468 469static DRIVER_ATTR_RW(rescan);470 471static struct attribute *hvcs_attrs[] = {472	&driver_attr_rescan.attr,473	NULL,474};475 476ATTRIBUTE_GROUPS(hvcs);477 478static void hvcs_kick(void)479{480	hvcs_kicked = 1;481	wmb();482	wake_up_process(hvcs_task);483}484 485static void hvcs_unthrottle(struct tty_struct *tty)486{487	struct hvcs_struct *hvcsd = tty->driver_data;488	unsigned long flags;489 490	spin_lock_irqsave(&hvcsd->lock, flags);491	hvcsd->todo_mask |= HVCS_SCHED_READ;492	spin_unlock_irqrestore(&hvcsd->lock, flags);493	hvcs_kick();494}495 496static void hvcs_throttle(struct tty_struct *tty)497{498	struct hvcs_struct *hvcsd = tty->driver_data;499	unsigned long flags;500 501	spin_lock_irqsave(&hvcsd->lock, flags);502	vio_disable_interrupts(hvcsd->vdev);503	spin_unlock_irqrestore(&hvcsd->lock, flags);504}505 506/*507 * If the device is being removed we don't have to worry about this interrupt508 * handler taking any further interrupts because they are disabled which means509 * the hvcs_struct will always be valid in this handler.510 */511static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance)512{513	struct hvcs_struct *hvcsd = dev_instance;514 515	spin_lock(&hvcsd->lock);516	vio_disable_interrupts(hvcsd->vdev);517	hvcsd->todo_mask |= HVCS_SCHED_READ;518	spin_unlock(&hvcsd->lock);519	hvcs_kick();520 521	return IRQ_HANDLED;522}523 524/* This function must be called with the hvcsd->lock held */525static void hvcs_try_write(struct hvcs_struct *hvcsd)526{527	uint32_t unit_address = hvcsd->vdev->unit_address;528	struct tty_struct *tty = hvcsd->port.tty;529	int sent;530 531	if (hvcsd->todo_mask & HVCS_TRY_WRITE) {532		/* won't send partial writes */533		sent = hvc_put_chars(unit_address,534				&hvcsd->buffer[0],535				hvcsd->chars_in_buffer );536		if (sent > 0) {537			hvcsd->chars_in_buffer = 0;538			/* wmb(); */539			hvcsd->todo_mask &= ~(HVCS_TRY_WRITE);540			/* wmb(); */541 542			/*543			 * We are still obligated to deliver the data to the544			 * hypervisor even if the tty has been closed because545			 * we committed to delivering it.  But don't try to wake546			 * a non-existent tty.547			 */548			if (tty) {549				tty_wakeup(tty);550			}551		}552	}553}554 555static int hvcs_io(struct hvcs_struct *hvcsd)556{557	uint32_t unit_address;558	struct tty_struct *tty;559	char buf[HVCS_BUFF_LEN] __ALIGNED__;560	unsigned long flags;561	int got = 0;562 563	spin_lock_irqsave(&hvcsd->lock, flags);564 565	unit_address = hvcsd->vdev->unit_address;566	tty = hvcsd->port.tty;567 568	hvcs_try_write(hvcsd);569 570	if (!tty || tty_throttled(tty)) {571		hvcsd->todo_mask &= ~(HVCS_READ_MASK);572		goto bail;573	} else if (!(hvcsd->todo_mask & (HVCS_READ_MASK)))574		goto bail;575 576	/* remove the read masks */577	hvcsd->todo_mask &= ~(HVCS_READ_MASK);578 579	if (tty_buffer_request_room(&hvcsd->port, HVCS_BUFF_LEN) >= HVCS_BUFF_LEN) {580		got = hvc_get_chars(unit_address,581				&buf[0],582				HVCS_BUFF_LEN);583		tty_insert_flip_string(&hvcsd->port, buf, got);584	}585 586	/* Give the TTY time to process the data we just sent. */587	if (got)588		hvcsd->todo_mask |= HVCS_QUICK_READ;589 590	spin_unlock_irqrestore(&hvcsd->lock, flags);591	/* This is synch -- FIXME :js: it is not! */592	if (got)593		tty_flip_buffer_push(&hvcsd->port);594	else {595		/* Do this _after_ the flip_buffer_push */596		spin_lock_irqsave(&hvcsd->lock, flags);597		vio_enable_interrupts(hvcsd->vdev);598		spin_unlock_irqrestore(&hvcsd->lock, flags);599	}600 601	return hvcsd->todo_mask;602 603 bail:604	spin_unlock_irqrestore(&hvcsd->lock, flags);605	return hvcsd->todo_mask;606}607 608static int khvcsd(void *unused)609{610	struct hvcs_struct *hvcsd;611	int hvcs_todo_mask;612 613	__set_current_state(TASK_RUNNING);614 615	do {616		hvcs_todo_mask = 0;617		hvcs_kicked = 0;618		wmb();619 620		spin_lock(&hvcs_structs_lock);621		list_for_each_entry(hvcsd, &hvcs_structs, next) {622			hvcs_todo_mask |= hvcs_io(hvcsd);623		}624		spin_unlock(&hvcs_structs_lock);625 626		/*627		 * If any of the hvcs adapters want to try a write or quick read628		 * don't schedule(), yield a smidgen then execute the hvcs_io629		 * thread again for those that want the write.630		 */631		 if (hvcs_todo_mask & (HVCS_TRY_WRITE | HVCS_QUICK_READ)) {632			yield();633			continue;634		}635 636		set_current_state(TASK_INTERRUPTIBLE);637		if (!hvcs_kicked)638			schedule();639		__set_current_state(TASK_RUNNING);640	} while (!kthread_should_stop());641 642	return 0;643}644 645static const struct vio_device_id hvcs_driver_table[] = {646	{"serial-server", "hvterm2"},647	{ "", "" }648};649MODULE_DEVICE_TABLE(vio, hvcs_driver_table);650 651static void hvcs_return_index(int index)652{653	/* Paranoia check */654	if (!hvcs_index_list)655		return;656	if (index < 0 || index >= hvcs_index_count)657		return;658	if (hvcs_index_list[index] == -1)659		return;660	else661		hvcs_index_list[index] = -1;662}663 664static void hvcs_destruct_port(struct tty_port *p)665{666	struct hvcs_struct *hvcsd = container_of(p, struct hvcs_struct, port);667	struct completion *comp;668	unsigned long flags;669 670	spin_lock(&hvcs_structs_lock);671	spin_lock_irqsave(&hvcsd->lock, flags);672 673	comp = hvcsd->destroyed;674	/* the list_del poisons the pointers */675	list_del(&(hvcsd->next));676 677	if (hvcsd->connected == 1) {678		hvcs_partner_free(hvcsd);679		printk(KERN_INFO "HVCS: Closed vty-server@%X and"680				" partner vty@%X:%d connection.\n",681				hvcsd->vdev->unit_address,682				hvcsd->p_unit_address,683				(uint32_t)hvcsd->p_partition_ID);684	}685	printk(KERN_INFO "HVCS: Destroyed hvcs_struct for vty-server@%X.\n",686			hvcsd->vdev->unit_address);687 688	hvcsd->vdev = NULL;689 690	hvcsd->p_unit_address = 0;691	hvcsd->p_partition_ID = 0;692	hvcsd->destroyed = NULL;693	hvcs_return_index(hvcsd->index);694	memset(&hvcsd->p_location_code[0], 0x00, HVCS_CLC_LENGTH + 1);695 696	spin_unlock_irqrestore(&hvcsd->lock, flags);697	spin_unlock(&hvcs_structs_lock);698 699	kfree(hvcsd);700	if (comp)701		complete(comp);702}703 704static const struct tty_port_operations hvcs_port_ops = {705	.destruct = hvcs_destruct_port,706};707 708static int hvcs_get_index(void)709{710	int i;711	/* Paranoia check */712	if (!hvcs_index_list) {713		printk(KERN_ERR "HVCS: hvcs_index_list NOT valid!.\n");714		return -EFAULT;715	}716	/* Find the numerically lowest first free index. */717	for(i = 0; i < hvcs_index_count; i++) {718		if (hvcs_index_list[i] == -1) {719			hvcs_index_list[i] = 0;720			return i;721		}722	}723	return -1;724}725 726static int hvcs_probe(727	struct vio_dev *dev,728	const struct vio_device_id *id)729{730	struct hvcs_struct *hvcsd;731	int index, rc;732 733	if (!dev || !id) {734		printk(KERN_ERR "HVCS: probed with invalid parameter.\n");735		return -EPERM;736	}737 738	/* Make sure we are properly initialized */739	rc = hvcs_initialize();740	if (rc) {741		pr_err("HVCS: Failed to initialize core driver.\n");742		return rc;743	}744 745	/* early to avoid cleanup on failure */746	index = hvcs_get_index();747	if (index < 0) {748		return -EFAULT;749	}750 751	hvcsd = kzalloc(sizeof(*hvcsd), GFP_KERNEL);752	if (!hvcsd)753		return -ENODEV;754 755	tty_port_init(&hvcsd->port);756	hvcsd->port.ops = &hvcs_port_ops;757	spin_lock_init(&hvcsd->lock);758 759	hvcsd->vdev = dev;760	dev_set_drvdata(&dev->dev, hvcsd);761 762	hvcsd->index = index;763 764	/* hvcsd->index = ++hvcs_struct_count; */765	hvcsd->chars_in_buffer = 0;766	hvcsd->todo_mask = 0;767	hvcsd->connected = 0;768 769	/*770	 * This will populate the hvcs_struct's partner info fields for the771	 * first time.772	 */773	if (hvcs_get_pi(hvcsd)) {774		printk(KERN_ERR "HVCS: Failed to fetch partner"775			" info for vty-server@%X on device probe.\n",776			hvcsd->vdev->unit_address);777	}778 779	/*780	 * If a user app opens a tty that corresponds to this vty-server before781	 * the hvcs_struct has been added to the devices list then the user app782	 * will get -ENODEV.783	 */784	spin_lock(&hvcs_structs_lock);785	list_add_tail(&(hvcsd->next), &hvcs_structs);786	spin_unlock(&hvcs_structs_lock);787 788	printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);789 790	/*791	 * DON'T enable interrupts here because there is no user to receive the792	 * data.793	 */794	return 0;795}796 797static void hvcs_remove(struct vio_dev *dev)798{799	struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);800	DECLARE_COMPLETION_ONSTACK(comp);801	unsigned long flags;802	struct tty_struct *tty;803 804	/* By this time the vty-server won't be getting any more interrupts */805 806	spin_lock_irqsave(&hvcsd->lock, flags);807 808	hvcsd->destroyed = &comp;809	tty = tty_port_tty_get(&hvcsd->port);810 811	spin_unlock_irqrestore(&hvcsd->lock, flags);812 813	/*814	 * The tty should always be valid at this time unless a815	 * simultaneous tty close already cleaned up the hvcs_struct.816	 */817	if (tty) {818		tty_vhangup(tty);819		tty_kref_put(tty);820	}821 822	tty_port_put(&hvcsd->port);823	wait_for_completion(&comp);824	printk(KERN_INFO "HVCS: vty-server@%X removed from the"825			" vio bus.\n", dev->unit_address);826};827 828static struct vio_driver hvcs_vio_driver = {829	.id_table	= hvcs_driver_table,830	.probe		= hvcs_probe,831	.remove		= hvcs_remove,832	.name		= hvcs_driver_name,833	.driver = {834		.groups = hvcs_groups,835		.dev_groups = hvcs_dev_groups,836	},837};838 839/* Only called from hvcs_get_pi please */840static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)841{842	hvcsd->p_unit_address = pi->unit_address;843	hvcsd->p_partition_ID  = pi->partition_ID;844 845	/* copy the null-term char too */846	strscpy(hvcsd->p_location_code, pi->location_code,847		sizeof(hvcsd->p_location_code));848}849 850/*851 * Traverse the list and add the partner info that is found to the hvcs_struct852 * struct entry. NOTE: At this time I know that partner info will return a853 * single entry but in the future there may be multiple partner info entries per854 * vty-server and you'll want to zero out that list and reset it.  If for some855 * reason you have an old version of this driver but there IS more than one856 * partner info then hvcsd->p_* will hold the last partner info data from the857 * firmware query.  A good way to update this code would be to replace the three858 * partner info fields in hvcs_struct with a list of hvcs_partner_info859 * instances.860 *861 * This function must be called with the hvcsd->lock held.862 */863static int hvcs_get_pi(struct hvcs_struct *hvcsd)864{865	struct hvcs_partner_info *pi;866	uint32_t unit_address = hvcsd->vdev->unit_address;867	struct list_head head;868	int retval;869 870	spin_lock(&hvcs_pi_lock);871	if (!hvcs_pi_buff) {872		spin_unlock(&hvcs_pi_lock);873		return -EFAULT;874	}875	retval = hvcs_get_partner_info(unit_address, &head, hvcs_pi_buff);876	spin_unlock(&hvcs_pi_lock);877	if (retval) {878		printk(KERN_ERR "HVCS: Failed to fetch partner"879			" info for vty-server@%x.\n", unit_address);880		return retval;881	}882 883	/* nixes the values if the partner vty went away */884	hvcsd->p_unit_address = 0;885	hvcsd->p_partition_ID = 0;886 887	list_for_each_entry(pi, &head, node)888		hvcs_set_pi(pi, hvcsd);889 890	hvcs_free_partner_info(&head);891	return 0;892}893 894/*895 * This function is executed by the driver "rescan" sysfs entry.  It shouldn't896 * be executed elsewhere, in order to prevent deadlock issues.897 */898static int hvcs_rescan_devices_list(void)899{900	struct hvcs_struct *hvcsd;901	unsigned long flags;902 903	spin_lock(&hvcs_structs_lock);904 905	list_for_each_entry(hvcsd, &hvcs_structs, next) {906		spin_lock_irqsave(&hvcsd->lock, flags);907		hvcs_get_pi(hvcsd);908		spin_unlock_irqrestore(&hvcsd->lock, flags);909	}910 911	spin_unlock(&hvcs_structs_lock);912 913	return 0;914}915 916/*917 * Farm this off into its own function because it could be more complex once918 * multiple partners support is added. This function should be called with919 * the hvcsd->lock held.920 */921static int hvcs_has_pi(struct hvcs_struct *hvcsd)922{923	if ((!hvcsd->p_unit_address) || (!hvcsd->p_partition_ID))924		return 0;925	return 1;926}927 928/*929 * NOTE: It is possible that the super admin removed a partner vty and then930 * added a different vty as the new partner.931 *932 * This function must be called with the hvcsd->lock held.933 */934static int hvcs_partner_connect(struct hvcs_struct *hvcsd)935{936	int retval;937	unsigned int unit_address = hvcsd->vdev->unit_address;938 939	/*940	 * If there wasn't any pi when the device was added it doesn't meant941	 * there isn't any now.  This driver isn't notified when a new partner942	 * vty is added to a vty-server so we discover changes on our own.943	 * Please see comments in hvcs_register_connection() for justification944	 * of this bizarre code.945	 */946	retval = hvcs_register_connection(unit_address,947			hvcsd->p_partition_ID,948			hvcsd->p_unit_address);949	if (!retval) {950		hvcsd->connected = 1;951		return 0;952	} else if (retval != -EINVAL)953		return retval;954 955	/*956	 * As per the spec re-get the pi and try again if -EINVAL after the957	 * first connection attempt.958	 */959	if (hvcs_get_pi(hvcsd))960		return -ENOMEM;961 962	if (!hvcs_has_pi(hvcsd))963		return -ENODEV;964 965	retval = hvcs_register_connection(unit_address,966			hvcsd->p_partition_ID,967			hvcsd->p_unit_address);968	if (retval != -EINVAL) {969		hvcsd->connected = 1;970		return retval;971	}972 973	/*974	 * EBUSY is the most likely scenario though the vty could have been975	 * removed or there really could be an hcall error due to the parameter976	 * data but thanks to ambiguous firmware return codes we can't really977	 * tell.978	 */979	printk(KERN_INFO "HVCS: vty-server or partner"980			" vty is busy.  Try again later.\n");981	return -EBUSY;982}983 984/* This function must be called with the hvcsd->lock held */985static void hvcs_partner_free(struct hvcs_struct *hvcsd)986{987	int retval;988	do {989		retval = hvcs_free_connection(hvcsd->vdev->unit_address);990	} while (retval == -EBUSY);991	hvcsd->connected = 0;992}993 994/* This helper function must be called WITHOUT the hvcsd->lock held */995static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,996		unsigned int irq, struct vio_dev *vdev)997{998	unsigned long flags;999	int rc;1000 1001	/*1002	 * It is possible that the vty-server was removed between the time that1003	 * the conn was registered and now.1004	 */1005	rc = request_irq(irq, &hvcs_handle_interrupt, 0, "ibmhvcs", hvcsd);1006	if (!rc) {1007		/*1008		 * It is possible the vty-server was removed after the irq was1009		 * requested but before we have time to enable interrupts.1010		 */1011		if (vio_enable_interrupts(vdev) == H_SUCCESS)1012			return 0;1013		else {1014			printk(KERN_ERR "HVCS: int enable failed for"1015					" vty-server@%X.\n", unit_address);1016			free_irq(irq, hvcsd);1017		}1018	} else1019		printk(KERN_ERR "HVCS: irq req failed for"1020				" vty-server@%X.\n", unit_address);1021 1022	spin_lock_irqsave(&hvcsd->lock, flags);1023	hvcs_partner_free(hvcsd);1024	spin_unlock_irqrestore(&hvcsd->lock, flags);1025 1026	return rc;1027 1028}1029 1030/*1031 * This always increments the kref ref count if the call is successful.1032 * Please remember to dec when you are done with the instance.1033 *1034 * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when1035 * calling this function or you will get deadlock.1036 */1037static struct hvcs_struct *hvcs_get_by_index(int index)1038{1039	struct hvcs_struct *hvcsd;1040	unsigned long flags;1041 1042	spin_lock(&hvcs_structs_lock);1043	list_for_each_entry(hvcsd, &hvcs_structs, next) {1044		spin_lock_irqsave(&hvcsd->lock, flags);1045		if (hvcsd->index == index) {1046			tty_port_get(&hvcsd->port);1047			spin_unlock_irqrestore(&hvcsd->lock, flags);1048			spin_unlock(&hvcs_structs_lock);1049			return hvcsd;1050		}1051		spin_unlock_irqrestore(&hvcsd->lock, flags);1052	}1053	spin_unlock(&hvcs_structs_lock);1054 1055	return NULL;1056}1057 1058static int hvcs_install(struct tty_driver *driver, struct tty_struct *tty)1059{1060	struct hvcs_struct *hvcsd;1061	struct vio_dev *vdev;1062	unsigned long unit_address, flags;1063	unsigned int irq;1064	int retval;1065 1066	/*1067	 * Is there a vty-server that shares the same index?1068	 * This function increments the kref index.1069	 */1070	hvcsd = hvcs_get_by_index(tty->index);1071	if (!hvcsd) {1072		printk(KERN_WARNING "HVCS: open failed, no device associated"1073				" with tty->index %d.\n", tty->index);1074		return -ENODEV;1075	}1076 1077	spin_lock_irqsave(&hvcsd->lock, flags);1078 1079	if (hvcsd->connected == 0) {1080		retval = hvcs_partner_connect(hvcsd);1081		if (retval) {1082			spin_unlock_irqrestore(&hvcsd->lock, flags);1083			printk(KERN_WARNING "HVCS: partner connect failed.\n");1084			goto err_put;1085		}1086	}1087 1088	hvcsd->port.count = 0;1089	hvcsd->port.tty = tty;1090	tty->driver_data = hvcsd;1091 1092	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);1093 1094	/*1095	 * Save these in the spinlock for the enable operations that need them1096	 * outside of the spinlock.1097	 */1098	irq = hvcsd->vdev->irq;1099	vdev = hvcsd->vdev;1100	unit_address = hvcsd->vdev->unit_address;1101 1102	hvcsd->todo_mask |= HVCS_SCHED_READ;1103	spin_unlock_irqrestore(&hvcsd->lock, flags);1104 1105	/*1106	 * This must be done outside of the spinlock because it requests irqs1107	 * and will grab the spinlock and free the connection if it fails.1108	 */1109	retval = hvcs_enable_device(hvcsd, unit_address, irq, vdev);1110	if (retval) {1111		printk(KERN_WARNING "HVCS: enable device failed.\n");1112		goto err_put;1113	}1114 1115	retval = tty_port_install(&hvcsd->port, driver, tty);1116	if (retval)1117		goto err_irq;1118 1119	return 0;1120err_irq:1121	spin_lock_irqsave(&hvcsd->lock, flags);1122	vio_disable_interrupts(hvcsd->vdev);1123	spin_unlock_irqrestore(&hvcsd->lock, flags);1124	free_irq(irq, hvcsd);1125err_put:1126	tty_port_put(&hvcsd->port);1127 1128	return retval;1129}1130 1131/*1132 * This is invoked via the tty_open interface when a user app connects to the1133 * /dev node.1134 */1135static int hvcs_open(struct tty_struct *tty, struct file *filp)1136{1137	struct hvcs_struct *hvcsd = tty->driver_data;1138	unsigned long flags;1139 1140	spin_lock_irqsave(&hvcsd->lock, flags);1141	hvcsd->port.count++;1142	hvcsd->todo_mask |= HVCS_SCHED_READ;1143	spin_unlock_irqrestore(&hvcsd->lock, flags);1144 1145	hvcs_kick();1146 1147	printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",1148		hvcsd->vdev->unit_address );1149 1150	return 0;1151}1152 1153static void hvcs_close(struct tty_struct *tty, struct file *filp)1154{1155	struct hvcs_struct *hvcsd;1156	unsigned long flags;1157	int irq;1158 1159	/*1160	 * Is someone trying to close the file associated with this device after1161	 * we have hung up?  If so tty->driver_data wouldn't be valid.1162	 */1163	if (tty_hung_up_p(filp))1164		return;1165 1166	/*1167	 * No driver_data means that this close was probably issued after a1168	 * failed hvcs_open by the tty layer's release_dev() api and we can just1169	 * exit cleanly.1170	 */1171	if (!tty->driver_data)1172		return;1173 1174	hvcsd = tty->driver_data;1175 1176	spin_lock_irqsave(&hvcsd->lock, flags);1177	if (hvcsd->port.count == 0) {1178		spin_unlock_irqrestore(&hvcsd->lock, flags);1179		return;1180	} else if (--hvcsd->port.count == 0) {1181 1182		vio_disable_interrupts(hvcsd->vdev);1183 1184		/*1185		 * NULL this early so that the kernel_thread doesn't try to1186		 * execute any operations on the TTY even though it is obligated1187		 * to deliver any pending I/O to the hypervisor.1188		 */1189		hvcsd->port.tty = NULL;1190 1191		irq = hvcsd->vdev->irq;1192		spin_unlock_irqrestore(&hvcsd->lock, flags);1193 1194		tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);1195 1196		free_irq(irq, hvcsd);1197		return;1198	} else if (hvcsd->port.count < 0) {1199		printk(KERN_ERR "HVCS: vty-server@%X open_count: %d is mismanaged.\n",1200		hvcsd->vdev->unit_address, hvcsd->port.count);1201	}1202 1203	spin_unlock_irqrestore(&hvcsd->lock, flags);1204}1205 1206static void hvcs_cleanup(struct tty_struct * tty)1207{1208	struct hvcs_struct *hvcsd = tty->driver_data;1209 1210	/*1211	 * This line is important because it tells hvcs_open that this1212	 * device needs to be re-configured the next time hvcs_open is1213	 * called.1214	 */1215	tty->driver_data = NULL;1216 1217	tty_port_put(&hvcsd->port);1218}1219 1220static void hvcs_hangup(struct tty_struct * tty)1221{1222	struct hvcs_struct *hvcsd = tty->driver_data;1223	unsigned long flags;1224	int irq;1225 1226	spin_lock_irqsave(&hvcsd->lock, flags);1227 1228	/*1229	 * Don't kref put inside the spinlock because the destruction1230	 * callback may use the spinlock and it may get called before the1231	 * spinlock has been released.1232	 */1233	vio_disable_interrupts(hvcsd->vdev);1234 1235	hvcsd->todo_mask = 0;1236	hvcsd->port.tty = NULL;1237	hvcsd->port.count = 0;1238 1239	/* This will drop any buffered data on the floor which is OK in a hangup1240	 * scenario. */1241	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);1242	hvcsd->chars_in_buffer = 0;1243 1244	irq = hvcsd->vdev->irq;1245 1246	spin_unlock_irqrestore(&hvcsd->lock, flags);1247 1248	free_irq(irq, hvcsd);1249}1250 1251/*1252 * NOTE: This is almost always from_user since user level apps interact with the1253 * /dev nodes. I'm trusting that if hvcs_write gets called and interrupted by1254 * hvcs_remove (which removes the target device and executes tty_hangup()) that1255 * tty_hangup will allow hvcs_write time to complete execution before it1256 * terminates our device.1257 */1258static ssize_t hvcs_write(struct tty_struct *tty, const u8 *buf, size_t count)1259{1260	struct hvcs_struct *hvcsd = tty->driver_data;1261	unsigned int unit_address;1262	const unsigned char *charbuf;1263	unsigned long flags;1264	size_t total_sent = 0;1265	size_t tosend = 0;1266	int result = 0;1267 1268	/*1269	 * If they don't check the return code off of their open they may1270	 * attempt this even if there is no connected device.1271	 */1272	if (!hvcsd)1273		return -ENODEV;1274 1275	/* Reasonable size to prevent user level flooding */1276	if (count > HVCS_MAX_FROM_USER) {1277		printk(KERN_WARNING "HVCS write: count being truncated to"1278				" HVCS_MAX_FROM_USER.\n");1279		count = HVCS_MAX_FROM_USER;1280	}1281 1282	charbuf = buf;1283 1284	spin_lock_irqsave(&hvcsd->lock, flags);1285 1286	/*1287	 * Somehow an open succeeded but the device was removed or the1288	 * connection terminated between the vty-server and partner vty during1289	 * the middle of a write operation?  This is a crummy place to do this1290	 * but we want to keep it all in the spinlock.1291	 */1292	if (hvcsd->port.count <= 0) {1293		spin_unlock_irqrestore(&hvcsd->lock, flags);1294		return -ENODEV;1295	}1296 1297	unit_address = hvcsd->vdev->unit_address;1298 1299	while (count > 0) {1300		tosend = min_t(size_t, count,1301			       (HVCS_BUFF_LEN - hvcsd->chars_in_buffer));1302		/*1303		 * No more space, this probably means that the last call to1304		 * hvcs_write() didn't succeed and the buffer was filled up.1305		 */1306		if (!tosend)1307			break;1308 1309		memcpy(&hvcsd->buffer[hvcsd->chars_in_buffer],1310				&charbuf[total_sent],1311				tosend);1312 1313		hvcsd->chars_in_buffer += tosend;1314 1315		result = 0;1316 1317		/*1318		 * If this is true then we don't want to try writing to the1319		 * hypervisor because that is the kernel_threads job now.  We'll1320		 * just add to the buffer.1321		 */1322		if (!(hvcsd->todo_mask & HVCS_TRY_WRITE))1323			/* won't send partial writes */1324			result = hvc_put_chars(unit_address,1325					&hvcsd->buffer[0],1326					hvcsd->chars_in_buffer);1327 1328		/*1329		 * Since we know we have enough room in hvcsd->buffer for1330		 * tosend we record that it was sent regardless of whether the1331		 * hypervisor actually took it because we have it buffered.1332		 */1333		total_sent+=tosend;1334		count-=tosend;1335		if (result == 0) {1336			hvcsd->todo_mask |= HVCS_TRY_WRITE;1337			hvcs_kick();1338			break;1339		}1340 1341		hvcsd->chars_in_buffer = 0;1342		/*1343		 * Test after the chars_in_buffer reset otherwise this could1344		 * deadlock our writes if hvc_put_chars fails.1345		 */1346		if (result < 0)1347			break;1348	}1349 1350	spin_unlock_irqrestore(&hvcsd->lock, flags);1351 1352	if (result == -1)1353		return -EIO;1354	else1355		return total_sent;1356}1357 1358/*1359 * This is really asking how much can we guarantee that we can send or that we1360 * absolutely WILL BUFFER if we can't send it.  This driver MUST honor the1361 * return value, hence the reason for hvcs_struct buffering.1362 */1363static unsigned int hvcs_write_room(struct tty_struct *tty)1364{1365	struct hvcs_struct *hvcsd = tty->driver_data;1366 1367	if (!hvcsd || hvcsd->port.count <= 0)1368		return 0;1369 1370	return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;1371}1372 1373static unsigned int hvcs_chars_in_buffer(struct tty_struct *tty)1374{1375	struct hvcs_struct *hvcsd = tty->driver_data;1376 1377	return hvcsd->chars_in_buffer;1378}1379 1380static const struct tty_operations hvcs_ops = {1381	.install = hvcs_install,1382	.open = hvcs_open,1383	.close = hvcs_close,1384	.cleanup = hvcs_cleanup,1385	.hangup = hvcs_hangup,1386	.write = hvcs_write,1387	.write_room = hvcs_write_room,1388	.chars_in_buffer = hvcs_chars_in_buffer,1389	.unthrottle = hvcs_unthrottle,1390	.throttle = hvcs_throttle,1391};1392 1393static int hvcs_alloc_index_list(int n)1394{1395	int i;1396 1397	hvcs_index_list = kmalloc_array(n, sizeof(hvcs_index_count),1398					GFP_KERNEL);1399	if (!hvcs_index_list)1400		return -ENOMEM;1401	hvcs_index_count = n;1402	for (i = 0; i < hvcs_index_count; i++)1403		hvcs_index_list[i] = -1;1404	return 0;1405}1406 1407static void hvcs_free_index_list(void)1408{1409	/* Paranoia check to be thorough. */1410	kfree(hvcs_index_list);1411	hvcs_index_list = NULL;1412	hvcs_index_count = 0;1413}1414 1415static int hvcs_initialize(void)1416{1417	int rc, num_ttys_to_alloc;1418 1419	mutex_lock(&hvcs_init_mutex);1420	if (hvcs_task) {1421		mutex_unlock(&hvcs_init_mutex);1422		return 0;1423	}1424 1425	/* Has the user specified an overload with an insmod param? */1426	if (hvcs_parm_num_devs <= 0 ||1427		(hvcs_parm_num_devs > HVCS_MAX_SERVER_ADAPTERS)) {1428		num_ttys_to_alloc = HVCS_DEFAULT_SERVER_ADAPTERS;1429	} else1430		num_ttys_to_alloc = hvcs_parm_num_devs;1431 1432	hvcs_tty_driver = tty_alloc_driver(num_ttys_to_alloc,1433			TTY_DRIVER_REAL_RAW);1434	if (IS_ERR(hvcs_tty_driver)) {1435		mutex_unlock(&hvcs_init_mutex);1436		return PTR_ERR(hvcs_tty_driver);1437	}1438 1439	if (hvcs_alloc_index_list(num_ttys_to_alloc)) {1440		rc = -ENOMEM;1441		goto index_fail;1442	}1443 1444	hvcs_tty_driver->driver_name = hvcs_driver_name;1445	hvcs_tty_driver->name = hvcs_device_node;1446 1447	/*1448	 * We'll let the system assign us a major number, indicated by leaving1449	 * it blank.1450	 */1451 1452	hvcs_tty_driver->minor_start = HVCS_MINOR_START;1453	hvcs_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;1454 1455	/*1456	 * We role our own so that we DONT ECHO.  We can't echo because the1457	 * device we are connecting to already echoes by default and this would1458	 * throw us into a horrible recursive echo-echo-echo loop.1459	 */1460	hvcs_tty_driver->init_termios = hvcs_tty_termios;1461 1462	tty_set_operations(hvcs_tty_driver, &hvcs_ops);1463 1464	/*1465	 * The following call will result in sysfs entries that denote the1466	 * dynamically assigned major and minor numbers for our devices.1467	 */1468	if (tty_register_driver(hvcs_tty_driver)) {1469		printk(KERN_ERR "HVCS: registration as a tty driver failed.\n");1470		rc = -EIO;1471		goto register_fail;1472	}1473 1474	hvcs_pi_buff = (unsigned long *) __get_free_page(GFP_KERNEL);1475	if (!hvcs_pi_buff) {1476		rc = -ENOMEM;1477		goto buff_alloc_fail;1478	}1479 1480	hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");1481	if (IS_ERR(hvcs_task)) {1482		printk(KERN_ERR "HVCS: khvcsd creation failed.\n");1483		rc = -EIO;1484		goto kthread_fail;1485	}1486	mutex_unlock(&hvcs_init_mutex);1487	return 0;1488 1489kthread_fail:1490	free_page((unsigned long)hvcs_pi_buff);1491buff_alloc_fail:1492	tty_unregister_driver(hvcs_tty_driver);1493register_fail:1494	hvcs_free_index_list();1495index_fail:1496	tty_driver_kref_put(hvcs_tty_driver);1497	hvcs_tty_driver = NULL;1498	mutex_unlock(&hvcs_init_mutex);1499	return rc;1500}1501 1502static int __init hvcs_module_init(void)1503{1504	int rc = vio_register_driver(&hvcs_vio_driver);1505	if (rc) {1506		printk(KERN_ERR "HVCS: can't register vio driver\n");1507		return rc;1508	}1509 1510	pr_info("HVCS: Driver registered.\n");1511 1512	return 0;1513}1514 1515static void __exit hvcs_module_exit(void)1516{1517	/*1518	 * This driver receives hvcs_remove callbacks for each device upon1519	 * module removal.1520	 */1521	vio_unregister_driver(&hvcs_vio_driver);1522	if (!hvcs_task)1523		return;1524 1525	/*1526	 * This synchronous operation  will wake the khvcsd kthread if it is1527	 * asleep and will return when khvcsd has terminated.1528	 */1529	kthread_stop(hvcs_task);1530 1531	spin_lock(&hvcs_pi_lock);1532	free_page((unsigned long)hvcs_pi_buff);1533	hvcs_pi_buff = NULL;1534	spin_unlock(&hvcs_pi_lock);1535 1536	tty_unregister_driver(hvcs_tty_driver);1537 1538	hvcs_free_index_list();1539 1540	tty_driver_kref_put(hvcs_tty_driver);1541 1542	printk(KERN_INFO "HVCS: driver module removed.\n");1543}1544 1545module_init(hvcs_module_init);1546module_exit(hvcs_module_exit);1547