aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/cyclades.c
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2009-09-19 16:13:15 -0400
committerLive-CD User <linux@linux.site>2009-09-19 16:13:15 -0400
commit4d7682005ca88a37667c4af03908798e188b5224 (patch)
tree12e149f103347f22daf718ae641b8868eccaeea7 /drivers/char/cyclades.c
parentf6e208c1119206e2382ef7df6e47aaee18eb7f10 (diff)
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.c280
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)
825 return IRQ_HANDLED; 825 return IRQ_HANDLED;
826} /* cyy_interrupt */ 826} /* cyy_interrupt */
827 827
828static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
829 unsigned int clear)
830{
831 struct cyclades_card *card = info->card;
832 void __iomem *base_addr;
833 int chip, channel, index;
834
835 channel = info->line - card->first_line;
836 chip = channel >> 2;
837 channel &= 0x03;
838 index = card->bus_index;
839 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
840
841 if (set & TIOCM_RTS) {
842 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
843 if (info->rtsdtr_inv) {
844 cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
845 } else {
846 cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
847 }
848 }
849 if (clear & TIOCM_RTS) {
850 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
851 if (info->rtsdtr_inv) {
852 cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
853 } else {
854 cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
855 }
856 }
857 if (set & TIOCM_DTR) {
858 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
859 if (info->rtsdtr_inv) {
860 cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
861 } else {
862 cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
863 }
864#ifdef CY_DEBUG_DTR
865 printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
866 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
867 readb(base_addr + (CyMSVR1 << index)),
868 readb(base_addr + (CyMSVR2 << index)));
869#endif
870 }
871 if (clear & TIOCM_DTR) {
872 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
873 if (info->rtsdtr_inv) {
874 cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
875 } else {
876 cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
877 }
878
879#ifdef CY_DEBUG_DTR
880 printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
881 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
882 readb(base_addr + (CyMSVR1 << index)),
883 readb(base_addr + (CyMSVR2 << index)));
884#endif
885 }
886}
887
828/***********************************************************/ 888/***********************************************************/
829/********* End of block of Cyclom-Y specific code **********/ 889/********* End of block of Cyclom-Y specific code **********/
830/******** Start of block of Cyclades-Z specific code *******/ 890/******** Start of block of Cyclades-Z specific code *******/
@@ -1290,16 +1350,7 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
1290 cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR, 1350 cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR,
1291 index); 1351 index);
1292 1352
1293 cy_writeb(base_addr + (CyCAR << index), (u_char) channel); 1353 cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0);
1294 cy_writeb(base_addr + (CyMSVR1 << index), CyRTS);
1295 cy_writeb(base_addr + (CyMSVR2 << index), CyDTR);
1296
1297#ifdef CY_DEBUG_DTR
1298 printk(KERN_DEBUG "cyc:startup raising DTR\n");
1299 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
1300 readb(base_addr + (CyMSVR1 << index)),
1301 readb(base_addr + (CyMSVR2 << index)));
1302#endif
1303 1354
1304 cy_writeb(base_addr + (CySRER << index), 1355 cy_writeb(base_addr + (CySRER << index),
1305 readb(base_addr + (CySRER << index)) | CyRxData); 1356 readb(base_addr + (CySRER << index)) | CyRxData);
@@ -1362,16 +1413,7 @@ static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
1362 1413
1363 /* set timeout !!! */ 1414 /* set timeout !!! */
1364 /* set RTS and DTR !!! */ 1415 /* set RTS and DTR !!! */
1365 cy_writel(&ch_ctrl->rs_control, readl(&ch_ctrl->rs_control) | 1416 tty_port_raise_dtr_rts(&info->port);
1366 C_RS_RTS | C_RS_DTR);
1367 retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
1368 if (retval != 0) {
1369 printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was "
1370 "%x\n", info->line, retval);
1371 }
1372#ifdef CY_DEBUG_DTR
1373 printk(KERN_DEBUG "cyc:startup raising Z DTR\n");
1374#endif
1375 1417
1376 /* enable send, recv, modem !!! */ 1418 /* enable send, recv, modem !!! */
1377 1419
@@ -1473,17 +1515,9 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
1473 info->port.xmit_buf = NULL; 1515 info->port.xmit_buf = NULL;
1474 free_page((unsigned long)temp); 1516 free_page((unsigned long)temp);
1475 } 1517 }
1476 cy_writeb(base_addr + (CyCAR << index), (u_char) channel); 1518 if (tty->termios->c_cflag & HUPCL)
1477 if (tty->termios->c_cflag & HUPCL) { 1519 cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
1478 cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); 1520
1479 cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
1480#ifdef CY_DEBUG_DTR
1481 printk(KERN_DEBUG "cyc shutdown dropping DTR\n");
1482 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
1483 readb(base_addr + (CyMSVR1 << index)),
1484 readb(base_addr + (CyMSVR2 << index)));
1485#endif
1486 }
1487 cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index); 1521 cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index);
1488 /* it may be appropriate to clear _XMIT at 1522 /* it may be appropriate to clear _XMIT at
1489 some later date (after testing)!!! */ 1523 some later date (after testing)!!! */
@@ -1492,9 +1526,6 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
1492 info->port.flags &= ~ASYNC_INITIALIZED; 1526 info->port.flags &= ~ASYNC_INITIALIZED;
1493 spin_unlock_irqrestore(&card->card_lock, flags); 1527 spin_unlock_irqrestore(&card->card_lock, flags);
1494 } else { 1528 } else {
1495 struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
1496 int retval;
1497
1498#ifdef CY_DEBUG_OPEN 1529#ifdef CY_DEBUG_OPEN
1499 printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " 1530 printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
1500 "base_addr %p\n", card, channel, card->base_addr); 1531 "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)
1512 free_page((unsigned long)temp); 1543 free_page((unsigned long)temp);
1513 } 1544 }
1514 1545
1515 if (tty->termios->c_cflag & HUPCL) { 1546 if (tty->termios->c_cflag & HUPCL)
1516 cy_writel(&ch_ctrl->rs_control, 1547 tty_port_lower_dtr_rts(&info->port);
1517 readl(&ch_ctrl->rs_control) &
1518 ~(C_RS_RTS | C_RS_DTR));
1519 retval = cyz_issue_cmd(info->card, channel,
1520 C_CM_IOCTLM, 0L);
1521 if (retval != 0) {
1522 printk(KERN_ERR"cyc:shutdown retval on ttyC%d "
1523 "was %x\n", info->line, retval);
1524 }
1525#ifdef CY_DEBUG_DTR
1526 printk(KERN_DEBUG "cyc:shutdown dropping Z DTR\n");
1527#endif
1528 }
1529 1548
1530 set_bit(TTY_IO_ERROR, &tty->flags); 1549 set_bit(TTY_IO_ERROR, &tty->flags);
1531 info->port.flags &= ~ASYNC_INITIALIZED; 1550 info->port.flags &= ~ASYNC_INITIALIZED;
@@ -2273,35 +2292,10 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
2273 CyDSR | CyCTS | CyRI | CyDCD); 2292 CyDSR | CyCTS | CyRI | CyDCD);
2274 } 2293 }
2275 2294
2276 if (i == 0) { /* baud rate is zero, turn off line */ 2295 if (i == 0) /* baud rate is zero, turn off line */
2277 if (info->rtsdtr_inv) { 2296 cyy_change_rts_dtr(info, 0, TIOCM_DTR);
2278 cy_writeb(base_addr + (CyMSVR1 << index), 2297 else
2279 ~CyRTS); 2298 cyy_change_rts_dtr(info, TIOCM_DTR, 0);
2280 } else {
2281 cy_writeb(base_addr + (CyMSVR2 << index),
2282 ~CyDTR);
2283 }
2284#ifdef CY_DEBUG_DTR
2285 printk(KERN_DEBUG "cyc:set_line_char dropping DTR\n");
2286 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
2287 readb(base_addr + (CyMSVR1 << index)),
2288 readb(base_addr + (CyMSVR2 << index)));
2289#endif
2290 } else {
2291 if (info->rtsdtr_inv) {
2292 cy_writeb(base_addr + (CyMSVR1 << index),
2293 CyRTS);
2294 } else {
2295 cy_writeb(base_addr + (CyMSVR2 << index),
2296 CyDTR);
2297 }
2298#ifdef CY_DEBUG_DTR
2299 printk(KERN_DEBUG "cyc:set_line_char raising DTR\n");
2300 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
2301 readb(base_addr + (CyMSVR1 << index)),
2302 readb(base_addr + (CyMSVR2 << index)));
2303#endif
2304 }
2305 2299
2306 clear_bit(TTY_IO_ERROR, &tty->flags); 2300 clear_bit(TTY_IO_ERROR, &tty->flags);
2307 spin_unlock_irqrestore(&card->card_lock, flags); 2301 spin_unlock_irqrestore(&card->card_lock, flags);
@@ -2604,9 +2598,8 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
2604{ 2598{
2605 struct cyclades_port *info = tty->driver_data; 2599 struct cyclades_port *info = tty->driver_data;
2606 struct cyclades_card *card; 2600 struct cyclades_card *card;
2607 int chip, channel, index;
2608 unsigned long flags; 2601 unsigned long flags;
2609 int retval; 2602 int channel, retval;
2610 2603
2611 if (serial_paranoia_check(info, tty->name, __func__)) 2604 if (serial_paranoia_check(info, tty->name, __func__))
2612 return -ENODEV; 2605 return -ENODEV;
@@ -2614,77 +2607,9 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
2614 card = info->card; 2607 card = info->card;
2615 channel = (info->line) - (card->first_line); 2608 channel = (info->line) - (card->first_line);
2616 if (!cy_is_Z(card)) { 2609 if (!cy_is_Z(card)) {
2617 void __iomem *base_addr; 2610 spin_lock_irqsave(&card->card_lock, flags);
2618 chip = channel >> 2; 2611 cyy_change_rts_dtr(info, set, clear);
2619 channel &= 0x03; 2612 spin_unlock_irqrestore(&card->card_lock, flags);
2620 index = card->bus_index;
2621 base_addr = card->base_addr + (cy_chip_offset[chip] << index);
2622
2623 if (set & TIOCM_RTS) {
2624 spin_lock_irqsave(&card->card_lock, flags);
2625 cy_writeb(base_addr + (CyCAR << index),
2626 (u_char) channel);
2627 if (info->rtsdtr_inv) {
2628 cy_writeb(base_addr + (CyMSVR2 << index),
2629 CyDTR);
2630 } else {
2631 cy_writeb(base_addr + (CyMSVR1 << index),
2632 CyRTS);
2633 }
2634 spin_unlock_irqrestore(&card->card_lock, flags);
2635 }
2636 if (clear & TIOCM_RTS) {
2637 spin_lock_irqsave(&card->card_lock, flags);
2638 cy_writeb(base_addr + (CyCAR << index),
2639 (u_char) channel);
2640 if (info->rtsdtr_inv) {
2641 cy_writeb(base_addr + (CyMSVR2 << index),
2642 ~CyDTR);
2643 } else {
2644 cy_writeb(base_addr + (CyMSVR1 << index),
2645 ~CyRTS);
2646 }
2647 spin_unlock_irqrestore(&card->card_lock, flags);
2648 }
2649 if (set & TIOCM_DTR) {
2650 spin_lock_irqsave(&card->card_lock, flags);
2651 cy_writeb(base_addr + (CyCAR << index),
2652 (u_char) channel);
2653 if (info->rtsdtr_inv) {
2654 cy_writeb(base_addr + (CyMSVR1 << index),
2655 CyRTS);
2656 } else {
2657 cy_writeb(base_addr + (CyMSVR2 << index),
2658 CyDTR);
2659 }
2660#ifdef CY_DEBUG_DTR
2661 printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
2662 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
2663 readb(base_addr + (CyMSVR1 << index)),
2664 readb(base_addr + (CyMSVR2 << index)));
2665#endif
2666 spin_unlock_irqrestore(&card->card_lock, flags);
2667 }
2668 if (clear & TIOCM_DTR) {
2669 spin_lock_irqsave(&card->card_lock, flags);
2670 cy_writeb(base_addr + (CyCAR << index),
2671 (u_char) channel);
2672 if (info->rtsdtr_inv) {
2673 cy_writeb(base_addr + (CyMSVR1 << index),
2674 ~CyRTS);
2675 } else {
2676 cy_writeb(base_addr + (CyMSVR2 << index),
2677 ~CyDTR);
2678 }
2679
2680#ifdef CY_DEBUG_DTR
2681 printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
2682 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
2683 readb(base_addr + (CyMSVR1 << index)),
2684 readb(base_addr + (CyMSVR2 << index)));
2685#endif
2686 spin_unlock_irqrestore(&card->card_lock, flags);
2687 }
2688 } else { 2613 } else {
2689 if (cyz_is_loaded(card)) { 2614 if (cyz_is_loaded(card)) {
2690 struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl; 2615 struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
@@ -3177,8 +3102,6 @@ static void cy_throttle(struct tty_struct *tty)
3177 struct cyclades_port *info = tty->driver_data; 3102 struct cyclades_port *info = tty->driver_data;
3178 struct cyclades_card *card; 3103 struct cyclades_card *card;
3179 unsigned long flags; 3104 unsigned long flags;
3180 void __iomem *base_addr;
3181 int chip, channel, index;
3182 3105
3183#ifdef CY_DEBUG_THROTTLE 3106#ifdef CY_DEBUG_THROTTLE
3184 char buf[64]; 3107 char buf[64];
@@ -3200,24 +3123,9 @@ static void cy_throttle(struct tty_struct *tty)
3200 } 3123 }
3201 3124
3202 if (tty->termios->c_cflag & CRTSCTS) { 3125 if (tty->termios->c_cflag & CRTSCTS) {
3203 channel = info->line - card->first_line;
3204 if (!cy_is_Z(card)) { 3126 if (!cy_is_Z(card)) {
3205 chip = channel >> 2;
3206 channel &= 0x03;
3207 index = card->bus_index;
3208 base_addr = card->base_addr +
3209 (cy_chip_offset[chip] << index);
3210
3211 spin_lock_irqsave(&card->card_lock, flags); 3127 spin_lock_irqsave(&card->card_lock, flags);
3212 cy_writeb(base_addr + (CyCAR << index), 3128 cyy_change_rts_dtr(info, 0, TIOCM_RTS);
3213 (u_char) channel);
3214 if (info->rtsdtr_inv) {
3215 cy_writeb(base_addr + (CyMSVR2 << index),
3216 ~CyDTR);
3217 } else {
3218 cy_writeb(base_addr + (CyMSVR1 << index),
3219 ~CyRTS);
3220 }
3221 spin_unlock_irqrestore(&card->card_lock, flags); 3129 spin_unlock_irqrestore(&card->card_lock, flags);
3222 } else { 3130 } else {
3223 info->throttle = 1; 3131 info->throttle = 1;
@@ -3235,8 +3143,6 @@ static void cy_unthrottle(struct tty_struct *tty)
3235 struct cyclades_port *info = tty->driver_data; 3143 struct cyclades_port *info = tty->driver_data;
3236 struct cyclades_card *card; 3144 struct cyclades_card *card;
3237 unsigned long flags; 3145 unsigned long flags;
3238 void __iomem *base_addr;
3239 int chip, channel, index;
3240 3146
3241#ifdef CY_DEBUG_THROTTLE 3147#ifdef CY_DEBUG_THROTTLE
3242 char buf[64]; 3148 char buf[64];
@@ -3257,24 +3163,9 @@ static void cy_unthrottle(struct tty_struct *tty)
3257 3163
3258 if (tty->termios->c_cflag & CRTSCTS) { 3164 if (tty->termios->c_cflag & CRTSCTS) {
3259 card = info->card; 3165 card = info->card;
3260 channel = info->line - card->first_line;
3261 if (!cy_is_Z(card)) { 3166 if (!cy_is_Z(card)) {
3262 chip = channel >> 2;
3263 channel &= 0x03;
3264 index = card->bus_index;
3265 base_addr = card->base_addr +
3266 (cy_chip_offset[chip] << index);
3267
3268 spin_lock_irqsave(&card->card_lock, flags); 3167 spin_lock_irqsave(&card->card_lock, flags);
3269 cy_writeb(base_addr + (CyCAR << index), 3168 cyy_change_rts_dtr(info, TIOCM_RTS, 0);
3270 (u_char) channel);
3271 if (info->rtsdtr_inv) {
3272 cy_writeb(base_addr + (CyMSVR2 << index),
3273 CyDTR);
3274 } else {
3275 cy_writeb(base_addr + (CyMSVR1 << index),
3276 CyRTS);
3277 }
3278 spin_unlock_irqrestore(&card->card_lock, flags); 3169 spin_unlock_irqrestore(&card->card_lock, flags);
3279 } else { 3170 } else {
3280 info->throttle = 0; 3171 info->throttle = 0;
@@ -3395,24 +3286,11 @@ static void cyy_dtr_rts(struct tty_port *port, int raise)
3395 struct cyclades_port *info = container_of(port, struct cyclades_port, 3286 struct cyclades_port *info = container_of(port, struct cyclades_port,
3396 port); 3287 port);
3397 struct cyclades_card *cinfo = info->card; 3288 struct cyclades_card *cinfo = info->card;
3398 void __iomem *base = cinfo->base_addr;
3399 unsigned long flags; 3289 unsigned long flags;
3400 int channel = info->line - cinfo->first_line;
3401 int chip = channel >> 2, index = cinfo->bus_index;
3402
3403 channel &= 0x03;
3404 base += cy_chip_offset[chip] << index;
3405 3290
3406 spin_lock_irqsave(&cinfo->card_lock, flags); 3291 spin_lock_irqsave(&cinfo->card_lock, flags);
3407 cy_writeb(base + (CyCAR << index), (u8)channel); 3292 cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0,
3408 cy_writeb(base + (CyMSVR1 << index), raise ? CyRTS : ~CyRTS); 3293 raise ? 0 : TIOCM_RTS | TIOCM_DTR);
3409 cy_writeb(base + (CyMSVR2 << index), raise ? CyDTR : ~CyDTR);
3410#ifdef CY_DEBUG_DTR
3411 printk(KERN_DEBUG "%s: raising DTR\n", __func__);
3412 printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
3413 readb(base + (CyMSVR1 << index)),
3414 readb(base + (CyMSVR2 << index)));
3415#endif
3416 spin_unlock_irqrestore(&cinfo->card_lock, flags); 3294 spin_unlock_irqrestore(&cinfo->card_lock, flags);
3417} 3295}
3418 3296