aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/synclink.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.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.c')
-rw-r--r--drivers/char/synclink.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 500f5176b6ba..fb2e6b5e0ef1 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -3281,6 +3281,23 @@ static void mgsl_hangup(struct tty_struct *tty)
3281 3281
3282} /* end of mgsl_hangup() */ 3282} /* end of mgsl_hangup() */
3283 3283
3284/*
3285 * carrier_raised()
3286 *
3287 * Return true if carrier is raised
3288 */
3289
3290static int carrier_raised(struct tty_port *port)
3291{
3292 unsigned long flags;
3293 struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
3294
3295 spin_lock_irqsave(&info->irq_spinlock, flags);
3296 usc_get_serial_signals(info);
3297 spin_unlock_irqrestore(&info->irq_spinlock, flags);
3298 return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
3299}
3300
3284/* block_til_ready() 3301/* block_til_ready()
3285 * 3302 *
3286 * Block the current process until the specified port 3303 * Block the current process until the specified port
@@ -3302,6 +3319,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
3302 bool do_clocal = false; 3319 bool do_clocal = false;
3303 bool extra_count = false; 3320 bool extra_count = false;
3304 unsigned long flags; 3321 unsigned long flags;
3322 int dcd;
3323 struct tty_port *port = &info->port;
3305 3324
3306 if (debug_level >= DEBUG_LEVEL_INFO) 3325 if (debug_level >= DEBUG_LEVEL_INFO)
3307 printk("%s(%d):block_til_ready on %s\n", 3326 printk("%s(%d):block_til_ready on %s\n",
@@ -3309,7 +3328,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
3309 3328
3310 if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ 3329 if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
3311 /* nonblock mode is set or port is not enabled */ 3330 /* nonblock mode is set or port is not enabled */
3312 info->port.flags |= ASYNC_NORMAL_ACTIVE; 3331 port->flags |= ASYNC_NORMAL_ACTIVE;
3313 return 0; 3332 return 0;
3314 } 3333 }
3315 3334
@@ -3318,25 +3337,25 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
3318 3337
3319 /* Wait for carrier detect and the line to become 3338 /* Wait for carrier detect and the line to become
3320 * free (i.e., not in use by the callout). While we are in 3339 * free (i.e., not in use by the callout). While we are in
3321 * this loop, info->port.count is dropped by one, so that 3340 * this loop, port->count is dropped by one, so that
3322 * mgsl_close() knows when to free things. We restore it upon 3341 * mgsl_close() knows when to free things. We restore it upon
3323 * exit, either normal or abnormal. 3342 * exit, either normal or abnormal.
3324 */ 3343 */
3325 3344
3326 retval = 0; 3345 retval = 0;
3327 add_wait_queue(&info->port.open_wait, &wait); 3346 add_wait_queue(&port->open_wait, &wait);
3328 3347
3329 if (debug_level >= DEBUG_LEVEL_INFO) 3348 if (debug_level >= DEBUG_LEVEL_INFO)
3330 printk("%s(%d):block_til_ready before block on %s count=%d\n", 3349 printk("%s(%d):block_til_ready before block on %s count=%d\n",
3331 __FILE__,__LINE__, tty->driver->name, info->port.count ); 3350 __FILE__,__LINE__, tty->driver->name, port->count );
3332 3351
3333 spin_lock_irqsave(&info->irq_spinlock, flags); 3352 spin_lock_irqsave(&info->irq_spinlock, flags);
3334 if (!tty_hung_up_p(filp)) { 3353 if (!tty_hung_up_p(filp)) {
3335 extra_count = true; 3354 extra_count = true;
3336 info->port.count--; 3355 port->count--;
3337 } 3356 }
3338 spin_unlock_irqrestore(&info->irq_spinlock, flags); 3357 spin_unlock_irqrestore(&info->irq_spinlock, flags);
3339 info->port.blocked_open++; 3358 port->blocked_open++;
3340 3359
3341 while (1) { 3360 while (1) {
3342 if (tty->termios->c_cflag & CBAUD) { 3361 if (tty->termios->c_cflag & CBAUD) {
@@ -3348,20 +3367,16 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
3348 3367
3349 set_current_state(TASK_INTERRUPTIBLE); 3368 set_current_state(TASK_INTERRUPTIBLE);
3350 3369
3351 if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ 3370 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
3352 retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? 3371 retval = (port->flags & ASYNC_HUP_NOTIFY) ?
3353 -EAGAIN : -ERESTARTSYS; 3372 -EAGAIN : -ERESTARTSYS;
3354 break; 3373 break;
3355 } 3374 }
3356 3375
3357 spin_lock_irqsave(&info->irq_spinlock,flags); 3376 dcd = tty_port_carrier_raised(&info->port);
3358 usc_get_serial_signals(info);
3359 spin_unlock_irqrestore(&info->irq_spinlock,flags);
3360 3377
3361 if (!(info->port.flags & ASYNC_CLOSING) && 3378 if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd))
3362 (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) {
3363 break; 3379 break;
3364 }
3365 3380
3366 if (signal_pending(current)) { 3381 if (signal_pending(current)) {
3367 retval = -ERESTARTSYS; 3382 retval = -ERESTARTSYS;
@@ -3370,24 +3385,24 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
3370 3385
3371 if (debug_level >= DEBUG_LEVEL_INFO) 3386 if (debug_level >= DEBUG_LEVEL_INFO)
3372 printk("%s(%d):block_til_ready blocking on %s count=%d\n", 3387 printk("%s(%d):block_til_ready blocking on %s count=%d\n",
3373 __FILE__,__LINE__, tty->driver->name, info->port.count ); 3388 __FILE__,__LINE__, tty->driver->name, port->count );
3374 3389
3375 schedule(); 3390 schedule();
3376 } 3391 }
3377 3392
3378 set_current_state(TASK_RUNNING); 3393 set_current_state(TASK_RUNNING);
3379 remove_wait_queue(&info->port.open_wait, &wait); 3394 remove_wait_queue(&port->open_wait, &wait);
3380 3395
3381 if (extra_count) 3396 if (extra_count)
3382 info->port.count++; 3397 port->count++;
3383 info->port.blocked_open--; 3398 port->blocked_open--;
3384 3399
3385 if (debug_level >= DEBUG_LEVEL_INFO) 3400 if (debug_level >= DEBUG_LEVEL_INFO)
3386 printk("%s(%d):block_til_ready after blocking on %s count=%d\n", 3401 printk("%s(%d):block_til_ready after blocking on %s count=%d\n",
3387 __FILE__,__LINE__, tty->driver->name, info->port.count ); 3402 __FILE__,__LINE__, tty->driver->name, port->count );
3388 3403
3389 if (!retval) 3404 if (!retval)
3390 info->port.flags |= ASYNC_NORMAL_ACTIVE; 3405 port->flags |= ASYNC_NORMAL_ACTIVE;
3391 3406
3392 return retval; 3407 return retval;
3393 3408
@@ -4304,6 +4319,11 @@ static void mgsl_add_device( struct mgsl_struct *info )
4304 4319
4305} /* end of mgsl_add_device() */ 4320} /* end of mgsl_add_device() */
4306 4321
4322static const struct tty_port_operations mgsl_port_ops = {
4323 .carrier_raised = carrier_raised,
4324};
4325
4326
4307/* mgsl_allocate_device() 4327/* mgsl_allocate_device()
4308 * 4328 *
4309 * Allocate and initialize a device instance structure 4329 * Allocate and initialize a device instance structure
@@ -4322,6 +4342,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
4322 printk("Error can't allocate device instance data\n"); 4342 printk("Error can't allocate device instance data\n");
4323 } else { 4343 } else {
4324 tty_port_init(&info->port); 4344 tty_port_init(&info->port);
4345 info->port.ops = &mgsl_port_ops;
4325 info->magic = MGSL_MAGIC; 4346 info->magic = MGSL_MAGIC;
4326 INIT_WORK(&info->task, mgsl_bh_handler); 4347 INIT_WORK(&info->task, mgsl_bh_handler);
4327 info->max_frame_size = 4096; 4348 info->max_frame_size = 4096;