Commit b65b5b59 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] stallion clean up

There are two locking sets involved.  One locks the board mappings and the
other is the tty open/close locking.  The low level code was clearly
designed to be ported to OS's with spin locks already so pretty much comes
out in the wash
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 33979734
...@@ -140,15 +140,6 @@ static char *stl_drvversion = "5.6.0"; ...@@ -140,15 +140,6 @@ static char *stl_drvversion = "5.6.0";
static struct tty_driver *stl_serial; static struct tty_driver *stl_serial;
/*
* We will need to allocate a temporary write buffer for chars that
* come direct from user space. The problem is that a copy from user
* space might cause a page fault (typically on a system that is
* swapping!). All ports will share one buffer - since if the system
* is already swapping a shared buffer won't make things any worse.
*/
static char *stl_tmpwritebuf;
/* /*
* Define a local default termios struct. All ports will be created * Define a local default termios struct. All ports will be created
* with this termios initially. Basically all it defines is a raw port * with this termios initially. Basically all it defines is a raw port
...@@ -362,6 +353,14 @@ static unsigned char stl_vecmap[] = { ...@@ -362,6 +353,14 @@ static unsigned char stl_vecmap[] = {
0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
}; };
/*
* Lock ordering is that you may not take stallion_lock holding
* brd_lock.
*/
static spinlock_t brd_lock; /* Guard the board mapping */
static spinlock_t stallion_lock; /* Guard the tty driver */
/* /*
* Set up enable and disable macros for the ECH boards. They require * Set up enable and disable macros for the ECH boards. They require
* the secondary io address space to be activated and deactivated. * the secondary io address space to be activated and deactivated.
...@@ -725,17 +724,7 @@ static struct class *stallion_class; ...@@ -725,17 +724,7 @@ static struct class *stallion_class;
static int __init stallion_module_init(void) static int __init stallion_module_init(void)
{ {
unsigned long flags;
#ifdef DEBUG
printk("init_module()\n");
#endif
save_flags(flags);
cli();
stl_init(); stl_init();
restore_flags(flags);
return 0; return 0;
} }
...@@ -746,7 +735,6 @@ static void __exit stallion_module_exit(void) ...@@ -746,7 +735,6 @@ static void __exit stallion_module_exit(void)
stlbrd_t *brdp; stlbrd_t *brdp;
stlpanel_t *panelp; stlpanel_t *panelp;
stlport_t *portp; stlport_t *portp;
unsigned long flags;
int i, j, k; int i, j, k;
#ifdef DEBUG #ifdef DEBUG
...@@ -756,9 +744,6 @@ static void __exit stallion_module_exit(void) ...@@ -756,9 +744,6 @@ static void __exit stallion_module_exit(void)
printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
stl_drvversion); stl_drvversion);
save_flags(flags);
cli();
/* /*
* Free up all allocated resources used by the ports. This includes * Free up all allocated resources used by the ports. This includes
* memory and interrupts. As part of this process we will also do * memory and interrupts. As part of this process we will also do
...@@ -770,7 +755,6 @@ static void __exit stallion_module_exit(void) ...@@ -770,7 +755,6 @@ static void __exit stallion_module_exit(void)
if (i) { if (i) {
printk("STALLION: failed to un-register tty driver, " printk("STALLION: failed to un-register tty driver, "
"errno=%d\n", -i); "errno=%d\n", -i);
restore_flags(flags);
return; return;
} }
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
...@@ -783,8 +767,6 @@ static void __exit stallion_module_exit(void) ...@@ -783,8 +767,6 @@ static void __exit stallion_module_exit(void)
"errno=%d\n", -i); "errno=%d\n", -i);
class_destroy(stallion_class); class_destroy(stallion_class);
kfree(stl_tmpwritebuf);
for (i = 0; (i < stl_nrbrds); i++) { for (i = 0; (i < stl_nrbrds); i++) {
if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL) if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
continue; continue;
...@@ -814,8 +796,6 @@ static void __exit stallion_module_exit(void) ...@@ -814,8 +796,6 @@ static void __exit stallion_module_exit(void)
kfree(brdp); kfree(brdp);
stl_brds[i] = (stlbrd_t *) NULL; stl_brds[i] = (stlbrd_t *) NULL;
} }
restore_flags(flags);
} }
module_init(stallion_module_init); module_init(stallion_module_init);
...@@ -948,7 +928,7 @@ static stlbrd_t *stl_allocbrd(void) ...@@ -948,7 +928,7 @@ static stlbrd_t *stl_allocbrd(void)
brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL); brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL);
if (!brdp) { if (!brdp) {
printk("STALLION: failed to allocate memory (size=%d)\n", printk("STALLION: failed to allocate memory (size=%Zd)\n",
sizeof(stlbrd_t)); sizeof(stlbrd_t));
return NULL; return NULL;
} }
...@@ -1066,16 +1046,17 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp) ...@@ -1066,16 +1046,17 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
rc = 0; rc = 0;
doclocal = 0; doclocal = 0;
spin_lock_irqsave(&stallion_lock, flags);
if (portp->tty->termios->c_cflag & CLOCAL) if (portp->tty->termios->c_cflag & CLOCAL)
doclocal++; doclocal++;
save_flags(flags);
cli();
portp->openwaitcnt++; portp->openwaitcnt++;
if (! tty_hung_up_p(filp)) if (! tty_hung_up_p(filp))
portp->refcount--; portp->refcount--;
for (;;) { for (;;) {
/* Takes brd_lock internally */
stl_setsignals(portp, 1, 1); stl_setsignals(portp, 1, 1);
if (tty_hung_up_p(filp) || if (tty_hung_up_p(filp) ||
((portp->flags & ASYNC_INITIALIZED) == 0)) { ((portp->flags & ASYNC_INITIALIZED) == 0)) {
...@@ -1093,13 +1074,14 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp) ...@@ -1093,13 +1074,14 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
rc = -ERESTARTSYS; rc = -ERESTARTSYS;
break; break;
} }
/* FIXME */
interruptible_sleep_on(&portp->open_wait); interruptible_sleep_on(&portp->open_wait);
} }
if (! tty_hung_up_p(filp)) if (! tty_hung_up_p(filp))
portp->refcount++; portp->refcount++;
portp->openwaitcnt--; portp->openwaitcnt--;
restore_flags(flags); spin_unlock_irqrestore(&stallion_lock, flags);
return rc; return rc;
} }
...@@ -1119,16 +1101,15 @@ static void stl_close(struct tty_struct *tty, struct file *filp) ...@@ -1119,16 +1101,15 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
if (portp == (stlport_t *) NULL) if (portp == (stlport_t *) NULL)
return; return;
save_flags(flags); spin_lock_irqsave(&stallion_lock, flags);
cli();
if (tty_hung_up_p(filp)) { if (tty_hung_up_p(filp)) {
restore_flags(flags); spin_unlock_irqrestore(&stallion_lock, flags);
return; return;
} }
if ((tty->count == 1) && (portp->refcount != 1)) if ((tty->count == 1) && (portp->refcount != 1))
portp->refcount = 1; portp->refcount = 1;
if (portp->refcount-- > 1) { if (portp->refcount-- > 1) {
restore_flags(flags); spin_unlock_irqrestore(&stallion_lock, flags);
return; return;
} }
...@@ -1142,11 +1123,18 @@ static void stl_close(struct tty_struct *tty, struct file *filp) ...@@ -1142,11 +1123,18 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
* (The sc26198 has no "end-of-data" interrupt only empty FIFO) * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
*/ */
tty->closing = 1; tty->closing = 1;
spin_unlock_irqrestore(&stallion_lock, flags);
if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, portp->closing_wait); tty_wait_until_sent(tty, portp->closing_wait);
stl_waituntilsent(tty, (HZ / 2)); stl_waituntilsent(tty, (HZ / 2));
spin_lock_irqsave(&stallion_lock, flags);
portp->flags &= ~ASYNC_INITIALIZED; portp->flags &= ~ASYNC_INITIALIZED;
spin_unlock_irqrestore(&stallion_lock, flags);
stl_disableintrs(portp); stl_disableintrs(portp);
if (tty->termios->c_cflag & HUPCL) if (tty->termios->c_cflag & HUPCL)
stl_setsignals(portp, 0, 0); stl_setsignals(portp, 0, 0);
...@@ -1173,7 +1161,6 @@ static void stl_close(struct tty_struct *tty, struct file *filp) ...@@ -1173,7 +1161,6 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&portp->close_wait); wake_up_interruptible(&portp->close_wait);
restore_flags(flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -1195,9 +1182,6 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count ...@@ -1195,9 +1182,6 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
(int) tty, (int) buf, count); (int) tty, (int) buf, count);
#endif #endif
if ((tty == (struct tty_struct *) NULL) ||
(stl_tmpwritebuf == (char *) NULL))
return 0;
portp = tty->driver_data; portp = tty->driver_data;
if (portp == (stlport_t *) NULL) if (portp == (stlport_t *) NULL)
return 0; return 0;
...@@ -1302,11 +1286,6 @@ static void stl_flushchars(struct tty_struct *tty) ...@@ -1302,11 +1286,6 @@ static void stl_flushchars(struct tty_struct *tty)
if (portp->tx.buf == (char *) NULL) if (portp->tx.buf == (char *) NULL)
return; return;
#if 0
if (tty->stopped || tty->hw_stopped ||
(portp->tx.head == portp->tx.tail))
return;
#endif
stl_startrxtx(portp, -1, 1); stl_startrxtx(portp, -1, 1);
} }
...@@ -1977,12 +1956,14 @@ static int stl_eiointr(stlbrd_t *brdp) ...@@ -1977,12 +1956,14 @@ static int stl_eiointr(stlbrd_t *brdp)
unsigned int iobase; unsigned int iobase;
int handled = 0; int handled = 0;
spin_lock(&brd_lock);
panelp = brdp->panels[0]; panelp = brdp->panels[0];
iobase = panelp->iobase; iobase = panelp->iobase;
while (inb(brdp->iostatus) & EIO_INTRPEND) { while (inb(brdp->iostatus) & EIO_INTRPEND) {
handled = 1; handled = 1;
(* panelp->isr)(panelp, iobase); (* panelp->isr)(panelp, iobase);
} }
spin_unlock(&brd_lock);
return handled; return handled;
} }
...@@ -2168,7 +2149,7 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) ...@@ -2168,7 +2149,7 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
portp = kzalloc(sizeof(stlport_t), GFP_KERNEL); portp = kzalloc(sizeof(stlport_t), GFP_KERNEL);
if (!portp) { if (!portp) {
printk("STALLION: failed to allocate memory " printk("STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlport_t)); "(size=%Zd)\n", sizeof(stlport_t));
break; break;
} }
...@@ -2304,7 +2285,7 @@ static inline int stl_initeio(stlbrd_t *brdp) ...@@ -2304,7 +2285,7 @@ static inline int stl_initeio(stlbrd_t *brdp)
panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
if (!panelp) { if (!panelp) {
printk(KERN_WARNING "STALLION: failed to allocate memory " printk(KERN_WARNING "STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlpanel_t)); "(size=%Zd)\n", sizeof(stlpanel_t));
return -ENOMEM; return -ENOMEM;
} }
...@@ -2478,7 +2459,7 @@ static inline int stl_initech(stlbrd_t *brdp) ...@@ -2478,7 +2459,7 @@ static inline int stl_initech(stlbrd_t *brdp)
panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
if (!panelp) { if (!panelp) {
printk("STALLION: failed to allocate memory " printk("STALLION: failed to allocate memory "
"(size=%d)\n", sizeof(stlpanel_t)); "(size=%Zd)\n", sizeof(stlpanel_t));
break; break;
} }
panelp->magic = STL_PANELMAGIC; panelp->magic = STL_PANELMAGIC;
...@@ -2879,8 +2860,7 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) ...@@ -2879,8 +2860,7 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
portp->stats.lflags = 0; portp->stats.lflags = 0;
portp->stats.rxbuffered = 0; portp->stats.rxbuffered = 0;
save_flags(flags); spin_lock_irqsave(&stallion_lock, flags);
cli();
if (portp->tty != (struct tty_struct *) NULL) { if (portp->tty != (struct tty_struct *) NULL) {
if (portp->tty->driver_data == portp) { if (portp->tty->driver_data == portp) {
portp->stats.ttystate = portp->tty->flags; portp->stats.ttystate = portp->tty->flags;
...@@ -2894,7 +2874,7 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) ...@@ -2894,7 +2874,7 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
} }
} }
} }
restore_flags(flags); spin_unlock_irqrestore(&stallion_lock, flags);
head = portp->tx.head; head = portp->tx.head;
tail = portp->tx.tail; tail = portp->tx.tail;
...@@ -3055,14 +3035,6 @@ static int __init stl_init(void) ...@@ -3055,14 +3035,6 @@ static int __init stl_init(void)
if (!stl_serial) if (!stl_serial)
return -1; return -1;
/*
* Allocate a temporary write buffer.
*/
stl_tmpwritebuf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
if (!stl_tmpwritebuf)
printk("STALLION: failed to allocate memory (size=%d)\n",
STL_TXBUFSIZE);
/* /*
* Set up a character driver for per board stuff. This is mainly used * Set up a character driver for per board stuff. This is mainly used
* to do stats ioctls on the ports. * to do stats ioctls on the ports.
...@@ -3147,11 +3119,13 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) ...@@ -3147,11 +3119,13 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
unsigned int gfrcr; unsigned int gfrcr;
int chipmask, i, j; int chipmask, i, j;
int nrchips, uartaddr, ioaddr; int nrchips, uartaddr, ioaddr;
unsigned long flags;
#ifdef DEBUG #ifdef DEBUG
printk("stl_panelinit(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp); printk("stl_panelinit(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp);
#endif #endif
spin_lock_irqsave(&brd_lock, flags);
BRDENABLE(panelp->brdnr, panelp->pagenr); BRDENABLE(panelp->brdnr, panelp->pagenr);
/* /*
...@@ -3189,6 +3163,7 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) ...@@ -3189,6 +3163,7 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
} }
BRDDISABLE(panelp->brdnr); BRDDISABLE(panelp->brdnr);
spin_unlock_irqrestore(&brd_lock, flags);
return chipmask; return chipmask;
} }
...@@ -3200,6 +3175,7 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) ...@@ -3200,6 +3175,7 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp) static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
{ {
unsigned long flags;
#ifdef DEBUG #ifdef DEBUG
printk("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n", printk("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n",
(int) brdp, (int) panelp, (int) portp); (int) brdp, (int) panelp, (int) portp);
...@@ -3209,6 +3185,7 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po ...@@ -3209,6 +3185,7 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po
(portp == (stlport_t *) NULL)) (portp == (stlport_t *) NULL))
return; return;
spin_lock_irqsave(&brd_lock, flags);
portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) || portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
(portp->portnr < 8)) ? 0 : EREG_BANKSIZE); (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
portp->uartaddr = (portp->portnr & 0x04) << 5; portp->uartaddr = (portp->portnr & 0x04) << 5;
...@@ -3219,6 +3196,7 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po ...@@ -3219,6 +3196,7 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po
stl_cd1400setreg(portp, LIVR, (portp->portnr << 3)); stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
portp->hwid = stl_cd1400getreg(portp, GFRCR); portp->hwid = stl_cd1400getreg(portp, GFRCR);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3428,8 +3406,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) ...@@ -3428,8 +3406,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
#endif #endif
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
srer = stl_cd1400getreg(portp, SRER); srer = stl_cd1400getreg(portp, SRER);
...@@ -3466,7 +3443,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) ...@@ -3466,7 +3443,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
portp->sigs &= ~TIOCM_CD; portp->sigs &= ~TIOCM_CD;
stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron)); stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3492,8 +3469,7 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts) ...@@ -3492,8 +3469,7 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
if (rts > 0) if (rts > 0)
msvr2 = MSVR2_RTS; msvr2 = MSVR2_RTS;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
if (rts >= 0) if (rts >= 0)
...@@ -3501,7 +3477,7 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts) ...@@ -3501,7 +3477,7 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
if (dtr >= 0) if (dtr >= 0)
stl_cd1400setreg(portp, MSVR1, msvr1); stl_cd1400setreg(portp, MSVR1, msvr1);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3520,14 +3496,13 @@ static int stl_cd1400getsignals(stlport_t *portp) ...@@ -3520,14 +3496,13 @@ static int stl_cd1400getsignals(stlport_t *portp)
printk("stl_cd1400getsignals(portp=%x)\n", (int) portp); printk("stl_cd1400getsignals(portp=%x)\n", (int) portp);
#endif #endif
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
msvr1 = stl_cd1400getreg(portp, MSVR1); msvr1 = stl_cd1400getreg(portp, MSVR1);
msvr2 = stl_cd1400getreg(portp, MSVR2); msvr2 = stl_cd1400getreg(portp, MSVR2);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
sigs = 0; sigs = 0;
sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0; sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
...@@ -3569,15 +3544,14 @@ static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx) ...@@ -3569,15 +3544,14 @@ static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx)
else if (rx > 0) else if (rx > 0)
ccr |= CCR_RXENABLE; ccr |= CCR_RXENABLE;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
stl_cd1400ccrwait(portp); stl_cd1400ccrwait(portp);
stl_cd1400setreg(portp, CCR, ccr); stl_cd1400setreg(portp, CCR, ccr);
stl_cd1400ccrwait(portp); stl_cd1400ccrwait(portp);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3609,8 +3583,7 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx) ...@@ -3609,8 +3583,7 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
else if (rx > 0) else if (rx > 0)
sreron |= SRER_RXDATA; sreron |= SRER_RXDATA;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
stl_cd1400setreg(portp, SRER, stl_cd1400setreg(portp, SRER,
...@@ -3618,7 +3591,7 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx) ...@@ -3618,7 +3591,7 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
if (tx > 0) if (tx > 0)
set_bit(ASYI_TXBUSY, &portp->istate); set_bit(ASYI_TXBUSY, &portp->istate);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3634,13 +3607,12 @@ static void stl_cd1400disableintrs(stlport_t *portp) ...@@ -3634,13 +3607,12 @@ static void stl_cd1400disableintrs(stlport_t *portp)
#ifdef DEBUG #ifdef DEBUG
printk("stl_cd1400disableintrs(portp=%x)\n", (int) portp); printk("stl_cd1400disableintrs(portp=%x)\n", (int) portp);
#endif #endif
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
stl_cd1400setreg(portp, SRER, 0); stl_cd1400setreg(portp, SRER, 0);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3653,8 +3625,7 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len) ...@@ -3653,8 +3625,7 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len)
printk("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, len); printk("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, len);
#endif #endif
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
stl_cd1400setreg(portp, SRER, stl_cd1400setreg(portp, SRER,
...@@ -3664,7 +3635,7 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len) ...@@ -3664,7 +3635,7 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len)
portp->brklen = len; portp->brklen = len;
if (len == 1) if (len == 1)
portp->stats.txbreaks++; portp->stats.txbreaks++;
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3688,8 +3659,7 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state) ...@@ -3688,8 +3659,7 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state)
if (tty == (struct tty_struct *) NULL) if (tty == (struct tty_struct *) NULL)
return; return;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
...@@ -3729,7 +3699,7 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state) ...@@ -3729,7 +3699,7 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state)
} }
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3753,8 +3723,7 @@ static void stl_cd1400sendflow(stlport_t *portp, int state) ...@@ -3753,8 +3723,7 @@ static void stl_cd1400sendflow(stlport_t *portp, int state)
if (tty == (struct tty_struct *) NULL) if (tty == (struct tty_struct *) NULL)
return; return;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
if (state) { if (state) {
...@@ -3769,7 +3738,7 @@ static void stl_cd1400sendflow(stlport_t *portp, int state) ...@@ -3769,7 +3738,7 @@ static void stl_cd1400sendflow(stlport_t *portp, int state)
stl_cd1400ccrwait(portp); stl_cd1400ccrwait(portp);
} }
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3785,8 +3754,7 @@ static void stl_cd1400flush(stlport_t *portp) ...@@ -3785,8 +3754,7 @@ static void stl_cd1400flush(stlport_t *portp)
if (portp == (stlport_t *) NULL) if (portp == (stlport_t *) NULL)
return; return;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
stl_cd1400ccrwait(portp); stl_cd1400ccrwait(portp);
...@@ -3794,7 +3762,7 @@ static void stl_cd1400flush(stlport_t *portp) ...@@ -3794,7 +3762,7 @@ static void stl_cd1400flush(stlport_t *portp)
stl_cd1400ccrwait(portp); stl_cd1400ccrwait(portp);
portp->tx.tail = portp->tx.head; portp->tx.tail = portp->tx.head;
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -3833,6 +3801,7 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase) ...@@ -3833,6 +3801,7 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
(int) panelp, iobase); (int) panelp, iobase);
#endif #endif
spin_lock(&brd_lock);
outb(SVRR, iobase); outb(SVRR, iobase);
svrtype = inb(iobase + EREG_DATA); svrtype = inb(iobase + EREG_DATA);
if (panelp->nrports > 4) { if (panelp->nrports > 4) {
...@@ -3846,6 +3815,8 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase) ...@@ -3846,6 +3815,8 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
stl_cd1400txisr(panelp, iobase); stl_cd1400txisr(panelp, iobase);
else if (svrtype & SVRR_MDM) else if (svrtype & SVRR_MDM)
stl_cd1400mdmisr(panelp, iobase); stl_cd1400mdmisr(panelp, iobase);
spin_unlock(&brd_lock);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4433,8 +4404,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) ...@@ -4433,8 +4404,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
#endif #endif
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_sc26198setreg(portp, IMR, 0); stl_sc26198setreg(portp, IMR, 0);
stl_sc26198updatereg(portp, MR0, mr0); stl_sc26198updatereg(portp, MR0, mr0);
...@@ -4461,7 +4431,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) ...@@ -4461,7 +4431,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
portp->imr = (portp->imr & ~imroff) | imron; portp->imr = (portp->imr & ~imroff) | imron;
stl_sc26198setreg(portp, IMR, portp->imr); stl_sc26198setreg(portp, IMR, portp->imr);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4491,13 +4461,12 @@ static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts) ...@@ -4491,13 +4461,12 @@ static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts)
else if (rts > 0) else if (rts > 0)
iopioron |= IPR_RTS; iopioron |= IPR_RTS;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_sc26198setreg(portp, IOPIOR, stl_sc26198setreg(portp, IOPIOR,
((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron)); ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4516,12 +4485,11 @@ static int stl_sc26198getsignals(stlport_t *portp) ...@@ -4516,12 +4485,11 @@ static int stl_sc26198getsignals(stlport_t *portp)
printk("stl_sc26198getsignals(portp=%x)\n", (int) portp); printk("stl_sc26198getsignals(portp=%x)\n", (int) portp);
#endif #endif
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
ipr = stl_sc26198getreg(portp, IPR); ipr = stl_sc26198getreg(portp, IPR);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
sigs = 0; sigs = 0;
sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD; sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
...@@ -4558,13 +4526,12 @@ static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx) ...@@ -4558,13 +4526,12 @@ static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx)
else if (rx > 0) else if (rx > 0)
ccr |= CR_RXENABLE; ccr |= CR_RXENABLE;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_sc26198setreg(portp, SCCR, ccr); stl_sc26198setreg(portp, SCCR, ccr);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
portp->crenable = ccr; portp->crenable = ccr;
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4593,15 +4560,14 @@ static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx) ...@@ -4593,15 +4560,14 @@ static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx)
else if (rx > 0) else if (rx > 0)
imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG; imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_sc26198setreg(portp, IMR, imr); stl_sc26198setreg(portp, IMR, imr);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
portp->imr = imr; portp->imr = imr;
if (tx > 0) if (tx > 0)
set_bit(ASYI_TXBUSY, &portp->istate); set_bit(ASYI_TXBUSY, &portp->istate);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4618,13 +4584,12 @@ static void stl_sc26198disableintrs(stlport_t *portp) ...@@ -4618,13 +4584,12 @@ static void stl_sc26198disableintrs(stlport_t *portp)
printk("stl_sc26198disableintrs(portp=%x)\n", (int) portp); printk("stl_sc26198disableintrs(portp=%x)\n", (int) portp);
#endif #endif
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
portp->imr = 0; portp->imr = 0;
stl_sc26198setreg(portp, IMR, 0); stl_sc26198setreg(portp, IMR, 0);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4637,8 +4602,7 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len) ...@@ -4637,8 +4602,7 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len)
printk("stl_sc26198sendbreak(portp=%x,len=%d)\n", (int) portp, len); printk("stl_sc26198sendbreak(portp=%x,len=%d)\n", (int) portp, len);
#endif #endif
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
if (len == 1) { if (len == 1) {
stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK); stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
...@@ -4647,7 +4611,7 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len) ...@@ -4647,7 +4611,7 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len)
stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK); stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
} }
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4672,8 +4636,7 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state) ...@@ -4672,8 +4636,7 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state)
if (tty == (struct tty_struct *) NULL) if (tty == (struct tty_struct *) NULL)
return; return;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
if (state) { if (state) {
...@@ -4719,7 +4682,7 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state) ...@@ -4719,7 +4682,7 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state)
} }
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4744,8 +4707,7 @@ static void stl_sc26198sendflow(stlport_t *portp, int state) ...@@ -4744,8 +4707,7 @@ static void stl_sc26198sendflow(stlport_t *portp, int state)
if (tty == (struct tty_struct *) NULL) if (tty == (struct tty_struct *) NULL)
return; return;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
if (state) { if (state) {
mr0 = stl_sc26198getreg(portp, MR0); mr0 = stl_sc26198getreg(portp, MR0);
...@@ -4765,7 +4727,7 @@ static void stl_sc26198sendflow(stlport_t *portp, int state) ...@@ -4765,7 +4727,7 @@ static void stl_sc26198sendflow(stlport_t *portp, int state)
stl_sc26198setreg(portp, MR0, mr0); stl_sc26198setreg(portp, MR0, mr0);
} }
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4781,14 +4743,13 @@ static void stl_sc26198flush(stlport_t *portp) ...@@ -4781,14 +4743,13 @@ static void stl_sc26198flush(stlport_t *portp)
if (portp == (stlport_t *) NULL) if (portp == (stlport_t *) NULL)
return; return;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
stl_sc26198setreg(portp, SCCR, CR_TXRESET); stl_sc26198setreg(portp, SCCR, CR_TXRESET);
stl_sc26198setreg(portp, SCCR, portp->crenable); stl_sc26198setreg(portp, SCCR, portp->crenable);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
portp->tx.tail = portp->tx.head; portp->tx.tail = portp->tx.head;
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
} }
/*****************************************************************************/ /*****************************************************************************/
...@@ -4815,12 +4776,11 @@ static int stl_sc26198datastate(stlport_t *portp) ...@@ -4815,12 +4776,11 @@ static int stl_sc26198datastate(stlport_t *portp)
if (test_bit(ASYI_TXBUSY, &portp->istate)) if (test_bit(ASYI_TXBUSY, &portp->istate))
return 1; return 1;
save_flags(flags); spin_lock_irqsave(&brd_lock, flags);
cli();
BRDENABLE(portp->brdnr, portp->pagenr); BRDENABLE(portp->brdnr, portp->pagenr);
sr = stl_sc26198getreg(portp, SR); sr = stl_sc26198getreg(portp, SR);
BRDDISABLE(portp->brdnr); BRDDISABLE(portp->brdnr);
restore_flags(flags); spin_unlock_irqrestore(&brd_lock, flags);
return (sr & SR_TXEMPTY) ? 0 : 1; return (sr & SR_TXEMPTY) ? 0 : 1;
} }
...@@ -4878,6 +4838,8 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) ...@@ -4878,6 +4838,8 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
stlport_t *portp; stlport_t *portp;
unsigned int iack; unsigned int iack;
spin_lock(&brd_lock);
/* /*
* Work around bug in sc26198 chip... Cannot have A6 address * Work around bug in sc26198 chip... Cannot have A6 address
* line of UART high, else iack will be returned as 0. * line of UART high, else iack will be returned as 0.
...@@ -4893,6 +4855,8 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) ...@@ -4893,6 +4855,8 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
stl_sc26198txisr(portp); stl_sc26198txisr(portp);
else else
stl_sc26198otherisr(portp, iack); stl_sc26198otherisr(portp, iack);
spin_unlock(&brd_lock);
} }
/*****************************************************************************/ /*****************************************************************************/
......
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