From: Patrick van de Lageweg This patch converts all save_flags/restore_flags to the new spin_lock_irqsave/spin_unlock_irqrestore calls, as well as some other 2.6.X cleanups. This allows the "sx" driver to become SMP safe. Signed-off-by: Patrick vd Lageweg Signed-off-by: Rogier Wolff Signed-off-by: Andrew Morton --- 25-akpm/drivers/char/Kconfig | 2 - 25-akpm/drivers/char/sx.c | 60 ++++++++++++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 21 deletions(-) diff -puN drivers/char/Kconfig~sx-cli-conversion drivers/char/Kconfig --- 25/drivers/char/Kconfig~sx-cli-conversion 2005-01-10 21:15:26.729390096 -0800 +++ 25-akpm/drivers/char/Kconfig 2005-01-10 21:15:26.734389336 -0800 @@ -301,7 +301,7 @@ config SPECIALIX_RTSCTS config SX tristate "Specialix SX (and SI) card support" - depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP + depends on SERIAL_NONSTANDARD help This is a driver for the SX and SI multiport serial cards. Please read the file for details. diff -puN drivers/char/sx.c~sx-cli-conversion drivers/char/sx.c --- 25/drivers/char/sx.c~sx-cli-conversion 2005-01-10 21:15:26.730389944 -0800 +++ 25-akpm/drivers/char/sx.c 2005-01-10 21:15:26.737388880 -0800 @@ -4,7 +4,7 @@ * This driver will also support the older SI, and XIO cards. * * - * (C) 1998 - 2000 R.E.Wolff@BitWizard.nl + * (C) 1998 - 2004 R.E.Wolff@BitWizard.nl * * Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous * version of this driver. Some fragments may have been copied. (none @@ -354,13 +354,13 @@ static int si1_probe_addrs[]= { 0xd0000} Some architectures may need more. */ static int sx_irqmask = -1; -MODULE_PARM(sx_probe_addrs, "i"); -MODULE_PARM(si_probe_addrs, "i"); -MODULE_PARM(sx_poll, "i"); -MODULE_PARM(sx_slowpoll, "i"); -MODULE_PARM(sx_maxints, "i"); -MODULE_PARM(sx_debug, "i"); -MODULE_PARM(sx_irqmask, "i"); +module_param_array(sx_probe_addrs, int, NULL, 0); +module_param_array(si_probe_addrs, int, NULL, 0); +module_param(sx_poll, int, 0); +module_param(sx_slowpoll, int, 0); +module_param(sx_maxints, int, 0); +module_param(sx_debug, int, 0); +module_param(sx_irqmask, int, 0); MODULE_LICENSE("GPL"); @@ -396,7 +396,7 @@ static struct real_driver sx_real_driver -#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\b",__FUNCTION__) +#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__) #define func_exit() sx_dprintk (SX_DEBUG_FLOW, "sx: exit %s\n", __FUNCTION__) #define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \ @@ -1158,7 +1158,6 @@ static inline void sx_check_modem_signal if (hi_state & ST_BREAK) { hi_state &= ~ST_BREAK; sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n"); - sx_write_channel_byte (port, hi_state, hi_state); gs_got_break (&port->gs); } @@ -1206,7 +1205,7 @@ static irqreturn_t sx_interrupt (int irq struct sx_port *port; int i; - /* func_enter (); */ + func_enter (); sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq); /* AAargh! The order in which to do these things is essential and @@ -1297,7 +1296,7 @@ static irqreturn_t sx_interrupt (int irq clear_bit (SX_BOARD_INTR_LOCK, &board->locks); sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq); - /* func_exit (); */ + func_exit (); return IRQ_HANDLED; } @@ -1428,6 +1427,7 @@ static int sx_open (struct tty_struct * { struct sx_port *port; int retval, line; + unsigned long flags; func_enter(); @@ -1449,9 +1449,12 @@ static int sx_open (struct tty_struct * sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd); + spin_lock_irqsave(&port->gs.driver_lock, flags); + tty->driver_data = port; port->gs.tty = tty; port->gs.count++; + spin_unlock_irqrestore(&port->gs.driver_lock, flags); sx_dprintk (SX_DEBUG_OPEN, "starting port\n"); @@ -1466,7 +1469,8 @@ static int sx_open (struct tty_struct * } port->gs.flags |= GS_ACTIVE; - sx_setsignals (port, 1,1); + if (port->gs.count <= 1) + sx_setsignals (port, 1,1); #if 0 if (sx_debug & SX_DEBUG_OPEN) @@ -1476,10 +1480,14 @@ static int sx_open (struct tty_struct * my_hd_io (port->board->base + port->ch_base, sizeof (*port)); #endif - if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { - printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n"); - port->gs.count--; - return -EIO; + if (port->gs.count <= 1) { + if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { + printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n"); + spin_lock_irqsave(&port->gs.driver_lock, flags); + port->gs.count--; + spin_unlock_irqrestore(&port->gs.driver_lock, flags); + return -EIO; + } } retval = gs_block_til_ready(port, filp); @@ -1497,6 +1505,7 @@ static int sx_open (struct tty_struct * port->c_dcd = sx_get_CD (port); sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); + func_exit(); return 0; @@ -1535,7 +1544,8 @@ static void sx_close (void *ptr) if(port->gs.count) { sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count); - port->gs.count = 0; + //printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count); + //port->gs.count = 0; } func_exit (); @@ -1751,12 +1761,16 @@ static void sx_break (struct tty_struct struct sx_port *port = tty->driver_data; int rv; + func_enter (); + if (flag) rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK); else rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN); if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n", read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat))); + + func_exit (); } @@ -2105,7 +2119,7 @@ static int probe_sx (struct sx_board *bo } if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) { - if (board->hw_base & 0x8000) { + if (((unsigned long)board->hw_base) & 0x8000) { printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base); printk (KERN_WARNING "sx: Read sx.txt for more info.\n"); } @@ -2154,6 +2168,7 @@ static int probe_si (struct sx_board *bo } for (i=0;i<8;i++) { if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) { + func_exit (); return 0; } } @@ -2168,11 +2183,13 @@ static int probe_si (struct sx_board *bo /* This should be an SI1 board, which has this location writable... */ if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) + func_exit (); return 0; } else { /* This should be an SI2 board, which has the bottom 3 bits non-writable... */ if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) + func_exit (); return 0; } @@ -2185,11 +2202,13 @@ static int probe_si (struct sx_board *bo /* This should be an SI1 board, which has this location writable... */ if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) + func_exit(); return 0; } else { /* This should be an SI2 board, which has the bottom 3 bits non-writable... */ if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) + func_exit (); return 0; } @@ -2306,6 +2325,7 @@ static int sx_init_portstructs (int nboa #ifdef NEW_WRITE_LOCKING port->gs.port_write_sem = MUTEX; #endif + port->gs.driver_lock = SPIN_LOCK_UNLOCKED; /* * Initializing wait queue */ @@ -2477,7 +2497,7 @@ static int __init sx_init(void) found++; fix_sx_pci (pdev, board); } else - iounmap(board->base); + iounmap(board->base2); } #endif _