cyclades: use dtr_rts helpers
authorJiri Slaby <jirislaby@gmail.com>
Sat, 19 Sep 2009 20:13:15 +0000 (13:13 -0700)
committerLive-CD User <linux@linux.site>
Sat, 19 Sep 2009 20:13:15 +0000 (13:13 -0700)
For Z cards, use tty helpers for dtr_rts.

If we did the same for Y cards, it will cause a deadlock, because
cyy_dtr_rts takes a lock which we already hold.

Instead, we introduce a Y helper expecting card lock to be held.
It may then be called with set/clear masks from other places.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/char/cyclades.c

index b6d40ad..7462795 100644 (file)
@@ -825,6 +825,66 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }                              /* cyy_interrupt */
 
+static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
+               unsigned int clear)
+{
+       struct cyclades_card *card = info->card;
+       void __iomem *base_addr;
+       int chip, channel, index;
+
+       channel = info->line - card->first_line;
+       chip = channel >> 2;
+       channel &= 0x03;
+       index = card->bus_index;
+       base_addr = card->base_addr + (cy_chip_offset[chip] << index);
+
+       if (set & TIOCM_RTS) {
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+               if (info->rtsdtr_inv) {
+                       cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
+               } else {
+                       cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
+               }
+       }
+       if (clear & TIOCM_RTS) {
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+               if (info->rtsdtr_inv) {
+                       cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
+               } else {
+                       cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
+               }
+       }
+       if (set & TIOCM_DTR) {
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+               if (info->rtsdtr_inv) {
+                       cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
+               } else {
+                       cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
+               }
+#ifdef CY_DEBUG_DTR
+               printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
+               printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                       readb(base_addr + (CyMSVR1 << index)),
+                       readb(base_addr + (CyMSVR2 << index)));
+#endif
+       }
+       if (clear & TIOCM_DTR) {
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
+               if (info->rtsdtr_inv) {
+                       cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
+               } else {
+                       cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
+               }
+
+#ifdef CY_DEBUG_DTR
+               printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
+               printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+                       readb(base_addr + (CyMSVR1 << index)),
+                       readb(base_addr + (CyMSVR2 << index)));
+#endif
+       }
+}
+
 /***********************************************************/
 /********* End of block of Cyclom-Y specific code **********/
 /******** Start of block of Cyclades-Z specific code *******/
@@ -1290,16 +1350,7 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
                cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR,
                                index);
 
-               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-               cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
-               cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
-
-#ifdef CY_DEBUG_DTR
-               printk(KERN_DEBUG "cyc:startup raising DTR\n");
-               printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-                       readb(base_addr + (CyMSVR1 << index)),
-                       readb(base_addr + (CyMSVR2 << index)));
-#endif
+               cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0);
 
                cy_writeb(base_addr + (CySRER << index),
                        readb(base_addr + (CySRER << index)) | CyRxData);
@@ -1362,16 +1413,7 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
 
                /* set timeout !!! */
                /* set RTS and DTR !!! */
-               cy_writel(&ch_ctrl->rs_control, readl(&ch_ctrl->rs_control) |
-                               C_RS_RTS | C_RS_DTR);
-               retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
-               if (retval != 0) {
-                       printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was "
-                               "%x\n", info->line, retval);
-               }
-#ifdef CY_DEBUG_DTR
-               printk(KERN_DEBUG "cyc:startup raising Z DTR\n");
-#endif
+               tty_port_raise_dtr_rts(&info->port);
 
                /* enable send, recv, modem !!! */
 
@@ -1473,17 +1515,9 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
                        info->port.xmit_buf = NULL;
                        free_page((unsigned long)temp);
                }
-               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
-               if (tty->termios->c_cflag & HUPCL) {
-                       cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
-                       cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
-#ifdef CY_DEBUG_DTR
-                       printk(KERN_DEBUG "cyc shutdown dropping DTR\n");
-                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-                               readb(base_addr + (CyMSVR1 << index)),
-                               readb(base_addr + (CyMSVR2 << index)));
-#endif
-               }
+               if (tty->termios->c_cflag & HUPCL)
+                       cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
+
                cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index);
                /* it may be appropriate to clear _XMIT at
                   some later date (after testing)!!! */
@@ -1492,9 +1526,6 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
                info->port.flags &= ~ASYNC_INITIALIZED;
                spin_unlock_irqrestore(&card->card_lock, flags);
        } else {
-               struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-               int retval;
-
 #ifdef CY_DEBUG_OPEN
                printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
                        "base_addr %p\n", card, channel, card->base_addr);
@@ -1512,20 +1543,8 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
                        free_page((unsigned long)temp);
                }
 
-               if (tty->termios->c_cflag & HUPCL) {
-                       cy_writel(&ch_ctrl->rs_control,
-                               readl(&ch_ctrl->rs_control) &
-                                       ~(C_RS_RTS | C_RS_DTR));
-                       retval = cyz_issue_cmd(info->card, channel,
-                                       C_CM_IOCTLM, 0L);
-                       if (retval != 0) {
-                               printk(KERN_ERR"cyc:shutdown retval on ttyC%d "
-                                       "was %x\n", info->line, retval);
-                       }
-#ifdef CY_DEBUG_DTR
-                       printk(KERN_DEBUG "cyc:shutdown dropping Z DTR\n");
-#endif
-               }
+               if (tty->termios->c_cflag & HUPCL)
+                       tty_port_lower_dtr_rts(&info->port);
 
                set_bit(TTY_IO_ERROR, &tty->flags);
                info->port.flags &= ~ASYNC_INITIALIZED;
@@ -2273,35 +2292,10 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
                                  CyDSR | CyCTS | CyRI | CyDCD);
                }
 
-               if (i == 0) {   /* baud rate is zero, turn off line */
-                       if (info->rtsdtr_inv) {
-                               cy_writeb(base_addr + (CyMSVR1 << index),
-                                         ~CyRTS);
-                       } else {
-                               cy_writeb(base_addr + (CyMSVR2 << index),
-                                         ~CyDTR);
-                       }
-#ifdef CY_DEBUG_DTR
-                       printk(KERN_DEBUG "cyc:set_line_char dropping DTR\n");
-                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-                               readb(base_addr + (CyMSVR1 << index)),
-                               readb(base_addr + (CyMSVR2 << index)));
-#endif
-               } else {
-                       if (info->rtsdtr_inv) {
-                               cy_writeb(base_addr + (CyMSVR1 << index),
-                                         CyRTS);
-                       } else {
-                               cy_writeb(base_addr + (CyMSVR2 << index),
-                                         CyDTR);
-                       }
-#ifdef CY_DEBUG_DTR
-                       printk(KERN_DEBUG "cyc:set_line_char raising DTR\n");
-                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-                               readb(base_addr + (CyMSVR1 << index)),
-                               readb(base_addr + (CyMSVR2 << index)));
-#endif
-               }
+               if (i == 0)     /* baud rate is zero, turn off line */
+                       cyy_change_rts_dtr(info, 0, TIOCM_DTR);
+               else
+                       cyy_change_rts_dtr(info, TIOCM_DTR, 0);
 
                clear_bit(TTY_IO_ERROR, &tty->flags);
                spin_unlock_irqrestore(&card->card_lock, flags);
@@ -2604,9 +2598,8 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 {
        struct cyclades_port *info = tty->driver_data;
        struct cyclades_card *card;
-       int chip, channel, index;
        unsigned long flags;
-       int retval;
+       int channel, retval;
 
        if (serial_paranoia_check(info, tty->name, __func__))
                return -ENODEV;
@@ -2614,77 +2607,9 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
        card = info->card;
        channel = (info->line) - (card->first_line);
        if (!cy_is_Z(card)) {
-               void __iomem *base_addr;
-               chip = channel >> 2;
-               channel &= 0x03;
-               index = card->bus_index;
-               base_addr = card->base_addr + (cy_chip_offset[chip] << index);
-
-               if (set & TIOCM_RTS) {
-                       spin_lock_irqsave(&card->card_lock, flags);
-                       cy_writeb(base_addr + (CyCAR << index),
-                                 (u_char) channel);
-                       if (info->rtsdtr_inv) {
-                               cy_writeb(base_addr + (CyMSVR2 << index),
-                                         CyDTR);
-                       } else {
-                               cy_writeb(base_addr + (CyMSVR1 << index),
-                                         CyRTS);
-                       }
-                       spin_unlock_irqrestore(&card->card_lock, flags);
-               }
-               if (clear & TIOCM_RTS) {
-                       spin_lock_irqsave(&card->card_lock, flags);
-                       cy_writeb(base_addr + (CyCAR << index),
-                                 (u_char) channel);
-                       if (info->rtsdtr_inv) {
-                               cy_writeb(base_addr + (CyMSVR2 << index),
-                                         ~CyDTR);
-                       } else {
-                               cy_writeb(base_addr + (CyMSVR1 << index),
-                                         ~CyRTS);
-                       }
-                       spin_unlock_irqrestore(&card->card_lock, flags);
-               }
-               if (set & TIOCM_DTR) {
-                       spin_lock_irqsave(&card->card_lock, flags);
-                       cy_writeb(base_addr + (CyCAR << index),
-                                 (u_char) channel);
-                       if (info->rtsdtr_inv) {
-                               cy_writeb(base_addr + (CyMSVR1 << index),
-                                         CyRTS);
-                       } else {
-                               cy_writeb(base_addr + (CyMSVR2 << index),
-                                         CyDTR);
-                       }
-#ifdef CY_DEBUG_DTR
-                       printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
-                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-                               readb(base_addr + (CyMSVR1 << index)),
-                               readb(base_addr + (CyMSVR2 << index)));
-#endif
-                       spin_unlock_irqrestore(&card->card_lock, flags);
-               }
-               if (clear & TIOCM_DTR) {
-                       spin_lock_irqsave(&card->card_lock, flags);
-                       cy_writeb(base_addr + (CyCAR << index),
-                                 (u_char) channel);
-                       if (info->rtsdtr_inv) {
-                               cy_writeb(base_addr + (CyMSVR1 << index),
-                                         ~CyRTS);
-                       } else {
-                               cy_writeb(base_addr + (CyMSVR2 << index),
-                                         ~CyDTR);
-                       }
-
-#ifdef CY_DEBUG_DTR
-                       printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
-                       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-                               readb(base_addr + (CyMSVR1 << index)),
-                               readb(base_addr + (CyMSVR2 << index)));
-#endif
-                       spin_unlock_irqrestore(&card->card_lock, flags);
-               }
+               spin_lock_irqsave(&card->card_lock, flags);
+               cyy_change_rts_dtr(info, set, clear);
+               spin_unlock_irqrestore(&card->card_lock, flags);
        } else {
                if (cyz_is_loaded(card)) {
                        struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
@@ -3177,8 +3102,6 @@ static void cy_throttle(struct tty_struct *tty)
        struct cyclades_port *info = tty->driver_data;
        struct cyclades_card *card;
        unsigned long flags;
-       void __iomem *base_addr;
-       int chip, channel, index;
 
 #ifdef CY_DEBUG_THROTTLE
        char buf[64];
@@ -3200,24 +3123,9 @@ static void cy_throttle(struct tty_struct *tty)
        }
 
        if (tty->termios->c_cflag & CRTSCTS) {
-               channel = info->line - card->first_line;
                if (!cy_is_Z(card)) {
-                       chip = channel >> 2;
-                       channel &= 0x03;
-                       index = card->bus_index;
-                       base_addr = card->base_addr +
-                               (cy_chip_offset[chip] << index);
-
                        spin_lock_irqsave(&card->card_lock, flags);
-                       cy_writeb(base_addr + (CyCAR << index),
-                                 (u_char) channel);
-                       if (info->rtsdtr_inv) {
-                               cy_writeb(base_addr + (CyMSVR2 << index),
-                                         ~CyDTR);
-                       } else {
-                               cy_writeb(base_addr + (CyMSVR1 << index),
-                                         ~CyRTS);
-                       }
+                       cyy_change_rts_dtr(info, 0, TIOCM_RTS);
                        spin_unlock_irqrestore(&card->card_lock, flags);
                } else {
                        info->throttle = 1;
@@ -3235,8 +3143,6 @@ static void cy_unthrottle(struct tty_struct *tty)
        struct cyclades_port *info = tty->driver_data;
        struct cyclades_card *card;
        unsigned long flags;
-       void __iomem *base_addr;
-       int chip, channel, index;
 
 #ifdef CY_DEBUG_THROTTLE
        char buf[64];
@@ -3257,24 +3163,9 @@ static void cy_unthrottle(struct tty_struct *tty)
 
        if (tty->termios->c_cflag & CRTSCTS) {
                card = info->card;
-               channel = info->line - card->first_line;
                if (!cy_is_Z(card)) {
-                       chip = channel >> 2;
-                       channel &= 0x03;
-                       index = card->bus_index;
-                       base_addr = card->base_addr +
-                               (cy_chip_offset[chip] << index);
-
                        spin_lock_irqsave(&card->card_lock, flags);
-                       cy_writeb(base_addr + (CyCAR << index),
-                                 (u_char) channel);
-                       if (info->rtsdtr_inv) {
-                               cy_writeb(base_addr + (CyMSVR2 << index),
-                                         CyDTR);
-                       } else {
-                               cy_writeb(base_addr + (CyMSVR1 << index),
-                                         CyRTS);
-                       }
+                       cyy_change_rts_dtr(info, TIOCM_RTS, 0);
                        spin_unlock_irqrestore(&card->card_lock, flags);
                } else {
                        info->throttle = 0;
@@ -3395,24 +3286,11 @@ static void cyy_dtr_rts(struct tty_port *port, int raise)
        struct cyclades_port *info = container_of(port, struct cyclades_port,
                        port);
        struct cyclades_card *cinfo = info->card;
-       void __iomem *base = cinfo->base_addr;
        unsigned long flags;
-       int channel = info->line - cinfo->first_line;
-       int chip = channel >> 2, index = cinfo->bus_index;
-
-       channel &= 0x03;
-       base += cy_chip_offset[chip] << index;
 
        spin_lock_irqsave(&cinfo->card_lock, flags);
-       cy_writeb(base + (CyCAR << index), (u8)channel);
-       cy_writeb(base + (CyMSVR1 << index), raise ? CyRTS : ~CyRTS);
-       cy_writeb(base + (CyMSVR2 << index), raise ? CyDTR : ~CyDTR);
-#ifdef CY_DEBUG_DTR
-       printk(KERN_DEBUG "%s: raising DTR\n", __func__);
-       printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-                       readb(base + (CyMSVR1 << index)),
-                       readb(base + (CyMSVR2 << index)));
-#endif
+       cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0,
+                       raise ? 0 : TIOCM_RTS | TIOCM_DTR);
        spin_unlock_irqrestore(&cinfo->card_lock, flags);
 }