summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-11-17 10:56:34 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-17 10:56:34 -0800
commit7652aab77fbf6de8bcc69ee6a864270b0da6b3f6 (patch)
treecc380ac53a720a905232463cd8fed9cb27875723 /drivers
parentcd02e27b1514a27b2a8ab59755ae6d23d4d8a10f (diff)
parentaec8b7557cf0fc4dac059112328b5aa89271c77e (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/Kconfig4
-rw-r--r--drivers/ide/Makefile2
-rw-r--r--drivers/ide/mips/Makefile1
-rw-r--r--drivers/ide/mips/swarm.c201
-rw-r--r--drivers/tc/zs.c150
-rw-r--r--drivers/tc/zs.h13
6 files changed, 277 insertions, 94 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 42e5b8175cb..ed2bc87f475 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -787,6 +787,10 @@ config BLK_DEV_IDE_PMAC_BLINK
This option enables the use of the sleep LED as a hard drive
activity LED.
+config BLK_DEV_IDE_SWARM
+ tristate "IDE for Sibyte evaluation boards"
+ depends on SIBYTE_SB1xxx_SOC
+
config BLK_DEV_IDE_AU1XXX
bool "IDE for AMD Alchemy Au1200"
depends on SOC_AU1200
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index cca9c075966..569fae71750 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -48,6 +48,6 @@ obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o
obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o
obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o
-obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/
+obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/ mips/
obj-$(CONFIG_BLK_DEV_HD) += legacy/
obj-$(CONFIG_ETRAX_IDE) += cris/
diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile
new file mode 100644
index 00000000000..578e52a5958
--- /dev/null
+++ b/drivers/ide/mips/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
new file mode 100644
index 00000000000..66f6064f464
--- /dev/null
+++ b/drivers/ide/mips/swarm.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved.
+ * Author: Maciej W. Rozycki <macro@mips.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Derived loosely from ide-pmac.c, so:
+ * Copyright (C) 1998 Paul Mackerras.
+ * Copyright (C) 1995-1998 Mark Lord
+ */
+
+/*
+ * Boards with SiByte processors so far have supported IDE devices via
+ * the Generic Bus, PCI bus, and built-in PCMCIA interface. In all
+ * cases, byte-swapping must be avoided for these devices (whereas
+ * other PCI devices, for example, will require swapping). Any
+ * SiByte-targetted kernel including IDE support will include this
+ * file. Probing of a Generic Bus for an IDE device is controlled by
+ * the definition of "SIBYTE_HAVE_IDE", which is provided by
+ * <asm/sibyte/board.h> for Broadcom boards.
+ */
+
+#include <linux/ide.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+
+#include <asm/sibyte/board.h>
+#include <asm/sibyte/sb1250_genbus.h>
+#include <asm/sibyte/sb1250_regs.h>
+
+#define DRV_NAME "ide-swarm"
+
+static char swarm_ide_string[] = DRV_NAME;
+
+static struct resource swarm_ide_resource = {
+ .name = "SWARM GenBus IDE",
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device *swarm_ide_dev;
+
+/*
+ * swarm_ide_probe - if the board header indicates the existence of
+ * Generic Bus IDE, allocate a HWIF for it.
+ */
+static int __devinit swarm_ide_probe(struct device *dev)
+{
+ ide_hwif_t *hwif;
+ u8 __iomem *base;
+ phys_t offset, size;
+ int i;
+
+ if (!SIBYTE_HAVE_IDE)
+ return -ENODEV;
+
+ /* Find an empty slot. */
+ for (i = 0; i < MAX_HWIFS; i++)
+ if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET])
+ break;
+ if (i >= MAX_HWIFS) {
+ printk(KERN_ERR DRV_NAME ": no free slot for interface\n");
+ return -ENOMEM;
+ }
+
+ hwif = ide_hwifs + i;
+
+ base = ioremap(A_IO_EXT_BASE, 0x800);
+ offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
+ size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
+ iounmap(base);
+
+ offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE;
+ size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE;
+ if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) {
+ printk(KERN_INFO DRV_NAME
+ ": IDE interface at GenBus disabled\n");
+ return -EBUSY;
+ }
+
+ printk(KERN_INFO DRV_NAME ": IDE interface at GenBus slot %i\n",
+ IDE_CS);
+
+ swarm_ide_resource.start = offset;
+ swarm_ide_resource.end = offset + size - 1;
+ if (request_resource(&iomem_resource, &swarm_ide_resource)) {
+ printk(KERN_ERR DRV_NAME
+ ": can't request I/O memory resource\n");
+ return -EBUSY;
+ }
+
+ base = ioremap(offset, size);
+
+ /* Setup MMIO ops. */
+ default_hwif_mmiops(hwif);
+ /* Prevent resource map manipulation. */
+ hwif->mmio = 2;
+ hwif->noprobe = 0;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+ hwif->hw.io_ports[i] =
+ (unsigned long)(base + ((0x1f0 + i) << 5));
+ hwif->hw.io_ports[IDE_CONTROL_OFFSET] =
+ (unsigned long)(base + (0x3f6 << 5));
+ hwif->hw.irq = K_INT_GB_IDE;
+
+ memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+ hwif->irq = hwif->hw.irq;
+
+ dev_set_drvdata(dev, hwif);
+
+ return 0;
+}
+
+static struct device_driver swarm_ide_driver = {
+ .name = swarm_ide_string,
+ .bus = &platform_bus_type,
+ .probe = swarm_ide_probe,
+};
+
+static void swarm_ide_platform_release(struct device *device)
+{
+ struct platform_device *pldev;
+
+ /* free device */
+ pldev = to_platform_device(device);
+ kfree(pldev);
+}
+
+static int __devinit swarm_ide_init_module(void)
+{
+ struct platform_device *pldev;
+ int err;
+
+ printk(KERN_INFO "SWARM IDE driver\n");
+
+ if (driver_register(&swarm_ide_driver)) {
+ printk(KERN_ERR "Driver registration failed\n");
+ err = -ENODEV;
+ goto out;
+ }
+
+ if (!(pldev = kmalloc(sizeof (*pldev), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto out_unregister_driver;
+ }
+
+ memset (pldev, 0, sizeof (*pldev));
+ pldev->name = swarm_ide_string;
+ pldev->id = 0;
+ pldev->dev.release = swarm_ide_platform_release;
+
+ if (platform_device_register(pldev)) {
+ err = -ENODEV;
+ goto out_free_pldev;
+ }
+
+ if (!pldev->dev.driver) {
+ /*
+ * The driver was not bound to this device, there was
+ * no hardware at this address. Unregister it, as the
+ * release fuction will take care of freeing the
+ * allocated structure
+ */
+ platform_device_unregister (pldev);
+ }
+
+ swarm_ide_dev = pldev;
+
+ return 0;
+
+out_free_pldev:
+ kfree(pldev);
+
+out_unregister_driver:
+ driver_unregister(&swarm_ide_driver);
+out:
+ return err;
+}
+
+module_init(swarm_ide_init_module);
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index c52af73a251..6756d0fab6f 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -6,7 +6,7 @@
*
* DECstation changes
* Copyright (C) 1998-2000 Harald Koerfgen
- * Copyright (C) 2000, 2001, 2002, 2003, 2004 Maciej W. Rozycki
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Maciej W. Rozycki
*
* For the rest of the code the original Copyright applies:
* Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
@@ -55,6 +55,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/spinlock.h>
#ifdef CONFIG_SERIAL_DEC_CONSOLE
#include <linux/console.h>
#endif
@@ -63,7 +64,6 @@
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/uaccess.h>
#include <asm/bootinfo.h>
#include <asm/dec/interrupts.h>
@@ -128,6 +128,8 @@ static struct zs_parms ds_parms = {
#define BUS_PRESENT (DS_BUS_PRESENT)
+DEFINE_SPINLOCK(zs_lock);
+
struct dec_zschannel zs_channels[NUM_CHANNELS];
struct dec_serial zs_soft[NUM_CHANNELS];
int zs_channels_found;
@@ -159,8 +161,6 @@ static unsigned char zs_init_regs[16] __initdata = {
0 /* write 15 */
};
-DECLARE_TASK_QUEUE(tq_zs_serial);
-
static struct tty_driver *serial_driver;
/* serial subtype definitions */
@@ -294,8 +294,7 @@ static inline void zs_rtsdtr(struct dec_serial *info, int which, int set)
{
unsigned long flags;
-
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
if (info->zs_channel != info->zs_chan_a) {
if (set) {
info->zs_chan_a->curregs[5] |= (which & (RTS | DTR));
@@ -304,7 +303,7 @@ static inline void zs_rtsdtr(struct dec_serial *info, int which, int set)
}
write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
/* Utility routines for the Zilog */
@@ -345,12 +344,10 @@ static inline void rs_recv_clear(struct dec_zschannel *zsc)
* This routine is used by the interrupt handler to schedule
* processing in the software interrupt portion of the driver.
*/
-static _INLINE_ void rs_sched_event(struct dec_serial *info,
- int event)
+static _INLINE_ void rs_sched_event(struct dec_serial *info, int event)
{
info->event |= 1 << event;
- queue_task(&info->tqueue, &tq_zs_serial);
- mark_bh(SERIAL_BH);
+ tasklet_schedule(&info->tlet);
}
static _INLINE_ void receive_chars(struct dec_serial *info,
@@ -497,9 +494,10 @@ static _INLINE_ void status_handle(struct dec_serial *info)
/*
* This is the serial driver's generic interrupt routine
*/
-void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct dec_serial *info = (struct dec_serial *) dev_id;
+ irqreturn_t status = IRQ_NONE;
unsigned char zs_intreg;
int shift;
@@ -521,6 +519,8 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if ((zs_intreg & CHAN_IRQMASK) == 0)
break;
+ status = IRQ_HANDLED;
+
if (zs_intreg & CHBRxIP) {
receive_chars(info, regs);
}
@@ -534,6 +534,8 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* Why do we need this ? */
write_zsreg(info->zs_channel, 0, RES_H_IUS);
+
+ return status;
}
#ifdef ZS_DEBUG_REGS
@@ -578,12 +580,12 @@ static void rs_stop(struct tty_struct *tty)
return;
#if 1
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
if (info->zs_channel->curregs[5] & TxENAB) {
info->zs_channel->curregs[5] &= ~TxENAB;
write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
#endif
}
@@ -595,7 +597,7 @@ static void rs_start(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->name, "rs_start"))
return;
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
#if 1
if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) {
info->zs_channel->curregs[5] |= TxENAB;
@@ -606,7 +608,7 @@ static void rs_start(struct tty_struct *tty)
transmit_chars(info);
}
#endif
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
/*
@@ -618,12 +620,8 @@ static void rs_start(struct tty_struct *tty)
* interrupt driver proper are done; the interrupt driver schedules
* them using rs_sched_event(), and they get done here.
*/
-static void do_serial_bh(void)
-{
- run_task_queue(&tq_zs_serial);
-}
-static void do_softint(void *private_)
+static void do_softint(unsigned long private_)
{
struct dec_serial *info = (struct dec_serial *) private_;
struct tty_struct *tty;
@@ -634,10 +632,11 @@ static void do_softint(void *private_)
if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
tty_wakeup(tty);
+ wake_up_interruptible(&tty->write_wait);
}
}
-int zs_startup(struct dec_serial * info)
+static int zs_startup(struct dec_serial * info)
{
unsigned long flags;
@@ -650,7 +649,7 @@ int zs_startup(struct dec_serial * info)
return -ENOMEM;
}
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
#ifdef SERIAL_DEBUG_OPEN
printk("starting up ttyS%d (irq %d)...", info->line, info->irq);
@@ -706,7 +705,7 @@ int zs_startup(struct dec_serial * info)
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
info->flags |= ZILOG_INITIALIZED;
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
return 0;
}
@@ -726,7 +725,7 @@ static void shutdown(struct dec_serial * info)
info->irq);
#endif
- save_flags(flags); cli(); /* Disable interrupts */
+ spin_lock_irqsave(&zs_lock, flags);
if (info->xmit_buf) {
free_page((unsigned long) info->xmit_buf);
@@ -749,7 +748,7 @@ static void shutdown(struct dec_serial * info)
set_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags &= ~ZILOG_INITIALIZED;
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
/*
@@ -785,7 +784,7 @@ static void change_speed(struct dec_serial *info)
i += 15;
}
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
info->zs_baud = baud_table[i];
if (info->zs_baud) {
brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor);
@@ -858,7 +857,7 @@ static void change_speed(struct dec_serial *info)
/* Load up the new values */
load_zsregs(info->zs_channel, info->zs_channel->curregs);
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
static void rs_flush_chars(struct tty_struct *tty)
@@ -874,9 +873,9 @@ static void rs_flush_chars(struct tty_struct *tty)
return;
/* Enable transmitter */
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
transmit_chars(info);
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
static int rs_write(struct tty_struct * tty,
@@ -892,26 +891,17 @@ static int rs_write(struct tty_struct * tty,
if (!tty || !info->xmit_buf)
return 0;
- save_flags(flags);
while (1) {
- cli();
+ spin_lock_irqsave(&zs_lock, flags);
c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
SERIAL_XMIT_SIZE - info->xmit_head));
if (c <= 0)
break;
- if (from_user) {
- down(&tmp_buf_sem);
- copy_from_user(tmp_buf, buf, c);
- c = min(c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - info->xmit_head));
- memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
- up(&tmp_buf_sem);
- } else
- memcpy(info->xmit_buf + info->xmit_head, buf, c);
+ memcpy(info->xmit_buf + info->xmit_head, buf, c);
info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
info->xmit_cnt += c;
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
buf += c;
count -= c;
total += c;
@@ -920,7 +910,7 @@ static int rs_write(struct tty_struct * tty,
if (info->xmit_cnt && !tty->stopped && !info->tx_stopped
&& !info->tx_active)
transmit_chars(info);
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
return total;
}
@@ -952,9 +942,9 @@ static void rs_flush_buffer(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
return;
- cli();
+ spin_lock_irq(&zs_lock);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- sti();
+ spin_unlock_irq(&zs_lock);
tty_wakeup(tty);
}
@@ -982,11 +972,11 @@ static void rs_throttle(struct tty_struct * tty)
return;
if (I_IXOFF(tty)) {
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
info->x_char = STOP_CHAR(tty);
if (!info->tx_active)
transmit_chars(info);
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
if (C_CRTSCTS(tty)) {
@@ -1010,7 +1000,7 @@ static void rs_unthrottle(struct tty_struct * tty)
return;
if (I_IXOFF(tty)) {
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
if (info->x_char)
info->x_char = 0;
else {
@@ -1018,7 +1008,7 @@ static void rs_unthrottle(struct tty_struct * tty)
if (!info->tx_active)
transmit_chars(info);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
if (C_CRTSCTS(tty)) {
@@ -1111,9 +1101,9 @@ static int get_lsr_info(struct dec_serial * info, unsigned int *value)
{
unsigned char status;
- cli();
+ spin_lock(&zs_lock);
status = read_zsreg(info->zs_channel, 0);
- sti();
+ spin_unlock_irq(&zs_lock);
put_user(status,value);
return 0;
}
@@ -1136,11 +1126,11 @@ static int rs_tiocmget(struct tty_struct *tty, struct file *file)
if (info->zs_channel == info->zs_chan_a)
result = 0;
else {
- cli();
+ spin_lock(&zs_lock);
control = info->zs_chan_a->curregs[5];
status_a = read_zsreg(info->zs_chan_a, 0);
status_b = read_zsreg(info->zs_channel, 0);
- sti();
+ spin_unlock_irq(&zs_lock);
result = ((control & RTS) ? TIOCM_RTS: 0)
| ((control & DTR) ? TIOCM_DTR: 0)
| ((status_b & DCD) ? TIOCM_CAR: 0)
@@ -1155,8 +1145,6 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct dec_serial * info = (struct dec_serial *)tty->driver_data;
- int error;
- unsigned int arg, bits;
if (info->hook)
return -ENODEV;
@@ -1170,8 +1158,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
if (info->zs_channel == info->zs_chan_a)
return 0;
- get_user(arg, value);
- cli();
+ spin_lock(&zs_lock);
if (set & TIOCM_RTS)
info->zs_chan_a->curregs[5] |= RTS;
if (set & TIOCM_DTR)
@@ -1181,7 +1168,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
if (clear & TIOCM_DTR)
info->zs_chan_a->curregs[5] &= ~DTR;
write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
- sti();
+ spin_unlock_irq(&zs_lock);
return 0;
}
@@ -1198,19 +1185,18 @@ static void rs_break(struct tty_struct *tty, int break_state)
if (!info->port)
return;
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
if (break_state == -1)
info->zs_channel->curregs[5] |= SND_BRK;
else
info->zs_channel->curregs[5] &= ~SND_BRK;
write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
static int rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
- int error;
struct dec_serial * info = (struct dec_serial *)tty->driver_data;
if (info->hook)
@@ -1287,10 +1273,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
return;
- save_flags(flags); cli();
+ spin_lock_irqsave(&zs_lock, flags);
if (tty_hung_up_p(filp)) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
return;
}
@@ -1315,7 +1301,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->count = 0;
}
if (info->count) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
return;
}
info->flags |= ZILOG_CLOSING;
@@ -1358,7 +1344,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
}
info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING);
wake_up_interruptible(&info->close_wait);
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
/*
@@ -1398,7 +1384,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
/*
* rs_hangup() --- called by tty_hangup() when a hangup is signaled.
*/
-void rs_hangup(struct tty_struct *tty)
+static void rs_hangup(struct tty_struct *tty)
{
struct dec_serial * info = (struct dec_serial *)tty->driver_data;
@@ -1466,16 +1452,16 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready before block: ttyS%d, count = %d\n",
info->line, info->count);
#endif
- cli();
+ spin_lock(&zs_lock);
if (!tty_hung_up_p(filp))
info->count--;
- sti();
+ spin_unlock_irq(&zs_lock);
info->blocked_open++;
while (1) {
- cli();
+ spin_lock(&zs_lock);
if (tty->termios->c_cflag & CBAUD)
zs_rtsdtr(info, RTS | DTR, 1);
- sti();
+ spin_unlock_irq(&zs_lock);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ZILOG_INITIALIZED)) {
@@ -1523,7 +1509,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
* the IRQ chain. It also performs the serial-specific
* initialization for the tty structure.
*/
-int rs_open(struct tty_struct *tty, struct file * filp)
+static int rs_open(struct tty_struct *tty, struct file * filp)
{
struct dec_serial *info;
int retval, line;
@@ -1706,7 +1692,7 @@ static void __init probe_sccs(void)
}
}
- save_and_cli(flags);
+ spin_lock_irqsave(&zs_lock, flags);
for (n = 0; n < zs_channels_found; n++) {
if (n % 2 == 0) {
write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES);
@@ -1716,7 +1702,7 @@ static void __init probe_sccs(void)
load_zsregs(zs_soft[n].zs_channel,
zs_soft[n].zs_channel->curregs);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
}
static struct tty_operations serial_ops = {
@@ -1749,9 +1735,6 @@ int __init zs_init(void)
if(!BUS_PRESENT)
return -ENODEV;
- /* Setup base handler, and timer table. */
- init_bh(SERIAL_BH, do_serial_bh);
-
/* Find out how many Z8530 SCCs we have */
if (zs_chain == 0)
probe_sccs();
@@ -1800,8 +1783,7 @@ int __init zs_init(void)
info->event = 0;
info->count = 0;
info->blocked_open = 0;
- info->tqueue.routine = do_softint;
- info->tqueue.data = info;
+ tasklet_init(&info->tlet, do_softint, (unsigned long)info);
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
printk("ttyS%02d at 0x%08x (irq = %d) is a Z85C30 SCC\n",
@@ -1833,8 +1815,7 @@ int __init zs_init(void)
/*
* polling I/O routines
*/
-static int
-zs_poll_tx_char(void *handle, unsigned char ch)
+static int zs_poll_tx_char(void *handle, unsigned char ch)
{
struct dec_serial *info = handle;
struct dec_zschannel *chan = info->zs_channel;
@@ -1857,8 +1838,7 @@ zs_poll_tx_char(void *handle, unsigned char ch)
return -ENODEV;
}
-static int
-zs_poll_rx_char(void *handle)
+static int zs_poll_rx_char(void *handle)
{
struct dec_serial *info = handle;
struct dec_zschannel *chan = info->zs_channel;
@@ -2037,7 +2017,7 @@ static int __init serial_console_setup(struct console *co, char *options)
}
co->cflag = cflag;
- save_and_cli(flags);
+ spin_lock_irqsave(&zs_lock, flags);
/*
* Set up the baud rate generator.
@@ -2092,7 +2072,7 @@ static int __init serial_console_setup(struct console *co, char *options)
zs_soft[co->index].clk_divisor = clk_divisor;
zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]);
- restore_flags(flags);
+ spin_unlock_irqrestore(&zs_lock, flags);
return 0;
}
@@ -2229,5 +2209,3 @@ void __init zs_kgdb_hook(int tty_num)
set_debug_traps(); /* init stub */
}
#endif /* ifdef CONFIG_KGDB */
-
-
diff --git a/drivers/tc/zs.h b/drivers/tc/zs.h
index c52edffa604..13512200ceb 100644
--- a/drivers/tc/zs.h
+++ b/drivers/tc/zs.h
@@ -6,14 +6,14 @@
*
* Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 2004 Maciej W. Rozycki
+ * Copyright (C) 2004, 2005 Maciej W. Rozycki
*/
#ifndef _DECSERIAL_H
#define _DECSERIAL_H
#include <asm/dec/serial.h>
-#define NUM_ZSREGS 16
+#define NUM_ZSREGS 16
struct serial_struct {
int type;
@@ -139,8 +139,7 @@ struct dec_serial {
int xmit_head;
int xmit_tail;
int xmit_cnt;
- struct tq_struct tqueue;
- struct tq_struct tqueue_hangup;
+ struct tasklet_struct tlet;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
};
@@ -282,7 +281,7 @@ struct dec_serial {
#define DLC 4 /* Disable Lower Chain */
#define MIE 8 /* Master Interrupt Enable */
#define STATHI 0x10 /* Status high */
-#define SOFTACK 0x20 /* Software Interrupt Acknowledge */
+#define SOFTACK 0x20 /* Software Interrupt Acknowledge */
#define NORESET 0 /* No reset on write to R9 */
#define CHRB 0x40 /* Reset channel B */
#define CHRA 0x80 /* Reset channel A */
@@ -395,8 +394,8 @@ struct dec_serial {
/* Read Register 15 (value of WR 15) */
/* Misc macros */
-#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES))
-#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \
+#define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES))
+#define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \
garbage = read_zsdata(channel); \
garbage = read_zsdata(channel); \
garbage = read_zsdata(channel); \