diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2009-09-19 13:13:15 -0700 |
---|---|---|
committer | Live-CD User <linux@linux.site> | 2009-09-19 13:13:15 -0700 |
commit | 4d7682005ca88a37667c4af03908798e188b5224 (patch) | |
tree | 12e149f103347f22daf718ae641b8868eccaeea7 /drivers/char/cyclades.c | |
parent | f6e208c1119206e2382ef7df6e47aaee18eb7f10 (diff) | |
download | lwn-4d7682005ca88a37667c4af03908798e188b5224.tar.gz lwn-4d7682005ca88a37667c4af03908798e188b5224.zip |
cyclades: use dtr_rts helpers
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>
Diffstat (limited to 'drivers/char/cyclades.c')
-rw-r--r-- | drivers/char/cyclades.c | 280 |
1 files changed, 79 insertions, 201 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index b6d40ad662ff..74627950f901 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -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); } |