Commit 5770ced9 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Module ref counting for vt console drivers

From: Herbert Xu <herbert@gondor.apana.org.au>

The following patch adds basic module reference counting to vt console
drivers.  Currently modules like fbcon are not counted at all.
parent f887808c
......@@ -661,11 +661,14 @@ int vc_cons_allocated(unsigned int i)
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;
......@@ -2668,25 +2671,38 @@ static void clear_buffer_attributes(int currcons)
* 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)
......@@ -2721,6 +2737,9 @@ void take_over_console(const struct consw *csw, int first, int last, int deflt)
printk("to %s\n", desc);
release_console_sem();
module_put(owner);
return 0;
}
void give_up_console(const struct consw *csw)
......@@ -2728,8 +2747,10 @@ void give_up_console(const struct consw *csw)
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
......
......@@ -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 @@ static int dummycon_dummy(void)
*/
const struct consw dummy_con = {
.owner = THIS_MODULE,
.con_startup = dummycon_startup,
.con_init = dummycon_init,
.con_deinit = DUMMY,
......
......@@ -304,8 +304,7 @@ int set_con2fb_map(int unit, int newidx)
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 @@ static int fbcon_event_notify(struct notifier_block *self,
*/
const struct consw fb_con = {
.owner = THIS_MODULE,
.con_startup = fbcon_startup,
.con_init = fbcon_init,
.con_deinit = fbcon_deinit,
......@@ -2286,10 +2286,16 @@ static int fbcon_event_notifier_registered;
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);
......
......@@ -370,8 +370,6 @@ static void mdacon_init(struct vc_data *c, int init)
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 @@ static void mdacon_deinit(struct vc_data *c)
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 @@ static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
*/
const struct consw mda_con = {
.owner = THIS_MODULE,
.con_startup = mdacon_startup,
.con_init = mdacon_init,
.con_deinit = mdacon_deinit,
......@@ -609,8 +606,7 @@ int __init mda_console_init(void)
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)
......
......@@ -705,6 +705,7 @@ static int newport_dummy(struct vc_data *c)
#define DUMMY (void *) newport_dummy
const struct consw newport_con = {
.owner = THIS_MODULE,
.con_startup = newport_startup,
.con_init = newport_init,
.con_deinit = newport_deinit,
......@@ -726,9 +727,7 @@ const struct consw newport_con = {
#ifdef MODULE
static int __init newport_console_init(void)
{
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);
}
static void __exit newport_console_exit(void)
......
......@@ -574,6 +574,7 @@ static int promcon_dummy(void)
#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,
......
......@@ -354,6 +354,7 @@ static void sticon_save_screen(struct vc_data *conp)
}
static struct consw sti_con = {
.owner = THIS_MODULE,
.con_startup = sticon_startup,
.con_init = sticon_init,
.con_deinit = sticon_deinit,
......@@ -390,7 +391,7 @@ int __init sticonsole_init(void)
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;
}
......
......@@ -1065,6 +1065,7 @@ static int vgacon_dummy(struct vc_data *c)
#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,
......
......@@ -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 @@ struct console_font_op;
#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 vga_con; /* VGA text console */
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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment