aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2012-06-04 07:35:20 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-12 18:50:23 -0400
commite673927d8a210ab1db27047080fc1bdb47f7e372 (patch)
treec817dc32bbc54e323909004a098fd29d16ee1ffb
parent849d5a997fe6a9e44401daed62a98121390ec0d3 (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>
-rw-r--r--include/net/irda/ircomm_tty.h1
-rw-r--r--net/irda/ircomm/ircomm_tty.c38
2 files changed, 18 insertions, 21 deletions
diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index e4db3b5f6e4..a9027d8f670 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -96,7 +96,6 @@ struct ircomm_tty_cb {
96 struct work_struct tqueue; 96 struct work_struct tqueue;
97 97
98 /* Protect concurent access to : 98 /* Protect concurent access to :
99 * o self->open_count
100 * o self->ctrl_skb 99 * o self->ctrl_skb
101 * o self->tx_skb 100 * o self->tx_skb
102 * Maybe other things may gain to be protected as well... 101 * Maybe other things may gain to be protected as well...
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index 8e61026b9dd..7b2152cfd42 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}