diff options
Diffstat (limited to 'drivers/char/synclink_gt.c')
-rw-r--r-- | drivers/char/synclink_gt.c | 120 |
1 files changed, 48 insertions, 72 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 08911ed66494..53544e21f191 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -720,44 +720,9 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
720 | return; | 720 | return; |
721 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); | 721 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); |
722 | 722 | ||
723 | if (!info->port.count) | 723 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
724 | return; | ||
725 | |||
726 | if (tty_hung_up_p(filp)) | ||
727 | goto cleanup; | ||
728 | |||
729 | if ((tty->count == 1) && (info->port.count != 1)) { | ||
730 | /* | ||
731 | * tty->count is 1 and the tty structure will be freed. | ||
732 | * info->port.count should be one in this case. | ||
733 | * if it's not, correct it so that the port is shutdown. | ||
734 | */ | ||
735 | DBGERR(("%s close: bad refcount; tty->count=1, " | ||
736 | "info->port.count=%d\n", info->device_name, info->port.count)); | ||
737 | info->port.count = 1; | ||
738 | } | ||
739 | |||
740 | info->port.count--; | ||
741 | |||
742 | /* if at least one open remaining, leave hardware active */ | ||
743 | if (info->port.count) | ||
744 | goto cleanup; | 724 | goto cleanup; |
745 | 725 | ||
746 | info->port.flags |= ASYNC_CLOSING; | ||
747 | |||
748 | /* set tty->closing to notify line discipline to | ||
749 | * only process XON/XOFF characters. Only the N_TTY | ||
750 | * discipline appears to use this (ppp does not). | ||
751 | */ | ||
752 | tty->closing = 1; | ||
753 | |||
754 | /* wait for transmit data to clear all layers */ | ||
755 | |||
756 | if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { | ||
757 | DBGINFO(("%s call tty_wait_until_sent\n", info->device_name)); | ||
758 | tty_wait_until_sent(tty, info->port.closing_wait); | ||
759 | } | ||
760 | |||
761 | if (info->port.flags & ASYNC_INITIALIZED) | 726 | if (info->port.flags & ASYNC_INITIALIZED) |
762 | wait_until_sent(tty, info->timeout); | 727 | wait_until_sent(tty, info->timeout); |
763 | flush_buffer(tty); | 728 | flush_buffer(tty); |
@@ -765,20 +730,8 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
765 | 730 | ||
766 | shutdown(info); | 731 | shutdown(info); |
767 | 732 | ||
768 | tty->closing = 0; | 733 | tty_port_close_end(&info->port, tty); |
769 | info->port.tty = NULL; | 734 | info->port.tty = NULL; |
770 | |||
771 | if (info->port.blocked_open) { | ||
772 | if (info->port.close_delay) { | ||
773 | msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); | ||
774 | } | ||
775 | wake_up_interruptible(&info->port.open_wait); | ||
776 | } | ||
777 | |||
778 | info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
779 | |||
780 | wake_up_interruptible(&info->port.close_wait); | ||
781 | |||
782 | cleanup: | 735 | cleanup: |
783 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); | 736 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); |
784 | } | 737 | } |
@@ -3132,6 +3085,29 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
3132 | return 0; | 3085 | return 0; |
3133 | } | 3086 | } |
3134 | 3087 | ||
3088 | static int carrier_raised(struct tty_port *port) | ||
3089 | { | ||
3090 | unsigned long flags; | ||
3091 | struct slgt_info *info = container_of(port, struct slgt_info, port); | ||
3092 | |||
3093 | spin_lock_irqsave(&info->lock,flags); | ||
3094 | get_signals(info); | ||
3095 | spin_unlock_irqrestore(&info->lock,flags); | ||
3096 | return (info->signals & SerialSignal_DCD) ? 1 : 0; | ||
3097 | } | ||
3098 | |||
3099 | static void raise_dtr_rts(struct tty_port *port) | ||
3100 | { | ||
3101 | unsigned long flags; | ||
3102 | struct slgt_info *info = container_of(port, struct slgt_info, port); | ||
3103 | |||
3104 | spin_lock_irqsave(&info->lock,flags); | ||
3105 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3106 | set_signals(info); | ||
3107 | spin_unlock_irqrestore(&info->lock,flags); | ||
3108 | } | ||
3109 | |||
3110 | |||
3135 | /* | 3111 | /* |
3136 | * block current process until the device is ready to open | 3112 | * block current process until the device is ready to open |
3137 | */ | 3113 | */ |
@@ -3143,12 +3119,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3143 | bool do_clocal = false; | 3119 | bool do_clocal = false; |
3144 | bool extra_count = false; | 3120 | bool extra_count = false; |
3145 | unsigned long flags; | 3121 | unsigned long flags; |
3122 | int cd; | ||
3123 | struct tty_port *port = &info->port; | ||
3146 | 3124 | ||
3147 | DBGINFO(("%s block_til_ready\n", tty->driver->name)); | 3125 | DBGINFO(("%s block_til_ready\n", tty->driver->name)); |
3148 | 3126 | ||
3149 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | 3127 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ |
3150 | /* nonblock mode is set or port is not enabled */ | 3128 | /* nonblock mode is set or port is not enabled */ |
3151 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3129 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3152 | return 0; | 3130 | return 0; |
3153 | } | 3131 | } |
3154 | 3132 | ||
@@ -3157,46 +3135,38 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3157 | 3135 | ||
3158 | /* Wait for carrier detect and the line to become | 3136 | /* Wait for carrier detect and the line to become |
3159 | * free (i.e., not in use by the callout). While we are in | 3137 | * free (i.e., not in use by the callout). While we are in |
3160 | * this loop, info->port.count is dropped by one, so that | 3138 | * this loop, port->count is dropped by one, so that |
3161 | * close() knows when to free things. We restore it upon | 3139 | * close() knows when to free things. We restore it upon |
3162 | * exit, either normal or abnormal. | 3140 | * exit, either normal or abnormal. |
3163 | */ | 3141 | */ |
3164 | 3142 | ||
3165 | retval = 0; | 3143 | retval = 0; |
3166 | add_wait_queue(&info->port.open_wait, &wait); | 3144 | add_wait_queue(&port->open_wait, &wait); |
3167 | 3145 | ||
3168 | spin_lock_irqsave(&info->lock, flags); | 3146 | spin_lock_irqsave(&info->lock, flags); |
3169 | if (!tty_hung_up_p(filp)) { | 3147 | if (!tty_hung_up_p(filp)) { |
3170 | extra_count = true; | 3148 | extra_count = true; |
3171 | info->port.count--; | 3149 | port->count--; |
3172 | } | 3150 | } |
3173 | spin_unlock_irqrestore(&info->lock, flags); | 3151 | spin_unlock_irqrestore(&info->lock, flags); |
3174 | info->port.blocked_open++; | 3152 | port->blocked_open++; |
3175 | 3153 | ||
3176 | while (1) { | 3154 | while (1) { |
3177 | if ((tty->termios->c_cflag & CBAUD)) { | 3155 | if ((tty->termios->c_cflag & CBAUD)) |
3178 | spin_lock_irqsave(&info->lock,flags); | 3156 | tty_port_raise_dtr_rts(port); |
3179 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3180 | set_signals(info); | ||
3181 | spin_unlock_irqrestore(&info->lock,flags); | ||
3182 | } | ||
3183 | 3157 | ||
3184 | set_current_state(TASK_INTERRUPTIBLE); | 3158 | set_current_state(TASK_INTERRUPTIBLE); |
3185 | 3159 | ||
3186 | if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ | 3160 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ |
3187 | retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? | 3161 | retval = (port->flags & ASYNC_HUP_NOTIFY) ? |
3188 | -EAGAIN : -ERESTARTSYS; | 3162 | -EAGAIN : -ERESTARTSYS; |
3189 | break; | 3163 | break; |
3190 | } | 3164 | } |
3191 | 3165 | ||
3192 | spin_lock_irqsave(&info->lock,flags); | 3166 | cd = tty_port_carrier_raised(port); |
3193 | get_signals(info); | ||
3194 | spin_unlock_irqrestore(&info->lock,flags); | ||
3195 | 3167 | ||
3196 | if (!(info->port.flags & ASYNC_CLOSING) && | 3168 | if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd )) |
3197 | (do_clocal || (info->signals & SerialSignal_DCD)) ) { | ||
3198 | break; | 3169 | break; |
3199 | } | ||
3200 | 3170 | ||
3201 | if (signal_pending(current)) { | 3171 | if (signal_pending(current)) { |
3202 | retval = -ERESTARTSYS; | 3172 | retval = -ERESTARTSYS; |
@@ -3208,14 +3178,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3208 | } | 3178 | } |
3209 | 3179 | ||
3210 | set_current_state(TASK_RUNNING); | 3180 | set_current_state(TASK_RUNNING); |
3211 | remove_wait_queue(&info->port.open_wait, &wait); | 3181 | remove_wait_queue(&port->open_wait, &wait); |
3212 | 3182 | ||
3213 | if (extra_count) | 3183 | if (extra_count) |
3214 | info->port.count++; | 3184 | port->count++; |
3215 | info->port.blocked_open--; | 3185 | port->blocked_open--; |
3216 | 3186 | ||
3217 | if (!retval) | 3187 | if (!retval) |
3218 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3188 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3219 | 3189 | ||
3220 | DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); | 3190 | DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); |
3221 | return retval; | 3191 | return retval; |
@@ -3444,6 +3414,11 @@ static void add_device(struct slgt_info *info) | |||
3444 | #endif | 3414 | #endif |
3445 | } | 3415 | } |
3446 | 3416 | ||
3417 | static const struct tty_port_operations slgt_port_ops = { | ||
3418 | .carrier_raised = carrier_raised, | ||
3419 | .raise_dtr_rts = raise_dtr_rts, | ||
3420 | }; | ||
3421 | |||
3447 | /* | 3422 | /* |
3448 | * allocate device instance structure, return NULL on failure | 3423 | * allocate device instance structure, return NULL on failure |
3449 | */ | 3424 | */ |
@@ -3458,6 +3433,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev | |||
3458 | driver_name, adapter_num, port_num)); | 3433 | driver_name, adapter_num, port_num)); |
3459 | } else { | 3434 | } else { |
3460 | tty_port_init(&info->port); | 3435 | tty_port_init(&info->port); |
3436 | info->port.ops = &slgt_port_ops; | ||
3461 | info->magic = MGSL_MAGIC; | 3437 | info->magic = MGSL_MAGIC; |
3462 | INIT_WORK(&info->task, bh_handler); | 3438 | INIT_WORK(&info->task, bh_handler); |
3463 | info->max_frame_size = 4096; | 3439 | info->max_frame_size = 4096; |