modules using init_bh in recent development kernels

a sun (asun@zoology.washington.edu)
Fri, 18 Apr 1997 15:59:28 -0700 (PDT)


as far as i can tell, all of the serial drivers install bottom-half
handlers. if they're installed as modules, however, the bottom-half
interrupt handler will get called on a non-existant handler, resulting
in an oops. following is a patch which adds remove_bh() to the various
serial modules and fixes binfmt_em86.c.

is this the correct way of doing things, or is it actually covering
something up?

--- linux/fs/binfmt_em86.c.save Sun Apr 13 11:34:21 1997
+++ linux/fs/binfmt_em86.c Tue Apr 15 01:33:18 1997
@@ -100,7 +100,7 @@
#ifndef MODULE
NULL, 0, load_em86, NULL, NULL
#else
- NULL, &mod_use_count_, load_em86, NULL, NULL
+ NULL, &__this_module, load_em86, NULL, NULL
#endif
};

--- linux/include/asm-i386/softirq.h.save Fri Apr 18 08:45:36 1997
+++ linux/include/asm-i386/softirq.h Fri Apr 18 08:46:23 1997
@@ -14,6 +14,12 @@
bh_mask |= 1 << nr;
}

+extern inline void remove_bh(int nr)
+{
+ bh_base[nr] = NULL;
+ bh_mask &= ~(1 << nr);
+}
+
extern inline void mark_bh(int nr)
{
set_bit(nr, &bh_active);
--- linux/include/asm-alpha/softirq.h.save Fri Apr 18 08:44:23 1997
+++ linux/include/asm-alpha/softirq.h Fri Apr 18 08:45:34 1997
@@ -31,6 +31,12 @@
bh_mask |= 1 << nr;
}

+extern inline void remove_bh(int nr)
+{
+ bh_base[nr] = NULL;
+ bh_mask &= ~(1 << nr);
+}
+
extern inline void mark_bh(int nr)
{
set_bit(nr, &bh_active);
--- linux/include/asm-sparc/softirq.h.save Fri Apr 18 08:46:24 1997
+++ linux/include/asm-sparc/softirq.h Fri Apr 18 08:52:02 1997
@@ -39,6 +39,15 @@
spin_unlock_irqrestore(&global_bh_lock, flags); \
} while(0)

+#define remove_bh(nr) \
+do { unsigned long flags; \
+ int ent = nr; \
+ spin_lock_irqsave(&global_bh_lock, flags); \
+ bh_base[ent] = NULL; \
+ bh_mask &= ~(1 << ent); \
+ spin_unlock_irqrestore(&global_bh_lock, flags); \
+} while(0)
+
#define mark_bh(nr) \
do { unsigned long flags; \
spin_lock_irqsave(&global_bh_lock, flags); \
--- linux/include/asm-sparc64/softirq.h.save Fri Apr 18 08:47:13 1997
+++ linux/include/asm-sparc64/softirq.h Fri Apr 18 08:52:53 1997
@@ -34,6 +34,12 @@
bh_mask |= 1 << ent; \
} while(0)

+#define remove_bh(nr) \
+do { int ent = nr; \
+ bh_base[ent] = NULL; \
+ bh_mask &= ~(1 << ent); \
+} while(0)
+
#define mark_bh(nr) (bh_active |= (1 << (nr)))

#define disable_bh(nr) \
--- linux/drivers/char/serial.c.save Fri Apr 18 08:27:24 1997
+++ linux/drivers/char/serial.c Fri Apr 18 08:54:19 1997
@@ -3410,6 +3410,7 @@
timer_active &= ~(1 << RS_TIMER);
timer_table[RS_TIMER].fn = NULL;
timer_table[RS_TIMER].expires = 0;
+ remove_bh(SERIAL_BH);
if ((e1 = tty_unregister_driver(&serial_driver)))
printk("SERIAL: failed to unregister serial driver (%d)\n",
e1);
--- linux/drivers/char/riscom8.c.save Fri Apr 18 09:02:20 1997
+++ linux/drivers/char/riscom8.c Wed Jan 1 15:09:25 1997
@@ -1799,15 +1799,9 @@

static void rc_release_drivers(void)
{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ remove_bh(RISCOM8_BH);
free_page((unsigned long)tmp_buf);
tty_unregister_driver(&riscom_driver);
tty_unregister_driver(&riscom_callout_driver);
+ restore_flags(flags);
}

#ifndef MODULE
--- linux/drivers/char/cyclades.c.save Fri Apr 18 08:55:00 1997
+++ linux/drivers/char/cyclades.c Fri Apr 18 08:59:07 1997
@@ -2941,13 +2941,17 @@
void
cleanup_module(void)
{
+ unsigned long flags;
int i;

-
+ save_flags(flags);
+ cli();
+ remove_bh(CYCLADES_BH);
if (tty_unregister_driver(&cy_callout_driver))
printk("Couldn't unregister Cyclom callout driver\n");
if (tty_unregister_driver(&cy_serial_driver))
printk("Couldn't unregister Cyclom serial driver\n");
+ restore_flags(flags);

for (i = 0; i < NR_CARDS; i++) {
if (cy_card[i].base_addr != 0)
--- linux/drivers/char/esp.c.save Fri Apr 18 08:59:49 1997
+++ linux/drivers/char/esp.c Thu Apr 3 02:00:21 1997
@@ -2565,7 +2565,6 @@
/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
save_flags(flags);
cli();
+ remove_bh(ESP_BH);
if ((e1 = tty_unregister_driver(&esp_driver)))
printk("SERIAL: failed to unregister serial driver (%d)\n",
e1);
--- linux/drivers/char/pcxx.c.save Fri Apr 18 09:00:25 1997
+++ linux/drivers/char/pcxx.c Fri Apr 11 22:56:50 1997
@@ -217,7 +217,6 @@
timer_active &= ~(1 << DIGI_TIMER);
timer_table[DIGI_TIMER].fn = NULL;
timer_table[DIGI_TIMER].expires = 0;
+ remove_bh(DIGI_BH);

if ((e1 = tty_unregister_driver(&pcxe_driver)))
printk("SERIAL: failed to unregister serial driver (%d)\n", e1);