aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2009-09-19 16:13:12 -0400
committerLive-CD User <linux@linux.site>2009-09-19 16:13:12 -0400
commitd13549f804d2965a9f279a8ff867f35d949572c8 (patch)
treef7e1a6781fe38ffe845e0cfe104e56a0efa309bb /drivers/char
parent1607acaec38319c5e0b48a3586c00e667e920a0d (diff)
cyclades: add tty refcounting
While this is not problem for Y card handlers (they are protected by card_lock), Z handlers and other functions may dereference NULL at any point after hangup/close. Even if (tty == NULL) was already performed in the handler. Note that it's not an issue for Y cards just for now. After switching to tty_port_close_* et al. this will be a problem. So add refcounting to them all. Also proc .show doesn't take a tty reference and it should (along with a ldisc one). While at it and changing prototypes (adding tty param), prepend cy_ to functions which don't have it yet. 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')
-rw-r--r--drivers/char/cyclades.c172
1 files changed, 93 insertions, 79 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 2dafc2da0648..e2f731b70763 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -850,7 +850,7 @@ MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
850#endif 850#endif
851 851
852static void cy_start(struct tty_struct *); 852static void cy_start(struct tty_struct *);
853static void set_line_char(struct cyclades_port *); 853static void cy_set_line_char(struct cyclades_port *, struct tty_struct *);
854static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); 854static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
855#ifdef CONFIG_ISA 855#ifdef CONFIG_ISA
856static unsigned detect_isa_irq(void __iomem *); 856static unsigned detect_isa_irq(void __iomem *);
@@ -1011,8 +1011,9 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
1011 save_car = readb(base_addr + (CyCAR << index)); 1011 save_car = readb(base_addr + (CyCAR << index));
1012 cy_writeb(base_addr + (CyCAR << index), save_xir); 1012 cy_writeb(base_addr + (CyCAR << index), save_xir);
1013 1013
1014 tty = tty_port_tty_get(&info->port);
1014 /* if there is nowhere to put the data, discard it */ 1015 /* if there is nowhere to put the data, discard it */
1015 if (info->port.tty == NULL) { 1016 if (tty == NULL) {
1016 if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) == 1017 if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
1017 CyIVRRxEx) { /* exception */ 1018 CyIVRRxEx) { /* exception */
1018 data = readb(base_addr + (CyRDSR << index)); 1019 data = readb(base_addr + (CyRDSR << index));
@@ -1024,7 +1025,6 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
1024 goto end; 1025 goto end;
1025 } 1026 }
1026 /* there is an open port for this data */ 1027 /* there is an open port for this data */
1027 tty = info->port.tty;
1028 if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) == 1028 if ((readb(base_addr + (CyRIVR << index)) & CyIVRMask) ==
1029 CyIVRRxEx) { /* exception */ 1029 CyIVRRxEx) { /* exception */
1030 data = readb(base_addr + (CyRDSR << index)); 1030 data = readb(base_addr + (CyRDSR << index));
@@ -1041,6 +1041,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
1041 1041
1042 if (data & info->ignore_status_mask) { 1042 if (data & info->ignore_status_mask) {
1043 info->icount.rx++; 1043 info->icount.rx++;
1044 tty_kref_put(tty);
1044 return; 1045 return;
1045 } 1046 }
1046 if (tty_buffer_request_room(tty, 1)) { 1047 if (tty_buffer_request_room(tty, 1)) {
@@ -1121,6 +1122,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
1121 info->idle_stats.recv_idle = jiffies; 1122 info->idle_stats.recv_idle = jiffies;
1122 } 1123 }
1123 tty_schedule_flip(tty); 1124 tty_schedule_flip(tty);
1125 tty_kref_put(tty);
1124end: 1126end:
1125 /* end of service */ 1127 /* end of service */
1126 cy_writeb(base_addr + (CyRIR << index), save_xir & 0x3f); 1128 cy_writeb(base_addr + (CyRIR << index), save_xir & 0x3f);
@@ -1131,6 +1133,7 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
1131 void __iomem *base_addr) 1133 void __iomem *base_addr)
1132{ 1134{
1133 struct cyclades_port *info; 1135 struct cyclades_port *info;
1136 struct tty_struct *tty;
1134 int char_count, index = cinfo->bus_index; 1137 int char_count, index = cinfo->bus_index;
1135 u8 save_xir, channel, save_car, outch; 1138 u8 save_xir, channel, save_car, outch;
1136 1139
@@ -1154,7 +1157,8 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
1154 goto end; 1157 goto end;
1155 } 1158 }
1156 info = &cinfo->ports[channel + chip * 4]; 1159 info = &cinfo->ports[channel + chip * 4];
1157 if (info->port.tty == NULL) { 1160 tty = tty_port_tty_get(&info->port);
1161 if (tty == NULL) {
1158 cy_writeb(base_addr + (CySRER << index), 1162 cy_writeb(base_addr + (CySRER << index),
1159 readb(base_addr + (CySRER << index)) & ~CyTxRdy); 1163 readb(base_addr + (CySRER << index)) & ~CyTxRdy);
1160 goto end; 1164 goto end;
@@ -1205,7 +1209,7 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
1205 ~CyTxRdy); 1209 ~CyTxRdy);
1206 goto done; 1210 goto done;
1207 } 1211 }
1208 if (info->port.tty->stopped || info->port.tty->hw_stopped) { 1212 if (tty->stopped || tty->hw_stopped) {
1209 cy_writeb(base_addr + (CySRER << index), 1213 cy_writeb(base_addr + (CySRER << index),
1210 readb(base_addr + (CySRER << index)) & 1214 readb(base_addr + (CySRER << index)) &
1211 ~CyTxRdy); 1215 ~CyTxRdy);
@@ -1241,7 +1245,8 @@ static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
1241 } 1245 }
1242 1246
1243done: 1247done:
1244 tty_wakeup(info->port.tty); 1248 tty_wakeup(tty);
1249 tty_kref_put(tty);
1245end: 1250end:
1246 /* end of service */ 1251 /* end of service */
1247 cy_writeb(base_addr + (CyTIR << index), save_xir & 0x3f); 1252 cy_writeb(base_addr + (CyTIR << index), save_xir & 0x3f);
@@ -1252,6 +1257,7 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
1252 void __iomem *base_addr) 1257 void __iomem *base_addr)
1253{ 1258{
1254 struct cyclades_port *info; 1259 struct cyclades_port *info;
1260 struct tty_struct *tty;
1255 int index = cinfo->bus_index; 1261 int index = cinfo->bus_index;
1256 u8 save_xir, channel, save_car, mdm_change, mdm_status; 1262 u8 save_xir, channel, save_car, mdm_change, mdm_status;
1257 1263
@@ -1265,7 +1271,8 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
1265 mdm_change = readb(base_addr + (CyMISR << index)); 1271 mdm_change = readb(base_addr + (CyMISR << index));
1266 mdm_status = readb(base_addr + (CyMSVR1 << index)); 1272 mdm_status = readb(base_addr + (CyMSVR1 << index));
1267 1273
1268 if (!info->port.tty) 1274 tty = tty_port_tty_get(&info->port);
1275 if (!tty)
1269 goto end; 1276 goto end;
1270 1277
1271 if (mdm_change & CyANY_DELTA) { 1278 if (mdm_change & CyANY_DELTA) {
@@ -1284,27 +1291,27 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
1284 1291
1285 if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) { 1292 if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
1286 if (!(mdm_status & CyDCD)) { 1293 if (!(mdm_status & CyDCD)) {
1287 tty_hangup(info->port.tty); 1294 tty_hangup(tty);
1288 info->port.flags &= ~ASYNC_NORMAL_ACTIVE; 1295 info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1289 } 1296 }
1290 wake_up_interruptible(&info->port.open_wait); 1297 wake_up_interruptible(&info->port.open_wait);
1291 } 1298 }
1292 if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) { 1299 if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
1293 if (info->port.tty->hw_stopped) { 1300 if (tty->hw_stopped) {
1294 if (mdm_status & CyCTS) { 1301 if (mdm_status & CyCTS) {
1295 /* cy_start isn't used 1302 /* cy_start isn't used
1296 because... !!! */ 1303 because... !!! */
1297 info->port.tty->hw_stopped = 0; 1304 tty->hw_stopped = 0;
1298 cy_writeb(base_addr + (CySRER << index), 1305 cy_writeb(base_addr + (CySRER << index),
1299 readb(base_addr + (CySRER << index)) | 1306 readb(base_addr + (CySRER << index)) |
1300 CyTxRdy); 1307 CyTxRdy);
1301 tty_wakeup(info->port.tty); 1308 tty_wakeup(tty);
1302 } 1309 }
1303 } else { 1310 } else {
1304 if (!(mdm_status & CyCTS)) { 1311 if (!(mdm_status & CyCTS)) {
1305 /* cy_stop isn't used 1312 /* cy_stop isn't used
1306 because ... !!! */ 1313 because ... !!! */
1307 info->port.tty->hw_stopped = 1; 1314 tty->hw_stopped = 1;
1308 cy_writeb(base_addr + (CySRER << index), 1315 cy_writeb(base_addr + (CySRER << index),
1309 readb(base_addr + (CySRER << index)) & 1316 readb(base_addr + (CySRER << index)) &
1310 ~CyTxRdy); 1317 ~CyTxRdy);
@@ -1315,6 +1322,7 @@ static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
1315 } 1322 }
1316 if (mdm_change & CyRI) { 1323 if (mdm_change & CyRI) {
1317 }*/ 1324 }*/
1325 tty_kref_put(tty);
1318end: 1326end:
1319 /* end of service */ 1327 /* end of service */
1320 cy_writeb(base_addr + (CyMIR << index), save_xir & 0x3f); 1328 cy_writeb(base_addr + (CyMIR << index), save_xir & 0x3f);
@@ -1449,11 +1457,10 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
1449 return 0; 1457 return 0;
1450} /* cyz_issue_cmd */ 1458} /* cyz_issue_cmd */
1451 1459
1452static void cyz_handle_rx(struct cyclades_port *info, 1460static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty,
1453 struct BUF_CTRL __iomem *buf_ctrl) 1461 struct BUF_CTRL __iomem *buf_ctrl)
1454{ 1462{
1455 struct cyclades_card *cinfo = info->card; 1463 struct cyclades_card *cinfo = info->card;
1456 struct tty_struct *tty = info->port.tty;
1457 unsigned int char_count; 1464 unsigned int char_count;
1458 int len; 1465 int len;
1459#ifdef BLOCKMOVE 1466#ifdef BLOCKMOVE
@@ -1542,11 +1549,10 @@ static void cyz_handle_rx(struct cyclades_port *info,
1542 } 1549 }
1543} 1550}
1544 1551
1545static void cyz_handle_tx(struct cyclades_port *info, 1552static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty,
1546 struct BUF_CTRL __iomem *buf_ctrl) 1553 struct BUF_CTRL __iomem *buf_ctrl)
1547{ 1554{
1548 struct cyclades_card *cinfo = info->card; 1555 struct cyclades_card *cinfo = info->card;
1549 struct tty_struct *tty = info->port.tty;
1550 u8 data; 1556 u8 data;
1551 unsigned int char_count; 1557 unsigned int char_count;
1552#ifdef BLOCKMOVE 1558#ifdef BLOCKMOVE
@@ -1642,7 +1648,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
1642 special_count = 0; 1648 special_count = 0;
1643 delta_count = 0; 1649 delta_count = 0;
1644 info = &cinfo->ports[channel]; 1650 info = &cinfo->ports[channel];
1645 tty = info->port.tty; 1651 tty = tty_port_tty_get(&info->port);
1646 if (tty == NULL) 1652 if (tty == NULL)
1647 continue; 1653 continue;
1648 1654
@@ -1674,7 +1680,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
1674 C_RS_DCD) { 1680 C_RS_DCD) {
1675 wake_up_interruptible(&info->port.open_wait); 1681 wake_up_interruptible(&info->port.open_wait);
1676 } else { 1682 } else {
1677 tty_hangup(info->port.tty); 1683 tty_hangup(tty);
1678 wake_up_interruptible(&info->port.open_wait); 1684 wake_up_interruptible(&info->port.open_wait);
1679 info->port.flags &= ~ASYNC_NORMAL_ACTIVE; 1685 info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1680 } 1686 }
@@ -1706,7 +1712,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
1706 printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, " 1712 printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
1707 "port %ld\n", info->card, channel); 1713 "port %ld\n", info->card, channel);
1708#endif 1714#endif
1709 cyz_handle_rx(info, buf_ctrl); 1715 cyz_handle_rx(info, tty, buf_ctrl);
1710 break; 1716 break;
1711 case C_CM_TXBEMPTY: 1717 case C_CM_TXBEMPTY:
1712 case C_CM_TXLOWWM: 1718 case C_CM_TXLOWWM:
@@ -1716,7 +1722,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
1716 printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, " 1722 printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
1717 "port %ld\n", info->card, channel); 1723 "port %ld\n", info->card, channel);
1718#endif 1724#endif
1719 cyz_handle_tx(info, buf_ctrl); 1725 cyz_handle_tx(info, tty, buf_ctrl);
1720 break; 1726 break;
1721#endif /* CONFIG_CYZ_INTR */ 1727#endif /* CONFIG_CYZ_INTR */
1722 case C_CM_FATAL: 1728 case C_CM_FATAL:
@@ -1729,6 +1735,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
1729 wake_up_interruptible(&info->delta_msr_wait); 1735 wake_up_interruptible(&info->delta_msr_wait);
1730 if (special_count) 1736 if (special_count)
1731 tty_schedule_flip(tty); 1737 tty_schedule_flip(tty);
1738 tty_kref_put(tty);
1732 } 1739 }
1733} 1740}
1734 1741
@@ -1774,7 +1781,6 @@ static void cyz_poll(unsigned long arg)
1774{ 1781{
1775 struct cyclades_card *cinfo; 1782 struct cyclades_card *cinfo;
1776 struct cyclades_port *info; 1783 struct cyclades_port *info;
1777 struct tty_struct *tty;
1778 struct FIRM_ID __iomem *firm_id; 1784 struct FIRM_ID __iomem *firm_id;
1779 struct ZFW_CTRL __iomem *zfw_ctrl; 1785 struct ZFW_CTRL __iomem *zfw_ctrl;
1780 struct BUF_CTRL __iomem *buf_ctrl; 1786 struct BUF_CTRL __iomem *buf_ctrl;
@@ -1802,13 +1808,19 @@ static void cyz_poll(unsigned long arg)
1802 cyz_handle_cmd(cinfo); 1808 cyz_handle_cmd(cinfo);
1803 1809
1804 for (port = 0; port < cinfo->nports; port++) { 1810 for (port = 0; port < cinfo->nports; port++) {
1811 struct tty_struct *tty;
1812
1805 info = &cinfo->ports[port]; 1813 info = &cinfo->ports[port];
1806 tty = info->port.tty;
1807 buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); 1814 buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
1808 1815
1816 tty = tty_port_tty_get(&info->port);
1817 /* OK to pass NULL to the handle functions below.
1818 They need to drop the data in that case. */
1819
1809 if (!info->throttle) 1820 if (!info->throttle)
1810 cyz_handle_rx(info, buf_ctrl); 1821 cyz_handle_rx(info, tty, buf_ctrl);
1811 cyz_handle_tx(info, buf_ctrl); 1822 cyz_handle_tx(info, tty, buf_ctrl);
1823 tty_kref_put(tty);
1812 } 1824 }
1813 /* poll every 'cyz_polling_cycle' period */ 1825 /* poll every 'cyz_polling_cycle' period */
1814 expires = jiffies + cyz_polling_cycle; 1826 expires = jiffies + cyz_polling_cycle;
@@ -1824,7 +1836,7 @@ static void cyz_poll(unsigned long arg)
1824/* This is called whenever a port becomes active; 1836/* This is called whenever a port becomes active;
1825 interrupts are enabled and DTR & RTS are turned on. 1837 interrupts are enabled and DTR & RTS are turned on.
1826 */ 1838 */
1827static int startup(struct cyclades_port *info) 1839static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
1828{ 1840{
1829 struct cyclades_card *card; 1841 struct cyclades_card *card;
1830 unsigned long flags; 1842 unsigned long flags;
@@ -1848,8 +1860,7 @@ static int startup(struct cyclades_port *info)
1848 } 1860 }
1849 1861
1850 if (!info->type) { 1862 if (!info->type) {
1851 if (info->port.tty) 1863 set_bit(TTY_IO_ERROR, &tty->flags);
1852 set_bit(TTY_IO_ERROR, &info->port.tty->flags);
1853 free_page(page); 1864 free_page(page);
1854 goto errout; 1865 goto errout;
1855 } 1866 }
@@ -1861,7 +1872,7 @@ static int startup(struct cyclades_port *info)
1861 1872
1862 spin_unlock_irqrestore(&card->card_lock, flags); 1873 spin_unlock_irqrestore(&card->card_lock, flags);
1863 1874
1864 set_line_char(info); 1875 cy_set_line_char(info, tty);
1865 1876
1866 if (!cy_is_Z(card)) { 1877 if (!cy_is_Z(card)) {
1867 chip = channel >> 2; 1878 chip = channel >> 2;
@@ -1900,8 +1911,7 @@ static int startup(struct cyclades_port *info)
1900 readb(base_addr + (CySRER << index)) | CyRxData); 1911 readb(base_addr + (CySRER << index)) | CyRxData);
1901 info->port.flags |= ASYNC_INITIALIZED; 1912 info->port.flags |= ASYNC_INITIALIZED;
1902 1913
1903 if (info->port.tty) 1914 clear_bit(TTY_IO_ERROR, &tty->flags);
1904 clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
1905 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; 1915 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1906 info->breakon = info->breakoff = 0; 1916 info->breakon = info->breakoff = 0;
1907 memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); 1917 memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
@@ -1984,8 +1994,7 @@ static int startup(struct cyclades_port *info)
1984 /* enable send, recv, modem !!! */ 1994 /* enable send, recv, modem !!! */
1985 1995
1986 info->port.flags |= ASYNC_INITIALIZED; 1996 info->port.flags |= ASYNC_INITIALIZED;
1987 if (info->port.tty) 1997 clear_bit(TTY_IO_ERROR, &tty->flags);
1988 clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
1989 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; 1998 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1990 info->breakon = info->breakoff = 0; 1999 info->breakon = info->breakoff = 0;
1991 memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); 2000 memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
@@ -2047,7 +2056,7 @@ static void start_xmit(struct cyclades_port *info)
2047 * This routine shuts down a serial port; interrupts are disabled, 2056 * This routine shuts down a serial port; interrupts are disabled,
2048 * and DTR is dropped if the hangup on close termio flag is on. 2057 * and DTR is dropped if the hangup on close termio flag is on.
2049 */ 2058 */
2050static void shutdown(struct cyclades_port *info) 2059static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
2051{ 2060{
2052 struct cyclades_card *card; 2061 struct cyclades_card *card;
2053 unsigned long flags; 2062 unsigned long flags;
@@ -2083,7 +2092,7 @@ static void shutdown(struct cyclades_port *info)
2083 free_page((unsigned long)temp); 2092 free_page((unsigned long)temp);
2084 } 2093 }
2085 cy_writeb(base_addr + (CyCAR << index), (u_char) channel); 2094 cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
2086 if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) { 2095 if (tty->termios->c_cflag & HUPCL) {
2087 cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); 2096 cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS);
2088 cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR); 2097 cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR);
2089#ifdef CY_DEBUG_DTR 2098#ifdef CY_DEBUG_DTR
@@ -2097,8 +2106,7 @@ static void shutdown(struct cyclades_port *info)
2097 /* it may be appropriate to clear _XMIT at 2106 /* it may be appropriate to clear _XMIT at
2098 some later date (after testing)!!! */ 2107 some later date (after testing)!!! */
2099 2108
2100 if (info->port.tty) 2109 set_bit(TTY_IO_ERROR, &tty->flags);
2101 set_bit(TTY_IO_ERROR, &info->port.tty->flags);
2102 info->port.flags &= ~ASYNC_INITIALIZED; 2110 info->port.flags &= ~ASYNC_INITIALIZED;
2103 spin_unlock_irqrestore(&card->card_lock, flags); 2111 spin_unlock_irqrestore(&card->card_lock, flags);
2104 } else { 2112 } else {
@@ -2132,7 +2140,7 @@ static void shutdown(struct cyclades_port *info)
2132 free_page((unsigned long)temp); 2140 free_page((unsigned long)temp);
2133 } 2141 }
2134 2142
2135 if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) { 2143 if (tty->termios->c_cflag & HUPCL) {
2136 cy_writel(&ch_ctrl[channel].rs_control, 2144 cy_writel(&ch_ctrl[channel].rs_control,
2137 (__u32)(readl(&ch_ctrl[channel].rs_control) & 2145 (__u32)(readl(&ch_ctrl[channel].rs_control) &
2138 ~(C_RS_RTS | C_RS_DTR))); 2146 ~(C_RS_RTS | C_RS_DTR)));
@@ -2147,8 +2155,7 @@ static void shutdown(struct cyclades_port *info)
2147#endif 2155#endif
2148 } 2156 }
2149 2157
2150 if (info->port.tty) 2158 set_bit(TTY_IO_ERROR, &tty->flags);
2151 set_bit(TTY_IO_ERROR, &info->port.tty->flags);
2152 info->port.flags &= ~ASYNC_INITIALIZED; 2159 info->port.flags &= ~ASYNC_INITIALIZED;
2153 2160
2154 spin_unlock_irqrestore(&card->card_lock, flags); 2161 spin_unlock_irqrestore(&card->card_lock, flags);
@@ -2436,7 +2443,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
2436 printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line); 2443 printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line);
2437#endif 2444#endif
2438 tty->driver_data = info; 2445 tty->driver_data = info;
2439 info->port.tty = tty;
2440 if (serial_paranoia_check(info, tty->name, "cy_open")) 2446 if (serial_paranoia_check(info, tty->name, "cy_open"))
2441 return -ENODEV; 2447 return -ENODEV;
2442 2448
@@ -2462,7 +2468,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
2462 /* 2468 /*
2463 * Start up serial port 2469 * Start up serial port
2464 */ 2470 */
2465 retval = startup(info); 2471 retval = cy_startup(info, tty);
2466 if (retval) 2472 if (retval)
2467 return retval; 2473 return retval;
2468 2474
@@ -2476,6 +2482,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
2476 } 2482 }
2477 2483
2478 info->throttle = 0; 2484 info->throttle = 0;
2485 tty_port_tty_set(&info->port, tty);
2479 2486
2480#ifdef CY_DEBUG_OPEN 2487#ifdef CY_DEBUG_OPEN
2481 printk(KERN_DEBUG "cyc:cy_open done\n"); 2488 printk(KERN_DEBUG "cyc:cy_open done\n");
@@ -2705,13 +2712,13 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
2705 } 2712 }
2706 2713
2707 spin_unlock_irqrestore(&card->card_lock, flags); 2714 spin_unlock_irqrestore(&card->card_lock, flags);
2708 shutdown(info); 2715 cy_shutdown(info, tty);
2709 cy_flush_buffer(tty); 2716 cy_flush_buffer(tty);
2710 tty_ldisc_flush(tty); 2717 tty_ldisc_flush(tty);
2711 spin_lock_irqsave(&card->card_lock, flags); 2718 spin_lock_irqsave(&card->card_lock, flags);
2712 2719
2713 tty->closing = 0; 2720 tty->closing = 0;
2714 info->port.tty = NULL; 2721 tty_port_tty_set(&info->port, NULL);
2715 if (info->port.blocked_open) { 2722 if (info->port.blocked_open) {
2716 spin_unlock_irqrestore(&card->card_lock, flags); 2723 spin_unlock_irqrestore(&card->card_lock, flags);
2717 if (info->port.close_delay) { 2724 if (info->port.close_delay) {
@@ -2957,7 +2964,7 @@ static void cyy_baud_calc(struct cyclades_port *info, __u32 baud)
2957 * This routine finds or computes the various line characteristics. 2964 * This routine finds or computes the various line characteristics.
2958 * It used to be called config_setup 2965 * It used to be called config_setup
2959 */ 2966 */
2960static void set_line_char(struct cyclades_port *info) 2967static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
2961{ 2968{
2962 struct cyclades_card *card; 2969 struct cyclades_card *card;
2963 unsigned long flags; 2970 unsigned long flags;
@@ -2967,28 +2974,26 @@ static void set_line_char(struct cyclades_port *info)
2967 int baud, baud_rate = 0; 2974 int baud, baud_rate = 0;
2968 int i; 2975 int i;
2969 2976
2970 if (!info->port.tty || !info->port.tty->termios) 2977 if (!tty->termios) /* XXX can this happen at all? */
2971 return; 2978 return;
2972 2979
2973 if (info->line == -1) 2980 if (info->line == -1)
2974 return; 2981 return;
2975 2982
2976 cflag = info->port.tty->termios->c_cflag; 2983 cflag = tty->termios->c_cflag;
2977 iflag = info->port.tty->termios->c_iflag; 2984 iflag = tty->termios->c_iflag;
2978 2985
2979 /* 2986 /*
2980 * Set up the tty->alt_speed kludge 2987 * Set up the tty->alt_speed kludge
2981 */ 2988 */
2982 if (info->port.tty) { 2989 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2983 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) 2990 tty->alt_speed = 57600;
2984 info->port.tty->alt_speed = 57600; 2991 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2985 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) 2992 tty->alt_speed = 115200;
2986 info->port.tty->alt_speed = 115200; 2993 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2987 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) 2994 tty->alt_speed = 230400;
2988 info->port.tty->alt_speed = 230400; 2995 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2989 if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) 2996 tty->alt_speed = 460800;
2990 info->port.tty->alt_speed = 460800;
2991 }
2992 2997
2993 card = info->card; 2998 card = info->card;
2994 channel = info->line - card->first_line; 2999 channel = info->line - card->first_line;
@@ -2998,7 +3003,7 @@ static void set_line_char(struct cyclades_port *info)
2998 index = card->bus_index; 3003 index = card->bus_index;
2999 3004
3000 /* baud rate */ 3005 /* baud rate */
3001 baud = tty_get_baud_rate(info->port.tty); 3006 baud = tty_get_baud_rate(tty);
3002 if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 3007 if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
3003 ASYNC_SPD_CUST) { 3008 ASYNC_SPD_CUST) {
3004 if (info->custom_divisor) 3009 if (info->custom_divisor)
@@ -3123,9 +3128,8 @@ static void set_line_char(struct cyclades_port *info)
3123 3128
3124 /* set line characteristics according configuration */ 3129 /* set line characteristics according configuration */
3125 3130
3126 cy_writeb(base_addr + (CySCHR1 << index), 3131 cy_writeb(base_addr + (CySCHR1 << index), START_CHAR(tty));
3127 START_CHAR(info->port.tty)); 3132 cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(tty));
3128 cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(info->port.tty));
3129 cy_writeb(base_addr + (CyCOR1 << index), info->cor1); 3133 cy_writeb(base_addr + (CyCOR1 << index), info->cor1);
3130 cy_writeb(base_addr + (CyCOR2 << index), info->cor2); 3134 cy_writeb(base_addr + (CyCOR2 << index), info->cor2);
3131 cy_writeb(base_addr + (CyCOR3 << index), info->cor3); 3135 cy_writeb(base_addr + (CyCOR3 << index), info->cor3);
@@ -3141,7 +3145,7 @@ static void set_line_char(struct cyclades_port *info)
3141 (info->default_timeout ? info->default_timeout : 0x02)); 3145 (info->default_timeout ? info->default_timeout : 0x02));
3142 /* 10ms rx timeout */ 3146 /* 10ms rx timeout */
3143 3147
3144 if (C_CLOCAL(info->port.tty)) { 3148 if (C_CLOCAL(tty)) {
3145 /* without modem intr */ 3149 /* without modem intr */
3146 cy_writeb(base_addr + (CySRER << index), 3150 cy_writeb(base_addr + (CySRER << index),
3147 readb(base_addr + (CySRER << index)) | CyMdmCh); 3151 readb(base_addr + (CySRER << index)) | CyMdmCh);
@@ -3204,8 +3208,7 @@ static void set_line_char(struct cyclades_port *info)
3204#endif 3208#endif
3205 } 3209 }
3206 3210
3207 if (info->port.tty) 3211 clear_bit(TTY_IO_ERROR, &tty->flags);
3208 clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
3209 spin_unlock_irqrestore(&card->card_lock, flags); 3212 spin_unlock_irqrestore(&card->card_lock, flags);
3210 3213
3211 } else { 3214 } else {
@@ -3224,7 +3227,7 @@ static void set_line_char(struct cyclades_port *info)
3224 ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); 3227 ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
3225 3228
3226 /* baud rate */ 3229 /* baud rate */
3227 baud = tty_get_baud_rate(info->port.tty); 3230 baud = tty_get_baud_rate(tty);
3228 if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) == 3231 if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
3229 ASYNC_SPD_CUST) { 3232 ASYNC_SPD_CUST) {
3230 if (info->custom_divisor) 3233 if (info->custom_divisor)
@@ -3335,8 +3338,7 @@ static void set_line_char(struct cyclades_port *info)
3335 "was %x\n", info->line, retval); 3338 "was %x\n", info->line, retval);
3336 } 3339 }
3337 3340
3338 if (info->port.tty) 3341 clear_bit(TTY_IO_ERROR, &tty->flags);
3339 clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
3340 } 3342 }
3341} /* set_line_char */ 3343} /* set_line_char */
3342 3344
@@ -3365,7 +3367,7 @@ get_serial_info(struct cyclades_port *info,
3365} /* get_serial_info */ 3367} /* get_serial_info */
3366 3368
3367static int 3369static int
3368set_serial_info(struct cyclades_port *info, 3370cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
3369 struct serial_struct __user *new_info) 3371 struct serial_struct __user *new_info)
3370{ 3372{
3371 struct serial_struct new_serial; 3373 struct serial_struct new_serial;
@@ -3403,10 +3405,10 @@ set_serial_info(struct cyclades_port *info,
3403 3405
3404check_and_exit: 3406check_and_exit:
3405 if (info->port.flags & ASYNC_INITIALIZED) { 3407 if (info->port.flags & ASYNC_INITIALIZED) {
3406 set_line_char(info); 3408 cy_set_line_char(info, tty);
3407 return 0; 3409 return 0;
3408 } else { 3410 } else {
3409 return startup(info); 3411 return cy_startup(info, tty);
3410 } 3412 }
3411} /* set_serial_info */ 3413} /* set_serial_info */
3412 3414
@@ -3955,7 +3957,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
3955 ret_val = get_serial_info(info, argp); 3957 ret_val = get_serial_info(info, argp);
3956 break; 3958 break;
3957 case TIOCSSERIAL: 3959 case TIOCSSERIAL:
3958 ret_val = set_serial_info(info, argp); 3960 ret_val = cy_set_serial_info(info, tty, argp);
3959 break; 3961 break;
3960 case TIOCSERGETLSR: /* Get line status register */ 3962 case TIOCSERGETLSR: /* Get line status register */
3961 ret_val = get_lsr_info(info, argp); 3963 ret_val = get_lsr_info(info, argp);
@@ -4055,7 +4057,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
4055 printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); 4057 printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
4056#endif 4058#endif
4057 4059
4058 set_line_char(info); 4060 cy_set_line_char(info, tty);
4059 4061
4060 if ((old_termios->c_cflag & CRTSCTS) && 4062 if ((old_termios->c_cflag & CRTSCTS) &&
4061 !(tty->termios->c_cflag & CRTSCTS)) { 4063 !(tty->termios->c_cflag & CRTSCTS)) {
@@ -4299,13 +4301,13 @@ static void cy_hangup(struct tty_struct *tty)
4299 return; 4301 return;
4300 4302
4301 cy_flush_buffer(tty); 4303 cy_flush_buffer(tty);
4302 shutdown(info); 4304 cy_shutdown(info, tty);
4303 info->port.count = 0; 4305 info->port.count = 0;
4304#ifdef CY_DEBUG_COUNT 4306#ifdef CY_DEBUG_COUNT
4305 printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n", 4307 printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n",
4306 current->pid); 4308 current->pid);
4307#endif 4309#endif
4308 info->port.tty = NULL; 4310 tty_port_tty_set(&info->port, NULL);
4309 info->port.flags &= ~ASYNC_NORMAL_ACTIVE; 4311 info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
4310 wake_up_interruptible(&info->port.open_wait); 4312 wake_up_interruptible(&info->port.open_wait);
4311} /* cy_hangup */ 4313} /* cy_hangup */
@@ -5191,18 +5193,30 @@ static int cyclades_proc_show(struct seq_file *m, void *v)
5191 for (j = 0; j < cy_card[i].nports; j++) { 5193 for (j = 0; j < cy_card[i].nports; j++) {
5192 info = &cy_card[i].ports[j]; 5194 info = &cy_card[i].ports[j];
5193 5195
5194 if (info->port.count) 5196 if (info->port.count) {
5197 /* XXX is the ldisc num worth this? */
5198 struct tty_struct *tty;
5199 struct tty_ldisc *ld;
5200 int num = 0;
5201 tty = tty_port_tty_get(&info->port);
5202 if (tty) {
5203 ld = tty_ldisc_ref(tty);
5204 if (ld) {
5205 num = ld->ops->num;
5206 tty_ldisc_deref(ld);
5207 }
5208 tty_kref_put(tty);
5209 }
5195 seq_printf(m, "%3d %8lu %10lu %8lu " 5210 seq_printf(m, "%3d %8lu %10lu %8lu "
5196 "%10lu %8lu %9lu %6ld\n", info->line, 5211 "%10lu %8lu %9lu %6d\n", info->line,
5197 (cur_jifs - info->idle_stats.in_use) / 5212 (cur_jifs - info->idle_stats.in_use) /
5198 HZ, info->idle_stats.xmit_bytes, 5213 HZ, info->idle_stats.xmit_bytes,
5199 (cur_jifs - info->idle_stats.xmit_idle)/ 5214 (cur_jifs - info->idle_stats.xmit_idle)/
5200 HZ, info->idle_stats.recv_bytes, 5215 HZ, info->idle_stats.recv_bytes,
5201 (cur_jifs - info->idle_stats.recv_idle)/ 5216 (cur_jifs - info->idle_stats.recv_idle)/
5202 HZ, info->idle_stats.overruns, 5217 HZ, info->idle_stats.overruns,
5203 /* FIXME: double check locking */ 5218 num);
5204 (long)info->port.tty->ldisc->ops->num); 5219 } else
5205 else
5206 seq_printf(m, "%3d %8lu %10lu %8lu " 5220 seq_printf(m, "%3d %8lu %10lu %8lu "
5207 "%10lu %8lu %9lu %6ld\n", 5221 "%10lu %8lu %9lu %6ld\n",
5208 info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); 5222 info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);