Messages in this thread Patch in this message |  | | Date | Tue, 10 Oct 2000 15:05:24 -0400 | From | Yong Chi <> | Subject | vgaconsole driver SMP safe fix against linux-2.4.0-test9 |
| |
My first contribution to kernel =) Someone please look over this one carefully =)
Thanks
--- vgacon.c.bak Tue Oct 10 13:50:09 2000 +++ vgacon.c Tue Oct 10 14:48:06 2000 @@ -27,6 +27,9 @@ * flashing on RHS of screen during heavy console scrolling . * Oct 1996, Paul Gortmaker. * + * Change cli()/sti() to SMP safe spin_lock_irqsave() + * /spin_unlock_irqrestore() calls, Yong Chi. + * Oct-10-2000 <ychi@home.com> * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -50,6 +53,7 @@ #include <linux/init.h> #include <asm/io.h> +#include <asm/spinlock.h> #define BLANK 0x0020 @@ -122,6 +126,10 @@ static int vga_video_font_height; static unsigned int vga_rolled_over = 0; +/* + * Spinlock used for irq atomic operations + */ +static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED; static int __init no_scroll(char *str) { @@ -152,8 +160,7 @@ * ddprintk might set the console position from interrupt * handlers, thus the write has to be IRQ-atomic. */ - save_flags(flags); - cli(); + spin_lock_irqsave(&irq_lock, flags); #ifndef SLOW_VGA v1 = reg + (val & 0xff00); @@ -166,7 +173,7 @@ outb_p(reg+1, vga_video_port_reg); outb_p(val & 0xff, vga_video_port_val); #endif - restore_flags(flags); + spin_unlock_irqrestore(&irq_lock, flags); } static const char __init *vgacon_startup(void) @@ -415,7 +422,7 @@ if ((from == lastfrom) && (to == lastto)) return; lastfrom = from; lastto = to; - save_flags(flags); cli(); + spin_lock_irqsave(&irq_lock, flags); outb_p(0x0a, vga_video_port_reg); /* Cursor start */ curs = inb_p(vga_video_port_val); outb_p(0x0b, vga_video_port_reg); /* Cursor end */ @@ -428,7 +435,7 @@ outb_p(curs, vga_video_port_val); outb_p(0x0b, vga_video_port_reg); /* Cursor end */ outb_p(cure, vga_video_port_val); - restore_flags(flags); + spin_unlock_irqrestore(&irq_lock, flags); } static void vgacon_cursor(struct vc_data *c, int mode) @@ -531,13 +538,14 @@ static void vga_vesa_blank(int mode) { + unsigned long flags; /* save original values of VGA controller registers */ if(!vga_vesa_blanked) { - cli(); + spin_lock_irqsave(&irq_lock, flags); vga_state.SeqCtrlIndex = inb_p(seq_port_reg); vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg); vga_state.CrtMiscIO = inb_p(video_misc_rd); - sti(); + spin_unlock_irqrestore(&irq_lock, flags); outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */ vga_state.HorizontalTotal = inb_p(vga_video_port_val); @@ -561,7 +569,7 @@ /* assure that video is enabled */ /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ - cli(); + spin_lock_irqsave(&irq_lock, flags); outb_p(0x01,seq_port_reg); outb_p(vga_state.ClockingMode | 0x20,seq_port_val); @@ -598,13 +606,15 @@ /* restore both index registers */ outb_p(vga_state.SeqCtrlIndex,seq_port_reg); outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg); - sti(); + spin_unlock_irqrestore(&irq_lock, flags); } static void vga_vesa_unblank(void) { + unsigned long flags; + /* restore original values of VGA controller registers */ - cli(); + spin_lock_irqsave(&irq_lock, flags); outb_p(vga_state.CrtMiscIO,video_misc_wr); outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */ @@ -629,7 +639,7 @@ /* restore index/control registers */ outb_p(vga_state.SeqCtrlIndex,seq_port_reg); outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg); - sti(); + spin_unlock_irqrestore(&irq_lock, flags); } static void vga_pal_blank(void) @@ -710,6 +720,7 @@ int beg; unsigned short video_port_status = vga_video_port_reg + 6; int font_select = 0x00; + unsigned long flags; if (vga_video_type != VIDEO_TYPE_EGAM) { charmap = (char *)VGA_MAP_MEM(colourmap); @@ -750,7 +761,7 @@ charmap += 4*cmapsz; #endif - cli(); + spin_lock_irqsave(&irq_lock, flags); outb_p( 0x00, seq_port_reg ); /* First, the sequencer */ outb_p( 0x01, seq_port_val ); /* Synchronous reset */ outb_p( 0x02, seq_port_reg ); @@ -766,7 +777,7 @@ outb_p( 0x00, gr_port_val ); /* disable odd-even addressing */ outb_p( 0x06, gr_port_reg ); outb_p( 0x00, gr_port_val ); /* map start at A000:0000 */ - sti(); + spin_unlock_irqrestore(&irq_lock, flags); if (arg) { if (set) @@ -793,7 +804,7 @@ } } - cli(); + spin_lock_irqsave(&irq_lock, flags); outb_p( 0x00, seq_port_reg ); /* First, the sequencer */ outb_p( 0x01, seq_port_val ); /* Synchronous reset */ outb_p( 0x02, seq_port_reg ); @@ -833,7 +844,7 @@ inb_p( video_port_status ); outb_p ( 0x20, attrib_port ); } - sti(); + spin_unlock_irqrestore(&irq_lock, flags); return 0; } @@ -846,6 +857,7 @@ { int rows, maxscan; unsigned char ovr, vde, fsr; + unsigned long flags; if (fontheight == vga_video_font_height) return 0; @@ -865,12 +877,12 @@ registers; they are write-only on EGA, but it appears that they are all don't care bits on EGA, so I guess it doesn't matter. */ - cli(); + spin_lock_irqsave(&irq_lock, flags); outb_p( 0x07, vga_video_port_reg ); /* CRTC overflow register */ ovr = inb_p(vga_video_port_val); outb_p( 0x09, vga_video_port_reg ); /* Font size register */ fsr = inb_p(vga_video_port_val); - sti(); + spin_unlock_irqrestore(&irq_lock, flags); vde = maxscan & 0xff; /* Vertical display end reg */ ovr = (ovr & 0xbd) + /* Overflow register */ @@ -878,14 +890,14 @@ ((maxscan & 0x200) >> 3); fsr = (fsr & 0xe0) + (fontheight-1); /* Font size register */ - cli(); + spin_lock_irqsave(&irq_lock, flags); outb_p( 0x07, vga_video_port_reg ); /* CRTC overflow register */ outb_p( ovr, vga_video_port_val ); outb_p( 0x09, vga_video_port_reg ); /* Font size */ outb_p( fsr, vga_video_port_val ); outb_p( 0x12, vga_video_port_reg ); /* Vertical display limit */ outb_p( vde, vga_video_port_val ); - sti(); + spin_unlock_irqrestore(&irq_lock, flags); vc_resize_all(rows, 0); /* Adjust console size */ return 0; |  |