Messages in this thread Patch in this message | | | Date | Tue, 28 Sep 1999 08:56:00 -0700 | From | "David S. Miller" <> | Subject | Re: Oops in cgsixfb.c, SparcStation 20/SMP [2.2.12] (fixed, patch) |
| |
Date: Fri, 24 Sep 1999 23:08:18 -0400 (EDT) From: Chris Noe <stiker@northlink.com>
I spent the night hacking out this patch which now keeps my ss20 up in even in the face of 'make config', multiple console switches, etc.
Nice work, I totally agree with this change, in fact I agree with it so much that I extended it to cover all of the other SBUS fbcon drivers as well.
Here is the patch I have checked into my current 2.2.x tree
Thanks again.
--- ./drivers/video/sbusfb.c.~1~ Mon Jun 28 04:45:29 1999 +++ ./drivers/video/sbusfb.c Tue Sep 28 00:38:24 1999 @@ -987,6 +987,7 @@ disp = &fb->disp; type = &fb->type; + spin_lock_init(&fb->lock); fb->prom_node = node; fb->prom_parent = parent; fb->sbdp = sbdp; --- ./drivers/video/bwtwofb.c.~1~ Wed Sep 1 01:42:46 1999 +++ ./drivers/video/bwtwofb.c Tue Sep 28 00:39:41 1999 @@ -85,12 +85,20 @@ static void bw2_blank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.bw2.regs->control &= ~BWTWO_CTL_ENABLE_VIDEO; + spin_unlock_irqrestore(&fb->lock, flags); } static void bw2_unblank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.bw2.regs->control |= BWTWO_CTL_ENABLE_VIDEO; + spin_unlock_irqrestore(&fb->lock, flags); } static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) --- ./drivers/video/cgsixfb.c.~1~ Tue Jun 15 08:46:42 1999 +++ ./drivers/video/cgsixfb.c Tue Sep 28 00:47:29 1999 @@ -231,9 +231,11 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; int x, y, w, h; int i; + spin_lock_irqsave(&fb->lock, flags); do { i = fbc->s; } while (i & 0x10000000); @@ -262,6 +264,7 @@ do { i = fbc->draw; } while (i < 0 && (i & 0x20000000)); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s, @@ -269,7 +272,9 @@ { int i; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); do { i = fbc->s; } while (i & 0x10000000); @@ -290,15 +295,18 @@ i = fbc->draw; } while (i < 0 && (i & 0x20000000)); } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; int i, x, y; u8 *fd; + spin_lock_irqsave(&fb->lock, flags); if (fontheightlog(p)) { y = fb->y_margin + (yy << fontheightlog(p)); i = ((c & p->charmask) << fontheightlog(p)); @@ -339,6 +347,7 @@ fd += 2; } } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, @@ -346,9 +355,11 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; + spin_lock_irqsave(&fb->lock, flags); do { i = fbc->s; } while (i & 0x10000000); @@ -443,6 +454,7 @@ } } } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_revc(struct display *p, int xx, int yy) @@ -453,24 +465,30 @@ static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct bt_regs *bt = fb->s.cg6.bt; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); bt->addr = index << 24; for (i = index; count--; i++){ bt->color_map = fb->color_map CM(i,0) << 24; bt->color_map = fb->color_map CM(i,1) << 24; bt->color_map = fb->color_map CM(i,2) << 24; } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_restore_palette (struct fb_info_sbusfb *fb) { struct bt_regs *bt = fb->s.cg6.bt; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); bt->addr = 0; bt->color_map = 0xffffffff; bt->color_map = 0xffffffff; bt->color_map = 0xffffffff; + spin_unlock_irqrestore(&fb->lock, flags); } static struct display_switch cg6_dispsw __initdata = { @@ -481,7 +499,9 @@ static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct bt_regs *bt = fb->s.cg6.bt; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); bt->addr = 1 << 24; bt->cursor = red[0] << 24; bt->cursor = green[0] << 24; @@ -490,26 +510,32 @@ bt->cursor = red[1] << 24; bt->cursor = green[1] << 24; bt->cursor = blue[1] << 24; + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void cg6_setcurshape (struct fb_info_sbusfb *fb) { struct cg6_thc *thc = fb->s.cg6.thc; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); for (i = 0; i < 32; i++) { thc->thc_cursmask [i] = fb->cursor.bits[0][i]; thc->thc_cursbits [i] = fb->cursor.bits[1][i]; } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ static void cg6_setcursor (struct fb_info_sbusfb *fb) { unsigned int v; + unsigned long flags; struct cg_cursor *c = &fb->cursor; + spin_lock_irqsave(&fb->lock, flags); if (c->enable) v = ((c->cpos.fbx - c->chot.fbx) << 16) |((c->cpos.fby - c->chot.fby) & 0xffff); @@ -517,16 +543,25 @@ /* Magic constant to turn off the cursor */ v = ((65536-32) << 16) | (65536-32); fb->s.cg6.thc->thc_cursxy = v; + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_blank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.cg6.thc->thc_misc &= ~CG6_THC_MISC_VIDEO; + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_unblank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.cg6.thc->thc_misc |= CG6_THC_MISC_VIDEO; + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_reset (struct fb_info_sbusfb *fb) @@ -534,9 +569,12 @@ unsigned int rev, conf; struct cg6_tec *tec = fb->s.cg6.tec; struct cg6_fbc *fbc = fb->s.cg6.fbc; + unsigned long flags; u32 mode; int i; + spin_lock_irqsave(&fb->lock, flags); + /* Turn off stuff in the Transform Engine. */ tec->tec_matrix = 0; tec->tec_clip = 0; @@ -581,6 +619,8 @@ /* Enable cursor in Brooktree DAC. */ fb->s.cg6.bt->addr = 0x06 << 24; fb->s.cg6.bt->control |= 0x03 << 24; + + spin_unlock_irqrestore(&fb->lock, flags); } static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) --- ./drivers/video/cgfourteenfb.c.~1~ Tue Jun 15 08:46:40 1999 +++ ./drivers/video/cgfourteenfb.c Tue Sep 28 07:12:30 1999 @@ -182,12 +182,15 @@ static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct cg14_clut *clut = fb->s.cg14.clut; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); for (; count--; index++) clut->c_clut[index] = (fb->color_map CM(index,2) << 16) | (fb->color_map CM(index,1) << 8) | (fb->color_map CM(index,0)); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) @@ -198,21 +201,27 @@ static void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct cg14_cursor *cur = fb->s.cg14.cursor; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); cur->color0 = ((red[0]) | (green[0] << 8) | (blue[0] << 16)); cur->color1 = ((red[1]) | (green[1] << 8) | (blue[1] << 16)); + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void cg14_setcurshape (struct fb_info_sbusfb *fb) { struct cg14_cursor *cur = fb->s.cg14.cursor; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); for (i = 0; i < 32; i++){ cur->cpl0 [i] = fb->cursor.bits[0][i]; cur->cpl1 [i] = fb->cursor.bits[1][i]; } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ @@ -220,15 +229,22 @@ { struct cg_cursor *c = &fb->cursor; struct cg14_cursor *cur = fb->s.cg14.cursor; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); if (c->enable) cur->ccr |= CG14_CCR_ENABLE; cur->cursx = ((c->cpos.fbx - c->chot.fbx) & 0xfff); cur->cursy = ((c->cpos.fby - c->chot.fby) & 0xfff); + spin_unlock_irqrestore(&fb->lock, flags); } static void cg14_switch_from_graph (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); + /* Set the 8-bpp mode */ if (fb->open && fb->mmaped){ volatile char *mcr = &fb->s.cg14.regs->mcr; @@ -236,24 +252,31 @@ fb->s.cg14.mode = 8; *mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK)); } + spin_unlock_irqrestore(&fb->lock, flags); } static void cg14_reset (struct fb_info_sbusfb *fb) { volatile char *mcr = &fb->s.cg14.regs->mcr; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); *mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK)); + spin_unlock_irqrestore(&fb->lock, flags); } static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned long arg) { volatile char *mcr = &fb->s.cg14.regs->mcr; struct mdi_cfginfo *mdii; - int mode; + unsigned long flags; + int mode, ret = 0; switch (cmd) { case MDI_RESET: + spin_lock_irqsave(&fb->lock, flags); *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK); + spin_unlock_irqrestore(&fb->lock, flags); break; case MDI_GET_CFGINFO: mdii = (struct mdi_cfginfo *)arg; @@ -266,6 +289,8 @@ break; case MDI_SET_PIXELMODE: get_user_ret(mode, (int *)arg, -EFAULT); + + spin_lock_irqsave(&fb->lock, flags); switch (mode){ case MDI_32_PIX: *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) | @@ -278,14 +303,19 @@ *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK); break; default: - return -ENOSYS; - } - fb->s.cg14.mode = mode; + ret = -ENOSYS; + break; + }; + + if (ret == 0) + fb->s.cg14.mode = mode; + spin_unlock_irqrestore(&fb->lock, flags); break; default: - return -EINVAL; - } - return 0; + ret = -EINVAL; + break; + }; + return ret; } __initfunc(static unsigned long get_phys(unsigned long addr)) --- ./drivers/video/leofb.c.~1~ Tue Jun 15 08:47:45 1999 +++ ./drivers/video/leofb.c Tue Sep 28 07:36:01 1999 @@ -175,10 +175,12 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; int x, y, w, h; int i; + spin_lock_irqsave(&fb->lock, flags); do { i = us->csr; } while (i & 0x20000000); @@ -196,6 +198,7 @@ us->extent = (w - 1) | ((h - 1) << 11); us->fill = (x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000; + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s, @@ -203,8 +206,10 @@ { int i; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); ss->fg = (attr_bgcol(p,s)<<24); while (count-- > 0) { do { @@ -215,17 +220,20 @@ us->fill = boxes[0] | (boxes[1] << 11) | 0x80000000; boxes += 4; } + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; int i, x, y; u8 *fd; u32 *u; + spin_lock_irqsave(&fb->lock, flags); if (fontheightlog(p)) { y = yy << (fontheightlog(p) + 11); i = (c & p->charmask) << fontheightlog(p); @@ -257,6 +265,7 @@ fd += 2; } } + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, @@ -264,11 +273,13 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; u32 *u; + spin_lock_irqsave(&fb->lock, flags); do { i = us->csr; } while (i & 0x20000000); @@ -352,6 +363,7 @@ } u += x; } + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_revc(struct display *p, int xx, int yy) @@ -372,11 +384,14 @@ static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); lx_krn->krn_type = LEO_KRN_TYPE_CLUT0; i = leo_wait (lx_krn); - if (i) return; + if (i) + goto out; lx_krn->krn_type = LEO_KRN_TYPE_CLUTDATA; for (i = 0; i < 256; i++) lx_krn->krn_value = fb->color_map CM(i,0) | @@ -384,11 +399,17 @@ (fb->color_map CM(i,2) << 16); /* Throw colors there :)) */ lx_krn->krn_type = LEO_KRN_TYPE_CLUT0; lx_krn->krn_csr |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2); +out: + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_restore_palette (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.leo.ld_ss1->ss1_misc &= ~(LEO_SS1_MISC_ENABLE); + spin_unlock_irqrestore(&fb->lock, flags); } static struct display_switch leo_dispsw __initdata = { @@ -400,14 +421,19 @@ { struct leo_cursor *l = fb->s.leo.cursor; int i; - + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); for (i = 0; (l->cur_misc & LEO_CUR_PROGRESS) && i < 300000; i++) udelay (1); /* Busy wait at most 0.3 sec */ - if (i == 300000) return; /* Timed out - should we print some message? */ + if (i == 300000) + goto out; /* Timed out - should we print some message? */ l->cur_type = LEO_CUR_TYPE_CMAP; l->cur_data = (red[0] | (green[0]<<8) | (blue[0]<<16)); l->cur_data = (red[1] | (green[1]<<8) | (blue[1]<<16)); l->cur_misc = LEO_CUR_UPDATECMAP; +out: + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ @@ -416,7 +442,9 @@ int i, j, k; u32 m, n, mask; struct leo_cursor *l = fb->s.leo.cursor; - + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); l->cur_misc &= ~LEO_CUR_ENABLE; for (k = 0; k < 2; k ++) { l->cur_type = (k * LEO_CUR_TYPE_IMAGE); /* LEO_CUR_TYPE_MASK is 0 */ @@ -431,6 +459,7 @@ } } l->cur_misc |= LEO_CUR_ENABLE; + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ @@ -438,26 +467,37 @@ { struct cg_cursor *c = &fb->cursor; struct leo_cursor *l = fb->s.leo.cursor; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); l->cur_misc &= ~LEO_CUR_ENABLE; l->cur_cursxy = ((c->cpos.fbx - c->chot.fbx) & 0x7ff) |(((c->cpos.fby - c->chot.fby) & 0x7ff) << 11); l->cur_misc |= LEO_CUR_UPDATE; if (c->enable) l->cur_misc |= LEO_CUR_ENABLE; + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_blank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO; fb->s.leo.lx_krn->krn_csr &= ~LEO_KRN_CSR_ENABLE; + spin_unlock_irqrestore(&fb->lock, flags); } static void leo_unblank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO; if (!(fb->s.leo.lx_krn->krn_csr & LEO_KRN_CSR_ENABLE)) fb->s.leo.lx_krn->krn_csr |= LEO_KRN_CSR_ENABLE; + spin_unlock_irqrestore(&fb->lock, flags); } static int __init @@ -492,8 +532,10 @@ static void leo_switch_from_graph (struct fb_info_sbusfb *fb) { register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); ss->wid = 0xffffffff; ss->wmask = 0xffff; ss->vclipmin = 0; @@ -503,12 +545,14 @@ ss->widclip = 0; us->addrspace = 4; us->fontt = 0; + spin_unlock_irqrestore(&fb->lock, flags); } -static void __init leo_rasterimg (struct fb_info_sbusfb *fb, int start) +static int __init leo_rasterimg (struct fb_info *info, int start) { + struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *) info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; if (start) { ss->wid = 1; @@ -521,6 +565,7 @@ ss->rop = 0x310850; us->addrspace = 4; } + return 0; } static char idstring[40] __initdata = { 0 }; @@ -566,9 +611,10 @@ us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *) sparc_alloc_io(phys + LEO_OFF_LC_SS0_USR, 0, 0x1000, "leo_lc_ss0_usr", fb->iospace, 0); - ss = fb->s.leo.ld_ss0 = (struct leo_ld *) + fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *) sparc_alloc_io(phys + LEO_OFF_LD_SS0, 0, 0x1000, "leo_ld_ss0", fb->iospace, 0); + ss = (struct leo_ld *) fb->s.leo.ld_ss0; fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *) sparc_alloc_io(phys + LEO_OFF_LD_SS1, 0, 0x1000, "leo_ld_ss1", fb->iospace, 0); --- ./drivers/video/cgthreefb.c.~1~ Tue Jun 15 08:46:42 1999 +++ ./drivers/video/cgthreefb.c Tue Sep 28 00:48:50 1999 @@ -88,25 +88,38 @@ static void cg3_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct bt_regs *bt = &fb->s.cg3.regs->cmap; + unsigned long flags; u32 *i; int steps; + spin_lock_irqsave(&fb->lock, flags); + i = (((u32 *)fb->color_map) + D4M3(index)); steps = D4M3(index+count-1) - D4M3(index)+3; *(volatile u8 *)&bt->addr = (u8)D4M4(index); while (steps--) bt->color_map = *i++; + + spin_unlock_irqrestore(&fb->lock, flags); } static void cg3_blank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.cg3.regs->control &= ~CG3_CR_ENABLE_VIDEO; + spin_unlock_irqrestore(&fb->lock, flags); } static void cg3_unblank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.cg3.regs->control |= CG3_CR_ENABLE_VIDEO; + spin_unlock_irqrestore(&fb->lock, flags); } static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) --- ./drivers/video/creatorfb.c.~1~ Tue Jun 15 08:46:51 1999 +++ ./drivers/video/creatorfb.c Tue Sep 28 07:07:37 1999 @@ -333,9 +333,11 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; u64 yx, hw; int fg; + spin_lock_irqsave(&fb->lock, flags); fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)]; if (fg != fb->s.ffb.fg_cache) { FFBFifo(fb, 5); @@ -356,14 +358,17 @@ } *(volatile u64 *)&fbc->by = yx + fb->s.ffb.yx_margin; *(volatile u64 *)&fbc->bh = hw; + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s, int count, unsigned short *boxes) { register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; int fg; + spin_lock_irqsave(&fb->lock, flags); fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)]; if (fg != fb->s.ffb.fg_cache) { FFBFifo(fb, 1); @@ -378,16 +383,19 @@ fbc->bw = boxes[2] - boxes[0]; boxes += 4; } + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; int i, xy; u8 *fd; u64 fgbg; + spin_lock_irqsave(&fb->lock, flags); if (fontheightlog(p)) { xy = (yy << (16 + fontheightlog(p))); i = ((c & p->charmask) << fontheightlog(p)); @@ -422,6 +430,7 @@ fd += 2; } } + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, @@ -429,10 +438,12 @@ { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; int i, xy; u8 *fd1, *fd2, *fd3, *fd4; u64 fgbg; + spin_lock_irqsave(&fb->lock, flags); fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))])) << 32) | ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))]; if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) { @@ -520,6 +531,7 @@ } xy += fontwidth(p); } + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_revc(struct display *p, int xx, int yy) @@ -530,8 +542,10 @@ static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct ffb_dac *dac = fb->s.ffb.dac; + unsigned long flags; int i, j = count; + spin_lock_irqsave(&fb->lock, flags); dac->type = 0x2000 | index; for (i = index; j--; i++) /* Feed the colors in :)) */ @@ -539,11 +553,13 @@ ((fb->color_map CM(i,1)) << 8) | ((fb->color_map CM(i,2)) << 16); if (!p) - return; + goto out; for (i = index, j = count; i < 16 && j--; i++) ((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) | ((fb->color_map CM(i,1)) << 8) | ((fb->color_map CM(i,2)) << 16); +out: + spin_unlock_irqrestore(&fb->lock, flags); } static struct display_switch ffb_dispsw __initdata = { @@ -554,17 +570,20 @@ static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) { register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); fb->s.ffb.xy_margin = (y_margin << 16) + x_margin; fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin; p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin); FFBWait(fbc); + spin_unlock_irqrestore(&fb->lock, flags); } -static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable) +static __inline__ void __ffb_curs_enable (struct fb_info_sbusfb *fb, int enable) { struct ffb_dac *dac = fb->s.ffb.dac; - + dac->type2 = 0x100; if (fb->s.ffb.dac_rev <= 2) dac->value2 = enable ? 3 : 0; @@ -575,20 +594,25 @@ static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct ffb_dac *dac = fb->s.ffb.dac; + unsigned long flags; - ffb_curs_enable (fb, 0); + spin_lock_irqsave(&fb->lock, flags); + __ffb_curs_enable (fb, 0); dac->type2 = 0x102; dac->value2 = (red[0] | (green[0]<<8) | (blue[0]<<16)); dac->value2 = (red[1] | (green[1]<<8) | (blue[1]<<16)); + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void ffb_setcurshape (struct fb_info_sbusfb *fb) { struct ffb_dac *dac = fb->s.ffb.dac; + unsigned long flags; int i, j; - ffb_curs_enable (fb, 0); + spin_lock_irqsave(&fb->lock, flags); + __ffb_curs_enable (fb, 0); for (j = 0; j < 2; j++) { dac->type2 = j ? 0 : 0x80; for (i = 0; i < 0x40; i++) { @@ -601,6 +625,7 @@ } } } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ @@ -608,19 +633,24 @@ { struct ffb_dac *dac = fb->s.ffb.dac; struct cg_cursor *c = &fb->cursor; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); dac->type2 = 0x104; /* Should this be just 0x7ff?? Should I do some margin handling and setcurshape in that case? */ dac->value2 = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16) |((c->cpos.fbx - c->chot.fbx) & 0xffff); - ffb_curs_enable (fb, fb->cursor.enable); + __ffb_curs_enable (fb, fb->cursor.enable); + spin_unlock_irqrestore(&fb->lock, flags); } static void ffb_switch_from_graph (struct fb_info_sbusfb *fb) { register struct ffb_fbc *fbc = fb->s.ffb.fbc; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); FFBWait(fbc); fb->s.ffb.fifo_cache = 0; FFBFifo(fb, 8); @@ -633,6 +663,7 @@ fbc->fg = fb->s.ffb.fg_cache; fbc->bg = fb->s.ffb.bg_cache; FFBWait(fbc); + spin_unlock_irqrestore(&fb->lock, flags); } static char idstring[60] __initdata = { 0 }; --- ./drivers/video/tcxfb.c.~1~ Tue Jun 15 08:48:10 1999 +++ ./drivers/video/tcxfb.c Tue Sep 28 04:28:46 1999 @@ -85,28 +85,37 @@ { 0, 0, 0 } }; -static void tcx_set_control_plane (struct fb_info_sbusfb *fb) +static void __tcx_set_control_plane (struct fb_info_sbusfb *fb) { u32 *p, *pend; p = fb->s.tcx.cplane; - if (!p) return; + if (!p) + return; for (pend = p + fb->type.fb_size; p < pend; p++) *p &= 0xffffff; } static void tcx_switch_from_graph (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); + /* Reset control plane to 8bit mode if necessary */ if (fb->open && fb->mmaped) - tcx_set_control_plane (fb); + __tcx_set_control_plane (fb); + + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) { struct bt_regs *bt = fb->s.tcx.bt; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); bt->addr = index << 24; for (i = index; count--; i++){ bt->color_map = fb->color_map CM(i,0) << 24; @@ -114,21 +123,28 @@ bt->color_map = fb->color_map CM(i,2) << 24; } bt->addr = 0; + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_restore_palette (struct fb_info_sbusfb *fb) { struct bt_regs *bt = fb->s.tcx.bt; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); bt->addr = 0; bt->color_map = 0xffffffff; bt->color_map = 0xffffffff; bt->color_map = 0xffffffff; + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct bt_regs *bt = fb->s.tcx.bt; + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); /* Note the 2 << 24 is different from cg6's 1 << 24 */ bt->addr = 2 << 24; @@ -140,18 +156,23 @@ bt->cursor = green[1] << 24; bt->cursor = blue[1] << 24; bt->addr = 0; + + spin_unlock_irqrestore(&fb->lock, flags); } /* Set cursor shape */ static void tcx_setcurshape (struct fb_info_sbusfb *fb) { struct tcx_thc *thc = fb->s.tcx.thc; + unsigned long flags; int i; + spin_lock_irqsave(&fb->lock, flags); for (i = 0; i < 32; i++){ thc->thc_cursmask [i] = fb->cursor.bits[0][i]; thc->thc_cursbits [i] = fb->cursor.bits[1][i]; } + spin_unlock_irqrestore(&fb->lock, flags); } /* Load cursor information */ @@ -159,7 +180,9 @@ { unsigned int v; struct cg_cursor *c = &fb->cursor; + unsigned long flags; + spin_lock_irqsave(&fb->lock, flags); if (c->enable) v = ((c->cpos.fbx - c->chot.fbx) << 16) |((c->cpos.fby - c->chot.fby) & 0xffff); @@ -167,27 +190,39 @@ /* Magic constant to turn off the cursor */ v = ((65536-32) << 16) | (65536-32); fb->s.tcx.thc->thc_cursxy = v; + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_blank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_VIDEO; /* This should put us in power-save */ fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_VSYNC_DIS; fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_HSYNC_DIS; + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_unblank (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_VSYNC_DIS; fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_HSYNC_DIS; fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_VIDEO; + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_reset (struct fb_info_sbusfb *fb) { + unsigned long flags; + + spin_lock_irqsave(&fb->lock, flags); if (fb->open && fb->mmaped) - tcx_set_control_plane(fb); + __tcx_set_control_plane(fb); /* Turn off stuff in the Transform Engine. */ fb->s.tcx.tec->tec_matrix = 0; @@ -197,6 +232,7 @@ /* Enable cursor in Brooktree DAC. */ fb->s.tcx.bt->addr = 0x06 << 24; fb->s.tcx.bt->control |= 0x03 << 24; + spin_unlock_irqrestore(&fb->lock, flags); } static void tcx_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) --- ./include/video/sbusfb.h.~1~ Tue Jun 15 09:17:05 1999 +++ ./include/video/sbusfb.h Tue Sep 28 00:38:44 1999 @@ -87,6 +87,7 @@ struct display_switch dispsw; struct fbtype type; struct linux_sbus_device *sbdp; + spinlock_t lock; int prom_node, prom_parent; union { struct fb_info_creator ffb; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |