diff options
-rw-r--r-- | drivers/char/pcmcia/synclink_cs.c | 479 |
1 files changed, 181 insertions, 298 deletions
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 4d64a02612a4..dc073e167abc 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -138,20 +138,15 @@ struct _input_signal_events { | |||
138 | */ | 138 | */ |
139 | 139 | ||
140 | typedef struct _mgslpc_info { | 140 | typedef struct _mgslpc_info { |
141 | struct tty_port port; | ||
141 | void *if_ptr; /* General purpose pointer (used by SPPP) */ | 142 | void *if_ptr; /* General purpose pointer (used by SPPP) */ |
142 | int magic; | 143 | int magic; |
143 | int flags; | ||
144 | int count; /* count of opens */ | ||
145 | int line; | 144 | int line; |
146 | unsigned short close_delay; | ||
147 | unsigned short closing_wait; /* time to wait before closing */ | ||
148 | 145 | ||
149 | struct mgsl_icount icount; | 146 | struct mgsl_icount icount; |
150 | 147 | ||
151 | struct tty_struct *tty; | ||
152 | int timeout; | 148 | int timeout; |
153 | int x_char; /* xon/xoff character */ | 149 | int x_char; /* xon/xoff character */ |
154 | int blocked_open; /* # of blocked opens */ | ||
155 | unsigned char read_status_mask; | 150 | unsigned char read_status_mask; |
156 | unsigned char ignore_status_mask; | 151 | unsigned char ignore_status_mask; |
157 | 152 | ||
@@ -170,9 +165,6 @@ typedef struct _mgslpc_info { | |||
170 | int rx_buf_count; /* total number of rx buffers */ | 165 | int rx_buf_count; /* total number of rx buffers */ |
171 | int rx_frame_count; /* number of full rx buffers */ | 166 | int rx_frame_count; /* number of full rx buffers */ |
172 | 167 | ||
173 | wait_queue_head_t open_wait; | ||
174 | wait_queue_head_t close_wait; | ||
175 | |||
176 | wait_queue_head_t status_event_wait_q; | 168 | wait_queue_head_t status_event_wait_q; |
177 | wait_queue_head_t event_wait_q; | 169 | wait_queue_head_t event_wait_q; |
178 | struct timer_list tx_timer; /* HDLC transmit timeout timer */ | 170 | struct timer_list tx_timer; /* HDLC transmit timeout timer */ |
@@ -375,7 +367,7 @@ static void irq_enable(MGSLPC_INFO *info, unsigned char channel, unsigned short | |||
375 | static void rx_start(MGSLPC_INFO *info); | 367 | static void rx_start(MGSLPC_INFO *info); |
376 | static void rx_stop(MGSLPC_INFO *info); | 368 | static void rx_stop(MGSLPC_INFO *info); |
377 | 369 | ||
378 | static void tx_start(MGSLPC_INFO *info); | 370 | static void tx_start(MGSLPC_INFO *info, struct tty_struct *tty); |
379 | static void tx_stop(MGSLPC_INFO *info); | 371 | static void tx_stop(MGSLPC_INFO *info); |
380 | static void tx_set_idle(MGSLPC_INFO *info); | 372 | static void tx_set_idle(MGSLPC_INFO *info); |
381 | 373 | ||
@@ -389,7 +381,8 @@ static void async_mode(MGSLPC_INFO *info); | |||
389 | 381 | ||
390 | static void tx_timeout(unsigned long context); | 382 | static void tx_timeout(unsigned long context); |
391 | 383 | ||
392 | static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg); | 384 | static int carrier_raised(struct tty_port *port); |
385 | static void raise_dtr_rts(struct tty_port *port); | ||
393 | 386 | ||
394 | #if SYNCLINK_GENERIC_HDLC | 387 | #if SYNCLINK_GENERIC_HDLC |
395 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) | 388 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) |
@@ -410,7 +403,7 @@ static void release_resources(MGSLPC_INFO *info); | |||
410 | static void mgslpc_add_device(MGSLPC_INFO *info); | 403 | static void mgslpc_add_device(MGSLPC_INFO *info); |
411 | static void mgslpc_remove_device(MGSLPC_INFO *info); | 404 | static void mgslpc_remove_device(MGSLPC_INFO *info); |
412 | 405 | ||
413 | static bool rx_get_frame(MGSLPC_INFO *info); | 406 | static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty); |
414 | static void rx_reset_buffers(MGSLPC_INFO *info); | 407 | static void rx_reset_buffers(MGSLPC_INFO *info); |
415 | static int rx_alloc_buffers(MGSLPC_INFO *info); | 408 | static int rx_alloc_buffers(MGSLPC_INFO *info); |
416 | static void rx_free_buffers(MGSLPC_INFO *info); | 409 | static void rx_free_buffers(MGSLPC_INFO *info); |
@@ -421,7 +414,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id); | |||
421 | * Bottom half interrupt handlers | 414 | * Bottom half interrupt handlers |
422 | */ | 415 | */ |
423 | static void bh_handler(struct work_struct *work); | 416 | static void bh_handler(struct work_struct *work); |
424 | static void bh_transmit(MGSLPC_INFO *info); | 417 | static void bh_transmit(MGSLPC_INFO *info, struct tty_struct *tty); |
425 | static void bh_status(MGSLPC_INFO *info); | 418 | static void bh_status(MGSLPC_INFO *info); |
426 | 419 | ||
427 | /* | 420 | /* |
@@ -432,10 +425,10 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
432 | unsigned int set, unsigned int clear); | 425 | unsigned int set, unsigned int clear); |
433 | static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount); | 426 | static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount); |
434 | static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params); | 427 | static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params); |
435 | static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params); | 428 | static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params, struct tty_struct *tty); |
436 | static int get_txidle(MGSLPC_INFO *info, int __user *idle_mode); | 429 | static int get_txidle(MGSLPC_INFO *info, int __user *idle_mode); |
437 | static int set_txidle(MGSLPC_INFO *info, int idle_mode); | 430 | static int set_txidle(MGSLPC_INFO *info, int idle_mode); |
438 | static int set_txenable(MGSLPC_INFO *info, int enable); | 431 | static int set_txenable(MGSLPC_INFO *info, int enable, struct tty_struct *tty); |
439 | static int tx_abort(MGSLPC_INFO *info); | 432 | static int tx_abort(MGSLPC_INFO *info); |
440 | static int set_rxenable(MGSLPC_INFO *info, int enable); | 433 | static int set_rxenable(MGSLPC_INFO *info, int enable); |
441 | static int wait_events(MGSLPC_INFO *info, int __user *mask); | 434 | static int wait_events(MGSLPC_INFO *info, int __user *mask); |
@@ -474,7 +467,7 @@ static struct tty_driver *serial_driver; | |||
474 | /* number of characters left in xmit buffer before we ask for more */ | 467 | /* number of characters left in xmit buffer before we ask for more */ |
475 | #define WAKEUP_CHARS 256 | 468 | #define WAKEUP_CHARS 256 |
476 | 469 | ||
477 | static void mgslpc_change_params(MGSLPC_INFO *info); | 470 | static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty); |
478 | static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); | 471 | static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); |
479 | 472 | ||
480 | /* PCMCIA prototypes */ | 473 | /* PCMCIA prototypes */ |
@@ -517,6 +510,11 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
517 | } | 510 | } |
518 | } | 511 | } |
519 | 512 | ||
513 | static const struct tty_port_operations mgslpc_port_ops = { | ||
514 | .carrier_raised = carrier_raised, | ||
515 | .raise_dtr_rts = raise_dtr_rts | ||
516 | }; | ||
517 | |||
520 | static int mgslpc_probe(struct pcmcia_device *link) | 518 | static int mgslpc_probe(struct pcmcia_device *link) |
521 | { | 519 | { |
522 | MGSLPC_INFO *info; | 520 | MGSLPC_INFO *info; |
@@ -532,12 +530,12 @@ static int mgslpc_probe(struct pcmcia_device *link) | |||
532 | } | 530 | } |
533 | 531 | ||
534 | info->magic = MGSLPC_MAGIC; | 532 | info->magic = MGSLPC_MAGIC; |
533 | tty_port_init(&info->port); | ||
534 | info->port.ops = &mgslpc_port_ops; | ||
535 | INIT_WORK(&info->task, bh_handler); | 535 | INIT_WORK(&info->task, bh_handler); |
536 | info->max_frame_size = 4096; | 536 | info->max_frame_size = 4096; |
537 | info->close_delay = 5*HZ/10; | 537 | info->port.close_delay = 5*HZ/10; |
538 | info->closing_wait = 30*HZ; | 538 | info->port.closing_wait = 30*HZ; |
539 | init_waitqueue_head(&info->open_wait); | ||
540 | init_waitqueue_head(&info->close_wait); | ||
541 | init_waitqueue_head(&info->status_event_wait_q); | 539 | init_waitqueue_head(&info->status_event_wait_q); |
542 | init_waitqueue_head(&info->event_wait_q); | 540 | init_waitqueue_head(&info->event_wait_q); |
543 | spin_lock_init(&info->lock); | 541 | spin_lock_init(&info->lock); |
@@ -784,7 +782,7 @@ static void tx_release(struct tty_struct *tty) | |||
784 | 782 | ||
785 | spin_lock_irqsave(&info->lock,flags); | 783 | spin_lock_irqsave(&info->lock,flags); |
786 | if (!info->tx_enabled) | 784 | if (!info->tx_enabled) |
787 | tx_start(info); | 785 | tx_start(info, tty); |
788 | spin_unlock_irqrestore(&info->lock,flags); | 786 | spin_unlock_irqrestore(&info->lock,flags); |
789 | } | 787 | } |
790 | 788 | ||
@@ -823,6 +821,7 @@ static int bh_action(MGSLPC_INFO *info) | |||
823 | static void bh_handler(struct work_struct *work) | 821 | static void bh_handler(struct work_struct *work) |
824 | { | 822 | { |
825 | MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task); | 823 | MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task); |
824 | struct tty_struct *tty; | ||
826 | int action; | 825 | int action; |
827 | 826 | ||
828 | if (!info) | 827 | if (!info) |
@@ -833,6 +832,7 @@ static void bh_handler(struct work_struct *work) | |||
833 | __FILE__,__LINE__,info->device_name); | 832 | __FILE__,__LINE__,info->device_name); |
834 | 833 | ||
835 | info->bh_running = true; | 834 | info->bh_running = true; |
835 | tty = tty_port_tty_get(&info->port); | ||
836 | 836 | ||
837 | while((action = bh_action(info)) != 0) { | 837 | while((action = bh_action(info)) != 0) { |
838 | 838 | ||
@@ -844,10 +844,10 @@ static void bh_handler(struct work_struct *work) | |||
844 | switch (action) { | 844 | switch (action) { |
845 | 845 | ||
846 | case BH_RECEIVE: | 846 | case BH_RECEIVE: |
847 | while(rx_get_frame(info)); | 847 | while(rx_get_frame(info, tty)); |
848 | break; | 848 | break; |
849 | case BH_TRANSMIT: | 849 | case BH_TRANSMIT: |
850 | bh_transmit(info); | 850 | bh_transmit(info, tty); |
851 | break; | 851 | break; |
852 | case BH_STATUS: | 852 | case BH_STATUS: |
853 | bh_status(info); | 853 | bh_status(info); |
@@ -859,14 +859,14 @@ static void bh_handler(struct work_struct *work) | |||
859 | } | 859 | } |
860 | } | 860 | } |
861 | 861 | ||
862 | tty_kref_put(tty); | ||
862 | if (debug_level >= DEBUG_LEVEL_BH) | 863 | if (debug_level >= DEBUG_LEVEL_BH) |
863 | printk( "%s(%d):bh_handler(%s) exit\n", | 864 | printk( "%s(%d):bh_handler(%s) exit\n", |
864 | __FILE__,__LINE__,info->device_name); | 865 | __FILE__,__LINE__,info->device_name); |
865 | } | 866 | } |
866 | 867 | ||
867 | static void bh_transmit(MGSLPC_INFO *info) | 868 | static void bh_transmit(MGSLPC_INFO *info, struct tty_struct *tty) |
868 | { | 869 | { |
869 | struct tty_struct *tty = info->tty; | ||
870 | if (debug_level >= DEBUG_LEVEL_BH) | 870 | if (debug_level >= DEBUG_LEVEL_BH) |
871 | printk("bh_transmit() entry on %s\n", info->device_name); | 871 | printk("bh_transmit() entry on %s\n", info->device_name); |
872 | 872 | ||
@@ -945,12 +945,11 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom) | |||
945 | issue_command(info, CHA, CMD_RXFIFO); | 945 | issue_command(info, CHA, CMD_RXFIFO); |
946 | } | 946 | } |
947 | 947 | ||
948 | static void rx_ready_async(MGSLPC_INFO *info, int tcd) | 948 | static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty) |
949 | { | 949 | { |
950 | unsigned char data, status, flag; | 950 | unsigned char data, status, flag; |
951 | int fifo_count; | 951 | int fifo_count; |
952 | int work = 0; | 952 | int work = 0; |
953 | struct tty_struct *tty = info->tty; | ||
954 | struct mgsl_icount *icount = &info->icount; | 953 | struct mgsl_icount *icount = &info->icount; |
955 | 954 | ||
956 | if (tcd) { | 955 | if (tcd) { |
@@ -1013,7 +1012,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd) | |||
1013 | } | 1012 | } |
1014 | 1013 | ||
1015 | 1014 | ||
1016 | static void tx_done(MGSLPC_INFO *info) | 1015 | static void tx_done(MGSLPC_INFO *info, struct tty_struct *tty) |
1017 | { | 1016 | { |
1018 | if (!info->tx_active) | 1017 | if (!info->tx_active) |
1019 | return; | 1018 | return; |
@@ -1042,7 +1041,7 @@ static void tx_done(MGSLPC_INFO *info) | |||
1042 | else | 1041 | else |
1043 | #endif | 1042 | #endif |
1044 | { | 1043 | { |
1045 | if (info->tty->stopped || info->tty->hw_stopped) { | 1044 | if (tty->stopped || tty->hw_stopped) { |
1046 | tx_stop(info); | 1045 | tx_stop(info); |
1047 | return; | 1046 | return; |
1048 | } | 1047 | } |
@@ -1050,7 +1049,7 @@ static void tx_done(MGSLPC_INFO *info) | |||
1050 | } | 1049 | } |
1051 | } | 1050 | } |
1052 | 1051 | ||
1053 | static void tx_ready(MGSLPC_INFO *info) | 1052 | static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty) |
1054 | { | 1053 | { |
1055 | unsigned char fifo_count = 32; | 1054 | unsigned char fifo_count = 32; |
1056 | int c; | 1055 | int c; |
@@ -1062,7 +1061,7 @@ static void tx_ready(MGSLPC_INFO *info) | |||
1062 | if (!info->tx_active) | 1061 | if (!info->tx_active) |
1063 | return; | 1062 | return; |
1064 | } else { | 1063 | } else { |
1065 | if (info->tty->stopped || info->tty->hw_stopped) { | 1064 | if (tty->stopped || tty->hw_stopped) { |
1066 | tx_stop(info); | 1065 | tx_stop(info); |
1067 | return; | 1066 | return; |
1068 | } | 1067 | } |
@@ -1099,7 +1098,7 @@ static void tx_ready(MGSLPC_INFO *info) | |||
1099 | } | 1098 | } |
1100 | } | 1099 | } |
1101 | 1100 | ||
1102 | static void cts_change(MGSLPC_INFO *info) | 1101 | static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) |
1103 | { | 1102 | { |
1104 | get_signals(info); | 1103 | get_signals(info); |
1105 | if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) | 1104 | if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) |
@@ -1112,14 +1111,14 @@ static void cts_change(MGSLPC_INFO *info) | |||
1112 | wake_up_interruptible(&info->status_event_wait_q); | 1111 | wake_up_interruptible(&info->status_event_wait_q); |
1113 | wake_up_interruptible(&info->event_wait_q); | 1112 | wake_up_interruptible(&info->event_wait_q); |
1114 | 1113 | ||
1115 | if (info->flags & ASYNC_CTS_FLOW) { | 1114 | if (info->port.flags & ASYNC_CTS_FLOW) { |
1116 | if (info->tty->hw_stopped) { | 1115 | if (tty->hw_stopped) { |
1117 | if (info->serial_signals & SerialSignal_CTS) { | 1116 | if (info->serial_signals & SerialSignal_CTS) { |
1118 | if (debug_level >= DEBUG_LEVEL_ISR) | 1117 | if (debug_level >= DEBUG_LEVEL_ISR) |
1119 | printk("CTS tx start..."); | 1118 | printk("CTS tx start..."); |
1120 | if (info->tty) | 1119 | if (tty) |
1121 | info->tty->hw_stopped = 0; | 1120 | tty->hw_stopped = 0; |
1122 | tx_start(info); | 1121 | tx_start(info, tty); |
1123 | info->pending_bh |= BH_TRANSMIT; | 1122 | info->pending_bh |= BH_TRANSMIT; |
1124 | return; | 1123 | return; |
1125 | } | 1124 | } |
@@ -1127,8 +1126,8 @@ static void cts_change(MGSLPC_INFO *info) | |||
1127 | if (!(info->serial_signals & SerialSignal_CTS)) { | 1126 | if (!(info->serial_signals & SerialSignal_CTS)) { |
1128 | if (debug_level >= DEBUG_LEVEL_ISR) | 1127 | if (debug_level >= DEBUG_LEVEL_ISR) |
1129 | printk("CTS tx stop..."); | 1128 | printk("CTS tx stop..."); |
1130 | if (info->tty) | 1129 | if (tty) |
1131 | info->tty->hw_stopped = 1; | 1130 | tty->hw_stopped = 1; |
1132 | tx_stop(info); | 1131 | tx_stop(info); |
1133 | } | 1132 | } |
1134 | } | 1133 | } |
@@ -1136,7 +1135,7 @@ static void cts_change(MGSLPC_INFO *info) | |||
1136 | info->pending_bh |= BH_STATUS; | 1135 | info->pending_bh |= BH_STATUS; |
1137 | } | 1136 | } |
1138 | 1137 | ||
1139 | static void dcd_change(MGSLPC_INFO *info) | 1138 | static void dcd_change(MGSLPC_INFO *info, struct tty_struct *tty) |
1140 | { | 1139 | { |
1141 | get_signals(info); | 1140 | get_signals(info); |
1142 | if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) | 1141 | if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) |
@@ -1158,17 +1157,17 @@ static void dcd_change(MGSLPC_INFO *info) | |||
1158 | wake_up_interruptible(&info->status_event_wait_q); | 1157 | wake_up_interruptible(&info->status_event_wait_q); |
1159 | wake_up_interruptible(&info->event_wait_q); | 1158 | wake_up_interruptible(&info->event_wait_q); |
1160 | 1159 | ||
1161 | if (info->flags & ASYNC_CHECK_CD) { | 1160 | if (info->port.flags & ASYNC_CHECK_CD) { |
1162 | if (debug_level >= DEBUG_LEVEL_ISR) | 1161 | if (debug_level >= DEBUG_LEVEL_ISR) |
1163 | printk("%s CD now %s...", info->device_name, | 1162 | printk("%s CD now %s...", info->device_name, |
1164 | (info->serial_signals & SerialSignal_DCD) ? "on" : "off"); | 1163 | (info->serial_signals & SerialSignal_DCD) ? "on" : "off"); |
1165 | if (info->serial_signals & SerialSignal_DCD) | 1164 | if (info->serial_signals & SerialSignal_DCD) |
1166 | wake_up_interruptible(&info->open_wait); | 1165 | wake_up_interruptible(&info->port.open_wait); |
1167 | else { | 1166 | else { |
1168 | if (debug_level >= DEBUG_LEVEL_ISR) | 1167 | if (debug_level >= DEBUG_LEVEL_ISR) |
1169 | printk("doing serial hangup..."); | 1168 | printk("doing serial hangup..."); |
1170 | if (info->tty) | 1169 | if (tty) |
1171 | tty_hangup(info->tty); | 1170 | tty_hangup(tty); |
1172 | } | 1171 | } |
1173 | } | 1172 | } |
1174 | info->pending_bh |= BH_STATUS; | 1173 | info->pending_bh |= BH_STATUS; |
@@ -1214,6 +1213,7 @@ static void ri_change(MGSLPC_INFO *info) | |||
1214 | static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | 1213 | static irqreturn_t mgslpc_isr(int dummy, void *dev_id) |
1215 | { | 1214 | { |
1216 | MGSLPC_INFO *info = dev_id; | 1215 | MGSLPC_INFO *info = dev_id; |
1216 | struct tty_struct *tty; | ||
1217 | unsigned short isr; | 1217 | unsigned short isr; |
1218 | unsigned char gis, pis; | 1218 | unsigned char gis, pis; |
1219 | int count=0; | 1219 | int count=0; |
@@ -1224,6 +1224,8 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1224 | if (!(info->p_dev->_locked)) | 1224 | if (!(info->p_dev->_locked)) |
1225 | return IRQ_HANDLED; | 1225 | return IRQ_HANDLED; |
1226 | 1226 | ||
1227 | tty = tty_port_tty_get(&info->port); | ||
1228 | |||
1227 | spin_lock(&info->lock); | 1229 | spin_lock(&info->lock); |
1228 | 1230 | ||
1229 | while ((gis = read_reg(info, CHA + GIS))) { | 1231 | while ((gis = read_reg(info, CHA + GIS))) { |
@@ -1239,9 +1241,9 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1239 | if (gis & (BIT1 + BIT0)) { | 1241 | if (gis & (BIT1 + BIT0)) { |
1240 | isr = read_reg16(info, CHB + ISR); | 1242 | isr = read_reg16(info, CHB + ISR); |
1241 | if (isr & IRQ_DCD) | 1243 | if (isr & IRQ_DCD) |
1242 | dcd_change(info); | 1244 | dcd_change(info, tty); |
1243 | if (isr & IRQ_CTS) | 1245 | if (isr & IRQ_CTS) |
1244 | cts_change(info); | 1246 | cts_change(info, tty); |
1245 | } | 1247 | } |
1246 | if (gis & (BIT3 + BIT2)) | 1248 | if (gis & (BIT3 + BIT2)) |
1247 | { | 1249 | { |
@@ -1258,8 +1260,8 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1258 | } | 1260 | } |
1259 | if (isr & IRQ_BREAK_ON) { | 1261 | if (isr & IRQ_BREAK_ON) { |
1260 | info->icount.brk++; | 1262 | info->icount.brk++; |
1261 | if (info->flags & ASYNC_SAK) | 1263 | if (info->port.flags & ASYNC_SAK) |
1262 | do_SAK(info->tty); | 1264 | do_SAK(tty); |
1263 | } | 1265 | } |
1264 | if (isr & IRQ_RXTIME) { | 1266 | if (isr & IRQ_RXTIME) { |
1265 | issue_command(info, CHA, CMD_RXFIFO_READ); | 1267 | issue_command(info, CHA, CMD_RXFIFO_READ); |
@@ -1268,7 +1270,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1268 | if (info->params.mode == MGSL_MODE_HDLC) | 1270 | if (info->params.mode == MGSL_MODE_HDLC) |
1269 | rx_ready_hdlc(info, isr & IRQ_RXEOM); | 1271 | rx_ready_hdlc(info, isr & IRQ_RXEOM); |
1270 | else | 1272 | else |
1271 | rx_ready_async(info, isr & IRQ_RXEOM); | 1273 | rx_ready_async(info, isr & IRQ_RXEOM, tty); |
1272 | } | 1274 | } |
1273 | 1275 | ||
1274 | /* transmit IRQs */ | 1276 | /* transmit IRQs */ |
@@ -1277,14 +1279,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1277 | info->icount.txabort++; | 1279 | info->icount.txabort++; |
1278 | else | 1280 | else |
1279 | info->icount.txunder++; | 1281 | info->icount.txunder++; |
1280 | tx_done(info); | 1282 | tx_done(info, tty); |
1281 | } | 1283 | } |
1282 | else if (isr & IRQ_ALLSENT) { | 1284 | else if (isr & IRQ_ALLSENT) { |
1283 | info->icount.txok++; | 1285 | info->icount.txok++; |
1284 | tx_done(info); | 1286 | tx_done(info, tty); |
1285 | } | 1287 | } |
1286 | else if (isr & IRQ_TXFIFO) | 1288 | else if (isr & IRQ_TXFIFO) |
1287 | tx_ready(info); | 1289 | tx_ready(info, tty); |
1288 | } | 1290 | } |
1289 | if (gis & BIT7) { | 1291 | if (gis & BIT7) { |
1290 | pis = read_reg(info, CHA + PIS); | 1292 | pis = read_reg(info, CHA + PIS); |
@@ -1308,6 +1310,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1308 | } | 1310 | } |
1309 | 1311 | ||
1310 | spin_unlock(&info->lock); | 1312 | spin_unlock(&info->lock); |
1313 | tty_kref_put(tty); | ||
1311 | 1314 | ||
1312 | if (debug_level >= DEBUG_LEVEL_ISR) | 1315 | if (debug_level >= DEBUG_LEVEL_ISR) |
1313 | printk("%s(%d):mgslpc_isr(%d)exit.\n", | 1316 | printk("%s(%d):mgslpc_isr(%d)exit.\n", |
@@ -1318,14 +1321,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) | |||
1318 | 1321 | ||
1319 | /* Initialize and start device. | 1322 | /* Initialize and start device. |
1320 | */ | 1323 | */ |
1321 | static int startup(MGSLPC_INFO * info) | 1324 | static int startup(MGSLPC_INFO * info, struct tty_struct *tty) |
1322 | { | 1325 | { |
1323 | int retval = 0; | 1326 | int retval = 0; |
1324 | 1327 | ||
1325 | if (debug_level >= DEBUG_LEVEL_INFO) | 1328 | if (debug_level >= DEBUG_LEVEL_INFO) |
1326 | printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name); | 1329 | printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name); |
1327 | 1330 | ||
1328 | if (info->flags & ASYNC_INITIALIZED) | 1331 | if (info->port.flags & ASYNC_INITIALIZED) |
1329 | return 0; | 1332 | return 0; |
1330 | 1333 | ||
1331 | if (!info->tx_buf) { | 1334 | if (!info->tx_buf) { |
@@ -1352,30 +1355,30 @@ static int startup(MGSLPC_INFO * info) | |||
1352 | retval = adapter_test(info); | 1355 | retval = adapter_test(info); |
1353 | 1356 | ||
1354 | if ( retval ) { | 1357 | if ( retval ) { |
1355 | if (capable(CAP_SYS_ADMIN) && info->tty) | 1358 | if (capable(CAP_SYS_ADMIN) && tty) |
1356 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 1359 | set_bit(TTY_IO_ERROR, &tty->flags); |
1357 | release_resources(info); | 1360 | release_resources(info); |
1358 | return retval; | 1361 | return retval; |
1359 | } | 1362 | } |
1360 | 1363 | ||
1361 | /* program hardware for current parameters */ | 1364 | /* program hardware for current parameters */ |
1362 | mgslpc_change_params(info); | 1365 | mgslpc_change_params(info, tty); |
1363 | 1366 | ||
1364 | if (info->tty) | 1367 | if (tty) |
1365 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | 1368 | clear_bit(TTY_IO_ERROR, &tty->flags); |
1366 | 1369 | ||
1367 | info->flags |= ASYNC_INITIALIZED; | 1370 | info->port.flags |= ASYNC_INITIALIZED; |
1368 | 1371 | ||
1369 | return 0; | 1372 | return 0; |
1370 | } | 1373 | } |
1371 | 1374 | ||
1372 | /* Called by mgslpc_close() and mgslpc_hangup() to shutdown hardware | 1375 | /* Called by mgslpc_close() and mgslpc_hangup() to shutdown hardware |
1373 | */ | 1376 | */ |
1374 | static void shutdown(MGSLPC_INFO * info) | 1377 | static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) |
1375 | { | 1378 | { |
1376 | unsigned long flags; | 1379 | unsigned long flags; |
1377 | 1380 | ||
1378 | if (!(info->flags & ASYNC_INITIALIZED)) | 1381 | if (!(info->port.flags & ASYNC_INITIALIZED)) |
1379 | return; | 1382 | return; |
1380 | 1383 | ||
1381 | if (debug_level >= DEBUG_LEVEL_INFO) | 1384 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -1402,7 +1405,7 @@ static void shutdown(MGSLPC_INFO * info) | |||
1402 | /* TODO:disable interrupts instead of reset to preserve signal states */ | 1405 | /* TODO:disable interrupts instead of reset to preserve signal states */ |
1403 | reset_device(info); | 1406 | reset_device(info); |
1404 | 1407 | ||
1405 | if (!info->tty || info->tty->termios->c_cflag & HUPCL) { | 1408 | if (!tty || tty->termios->c_cflag & HUPCL) { |
1406 | info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); | 1409 | info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); |
1407 | set_signals(info); | 1410 | set_signals(info); |
1408 | } | 1411 | } |
@@ -1411,13 +1414,13 @@ static void shutdown(MGSLPC_INFO * info) | |||
1411 | 1414 | ||
1412 | release_resources(info); | 1415 | release_resources(info); |
1413 | 1416 | ||
1414 | if (info->tty) | 1417 | if (tty) |
1415 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 1418 | set_bit(TTY_IO_ERROR, &tty->flags); |
1416 | 1419 | ||
1417 | info->flags &= ~ASYNC_INITIALIZED; | 1420 | info->port.flags &= ~ASYNC_INITIALIZED; |
1418 | } | 1421 | } |
1419 | 1422 | ||
1420 | static void mgslpc_program_hw(MGSLPC_INFO *info) | 1423 | static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) |
1421 | { | 1424 | { |
1422 | unsigned long flags; | 1425 | unsigned long flags; |
1423 | 1426 | ||
@@ -1443,7 +1446,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info) | |||
1443 | port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); | 1446 | port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); |
1444 | get_signals(info); | 1447 | get_signals(info); |
1445 | 1448 | ||
1446 | if (info->netcount || info->tty->termios->c_cflag & CREAD) | 1449 | if (info->netcount || (tty && (tty->termios->c_cflag & CREAD))) |
1447 | rx_start(info); | 1450 | rx_start(info); |
1448 | 1451 | ||
1449 | spin_unlock_irqrestore(&info->lock,flags); | 1452 | spin_unlock_irqrestore(&info->lock,flags); |
@@ -1451,19 +1454,19 @@ static void mgslpc_program_hw(MGSLPC_INFO *info) | |||
1451 | 1454 | ||
1452 | /* Reconfigure adapter based on new parameters | 1455 | /* Reconfigure adapter based on new parameters |
1453 | */ | 1456 | */ |
1454 | static void mgslpc_change_params(MGSLPC_INFO *info) | 1457 | static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty) |
1455 | { | 1458 | { |
1456 | unsigned cflag; | 1459 | unsigned cflag; |
1457 | int bits_per_char; | 1460 | int bits_per_char; |
1458 | 1461 | ||
1459 | if (!info->tty || !info->tty->termios) | 1462 | if (!tty || !tty->termios) |
1460 | return; | 1463 | return; |
1461 | 1464 | ||
1462 | if (debug_level >= DEBUG_LEVEL_INFO) | 1465 | if (debug_level >= DEBUG_LEVEL_INFO) |
1463 | printk("%s(%d):mgslpc_change_params(%s)\n", | 1466 | printk("%s(%d):mgslpc_change_params(%s)\n", |
1464 | __FILE__,__LINE__, info->device_name ); | 1467 | __FILE__,__LINE__, info->device_name ); |
1465 | 1468 | ||
1466 | cflag = info->tty->termios->c_cflag; | 1469 | cflag = tty->termios->c_cflag; |
1467 | 1470 | ||
1468 | /* if B0 rate (hangup) specified then negate DTR and RTS */ | 1471 | /* if B0 rate (hangup) specified then negate DTR and RTS */ |
1469 | /* otherwise assert DTR and RTS */ | 1472 | /* otherwise assert DTR and RTS */ |
@@ -1510,7 +1513,7 @@ static void mgslpc_change_params(MGSLPC_INFO *info) | |||
1510 | * current data rate. | 1513 | * current data rate. |
1511 | */ | 1514 | */ |
1512 | if (info->params.data_rate <= 460800) { | 1515 | if (info->params.data_rate <= 460800) { |
1513 | info->params.data_rate = tty_get_baud_rate(info->tty); | 1516 | info->params.data_rate = tty_get_baud_rate(tty); |
1514 | } | 1517 | } |
1515 | 1518 | ||
1516 | if ( info->params.data_rate ) { | 1519 | if ( info->params.data_rate ) { |
@@ -1520,24 +1523,24 @@ static void mgslpc_change_params(MGSLPC_INFO *info) | |||
1520 | info->timeout += HZ/50; /* Add .02 seconds of slop */ | 1523 | info->timeout += HZ/50; /* Add .02 seconds of slop */ |
1521 | 1524 | ||
1522 | if (cflag & CRTSCTS) | 1525 | if (cflag & CRTSCTS) |
1523 | info->flags |= ASYNC_CTS_FLOW; | 1526 | info->port.flags |= ASYNC_CTS_FLOW; |
1524 | else | 1527 | else |
1525 | info->flags &= ~ASYNC_CTS_FLOW; | 1528 | info->port.flags &= ~ASYNC_CTS_FLOW; |
1526 | 1529 | ||
1527 | if (cflag & CLOCAL) | 1530 | if (cflag & CLOCAL) |
1528 | info->flags &= ~ASYNC_CHECK_CD; | 1531 | info->port.flags &= ~ASYNC_CHECK_CD; |
1529 | else | 1532 | else |
1530 | info->flags |= ASYNC_CHECK_CD; | 1533 | info->port.flags |= ASYNC_CHECK_CD; |
1531 | 1534 | ||
1532 | /* process tty input control flags */ | 1535 | /* process tty input control flags */ |
1533 | 1536 | ||
1534 | info->read_status_mask = 0; | 1537 | info->read_status_mask = 0; |
1535 | if (I_INPCK(info->tty)) | 1538 | if (I_INPCK(tty)) |
1536 | info->read_status_mask |= BIT7 | BIT6; | 1539 | info->read_status_mask |= BIT7 | BIT6; |
1537 | if (I_IGNPAR(info->tty)) | 1540 | if (I_IGNPAR(tty)) |
1538 | info->ignore_status_mask |= BIT7 | BIT6; | 1541 | info->ignore_status_mask |= BIT7 | BIT6; |
1539 | 1542 | ||
1540 | mgslpc_program_hw(info); | 1543 | mgslpc_program_hw(info, tty); |
1541 | } | 1544 | } |
1542 | 1545 | ||
1543 | /* Add a character to the transmit buffer | 1546 | /* Add a character to the transmit buffer |
@@ -1597,7 +1600,7 @@ static void mgslpc_flush_chars(struct tty_struct *tty) | |||
1597 | 1600 | ||
1598 | spin_lock_irqsave(&info->lock,flags); | 1601 | spin_lock_irqsave(&info->lock,flags); |
1599 | if (!info->tx_active) | 1602 | if (!info->tx_active) |
1600 | tx_start(info); | 1603 | tx_start(info, tty); |
1601 | spin_unlock_irqrestore(&info->lock,flags); | 1604 | spin_unlock_irqrestore(&info->lock,flags); |
1602 | } | 1605 | } |
1603 | 1606 | ||
@@ -1659,7 +1662,7 @@ start: | |||
1659 | if (info->tx_count && !tty->stopped && !tty->hw_stopped) { | 1662 | if (info->tx_count && !tty->stopped && !tty->hw_stopped) { |
1660 | spin_lock_irqsave(&info->lock,flags); | 1663 | spin_lock_irqsave(&info->lock,flags); |
1661 | if (!info->tx_active) | 1664 | if (!info->tx_active) |
1662 | tx_start(info); | 1665 | tx_start(info, tty); |
1663 | spin_unlock_irqrestore(&info->lock,flags); | 1666 | spin_unlock_irqrestore(&info->lock,flags); |
1664 | } | 1667 | } |
1665 | cleanup: | 1668 | cleanup: |
@@ -1764,7 +1767,7 @@ static void mgslpc_send_xchar(struct tty_struct *tty, char ch) | |||
1764 | if (ch) { | 1767 | if (ch) { |
1765 | spin_lock_irqsave(&info->lock,flags); | 1768 | spin_lock_irqsave(&info->lock,flags); |
1766 | if (!info->tx_enabled) | 1769 | if (!info->tx_enabled) |
1767 | tx_start(info); | 1770 | tx_start(info, tty); |
1768 | spin_unlock_irqrestore(&info->lock,flags); | 1771 | spin_unlock_irqrestore(&info->lock,flags); |
1769 | } | 1772 | } |
1770 | } | 1773 | } |
@@ -1862,7 +1865,7 @@ static int get_params(MGSLPC_INFO * info, MGSL_PARAMS __user *user_params) | |||
1862 | * | 1865 | * |
1863 | * Returns: 0 if success, otherwise error code | 1866 | * Returns: 0 if success, otherwise error code |
1864 | */ | 1867 | */ |
1865 | static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params) | 1868 | static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params, struct tty_struct *tty) |
1866 | { | 1869 | { |
1867 | unsigned long flags; | 1870 | unsigned long flags; |
1868 | MGSL_PARAMS tmp_params; | 1871 | MGSL_PARAMS tmp_params; |
@@ -1883,7 +1886,7 @@ static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params) | |||
1883 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); | 1886 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); |
1884 | spin_unlock_irqrestore(&info->lock,flags); | 1887 | spin_unlock_irqrestore(&info->lock,flags); |
1885 | 1888 | ||
1886 | mgslpc_change_params(info); | 1889 | mgslpc_change_params(info, tty); |
1887 | 1890 | ||
1888 | return 0; | 1891 | return 0; |
1889 | } | 1892 | } |
@@ -1944,7 +1947,7 @@ static int set_interface(MGSLPC_INFO * info, int if_mode) | |||
1944 | return 0; | 1947 | return 0; |
1945 | } | 1948 | } |
1946 | 1949 | ||
1947 | static int set_txenable(MGSLPC_INFO * info, int enable) | 1950 | static int set_txenable(MGSLPC_INFO * info, int enable, struct tty_struct *tty) |
1948 | { | 1951 | { |
1949 | unsigned long flags; | 1952 | unsigned long flags; |
1950 | 1953 | ||
@@ -1954,7 +1957,7 @@ static int set_txenable(MGSLPC_INFO * info, int enable) | |||
1954 | spin_lock_irqsave(&info->lock,flags); | 1957 | spin_lock_irqsave(&info->lock,flags); |
1955 | if (enable) { | 1958 | if (enable) { |
1956 | if (!info->tx_enabled) | 1959 | if (!info->tx_enabled) |
1957 | tx_start(info); | 1960 | tx_start(info, tty); |
1958 | } else { | 1961 | } else { |
1959 | if (info->tx_enabled) | 1962 | if (info->tx_enabled) |
1960 | tx_stop(info); | 1963 | tx_stop(info); |
@@ -2263,6 +2266,11 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, | |||
2263 | unsigned int cmd, unsigned long arg) | 2266 | unsigned int cmd, unsigned long arg) |
2264 | { | 2267 | { |
2265 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; | 2268 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; |
2269 | int error; | ||
2270 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
2271 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
2272 | void __user *argp = (void __user *)arg; | ||
2273 | unsigned long flags; | ||
2266 | 2274 | ||
2267 | if (debug_level >= DEBUG_LEVEL_INFO) | 2275 | if (debug_level >= DEBUG_LEVEL_INFO) |
2268 | printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, | 2276 | printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, |
@@ -2277,22 +2285,11 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file, | |||
2277 | return -EIO; | 2285 | return -EIO; |
2278 | } | 2286 | } |
2279 | 2287 | ||
2280 | return ioctl_common(info, cmd, arg); | ||
2281 | } | ||
2282 | |||
2283 | static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) | ||
2284 | { | ||
2285 | int error; | ||
2286 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
2287 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
2288 | void __user *argp = (void __user *)arg; | ||
2289 | unsigned long flags; | ||
2290 | |||
2291 | switch (cmd) { | 2288 | switch (cmd) { |
2292 | case MGSL_IOCGPARAMS: | 2289 | case MGSL_IOCGPARAMS: |
2293 | return get_params(info, argp); | 2290 | return get_params(info, argp); |
2294 | case MGSL_IOCSPARAMS: | 2291 | case MGSL_IOCSPARAMS: |
2295 | return set_params(info, argp); | 2292 | return set_params(info, argp, tty); |
2296 | case MGSL_IOCGTXIDLE: | 2293 | case MGSL_IOCGTXIDLE: |
2297 | return get_txidle(info, argp); | 2294 | return get_txidle(info, argp); |
2298 | case MGSL_IOCSTXIDLE: | 2295 | case MGSL_IOCSTXIDLE: |
@@ -2302,7 +2299,7 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) | |||
2302 | case MGSL_IOCSIF: | 2299 | case MGSL_IOCSIF: |
2303 | return set_interface(info,(int)arg); | 2300 | return set_interface(info,(int)arg); |
2304 | case MGSL_IOCTXENABLE: | 2301 | case MGSL_IOCTXENABLE: |
2305 | return set_txenable(info,(int)arg); | 2302 | return set_txenable(info,(int)arg, tty); |
2306 | case MGSL_IOCRXENABLE: | 2303 | case MGSL_IOCRXENABLE: |
2307 | return set_rxenable(info,(int)arg); | 2304 | return set_rxenable(info,(int)arg); |
2308 | case MGSL_IOCTXABORT: | 2305 | case MGSL_IOCTXABORT: |
@@ -2369,7 +2366,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term | |||
2369 | == RELEVANT_IFLAG(old_termios->c_iflag))) | 2366 | == RELEVANT_IFLAG(old_termios->c_iflag))) |
2370 | return; | 2367 | return; |
2371 | 2368 | ||
2372 | mgslpc_change_params(info); | 2369 | mgslpc_change_params(info, tty); |
2373 | 2370 | ||
2374 | /* Handle transition to B0 status */ | 2371 | /* Handle transition to B0 status */ |
2375 | if (old_termios->c_cflag & CBAUD && | 2372 | if (old_termios->c_cflag & CBAUD && |
@@ -2404,81 +2401,34 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term | |||
2404 | static void mgslpc_close(struct tty_struct *tty, struct file * filp) | 2401 | static void mgslpc_close(struct tty_struct *tty, struct file * filp) |
2405 | { | 2402 | { |
2406 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; | 2403 | MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; |
2404 | struct tty_port *port = &info->port; | ||
2407 | 2405 | ||
2408 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close")) | 2406 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close")) |
2409 | return; | 2407 | return; |
2410 | 2408 | ||
2411 | if (debug_level >= DEBUG_LEVEL_INFO) | 2409 | if (debug_level >= DEBUG_LEVEL_INFO) |
2412 | printk("%s(%d):mgslpc_close(%s) entry, count=%d\n", | 2410 | printk("%s(%d):mgslpc_close(%s) entry, count=%d\n", |
2413 | __FILE__,__LINE__, info->device_name, info->count); | 2411 | __FILE__,__LINE__, info->device_name, port->count); |
2414 | |||
2415 | if (!info->count) | ||
2416 | return; | ||
2417 | 2412 | ||
2418 | if (tty_hung_up_p(filp)) | 2413 | WARN_ON(!port->count); |
2419 | goto cleanup; | ||
2420 | |||
2421 | if ((tty->count == 1) && (info->count != 1)) { | ||
2422 | /* | ||
2423 | * tty->count is 1 and the tty structure will be freed. | ||
2424 | * info->count should be one in this case. | ||
2425 | * if it's not, correct it so that the port is shutdown. | ||
2426 | */ | ||
2427 | printk("mgslpc_close: bad refcount; tty->count is 1, " | ||
2428 | "info->count is %d\n", info->count); | ||
2429 | info->count = 1; | ||
2430 | } | ||
2431 | 2414 | ||
2432 | info->count--; | 2415 | if (tty_port_close_start(port, tty, filp) == 0) |
2433 | |||
2434 | /* if at least one open remaining, leave hardware active */ | ||
2435 | if (info->count) | ||
2436 | goto cleanup; | 2416 | goto cleanup; |
2437 | 2417 | ||
2438 | info->flags |= ASYNC_CLOSING; | 2418 | if (port->flags & ASYNC_INITIALIZED) |
2439 | |||
2440 | /* set tty->closing to notify line discipline to | ||
2441 | * only process XON/XOFF characters. Only the N_TTY | ||
2442 | * discipline appears to use this (ppp does not). | ||
2443 | */ | ||
2444 | tty->closing = 1; | ||
2445 | |||
2446 | /* wait for transmit data to clear all layers */ | ||
2447 | |||
2448 | if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) { | ||
2449 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
2450 | printk("%s(%d):mgslpc_close(%s) calling tty_wait_until_sent\n", | ||
2451 | __FILE__,__LINE__, info->device_name ); | ||
2452 | tty_wait_until_sent(tty, info->closing_wait); | ||
2453 | } | ||
2454 | |||
2455 | if (info->flags & ASYNC_INITIALIZED) | ||
2456 | mgslpc_wait_until_sent(tty, info->timeout); | 2419 | mgslpc_wait_until_sent(tty, info->timeout); |
2457 | 2420 | ||
2458 | mgslpc_flush_buffer(tty); | 2421 | mgslpc_flush_buffer(tty); |
2459 | 2422 | ||
2460 | tty_ldisc_flush(tty); | 2423 | tty_ldisc_flush(tty); |
2461 | 2424 | shutdown(info, tty); | |
2462 | shutdown(info); | 2425 | |
2463 | 2426 | tty_port_close_end(port, tty); | |
2464 | tty->closing = 0; | 2427 | tty_port_tty_set(port, NULL); |
2465 | info->tty = NULL; | ||
2466 | |||
2467 | if (info->blocked_open) { | ||
2468 | if (info->close_delay) { | ||
2469 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | ||
2470 | } | ||
2471 | wake_up_interruptible(&info->open_wait); | ||
2472 | } | ||
2473 | |||
2474 | info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
2475 | |||
2476 | wake_up_interruptible(&info->close_wait); | ||
2477 | |||
2478 | cleanup: | 2428 | cleanup: |
2479 | if (debug_level >= DEBUG_LEVEL_INFO) | 2429 | if (debug_level >= DEBUG_LEVEL_INFO) |
2480 | printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__,__LINE__, | 2430 | printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__,__LINE__, |
2481 | tty->driver->name, info->count); | 2431 | tty->driver->name, port->count); |
2482 | } | 2432 | } |
2483 | 2433 | ||
2484 | /* Wait until the transmitter is empty. | 2434 | /* Wait until the transmitter is empty. |
@@ -2498,7 +2448,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2498 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_wait_until_sent")) | 2448 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_wait_until_sent")) |
2499 | return; | 2449 | return; |
2500 | 2450 | ||
2501 | if (!(info->flags & ASYNC_INITIALIZED)) | 2451 | if (!(info->port.flags & ASYNC_INITIALIZED)) |
2502 | goto exit; | 2452 | goto exit; |
2503 | 2453 | ||
2504 | orig_jiffies = jiffies; | 2454 | orig_jiffies = jiffies; |
@@ -2559,120 +2509,40 @@ static void mgslpc_hangup(struct tty_struct *tty) | |||
2559 | return; | 2509 | return; |
2560 | 2510 | ||
2561 | mgslpc_flush_buffer(tty); | 2511 | mgslpc_flush_buffer(tty); |
2562 | shutdown(info); | 2512 | shutdown(info, tty); |
2563 | 2513 | tty_port_hangup(&info->port); | |
2564 | info->count = 0; | ||
2565 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
2566 | info->tty = NULL; | ||
2567 | |||
2568 | wake_up_interruptible(&info->open_wait); | ||
2569 | } | 2514 | } |
2570 | 2515 | ||
2571 | /* Block the current process until the specified port | 2516 | static int carrier_raised(struct tty_port *port) |
2572 | * is ready to be opened. | ||
2573 | */ | ||
2574 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | ||
2575 | MGSLPC_INFO *info) | ||
2576 | { | 2517 | { |
2577 | DECLARE_WAITQUEUE(wait, current); | 2518 | MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); |
2578 | int retval; | 2519 | unsigned long flags; |
2579 | bool do_clocal = false; | ||
2580 | bool extra_count = false; | ||
2581 | unsigned long flags; | ||
2582 | |||
2583 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
2584 | printk("%s(%d):block_til_ready on %s\n", | ||
2585 | __FILE__,__LINE__, tty->driver->name ); | ||
2586 | |||
2587 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | ||
2588 | /* nonblock mode is set or port is not enabled */ | ||
2589 | /* just verify that callout device is not active */ | ||
2590 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
2591 | return 0; | ||
2592 | } | ||
2593 | |||
2594 | if (tty->termios->c_cflag & CLOCAL) | ||
2595 | do_clocal = true; | ||
2596 | |||
2597 | /* Wait for carrier detect and the line to become | ||
2598 | * free (i.e., not in use by the callout). While we are in | ||
2599 | * this loop, info->count is dropped by one, so that | ||
2600 | * mgslpc_close() knows when to free things. We restore it upon | ||
2601 | * exit, either normal or abnormal. | ||
2602 | */ | ||
2603 | |||
2604 | retval = 0; | ||
2605 | add_wait_queue(&info->open_wait, &wait); | ||
2606 | |||
2607 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
2608 | printk("%s(%d):block_til_ready before block on %s count=%d\n", | ||
2609 | __FILE__,__LINE__, tty->driver->name, info->count ); | ||
2610 | |||
2611 | spin_lock_irqsave(&info->lock, flags); | ||
2612 | if (!tty_hung_up_p(filp)) { | ||
2613 | extra_count = true; | ||
2614 | info->count--; | ||
2615 | } | ||
2616 | spin_unlock_irqrestore(&info->lock, flags); | ||
2617 | info->blocked_open++; | ||
2618 | |||
2619 | while (1) { | ||
2620 | if ((tty->termios->c_cflag & CBAUD)) { | ||
2621 | spin_lock_irqsave(&info->lock,flags); | ||
2622 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
2623 | set_signals(info); | ||
2624 | spin_unlock_irqrestore(&info->lock,flags); | ||
2625 | } | ||
2626 | |||
2627 | set_current_state(TASK_INTERRUPTIBLE); | ||
2628 | |||
2629 | if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){ | ||
2630 | retval = (info->flags & ASYNC_HUP_NOTIFY) ? | ||
2631 | -EAGAIN : -ERESTARTSYS; | ||
2632 | break; | ||
2633 | } | ||
2634 | |||
2635 | spin_lock_irqsave(&info->lock,flags); | ||
2636 | get_signals(info); | ||
2637 | spin_unlock_irqrestore(&info->lock,flags); | ||
2638 | |||
2639 | if (!(info->flags & ASYNC_CLOSING) && | ||
2640 | (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) { | ||
2641 | break; | ||
2642 | } | ||
2643 | |||
2644 | if (signal_pending(current)) { | ||
2645 | retval = -ERESTARTSYS; | ||
2646 | break; | ||
2647 | } | ||
2648 | |||
2649 | if (debug_level >= DEBUG_LEVEL_INFO) | ||
2650 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", | ||
2651 | __FILE__,__LINE__, tty->driver->name, info->count ); | ||
2652 | |||
2653 | schedule(); | ||
2654 | } | ||
2655 | |||
2656 | set_current_state(TASK_RUNNING); | ||
2657 | remove_wait_queue(&info->open_wait, &wait); | ||
2658 | 2520 | ||
2659 | if (extra_count) | 2521 | spin_lock_irqsave(&info->lock,flags); |
2660 | info->count++; | 2522 | get_signals(info); |
2661 | info->blocked_open--; | 2523 | spin_unlock_irqrestore(&info->lock,flags); |
2662 | 2524 | ||
2663 | if (debug_level >= DEBUG_LEVEL_INFO) | 2525 | if (info->serial_signals & SerialSignal_DCD) |
2664 | printk("%s(%d):block_til_ready after blocking on %s count=%d\n", | 2526 | return 1; |
2665 | __FILE__,__LINE__, tty->driver->name, info->count ); | 2527 | return 0; |
2528 | } | ||
2666 | 2529 | ||
2667 | if (!retval) | 2530 | static void raise_dtr_rts(struct tty_port *port) |
2668 | info->flags |= ASYNC_NORMAL_ACTIVE; | 2531 | { |
2532 | MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); | ||
2533 | unsigned long flags; | ||
2669 | 2534 | ||
2670 | return retval; | 2535 | spin_lock_irqsave(&info->lock,flags); |
2536 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
2537 | set_signals(info); | ||
2538 | spin_unlock_irqrestore(&info->lock,flags); | ||
2671 | } | 2539 | } |
2672 | 2540 | ||
2541 | |||
2673 | static int mgslpc_open(struct tty_struct *tty, struct file * filp) | 2542 | static int mgslpc_open(struct tty_struct *tty, struct file * filp) |
2674 | { | 2543 | { |
2675 | MGSLPC_INFO *info; | 2544 | MGSLPC_INFO *info; |
2545 | struct tty_port *port; | ||
2676 | int retval, line; | 2546 | int retval, line; |
2677 | unsigned long flags; | 2547 | unsigned long flags; |
2678 | 2548 | ||
@@ -2691,23 +2561,24 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) | |||
2691 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open")) | 2561 | if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open")) |
2692 | return -ENODEV; | 2562 | return -ENODEV; |
2693 | 2563 | ||
2564 | port = &info->port; | ||
2694 | tty->driver_data = info; | 2565 | tty->driver_data = info; |
2695 | info->tty = tty; | 2566 | tty_port_tty_set(port, tty); |
2696 | 2567 | ||
2697 | if (debug_level >= DEBUG_LEVEL_INFO) | 2568 | if (debug_level >= DEBUG_LEVEL_INFO) |
2698 | printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", | 2569 | printk("%s(%d):mgslpc_open(%s), old ref count = %d\n", |
2699 | __FILE__,__LINE__,tty->driver->name, info->count); | 2570 | __FILE__,__LINE__,tty->driver->name, port->count); |
2700 | 2571 | ||
2701 | /* If port is closing, signal caller to try again */ | 2572 | /* If port is closing, signal caller to try again */ |
2702 | if (tty_hung_up_p(filp) || info->flags & ASYNC_CLOSING){ | 2573 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){ |
2703 | if (info->flags & ASYNC_CLOSING) | 2574 | if (port->flags & ASYNC_CLOSING) |
2704 | interruptible_sleep_on(&info->close_wait); | 2575 | interruptible_sleep_on(&port->close_wait); |
2705 | retval = ((info->flags & ASYNC_HUP_NOTIFY) ? | 2576 | retval = ((port->flags & ASYNC_HUP_NOTIFY) ? |
2706 | -EAGAIN : -ERESTARTSYS); | 2577 | -EAGAIN : -ERESTARTSYS); |
2707 | goto cleanup; | 2578 | goto cleanup; |
2708 | } | 2579 | } |
2709 | 2580 | ||
2710 | info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 2581 | tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
2711 | 2582 | ||
2712 | spin_lock_irqsave(&info->netlock, flags); | 2583 | spin_lock_irqsave(&info->netlock, flags); |
2713 | if (info->netcount) { | 2584 | if (info->netcount) { |
@@ -2715,17 +2586,19 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) | |||
2715 | spin_unlock_irqrestore(&info->netlock, flags); | 2586 | spin_unlock_irqrestore(&info->netlock, flags); |
2716 | goto cleanup; | 2587 | goto cleanup; |
2717 | } | 2588 | } |
2718 | info->count++; | 2589 | spin_lock(&port->lock); |
2590 | port->count++; | ||
2591 | spin_unlock(&port->lock); | ||
2719 | spin_unlock_irqrestore(&info->netlock, flags); | 2592 | spin_unlock_irqrestore(&info->netlock, flags); |
2720 | 2593 | ||
2721 | if (info->count == 1) { | 2594 | if (port->count == 1) { |
2722 | /* 1st open on this device, init hardware */ | 2595 | /* 1st open on this device, init hardware */ |
2723 | retval = startup(info); | 2596 | retval = startup(info, tty); |
2724 | if (retval < 0) | 2597 | if (retval < 0) |
2725 | goto cleanup; | 2598 | goto cleanup; |
2726 | } | 2599 | } |
2727 | 2600 | ||
2728 | retval = block_til_ready(tty, filp, info); | 2601 | retval = tty_port_block_til_ready(&info->port, tty, filp); |
2729 | if (retval) { | 2602 | if (retval) { |
2730 | if (debug_level >= DEBUG_LEVEL_INFO) | 2603 | if (debug_level >= DEBUG_LEVEL_INFO) |
2731 | printk("%s(%d):block_til_ready(%s) returned %d\n", | 2604 | printk("%s(%d):block_til_ready(%s) returned %d\n", |
@@ -2739,13 +2612,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) | |||
2739 | retval = 0; | 2612 | retval = 0; |
2740 | 2613 | ||
2741 | cleanup: | 2614 | cleanup: |
2742 | if (retval) { | ||
2743 | if (tty->count == 1) | ||
2744 | info->tty = NULL; /* tty layer will release tty struct */ | ||
2745 | if(info->count) | ||
2746 | info->count--; | ||
2747 | } | ||
2748 | |||
2749 | return retval; | 2615 | return retval; |
2750 | } | 2616 | } |
2751 | 2617 | ||
@@ -3500,7 +3366,7 @@ static void rx_start(MGSLPC_INFO *info) | |||
3500 | info->rx_enabled = true; | 3366 | info->rx_enabled = true; |
3501 | } | 3367 | } |
3502 | 3368 | ||
3503 | static void tx_start(MGSLPC_INFO *info) | 3369 | static void tx_start(MGSLPC_INFO *info, struct tty_struct *tty) |
3504 | { | 3370 | { |
3505 | if (debug_level >= DEBUG_LEVEL_ISR) | 3371 | if (debug_level >= DEBUG_LEVEL_ISR) |
3506 | printk("%s(%d):tx_start(%s)\n", | 3372 | printk("%s(%d):tx_start(%s)\n", |
@@ -3524,11 +3390,11 @@ static void tx_start(MGSLPC_INFO *info) | |||
3524 | if (info->params.mode == MGSL_MODE_ASYNC) { | 3390 | if (info->params.mode == MGSL_MODE_ASYNC) { |
3525 | if (!info->tx_active) { | 3391 | if (!info->tx_active) { |
3526 | info->tx_active = true; | 3392 | info->tx_active = true; |
3527 | tx_ready(info); | 3393 | tx_ready(info, tty); |
3528 | } | 3394 | } |
3529 | } else { | 3395 | } else { |
3530 | info->tx_active = true; | 3396 | info->tx_active = true; |
3531 | tx_ready(info); | 3397 | tx_ready(info, tty); |
3532 | mod_timer(&info->tx_timer, jiffies + | 3398 | mod_timer(&info->tx_timer, jiffies + |
3533 | msecs_to_jiffies(5000)); | 3399 | msecs_to_jiffies(5000)); |
3534 | } | 3400 | } |
@@ -3849,13 +3715,12 @@ static void rx_reset_buffers(MGSLPC_INFO *info) | |||
3849 | * | 3715 | * |
3850 | * Returns true if frame returned, otherwise false | 3716 | * Returns true if frame returned, otherwise false |
3851 | */ | 3717 | */ |
3852 | static bool rx_get_frame(MGSLPC_INFO *info) | 3718 | static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty) |
3853 | { | 3719 | { |
3854 | unsigned short status; | 3720 | unsigned short status; |
3855 | RXBUF *buf; | 3721 | RXBUF *buf; |
3856 | unsigned int framesize = 0; | 3722 | unsigned int framesize = 0; |
3857 | unsigned long flags; | 3723 | unsigned long flags; |
3858 | struct tty_struct *tty = info->tty; | ||
3859 | bool return_frame = false; | 3724 | bool return_frame = false; |
3860 | 3725 | ||
3861 | if (info->rx_frame_count == 0) | 3726 | if (info->rx_frame_count == 0) |
@@ -4075,7 +3940,11 @@ static void tx_timeout(unsigned long context) | |||
4075 | hdlcdev_tx_done(info); | 3940 | hdlcdev_tx_done(info); |
4076 | else | 3941 | else |
4077 | #endif | 3942 | #endif |
4078 | bh_transmit(info); | 3943 | { |
3944 | struct tty_struct *tty = tty_port_tty_get(&info->port); | ||
3945 | bh_transmit(info, tty); | ||
3946 | tty_kref_put(tty); | ||
3947 | } | ||
4079 | } | 3948 | } |
4080 | 3949 | ||
4081 | #if SYNCLINK_GENERIC_HDLC | 3950 | #if SYNCLINK_GENERIC_HDLC |
@@ -4094,11 +3963,12 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, | |||
4094 | unsigned short parity) | 3963 | unsigned short parity) |
4095 | { | 3964 | { |
4096 | MGSLPC_INFO *info = dev_to_port(dev); | 3965 | MGSLPC_INFO *info = dev_to_port(dev); |
3966 | struct tty_struct *tty; | ||
4097 | unsigned char new_encoding; | 3967 | unsigned char new_encoding; |
4098 | unsigned short new_crctype; | 3968 | unsigned short new_crctype; |
4099 | 3969 | ||
4100 | /* return error if TTY interface open */ | 3970 | /* return error if TTY interface open */ |
4101 | if (info->count) | 3971 | if (info->port.count) |
4102 | return -EBUSY; | 3972 | return -EBUSY; |
4103 | 3973 | ||
4104 | switch (encoding) | 3974 | switch (encoding) |
@@ -4123,8 +3993,11 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, | |||
4123 | info->params.crc_type = new_crctype; | 3993 | info->params.crc_type = new_crctype; |
4124 | 3994 | ||
4125 | /* if network interface up, reprogram hardware */ | 3995 | /* if network interface up, reprogram hardware */ |
4126 | if (info->netcount) | 3996 | if (info->netcount) { |
4127 | mgslpc_program_hw(info); | 3997 | tty = tty_port_tty_get(&info->port); |
3998 | mgslpc_program_hw(info, tty); | ||
3999 | tty_kref_put(tty); | ||
4000 | } | ||
4128 | 4001 | ||
4129 | return 0; | 4002 | return 0; |
4130 | } | 4003 | } |
@@ -4165,8 +4038,11 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
4165 | 4038 | ||
4166 | /* start hardware transmitter if necessary */ | 4039 | /* start hardware transmitter if necessary */ |
4167 | spin_lock_irqsave(&info->lock,flags); | 4040 | spin_lock_irqsave(&info->lock,flags); |
4168 | if (!info->tx_active) | 4041 | if (!info->tx_active) { |
4169 | tx_start(info); | 4042 | struct tty_struct *tty = tty_port_tty_get(&info->port); |
4043 | tx_start(info, tty); | ||
4044 | tty_kref_put(tty); | ||
4045 | } | ||
4170 | spin_unlock_irqrestore(&info->lock,flags); | 4046 | spin_unlock_irqrestore(&info->lock,flags); |
4171 | 4047 | ||
4172 | return 0; | 4048 | return 0; |
@@ -4183,6 +4059,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
4183 | static int hdlcdev_open(struct net_device *dev) | 4059 | static int hdlcdev_open(struct net_device *dev) |
4184 | { | 4060 | { |
4185 | MGSLPC_INFO *info = dev_to_port(dev); | 4061 | MGSLPC_INFO *info = dev_to_port(dev); |
4062 | struct tty_struct *tty; | ||
4186 | int rc; | 4063 | int rc; |
4187 | unsigned long flags; | 4064 | unsigned long flags; |
4188 | 4065 | ||
@@ -4195,7 +4072,7 @@ static int hdlcdev_open(struct net_device *dev) | |||
4195 | 4072 | ||
4196 | /* arbitrate between network and tty opens */ | 4073 | /* arbitrate between network and tty opens */ |
4197 | spin_lock_irqsave(&info->netlock, flags); | 4074 | spin_lock_irqsave(&info->netlock, flags); |
4198 | if (info->count != 0 || info->netcount != 0) { | 4075 | if (info->port.count != 0 || info->netcount != 0) { |
4199 | printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); | 4076 | printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); |
4200 | spin_unlock_irqrestore(&info->netlock, flags); | 4077 | spin_unlock_irqrestore(&info->netlock, flags); |
4201 | return -EBUSY; | 4078 | return -EBUSY; |
@@ -4203,17 +4080,19 @@ static int hdlcdev_open(struct net_device *dev) | |||
4203 | info->netcount=1; | 4080 | info->netcount=1; |
4204 | spin_unlock_irqrestore(&info->netlock, flags); | 4081 | spin_unlock_irqrestore(&info->netlock, flags); |
4205 | 4082 | ||
4083 | tty = tty_port_tty_get(&info->port); | ||
4206 | /* claim resources and init adapter */ | 4084 | /* claim resources and init adapter */ |
4207 | if ((rc = startup(info)) != 0) { | 4085 | if ((rc = startup(info, tty)) != 0) { |
4086 | tty_kref_put(tty); | ||
4208 | spin_lock_irqsave(&info->netlock, flags); | 4087 | spin_lock_irqsave(&info->netlock, flags); |
4209 | info->netcount=0; | 4088 | info->netcount=0; |
4210 | spin_unlock_irqrestore(&info->netlock, flags); | 4089 | spin_unlock_irqrestore(&info->netlock, flags); |
4211 | return rc; | 4090 | return rc; |
4212 | } | 4091 | } |
4213 | |||
4214 | /* assert DTR and RTS, apply hardware settings */ | 4092 | /* assert DTR and RTS, apply hardware settings */ |
4215 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | 4093 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; |
4216 | mgslpc_program_hw(info); | 4094 | mgslpc_program_hw(info, tty); |
4095 | tty_kref_put(tty); | ||
4217 | 4096 | ||
4218 | /* enable network layer transmit */ | 4097 | /* enable network layer transmit */ |
4219 | dev->trans_start = jiffies; | 4098 | dev->trans_start = jiffies; |
@@ -4241,6 +4120,7 @@ static int hdlcdev_open(struct net_device *dev) | |||
4241 | static int hdlcdev_close(struct net_device *dev) | 4120 | static int hdlcdev_close(struct net_device *dev) |
4242 | { | 4121 | { |
4243 | MGSLPC_INFO *info = dev_to_port(dev); | 4122 | MGSLPC_INFO *info = dev_to_port(dev); |
4123 | struct tty_struct *tty = tty_port_tty_get(&info->port); | ||
4244 | unsigned long flags; | 4124 | unsigned long flags; |
4245 | 4125 | ||
4246 | if (debug_level >= DEBUG_LEVEL_INFO) | 4126 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -4249,8 +4129,8 @@ static int hdlcdev_close(struct net_device *dev) | |||
4249 | netif_stop_queue(dev); | 4129 | netif_stop_queue(dev); |
4250 | 4130 | ||
4251 | /* shutdown adapter and release resources */ | 4131 | /* shutdown adapter and release resources */ |
4252 | shutdown(info); | 4132 | shutdown(info, tty); |
4253 | 4133 | tty_kref_put(tty); | |
4254 | hdlc_close(dev); | 4134 | hdlc_close(dev); |
4255 | 4135 | ||
4256 | spin_lock_irqsave(&info->netlock, flags); | 4136 | spin_lock_irqsave(&info->netlock, flags); |
@@ -4281,7 +4161,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
4281 | printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); | 4161 | printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); |
4282 | 4162 | ||
4283 | /* return error if TTY interface open */ | 4163 | /* return error if TTY interface open */ |
4284 | if (info->count) | 4164 | if (info->port.count) |
4285 | return -EBUSY; | 4165 | return -EBUSY; |
4286 | 4166 | ||
4287 | if (cmd != SIOCWANDEV) | 4167 | if (cmd != SIOCWANDEV) |
@@ -4354,8 +4234,11 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
4354 | info->params.clock_speed = 0; | 4234 | info->params.clock_speed = 0; |
4355 | 4235 | ||
4356 | /* if network interface up, reprogram hardware */ | 4236 | /* if network interface up, reprogram hardware */ |
4357 | if (info->netcount) | 4237 | if (info->netcount) { |
4358 | mgslpc_program_hw(info); | 4238 | struct tty_struct *tty = tty_port_tty_get(&info->port); |
4239 | mgslpc_program_hw(info, tty); | ||
4240 | tty_kref_put(tty); | ||
4241 | } | ||
4359 | return 0; | 4242 | return 0; |
4360 | 4243 | ||
4361 | default: | 4244 | default: |