diff options
author | Jiri Slaby <jslaby@suse.cz> | 2012-06-04 07:35:20 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-12 18:50:23 -0400 |
commit | e673927d8a210ab1db27047080fc1bdb47f7e372 (patch) | |
tree | c817dc32bbc54e323909004a098fd29d16ee1ffb /net/irda | |
parent | 849d5a997fe6a9e44401daed62a98121390ec0d3 (diff) |
TTY: ircomm, revamp locking
Use self->spinlock only for ctrl_skb and tx_skb. TTY stuff is now
protected by tty_port->lock. This is needed for further cleanup (and
conversion to tty_port helpers).
This also closes the race in the end of close.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Samuel Ortiz <samuel@sortiz.org>
Cc: netdev@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/irda')
-rw-r--r-- | net/irda/ircomm/ircomm_tty.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 8e61026b9dd4..7b2152cfd42a 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c | |||
@@ -283,13 +283,12 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | |||
283 | IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n", | 283 | IRDA_DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n", |
284 | __FILE__, __LINE__, tty->driver->name, self->port.count); | 284 | __FILE__, __LINE__, tty->driver->name, self->port.count); |
285 | 285 | ||
286 | /* As far as I can see, we protect port.count - Jean II */ | 286 | spin_lock_irqsave(&self->port.lock, flags); |
287 | spin_lock_irqsave(&self->spinlock, flags); | ||
288 | if (!tty_hung_up_p(filp)) { | 287 | if (!tty_hung_up_p(filp)) { |
289 | extra_count = 1; | 288 | extra_count = 1; |
290 | self->port.count--; | 289 | self->port.count--; |
291 | } | 290 | } |
292 | spin_unlock_irqrestore(&self->spinlock, flags); | 291 | spin_unlock_irqrestore(&self->port.lock, flags); |
293 | self->port.blocked_open++; | 292 | self->port.blocked_open++; |
294 | 293 | ||
295 | while (1) { | 294 | while (1) { |
@@ -340,9 +339,9 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | |||
340 | 339 | ||
341 | if (extra_count) { | 340 | if (extra_count) { |
342 | /* ++ is not atomic, so this should be protected - Jean II */ | 341 | /* ++ is not atomic, so this should be protected - Jean II */ |
343 | spin_lock_irqsave(&self->spinlock, flags); | 342 | spin_lock_irqsave(&self->port.lock, flags); |
344 | self->port.count++; | 343 | self->port.count++; |
345 | spin_unlock_irqrestore(&self->spinlock, flags); | 344 | spin_unlock_irqrestore(&self->port.lock, flags); |
346 | } | 345 | } |
347 | self->port.blocked_open--; | 346 | self->port.blocked_open--; |
348 | 347 | ||
@@ -409,12 +408,12 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
409 | hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL); | 408 | hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL); |
410 | } | 409 | } |
411 | /* ++ is not atomic, so this should be protected - Jean II */ | 410 | /* ++ is not atomic, so this should be protected - Jean II */ |
412 | spin_lock_irqsave(&self->spinlock, flags); | 411 | spin_lock_irqsave(&self->port.lock, flags); |
413 | self->port.count++; | 412 | self->port.count++; |
414 | 413 | ||
415 | tty->driver_data = self; | 414 | tty->driver_data = self; |
416 | self->tty = tty; | 415 | self->tty = tty; |
417 | spin_unlock_irqrestore(&self->spinlock, flags); | 416 | spin_unlock_irqrestore(&self->port.lock, flags); |
418 | 417 | ||
419 | IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name, | 418 | IRDA_DEBUG(1, "%s(), %s%d, count = %d\n", __func__ , tty->driver->name, |
420 | self->line, self->port.count); | 419 | self->line, self->port.count); |
@@ -495,10 +494,10 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) | |||
495 | IRDA_ASSERT(self != NULL, return;); | 494 | IRDA_ASSERT(self != NULL, return;); |
496 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); | 495 | IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); |
497 | 496 | ||
498 | spin_lock_irqsave(&self->spinlock, flags); | 497 | spin_lock_irqsave(&self->port.lock, flags); |
499 | 498 | ||
500 | if (tty_hung_up_p(filp)) { | 499 | if (tty_hung_up_p(filp)) { |
501 | spin_unlock_irqrestore(&self->spinlock, flags); | 500 | spin_unlock_irqrestore(&self->port.lock, flags); |
502 | 501 | ||
503 | IRDA_DEBUG(0, "%s(), returning 1\n", __func__ ); | 502 | IRDA_DEBUG(0, "%s(), returning 1\n", __func__ ); |
504 | return; | 503 | return; |
@@ -524,20 +523,15 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) | |||
524 | self->port.count = 0; | 523 | self->port.count = 0; |
525 | } | 524 | } |
526 | if (self->port.count) { | 525 | if (self->port.count) { |
527 | spin_unlock_irqrestore(&self->spinlock, flags); | 526 | spin_unlock_irqrestore(&self->port.lock, flags); |
528 | 527 | ||
529 | IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ ); | 528 | IRDA_DEBUG(0, "%s(), open count > 0\n", __func__ ); |
530 | return; | 529 | return; |
531 | } | 530 | } |
532 | 531 | ||
533 | /* Hum... Should be test_and_set_bit ??? - Jean II */ | ||
534 | set_bit(ASYNCB_CLOSING, &self->port.flags); | 532 | set_bit(ASYNCB_CLOSING, &self->port.flags); |
535 | 533 | ||
536 | /* We need to unlock here (we were unlocking at the end of this | 534 | spin_unlock_irqrestore(&self->port.lock, flags); |
537 | * function), because tty_wait_until_sent() may schedule. | ||
538 | * I don't know if the rest should be protected somehow, | ||
539 | * so someone should check. - Jean II */ | ||
540 | spin_unlock_irqrestore(&self->spinlock, flags); | ||
541 | 535 | ||
542 | /* | 536 | /* |
543 | * Now we wait for the transmit buffer to clear; and we notify | 537 | * Now we wait for the transmit buffer to clear; and we notify |
@@ -552,16 +546,21 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) | |||
552 | tty_driver_flush_buffer(tty); | 546 | tty_driver_flush_buffer(tty); |
553 | tty_ldisc_flush(tty); | 547 | tty_ldisc_flush(tty); |
554 | 548 | ||
549 | spin_lock_irqsave(&self->port.lock, flags); | ||
555 | tty->closing = 0; | 550 | tty->closing = 0; |
556 | self->tty = NULL; | 551 | self->tty = NULL; |
557 | 552 | ||
558 | if (self->port.blocked_open) { | 553 | if (self->port.blocked_open) { |
559 | if (self->port.close_delay) | 554 | if (self->port.close_delay) { |
555 | spin_unlock_irqrestore(&self->port.lock, flags); | ||
560 | schedule_timeout_interruptible(self->port.close_delay); | 556 | schedule_timeout_interruptible(self->port.close_delay); |
557 | spin_lock_irqsave(&self->port.lock, flags); | ||
558 | } | ||
561 | wake_up_interruptible(&self->port.open_wait); | 559 | wake_up_interruptible(&self->port.open_wait); |
562 | } | 560 | } |
563 | 561 | ||
564 | self->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 562 | self->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
563 | spin_unlock_irqrestore(&self->port.lock, flags); | ||
565 | wake_up_interruptible(&self->port.close_wait); | 564 | wake_up_interruptible(&self->port.close_wait); |
566 | } | 565 | } |
567 | 566 | ||
@@ -1003,12 +1002,11 @@ static void ircomm_tty_hangup(struct tty_struct *tty) | |||
1003 | /* ircomm_tty_flush_buffer(tty); */ | 1002 | /* ircomm_tty_flush_buffer(tty); */ |
1004 | ircomm_tty_shutdown(self); | 1003 | ircomm_tty_shutdown(self); |
1005 | 1004 | ||
1006 | /* I guess we need to lock here - Jean II */ | 1005 | spin_lock_irqsave(&self->port.lock, flags); |
1007 | spin_lock_irqsave(&self->spinlock, flags); | ||
1008 | self->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1006 | self->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1009 | self->tty = NULL; | 1007 | self->tty = NULL; |
1010 | self->port.count = 0; | 1008 | self->port.count = 0; |
1011 | spin_unlock_irqrestore(&self->spinlock, flags); | 1009 | spin_unlock_irqrestore(&self->port.lock, flags); |
1012 | 1010 | ||
1013 | wake_up_interruptible(&self->port.open_wait); | 1011 | wake_up_interruptible(&self->port.open_wait); |
1014 | } | 1012 | } |