aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/synclink_gt.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2009-01-02 08:45:05 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-02 13:19:38 -0500
commit31f35939d1d9bcfb3099b32c67b896d2792603f9 (patch)
tree39b6ceaf0e7477e0357ff8235814f579adad3f28 /drivers/char/synclink_gt.c
parentc9b3976e3fec266be25c5001a70aa0a890b6c476 (diff)
tty_port: Add a port level carrier detect operation
This is the first step to generalising the various pieces of waiting logic duplicated in all sorts of serial drivers. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/synclink_gt.c')
-rw-r--r--drivers/char/synclink_gt.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 08911ed66494..39ccaba8ca37 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -3132,6 +3132,17 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
3132 return 0; 3132 return 0;
3133} 3133}
3134 3134
3135static int carrier_raised(struct tty_port *port)
3136{
3137 unsigned long flags;
3138 struct slgt_info *info = container_of(port, struct slgt_info, port);
3139
3140 spin_lock_irqsave(&info->lock,flags);
3141 get_signals(info);
3142 spin_unlock_irqrestore(&info->lock,flags);
3143 return (info->signals & SerialSignal_DCD) ? 1 : 0;
3144}
3145
3135/* 3146/*
3136 * block current process until the device is ready to open 3147 * block current process until the device is ready to open
3137 */ 3148 */
@@ -3143,12 +3154,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
3143 bool do_clocal = false; 3154 bool do_clocal = false;
3144 bool extra_count = false; 3155 bool extra_count = false;
3145 unsigned long flags; 3156 unsigned long flags;
3157 int cd;
3158 struct tty_port *port = &info->port;
3146 3159
3147 DBGINFO(("%s block_til_ready\n", tty->driver->name)); 3160 DBGINFO(("%s block_til_ready\n", tty->driver->name));
3148 3161
3149 if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ 3162 if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
3150 /* nonblock mode is set or port is not enabled */ 3163 /* nonblock mode is set or port is not enabled */
3151 info->port.flags |= ASYNC_NORMAL_ACTIVE; 3164 port->flags |= ASYNC_NORMAL_ACTIVE;
3152 return 0; 3165 return 0;
3153 } 3166 }
3154 3167
@@ -3157,21 +3170,21 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
3157 3170
3158 /* Wait for carrier detect and the line to become 3171 /* Wait for carrier detect and the line to become
3159 * free (i.e., not in use by the callout). While we are in 3172 * 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 3173 * this loop, port->count is dropped by one, so that
3161 * close() knows when to free things. We restore it upon 3174 * close() knows when to free things. We restore it upon
3162 * exit, either normal or abnormal. 3175 * exit, either normal or abnormal.
3163 */ 3176 */
3164 3177
3165 retval = 0; 3178 retval = 0;
3166 add_wait_queue(&info->port.open_wait, &wait); 3179 add_wait_queue(&port->open_wait, &wait);
3167 3180
3168 spin_lock_irqsave(&info->lock, flags); 3181 spin_lock_irqsave(&info->lock, flags);
3169 if (!tty_hung_up_p(filp)) { 3182 if (!tty_hung_up_p(filp)) {
3170 extra_count = true; 3183 extra_count = true;
3171 info->port.count--; 3184 port->count--;
3172 } 3185 }
3173 spin_unlock_irqrestore(&info->lock, flags); 3186 spin_unlock_irqrestore(&info->lock, flags);
3174 info->port.blocked_open++; 3187 port->blocked_open++;
3175 3188
3176 while (1) { 3189 while (1) {
3177 if ((tty->termios->c_cflag & CBAUD)) { 3190 if ((tty->termios->c_cflag & CBAUD)) {
@@ -3183,20 +3196,16 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
3183 3196
3184 set_current_state(TASK_INTERRUPTIBLE); 3197 set_current_state(TASK_INTERRUPTIBLE);
3185 3198
3186 if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ 3199 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
3187 retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? 3200 retval = (port->flags & ASYNC_HUP_NOTIFY) ?
3188 -EAGAIN : -ERESTARTSYS; 3201 -EAGAIN : -ERESTARTSYS;
3189 break; 3202 break;
3190 } 3203 }
3191 3204
3192 spin_lock_irqsave(&info->lock,flags); 3205 cd = tty_port_carrier_raised(port);
3193 get_signals(info);
3194 spin_unlock_irqrestore(&info->lock,flags);
3195 3206
3196 if (!(info->port.flags & ASYNC_CLOSING) && 3207 if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
3197 (do_clocal || (info->signals & SerialSignal_DCD)) ) {
3198 break; 3208 break;
3199 }
3200 3209
3201 if (signal_pending(current)) { 3210 if (signal_pending(current)) {
3202 retval = -ERESTARTSYS; 3211 retval = -ERESTARTSYS;
@@ -3208,14 +3217,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
3208 } 3217 }
3209 3218
3210 set_current_state(TASK_RUNNING); 3219 set_current_state(TASK_RUNNING);
3211 remove_wait_queue(&info->port.open_wait, &wait); 3220 remove_wait_queue(&port->open_wait, &wait);
3212 3221
3213 if (extra_count) 3222 if (extra_count)
3214 info->port.count++; 3223 port->count++;
3215 info->port.blocked_open--; 3224 port->blocked_open--;
3216 3225
3217 if (!retval) 3226 if (!retval)
3218 info->port.flags |= ASYNC_NORMAL_ACTIVE; 3227 port->flags |= ASYNC_NORMAL_ACTIVE;
3219 3228
3220 DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); 3229 DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval));
3221 return retval; 3230 return retval;
@@ -3444,6 +3453,10 @@ static void add_device(struct slgt_info *info)
3444#endif 3453#endif
3445} 3454}
3446 3455
3456static const struct tty_port_operations slgt_port_ops = {
3457 .carrier_raised = carrier_raised,
3458};
3459
3447/* 3460/*
3448 * allocate device instance structure, return NULL on failure 3461 * allocate device instance structure, return NULL on failure
3449 */ 3462 */
@@ -3458,6 +3471,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
3458 driver_name, adapter_num, port_num)); 3471 driver_name, adapter_num, port_num));
3459 } else { 3472 } else {
3460 tty_port_init(&info->port); 3473 tty_port_init(&info->port);
3474 info->port.ops = &slgt_port_ops;
3461 info->magic = MGSL_MAGIC; 3475 info->magic = MGSL_MAGIC;
3462 INIT_WORK(&info->task, bh_handler); 3476 INIT_WORK(&info->task, bh_handler);
3463 info->max_frame_size = 4096; 3477 info->max_frame_size = 4096;