Messages in this thread Patch in this message | | | Date | Thu, 29 Apr 2004 21:46:06 +1000 | Subject | [PATCH] Module ref counting for vt console drivers | From | Herbert Xu <> |
| |
Hi:
The following patch adds basic module reference counting to vt console drivers. Currently modules like fbcon are not counted at all.
Cheers, -- Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ ) Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt Index: drivers/char/vt.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/char/vt.c,v retrieving revision 1.6 diff -u -r1.6 vt.c --- a/drivers/char/vt.c 5 Apr 2004 10:54:32 -0000 1.6 +++ b/drivers/char/vt.c 29 Apr 2004 11:30:11 -0000 @@ -661,11 +661,14 @@ static void visual_init(int currcons, int init) { /* ++Geert: sw->con_init determines console size */ + if (sw) + module_put(sw->owner); sw = conswitchp; #ifndef VT_SINGLE_DRIVER if (con_driver_map[currcons]) sw = con_driver_map[currcons]; #endif + __module_get(sw->owner); cons_num = currcons; display_fg = &master_display_fg; vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir; @@ -2653,25 +2656,38 @@ * and become default driver for newly opened ones. */ -void take_over_console(const struct consw *csw, int first, int last, int deflt) +int take_over_console(const struct consw *csw, int first, int last, int deflt) { int i, j = -1; const char *desc; + struct module *owner; + + owner = csw->owner; + if (!try_module_get(owner)) + return -ENODEV; acquire_console_sem(); desc = csw->con_startup(); if (!desc) { release_console_sem(); - return; + module_put(owner); + return -ENODEV; } - if (deflt) + if (deflt) { + if (conswitchp) + module_put(conswitchp->owner); + __module_get(owner); conswitchp = csw; + } for (i = first; i <= last; i++) { int old_was_color; int currcons = i; + if (con_driver_map[i]) + module_put(con_driver_map[i]->owner); + __module_get(owner); con_driver_map[i] = csw; if (!vc_cons[i].d || !vc_cons[i].d->vc_sw) @@ -2706,6 +2722,9 @@ printk("to %s\n", desc); release_console_sem(); + + module_put(owner); + return 0; } void give_up_console(const struct consw *csw) @@ -2713,8 +2732,10 @@ int i; for(i = 0; i < MAX_NR_CONSOLES; i++) - if (con_driver_map[i] == csw) + if (con_driver_map[i] == csw) { + module_put(csw->owner); con_driver_map[i] = NULL; + } } #endif Index: drivers/video/console/dummycon.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/video/console/dummycon.c,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 dummycon.c --- a/drivers/video/console/dummycon.c 3 Jan 2003 01:36:55 -0000 1.1.1.2 +++ b/drivers/video/console/dummycon.c 29 Apr 2004 10:58:51 -0000 @@ -11,6 +11,7 @@ #include <linux/console.h> #include <linux/vt_kern.h> #include <linux/init.h> +#include <linux/module.h> /* * Dummy console driver @@ -58,6 +59,7 @@ */ const struct consw dummy_con = { + .owner = THIS_MODULE, .con_startup = dummycon_startup, .con_init = dummycon_init, .con_deinit = DUMMY, Index: drivers/video/console/fbcon.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/video/console/fbcon.c,v retrieving revision 1.1.1.10 diff -u -r1.1.1.10 fbcon.c --- a/drivers/video/console/fbcon.c 5 Apr 2004 09:49:37 -0000 1.1.1.10 +++ b/drivers/video/console/fbcon.c 29 Apr 2004 11:12:28 -0000 @@ -304,8 +304,7 @@ return -ENODEV; con2fb_map[unit] = newidx; fbcon_is_default = (vc->vc_sw == &fb_con) ? 1 : 0; - take_over_console(&fb_con, unit, unit, fbcon_is_default); - return 0; + return take_over_console(&fb_con, unit, unit, fbcon_is_default); } /* @@ -2257,6 +2256,7 @@ */ const struct consw fb_con = { + .owner = THIS_MODULE, .con_startup = fbcon_startup, .con_init = fbcon_init, .con_deinit = fbcon_deinit, @@ -2286,10 +2286,16 @@ int __init fb_console_init(void) { + int err; + if (!num_registered_fb) return -ENODEV; - take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); + err = take_over_console(&fb_con, first_fb_vc, last_fb_vc, + fbcon_is_default); + if (err) + return err; + acquire_console_sem(); if (!fbcon_event_notifier_registered) { fb_register_client(&fbcon_event_notifer); Index: drivers/video/console/mdacon.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/video/console/mdacon.c,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 mdacon.c --- a/drivers/video/console/mdacon.c 3 Jan 2003 01:36:55 -0000 1.1.1.2 +++ b/drivers/video/console/mdacon.c 29 Apr 2004 11:17:39 -0000 @@ -370,8 +370,6 @@ if (mda_display_fg == NULL) mda_display_fg = c; - - MOD_INC_USE_COUNT; } static void mdacon_deinit(struct vc_data *c) @@ -380,8 +378,6 @@ if (mda_display_fg == c) mda_display_fg = NULL; - - MOD_DEC_USE_COUNT; } static inline u16 mda_convert_attr(u16 ch) @@ -586,6 +582,7 @@ */ const struct consw mda_con = { + .owner = THIS_MODULE, .con_startup = mdacon_startup, .con_init = mdacon_init, .con_deinit = mdacon_deinit, @@ -609,8 +606,7 @@ if (mda_first_vc > mda_last_vc) return 1; - take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0); - return 0; + return take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0); } void __exit mda_console_exit(void) Index: drivers/video/console/newport_con.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/video/console/newport_con.c,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 newport_con.c --- a/drivers/video/console/newport_con.c 24 Mar 2003 22:01:16 -0000 1.1.1.3 +++ b/drivers/video/console/newport_con.c 29 Apr 2004 11:12:38 -0000 @@ -677,6 +677,7 @@ #define DUMMY (void *) newport_dummy const struct consw newport_con = { + .owner = THIS_MODULE, .con_startup = newport_startup, .con_init = newport_init, .con_deinit = DUMMY, @@ -704,9 +705,7 @@ printk("Error loading SGI Newport Console driver\n"); else printk("Loading SGI Newport Console Driver\n"); - take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1); - - return 0; + return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1); } int cleanup_module(void) Index: drivers/video/console/promcon.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/video/console/promcon.c,v retrieving revision 1.1.1.2 diff -u -r1.1.1.2 promcon.c --- a/drivers/video/console/promcon.c 11 Mar 2004 02:55:33 -0000 1.1.1.2 +++ b/drivers/video/console/promcon.c 29 Apr 2004 10:59:56 -0000 @@ -574,6 +574,7 @@ #define DUMMY (void *) promcon_dummy const struct consw prom_con = { + .owner = THIS_MODULE, .con_startup = promcon_startup, .con_init = promcon_init, .con_deinit = promcon_deinit, Index: drivers/video/console/sticon.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/video/console/sticon.c,v retrieving revision 1.1.1.4 diff -u -r1.1.1.4 sticon.c --- a/drivers/video/console/sticon.c 11 Mar 2004 02:55:37 -0000 1.1.1.4 +++ b/drivers/video/console/sticon.c 29 Apr 2004 11:13:13 -0000 @@ -354,6 +354,7 @@ } static struct consw sti_con = { + .owner = THIS_MODULE, .con_startup = sticon_startup, .con_init = sticon_init, .con_deinit = sticon_deinit, @@ -390,7 +391,7 @@ if (conswitchp == &dummy_con) { printk(KERN_INFO "sticon: Initializing STI text console.\n"); - take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1); + return take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1); } return 0; } Index: drivers/video/console/vgacon.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/video/console/vgacon.c,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 vgacon.c --- a/drivers/video/console/vgacon.c 11 Mar 2004 02:55:26 -0000 1.1.1.3 +++ b/drivers/video/console/vgacon.c 29 Apr 2004 11:00:24 -0000 @@ -1065,6 +1065,7 @@ #define DUMMY (void *) vgacon_dummy const struct consw vga_con = { + .owner = THIS_MODULE, .con_startup = vgacon_startup, .con_init = vgacon_init, .con_deinit = vgacon_deinit, Index: include/linux/console.h =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/linux/console.h,v retrieving revision 1.1.1.8 diff -u -r1.1.1.8 console.h --- a/include/linux/console.h 11 Mar 2004 02:55:26 -0000 1.1.1.8 +++ b/include/linux/console.h 29 Apr 2004 10:47:39 -0000 @@ -19,6 +19,7 @@ struct vc_data; struct console_font_op; +struct module; /* * this is what the terminal answers to a ESC-Z or csi0c query. @@ -27,6 +28,7 @@ #define VT102ID "\033[?6c" struct consw { + struct module *owner; const char *(*con_startup)(void); void (*con_init)(struct vc_data *, int); void (*con_deinit)(struct vc_data *); @@ -58,7 +60,7 @@ extern const struct consw newport_con; /* SGI Newport console */ extern const struct consw prom_con; /* SPARC PROM console */ -void take_over_console(const struct consw *sw, int first, int last, int deflt); +int take_over_console(const struct consw *sw, int first, int last, int deflt); void give_up_console(const struct consw *sw); /* scroll */ | |