[PATCH] IPMI: system interface hotplug
[safe/jmp/linux-2.6] / drivers / char / synclink.c
index 789572f..645187b 100644 (file)
@@ -63,7 +63,6 @@
 #define MAX_PCI_DEVICES 10
 #define MAX_TOTAL_DEVICES 20
 
-#include <linux/config.h>      
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
@@ -87,7 +86,6 @@
 
 #include <linux/vmalloc.h>
 #include <linux/init.h>
-#include <asm/serial.h>
 
 #include <linux/delay.h>
 #include <linux/ioctl.h>
 #include <linux/hdlc.h>
 #include <linux/dma-mapping.h>
 
-#ifdef CONFIG_HDLC_MODULE
-#define CONFIG_HDLC 1
+#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_MODULE))
+#define SYNCLINK_GENERIC_HDLC 1
+#else
+#define SYNCLINK_GENERIC_HDLC 0
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -135,8 +135,8 @@ static MGSL_PARAMS default_params = {
 };
 
 #define SHARED_MEM_ADDRESS_SIZE 0x40000
-#define BUFFERLISTSIZE (PAGE_SIZE)
-#define DMABUFFERSIZE (PAGE_SIZE)
+#define BUFFERLISTSIZE 4096
+#define DMABUFFERSIZE 4096
 #define MAXRXFRAMES 7
 
 typedef struct _DMABUFFERENTRY
@@ -322,7 +322,7 @@ struct mgsl_struct {
        int dosyncppp;
        spinlock_t netlock;
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        struct net_device *netdev;
 #endif
 };
@@ -730,7 +730,7 @@ static void usc_loopmode_send_done( struct mgsl_struct * info );
 
 static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 #define dev_to_port(D) (dev_to_hdlc(D)->priv)
 static void hdlcdev_tx_done(struct mgsl_struct *info);
 static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size);
@@ -804,7 +804,7 @@ static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, u
 /*
  * Bottom half interrupt handlers
  */
-static void mgsl_bh_handler(void* Context);
+static void mgsl_bh_handler(struct work_struct *work);
 static void mgsl_bh_receive(struct mgsl_struct *info);
 static void mgsl_bh_transmit(struct mgsl_struct *info);
 static void mgsl_bh_status(struct mgsl_struct *info);
@@ -941,18 +941,6 @@ static void* mgsl_get_text_ptr(void)
        return mgsl_get_text_ptr;
 }
 
-/*
- * tmp_buf is used as a temporary buffer by mgsl_write.  We need to
- * lock it in case the COPY_FROM_USER blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ioports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
-
 static inline int mgsl_paranoia_check(struct mgsl_struct *info,
                                        char *name, const char *routine)
 {
@@ -1085,9 +1073,10 @@ static int mgsl_bh_action(struct mgsl_struct *info)
 /*
  *     Perform bottom half processing of work items queued by ISR.
  */
-static void mgsl_bh_handler(void* Context)
+static void mgsl_bh_handler(struct work_struct *work)
 {
-       struct mgsl_struct *info = (struct mgsl_struct*)Context;
+       struct mgsl_struct *info =
+               container_of(work, struct mgsl_struct, task);
        int action;
 
        if (!info)
@@ -1290,7 +1279,7 @@ static void mgsl_isr_transmit_status( struct mgsl_struct *info )
                info->drop_rts_on_tx_done = 0;
        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount)
                hdlcdev_tx_done(info);
        else 
@@ -1355,9 +1344,13 @@ static void mgsl_isr_io_pin( struct mgsl_struct *info )
                                info->input_signal_events.dcd_up++;
                        } else
                                info->input_signal_events.dcd_down++;
-#ifdef CONFIG_HDLC
-                       if (info->netcount)
-                               hdlc_set_carrier(status & MISCSTATUS_DCD, info->netdev);
+#if SYNCLINK_GENERIC_HDLC
+                       if (info->netcount) {
+                               if (status & MISCSTATUS_DCD)
+                                       netif_carrier_on(info->netdev);
+                               else
+                                       netif_carrier_off(info->netdev);
+                       }
 #endif
                }
                if (status & MISCSTATUS_CTS_LATCHED)
@@ -1467,6 +1460,7 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
 {
        int Fifocount;
        u16 status;
+       int work = 0;
        unsigned char DataByte;
        struct tty_struct *tty = info->tty;
        struct  mgsl_icount *icount = &info->icount;
@@ -1487,6 +1481,8 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
        /* flush the receive FIFO */
 
        while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) {
+               int flag;
+
                /* read one byte from RxFIFO */
                outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY),
                      info->io_base + CCAR );
@@ -1498,13 +1494,9 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
                                RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) )
                        usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
                
-               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                       continue;
-                       
-               *tty->flip.char_buf_ptr = DataByte;
                icount->rx++;
                
-               *tty->flip.flag_buf_ptr = 0;
+               flag = 0;
                if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
                                RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) {
                        printk("rxerr=%04X\n",status);                                  
@@ -1530,41 +1522,31 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
                        status &= info->read_status_mask;
                
                        if (status & RXSTATUS_BREAK_RECEIVED) {
-                               *tty->flip.flag_buf_ptr = TTY_BREAK;
+                               flag = TTY_BREAK;
                                if (info->flags & ASYNC_SAK)
                                        do_SAK(tty);
                        } else if (status & RXSTATUS_PARITY_ERROR)
-                               *tty->flip.flag_buf_ptr = TTY_PARITY;
+                               flag = TTY_PARITY;
                        else if (status & RXSTATUS_FRAMING_ERROR)
-                               *tty->flip.flag_buf_ptr = TTY_FRAME;
-                       if (status & RXSTATUS_OVERRUN) {
-                               /* Overrun is special, since it's
-                                * reported immediately, and doesn't
-                                * affect the current character
-                                */
-                               if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-                                       tty->flip.count++;
-                                       tty->flip.flag_buf_ptr++;
-                                       tty->flip.char_buf_ptr++;
-                                       *tty->flip.flag_buf_ptr = TTY_OVERRUN;
-                               }
-                       }
+                               flag = TTY_FRAME;
                }       /* end of if (error) */
-               
-               tty->flip.flag_buf_ptr++;
-               tty->flip.char_buf_ptr++;
-               tty->flip.count++;
+               tty_insert_flip_char(tty, DataByte, flag);
+               if (status & RXSTATUS_OVERRUN) {
+                       /* Overrun is special, since it's
+                        * reported immediately, and doesn't
+                        * affect the current character
+                        */
+                       work += tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+               }
        }
 
        if ( debug_level >= DEBUG_LEVEL_ISR ) {
-               printk("%s(%d):mgsl_isr_receive_data flip count=%d\n",
-                       __FILE__,__LINE__,tty->flip.count);
                printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
                        __FILE__,__LINE__,icount->rx,icount->brk,
                        icount->parity,icount->frame,icount->overrun);
        }
                        
-       if ( tty->flip.count )
+       if(work)
                tty_flip_buffer_push(tty);
 }
 
@@ -1719,11 +1701,10 @@ static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
  * 
  *     irq             interrupt number that caused interrupt
  *     dev_id          device ID supplied during interrupt registration
- *     regs            interrupted processor context
  *     
  * Return Value: None
  */
-static irqreturn_t mgsl_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t mgsl_interrupt(int irq, void *dev_id)
 {
        struct mgsl_struct * info;
        u16 UscVector;
@@ -2162,7 +2143,7 @@ static int mgsl_write(struct tty_struct * tty,
        if (mgsl_paranoia_check(info, tty->name, "mgsl_write"))
                goto cleanup;
 
-       if (!tty || !info->xmit_buf || !tmp_buf)
+       if (!tty || !info->xmit_buf)
                goto cleanup;
 
        if ( info->params.mode == MGSL_MODE_HDLC ||
@@ -3450,7 +3431,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
 {
        struct mgsl_struct      *info;
        int                     retval, line;
-       unsigned long           page;
        unsigned long flags;
 
        /* verify range of specified line number */     
@@ -3484,18 +3464,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
                goto cleanup;
        }
        
-       if (!tmp_buf) {
-               page = get_zeroed_page(GFP_KERNEL);
-               if (!page) {
-                       retval = -ENOMEM;
-                       goto cleanup;
-               }
-               if (tmp_buf)
-                       free_page(page);
-               else
-                       tmp_buf = (unsigned char *) page;
-       }
-       
        info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
        spin_lock_irqsave(&info->netlock, flags);
@@ -4347,7 +4315,7 @@ static void mgsl_add_device( struct mgsl_struct *info )
                        info->max_frame_size );
        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        hdlcdev_init(info);
 #endif
 
@@ -4372,7 +4340,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
        } else {
                memset(info, 0, sizeof(struct mgsl_struct));
                info->magic = MGSL_MAGIC;
-               INIT_WORK(&info->task, mgsl_bh_handler, info);
+               INIT_WORK(&info->task, mgsl_bh_handler);
                info->max_frame_size = 4096;
                info->close_delay = 5*HZ/10;
                info->closing_wait = 30*HZ;
@@ -4392,7 +4360,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
 
 }      /* end of mgsl_allocate_device()*/
 
-static struct tty_operations mgsl_ops = {
+static const struct tty_operations mgsl_ops = {
        .open = mgsl_open,
        .close = mgsl_close,
        .write = mgsl_write,
@@ -4505,7 +4473,7 @@ static void synclink_cleanup(void)
 
        info = mgsl_device_list;
        while(info) {
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                hdlcdev_exit(info);
 #endif
                mgsl_release_resources(info);
@@ -4514,11 +4482,6 @@ static void synclink_cleanup(void)
                kfree(tmp);
        }
        
-       if (tmp_buf) {
-               free_page((unsigned long) tmp_buf);
-               tmp_buf = NULL;
-       }
-       
        if (pci_registered)
                pci_unregister_driver(&synclink_pci_driver);
 }
@@ -6037,7 +6000,7 @@ static void usc_set_async_mode( struct mgsl_struct *info )
         * <15..8>      ?               RxFIFO IRQ Request Level
         *
         * Note: For async mode the receive FIFO level must be set
-        * to 0 to aviod the situation where the FIFO contains fewer bytes
+        * to 0 to avoid the situation where the FIFO contains fewer bytes
         * than the trigger level and no more data is expected.
         *
         * <7>          0               Exited Hunt IA (Interrupt Arm)
@@ -6684,7 +6647,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info)
                                return_frame = 1;
                }
                framesize = 0;
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                {
                        struct net_device_stats *stats = hdlc_stats(info->netdev);
                        stats->rx_errors++;
@@ -6760,7 +6723,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info)
                                                *ptmp);
                        }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
                        if (info->netcount)
                                hdlcdev_rx(info,info->intermediate_rxbuffer,framesize);
                        else
@@ -7664,7 +7627,7 @@ static void mgsl_tx_timeout(unsigned long context)
 
        spin_unlock_irqrestore(&info->irq_spinlock,flags);
        
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
        if (info->netcount)
                hdlcdev_tx_done(info);
        else
@@ -7740,7 +7703,7 @@ static int usc_loopmode_active( struct mgsl_struct * info)
        return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ;
 }
 
-#ifdef CONFIG_HDLC
+#if SYNCLINK_GENERIC_HDLC
 
 /**
  * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
@@ -7782,7 +7745,7 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
        }
 
        info->params.encoding = new_encoding;
-       info->params.crc_type = new_crctype;;
+       info->params.crc_type = new_crctype;
 
        /* if network interface up, reprogram hardware */
        if (info->netcount)
@@ -7885,8 +7848,10 @@ static int hdlcdev_open(struct net_device *dev)
        spin_lock_irqsave(&info->irq_spinlock, flags);
        usc_get_serial_signals(info);
        spin_unlock_irqrestore(&info->irq_spinlock, flags);
-       hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
-
+       if (info->serial_signals & SerialSignal_DCD)
+               netif_carrier_on(dev);
+       else
+               netif_carrier_off(dev);
        return 0;
 }
 
@@ -8191,7 +8156,7 @@ static int __devinit synclink_init_one (struct pci_dev *dev,
                                
        info->bus_type = MGSL_BUS_TYPE_PCI;
        info->io_addr_size = 8;
-       info->irq_flags = SA_SHIRQ;
+       info->irq_flags = IRQF_SHARED;
 
        if (dev->device == 0x0210) {
                /* Version 1 PCI9030 based universal PCI adapter */