diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:45:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:38 -0500 |
commit | 31f35939d1d9bcfb3099b32c67b896d2792603f9 (patch) | |
tree | 39b6ceaf0e7477e0357ff8235814f579adad3f28 /drivers/char/synclinkmp.c | |
parent | c9b3976e3fec266be25c5001a70aa0a890b6c476 (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/synclinkmp.c')
-rw-r--r-- | drivers/char/synclinkmp.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 6bdb44f7bec2..fcf1ec77450d 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -558,6 +558,7 @@ static void release_resources(SLMP_INFO *info); | |||
558 | 558 | ||
559 | static int startup(SLMP_INFO *info); | 559 | static int startup(SLMP_INFO *info); |
560 | static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info); | 560 | static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info); |
561 | static int carrier_raised(struct tty_port *port); | ||
561 | static void shutdown(SLMP_INFO *info); | 562 | static void shutdown(SLMP_INFO *info); |
562 | static void program_hw(SLMP_INFO *info); | 563 | static void program_hw(SLMP_INFO *info); |
563 | static void change_params(SLMP_INFO *info); | 564 | static void change_params(SLMP_INFO *info); |
@@ -3318,7 +3319,17 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
3318 | return 0; | 3319 | return 0; |
3319 | } | 3320 | } |
3320 | 3321 | ||
3322 | static int carrier_raised(struct tty_port *port) | ||
3323 | { | ||
3324 | SLMP_INFO *info = container_of(port, SLMP_INFO, port); | ||
3325 | unsigned long flags; | ||
3321 | 3326 | ||
3327 | spin_lock_irqsave(&info->lock,flags); | ||
3328 | get_signals(info); | ||
3329 | spin_unlock_irqrestore(&info->lock,flags); | ||
3330 | |||
3331 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; | ||
3332 | } | ||
3322 | 3333 | ||
3323 | /* Block the current process until the specified port is ready to open. | 3334 | /* Block the current process until the specified port is ready to open. |
3324 | */ | 3335 | */ |
@@ -3330,6 +3341,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3330 | bool do_clocal = false; | 3341 | bool do_clocal = false; |
3331 | bool extra_count = false; | 3342 | bool extra_count = false; |
3332 | unsigned long flags; | 3343 | unsigned long flags; |
3344 | int cd; | ||
3345 | struct tty_port *port = &info->port; | ||
3333 | 3346 | ||
3334 | if (debug_level >= DEBUG_LEVEL_INFO) | 3347 | if (debug_level >= DEBUG_LEVEL_INFO) |
3335 | printk("%s(%d):%s block_til_ready()\n", | 3348 | printk("%s(%d):%s block_til_ready()\n", |
@@ -3338,7 +3351,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3338 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | 3351 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ |
3339 | /* nonblock mode is set or port is not enabled */ | 3352 | /* nonblock mode is set or port is not enabled */ |
3340 | /* just verify that callout device is not active */ | 3353 | /* just verify that callout device is not active */ |
3341 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3354 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3342 | return 0; | 3355 | return 0; |
3343 | } | 3356 | } |
3344 | 3357 | ||
@@ -3347,25 +3360,25 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3347 | 3360 | ||
3348 | /* Wait for carrier detect and the line to become | 3361 | /* Wait for carrier detect and the line to become |
3349 | * free (i.e., not in use by the callout). While we are in | 3362 | * free (i.e., not in use by the callout). While we are in |
3350 | * this loop, info->port.count is dropped by one, so that | 3363 | * this loop, port->count is dropped by one, so that |
3351 | * close() knows when to free things. We restore it upon | 3364 | * close() knows when to free things. We restore it upon |
3352 | * exit, either normal or abnormal. | 3365 | * exit, either normal or abnormal. |
3353 | */ | 3366 | */ |
3354 | 3367 | ||
3355 | retval = 0; | 3368 | retval = 0; |
3356 | add_wait_queue(&info->port.open_wait, &wait); | 3369 | add_wait_queue(&port->open_wait, &wait); |
3357 | 3370 | ||
3358 | if (debug_level >= DEBUG_LEVEL_INFO) | 3371 | if (debug_level >= DEBUG_LEVEL_INFO) |
3359 | printk("%s(%d):%s block_til_ready() before block, count=%d\n", | 3372 | printk("%s(%d):%s block_til_ready() before block, count=%d\n", |
3360 | __FILE__,__LINE__, tty->driver->name, info->port.count ); | 3373 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3361 | 3374 | ||
3362 | spin_lock_irqsave(&info->lock, flags); | 3375 | spin_lock_irqsave(&info->lock, flags); |
3363 | if (!tty_hung_up_p(filp)) { | 3376 | if (!tty_hung_up_p(filp)) { |
3364 | extra_count = true; | 3377 | extra_count = true; |
3365 | info->port.count--; | 3378 | port->count--; |
3366 | } | 3379 | } |
3367 | spin_unlock_irqrestore(&info->lock, flags); | 3380 | spin_unlock_irqrestore(&info->lock, flags); |
3368 | info->port.blocked_open++; | 3381 | port->blocked_open++; |
3369 | 3382 | ||
3370 | while (1) { | 3383 | while (1) { |
3371 | if ((tty->termios->c_cflag & CBAUD)) { | 3384 | if ((tty->termios->c_cflag & CBAUD)) { |
@@ -3377,20 +3390,16 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3377 | 3390 | ||
3378 | set_current_state(TASK_INTERRUPTIBLE); | 3391 | set_current_state(TASK_INTERRUPTIBLE); |
3379 | 3392 | ||
3380 | if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ | 3393 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ |
3381 | retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? | 3394 | retval = (port->flags & ASYNC_HUP_NOTIFY) ? |
3382 | -EAGAIN : -ERESTARTSYS; | 3395 | -EAGAIN : -ERESTARTSYS; |
3383 | break; | 3396 | break; |
3384 | } | 3397 | } |
3385 | 3398 | ||
3386 | spin_lock_irqsave(&info->lock,flags); | 3399 | cd = tty_port_carrier_raised(port); |
3387 | get_signals(info); | ||
3388 | spin_unlock_irqrestore(&info->lock,flags); | ||
3389 | 3400 | ||
3390 | if (!(info->port.flags & ASYNC_CLOSING) && | 3401 | if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd)) |
3391 | (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) { | ||
3392 | break; | 3402 | break; |
3393 | } | ||
3394 | 3403 | ||
3395 | if (signal_pending(current)) { | 3404 | if (signal_pending(current)) { |
3396 | retval = -ERESTARTSYS; | 3405 | retval = -ERESTARTSYS; |
@@ -3399,24 +3408,24 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3399 | 3408 | ||
3400 | if (debug_level >= DEBUG_LEVEL_INFO) | 3409 | if (debug_level >= DEBUG_LEVEL_INFO) |
3401 | printk("%s(%d):%s block_til_ready() count=%d\n", | 3410 | printk("%s(%d):%s block_til_ready() count=%d\n", |
3402 | __FILE__,__LINE__, tty->driver->name, info->port.count ); | 3411 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3403 | 3412 | ||
3404 | schedule(); | 3413 | schedule(); |
3405 | } | 3414 | } |
3406 | 3415 | ||
3407 | set_current_state(TASK_RUNNING); | 3416 | set_current_state(TASK_RUNNING); |
3408 | remove_wait_queue(&info->port.open_wait, &wait); | 3417 | remove_wait_queue(&port->open_wait, &wait); |
3409 | 3418 | ||
3410 | if (extra_count) | 3419 | if (extra_count) |
3411 | info->port.count++; | 3420 | port->count++; |
3412 | info->port.blocked_open--; | 3421 | port->blocked_open--; |
3413 | 3422 | ||
3414 | if (debug_level >= DEBUG_LEVEL_INFO) | 3423 | if (debug_level >= DEBUG_LEVEL_INFO) |
3415 | printk("%s(%d):%s block_til_ready() after, count=%d\n", | 3424 | printk("%s(%d):%s block_til_ready() after, count=%d\n", |
3416 | __FILE__,__LINE__, tty->driver->name, info->port.count ); | 3425 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3417 | 3426 | ||
3418 | if (!retval) | 3427 | if (!retval) |
3419 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3428 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3420 | 3429 | ||
3421 | return retval; | 3430 | return retval; |
3422 | } | 3431 | } |
@@ -3782,6 +3791,10 @@ static void add_device(SLMP_INFO *info) | |||
3782 | #endif | 3791 | #endif |
3783 | } | 3792 | } |
3784 | 3793 | ||
3794 | static const struct tty_port_operations port_ops = { | ||
3795 | .carrier_raised = carrier_raised, | ||
3796 | }; | ||
3797 | |||
3785 | /* Allocate and initialize a device instance structure | 3798 | /* Allocate and initialize a device instance structure |
3786 | * | 3799 | * |
3787 | * Return Value: pointer to SLMP_INFO if success, otherwise NULL | 3800 | * Return Value: pointer to SLMP_INFO if success, otherwise NULL |
@@ -3798,6 +3811,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) | |||
3798 | __FILE__,__LINE__, adapter_num, port_num); | 3811 | __FILE__,__LINE__, adapter_num, port_num); |
3799 | } else { | 3812 | } else { |
3800 | tty_port_init(&info->port); | 3813 | tty_port_init(&info->port); |
3814 | info->port.ops = &port_ops; | ||
3801 | info->magic = MGSL_MAGIC; | 3815 | info->magic = MGSL_MAGIC; |
3802 | INIT_WORK(&info->task, bh_handler); | 3816 | INIT_WORK(&info->task, bh_handler); |
3803 | info->max_frame_size = 4096; | 3817 | info->max_frame_size = 4096; |
@@ -3940,6 +3954,7 @@ static const struct tty_operations ops = { | |||
3940 | .tiocmset = tiocmset, | 3954 | .tiocmset = tiocmset, |
3941 | }; | 3955 | }; |
3942 | 3956 | ||
3957 | |||
3943 | static void synclinkmp_cleanup(void) | 3958 | static void synclinkmp_cleanup(void) |
3944 | { | 3959 | { |
3945 | int rc; | 3960 | int rc; |