Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 70697
b: refs/heads/master
c: 3e6c6f6
h: refs/heads/master
i:
  70695: 8bc116f
v: v3
  • Loading branch information
Rusty Russell authored and Linus Torvalds committed Oct 17, 2007
1 parent 36d752b commit ddd2435
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fd5eea4214f72bd7ac77c1c5346a9c096319131a
refs/heads/master: 3e6c6f630a5282df8f3393a59f10eb9c56536d23
4 changes: 2 additions & 2 deletions trunk/drivers/char/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,8 @@ config TIPAR
config HVC_DRIVER
bool
help
Users of pSeries machines that want to utilize the hvc console front-end
module for their backend console driver should select this option.
Generic "hypervisor virtual console" infrastructure for various
hypervisors (pSeries, Xen, lguest).
It will automatically be selected if one of the back-end console drivers
is selected.

Expand Down
56 changes: 40 additions & 16 deletions trunk/drivers/char/hvc_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ static struct task_struct *hvc_task;
/* Picks up late kicks after list walk but before schedule() */
static int hvc_kicked;

static int hvc_init(void);

#ifdef CONFIG_MAGIC_SYSRQ
static int sysrq_pressed;
#endif
Expand Down Expand Up @@ -754,6 +756,13 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
struct hvc_struct *hp;
int i;

/* We wait until a driver actually comes along */
if (!hvc_driver) {
int err = hvc_init();
if (err)
return ERR_PTR(err);
}

hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
GFP_KERNEL);
if (!hp)
Expand Down Expand Up @@ -829,16 +838,18 @@ int __devexit hvc_remove(struct hvc_struct *hp)
return 0;
}

/* Driver initialization. Follow console initialization. This is where the TTY
* interfaces start to become available. */
static int __init hvc_init(void)
/* Driver initialization: called as soon as someone uses hvc_alloc(). */
static int hvc_init(void)
{
struct tty_driver *drv;
int err;

/* We need more than hvc_count adapters due to hotplug additions. */
drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
if (!drv)
return -ENOMEM;
if (!drv) {
err = -ENOMEM;
goto out;
}

drv->owner = THIS_MODULE;
drv->driver_name = "hvc";
Expand All @@ -854,30 +865,43 @@ static int __init hvc_init(void)
* added later. */
hvc_task = kthread_run(khvcd, NULL, "khvcd");
if (IS_ERR(hvc_task)) {
panic("Couldn't create kthread for console.\n");
put_tty_driver(drv);
return -EIO;
printk(KERN_ERR "Couldn't create kthread for console.\n");
err = PTR_ERR(hvc_task);
goto put_tty;
}

if (tty_register_driver(drv))
panic("Couldn't register hvc console driver\n");
err = tty_register_driver(drv);
if (err) {
printk(KERN_ERR "Couldn't register hvc console driver\n");
goto stop_thread;
}

/* FIXME: This mb() seems completely random. Remove it. */
mb();
hvc_driver = drv;
return 0;

put_tty:
put_tty_driver(hvc_driver);
stop_thread:
kthread_stop(hvc_task);
hvc_task = NULL;
out:
return err;
}
module_init(hvc_init);

/* This isn't particularly necessary due to this being a console driver
* but it is nice to be thorough.
*/
static void __exit hvc_exit(void)
{
kthread_stop(hvc_task);
if (hvc_driver) {
kthread_stop(hvc_task);

tty_unregister_driver(hvc_driver);
/* return tty_struct instances allocated in hvc_init(). */
put_tty_driver(hvc_driver);
unregister_console(&hvc_con_driver);
tty_unregister_driver(hvc_driver);
/* return tty_struct instances allocated in hvc_init(). */
put_tty_driver(hvc_driver);
unregister_console(&hvc_con_driver);
}
}
module_exit(hvc_exit);

0 comments on commit ddd2435

Please sign in to comment.