aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hvc_console.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-10-17 02:30:13 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:43:00 -0400
commit3e6c6f630a5282df8f3393a59f10eb9c56536d23 (patch)
tree744539fb9d35425784149e2f015589d593e2b968 /drivers/char/hvc_console.c
parentfd5eea4214f72bd7ac77c1c5346a9c096319131a (diff)
Delay creation of khcvd thread
This changes hvc_init() to be called only when someone actually uses the hvc_console driver. Dave Jones complained when profiling bootup. hvc_console used to only be for Power aka pSeries: now lguest and Xen both want it built-in in case the kernel is a guest under one of those, even though usually it will be a native boot. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Cc: Paul Mackerras <paulus@samba.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Jeremy Fitzhardinge <jeremy@goop.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/hvc_console.c')
-rw-r--r--drivers/char/hvc_console.c56
1 files changed, 40 insertions, 16 deletions
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 83c1151ec7a2..8252f8668538 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -69,6 +69,8 @@ static struct task_struct *hvc_task;
69/* Picks up late kicks after list walk but before schedule() */ 69/* Picks up late kicks after list walk but before schedule() */
70static int hvc_kicked; 70static int hvc_kicked;
71 71
72static int hvc_init(void);
73
72#ifdef CONFIG_MAGIC_SYSRQ 74#ifdef CONFIG_MAGIC_SYSRQ
73static int sysrq_pressed; 75static int sysrq_pressed;
74#endif 76#endif
@@ -754,6 +756,13 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
754 struct hvc_struct *hp; 756 struct hvc_struct *hp;
755 int i; 757 int i;
756 758
759 /* We wait until a driver actually comes along */
760 if (!hvc_driver) {
761 int err = hvc_init();
762 if (err)
763 return ERR_PTR(err);
764 }
765
757 hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size, 766 hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
758 GFP_KERNEL); 767 GFP_KERNEL);
759 if (!hp) 768 if (!hp)
@@ -829,16 +838,18 @@ int __devexit hvc_remove(struct hvc_struct *hp)
829 return 0; 838 return 0;
830} 839}
831 840
832/* Driver initialization. Follow console initialization. This is where the TTY 841/* Driver initialization: called as soon as someone uses hvc_alloc(). */
833 * interfaces start to become available. */ 842static int hvc_init(void)
834static int __init hvc_init(void)
835{ 843{
836 struct tty_driver *drv; 844 struct tty_driver *drv;
845 int err;
837 846
838 /* We need more than hvc_count adapters due to hotplug additions. */ 847 /* We need more than hvc_count adapters due to hotplug additions. */
839 drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); 848 drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
840 if (!drv) 849 if (!drv) {
841 return -ENOMEM; 850 err = -ENOMEM;
851 goto out;
852 }
842 853
843 drv->owner = THIS_MODULE; 854 drv->owner = THIS_MODULE;
844 drv->driver_name = "hvc"; 855 drv->driver_name = "hvc";
@@ -854,30 +865,43 @@ static int __init hvc_init(void)
854 * added later. */ 865 * added later. */
855 hvc_task = kthread_run(khvcd, NULL, "khvcd"); 866 hvc_task = kthread_run(khvcd, NULL, "khvcd");
856 if (IS_ERR(hvc_task)) { 867 if (IS_ERR(hvc_task)) {
857 panic("Couldn't create kthread for console.\n"); 868 printk(KERN_ERR "Couldn't create kthread for console.\n");
858 put_tty_driver(drv); 869 err = PTR_ERR(hvc_task);
859 return -EIO; 870 goto put_tty;
860 } 871 }
861 872
862 if (tty_register_driver(drv)) 873 err = tty_register_driver(drv);
863 panic("Couldn't register hvc console driver\n"); 874 if (err) {
875 printk(KERN_ERR "Couldn't register hvc console driver\n");
876 goto stop_thread;
877 }
864 878
879 /* FIXME: This mb() seems completely random. Remove it. */
865 mb(); 880 mb();
866 hvc_driver = drv; 881 hvc_driver = drv;
867 return 0; 882 return 0;
883
884put_tty:
885 put_tty_driver(hvc_driver);
886stop_thread:
887 kthread_stop(hvc_task);
888 hvc_task = NULL;
889out:
890 return err;
868} 891}
869module_init(hvc_init);
870 892
871/* This isn't particularly necessary due to this being a console driver 893/* This isn't particularly necessary due to this being a console driver
872 * but it is nice to be thorough. 894 * but it is nice to be thorough.
873 */ 895 */
874static void __exit hvc_exit(void) 896static void __exit hvc_exit(void)
875{ 897{
876 kthread_stop(hvc_task); 898 if (hvc_driver) {
899 kthread_stop(hvc_task);
877 900
878 tty_unregister_driver(hvc_driver); 901 tty_unregister_driver(hvc_driver);
879 /* return tty_struct instances allocated in hvc_init(). */ 902 /* return tty_struct instances allocated in hvc_init(). */
880 put_tty_driver(hvc_driver); 903 put_tty_driver(hvc_driver);
881 unregister_console(&hvc_con_driver); 904 unregister_console(&hvc_con_driver);
905 }
882} 906}
883module_exit(hvc_exit); 907module_exit(hvc_exit);