Re: Oops in cgsixfb.c, SparcStation 20/SMP [2.2.12] (fixed, patch)

David S. Miller (davem@redhat.com)
Tue, 28 Sep 1999 08:56:00 -0700


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/