aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/n_tty.c
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2013-06-15 10:04:24 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-23 20:02:21 -0400
commit17bd79074003d73f2207289b9d3ce0553d000856 (patch)
tree51247dfd99d2d62693c08e84a85ad0882c0f8d82 /drivers/tty/n_tty.c
parent862eeffef1b465a12412f4ae6e5987ae292c968d (diff)
n_tty: Remove echo_lock
Adding data to echo_buf (via add_echo_byte()) is guaranteed to be single-threaded, since all callers are from the n_tty_receive_buf() path. Processing the echo_buf can be called from either the n_tty_receive_buf() path or the n_tty_write() path; however, these callers are already serialized by output_lock. Publish cumulative echo_head changes to echo_commit; process echo_buf from echo_tail to echo_commit; remove echo_lock. On echo_buf overrun, claim output_lock to serialize changes to echo_tail. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/n_tty.c')
-rw-r--r--drivers/tty/n_tty.c75
1 files changed, 28 insertions, 47 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 8406a23ee920..3b499451b7ed 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -106,10 +106,10 @@ struct n_tty_data {
106 /* consumer-published */ 106 /* consumer-published */
107 size_t read_tail; 107 size_t read_tail;
108 108
109 /* protected by echo_lock */
110 unsigned char *echo_buf; 109 unsigned char *echo_buf;
111 size_t echo_head; 110 size_t echo_head;
112 size_t echo_tail; 111 size_t echo_tail;
112 size_t echo_commit;
113 113
114 /* protected by output lock */ 114 /* protected by output lock */
115 unsigned int column; 115 unsigned int column;
@@ -117,7 +117,6 @@ struct n_tty_data {
117 117
118 struct mutex atomic_read_lock; 118 struct mutex atomic_read_lock;
119 struct mutex output_lock; 119 struct mutex output_lock;
120 struct mutex echo_lock;
121}; 120};
122 121
123static inline size_t read_cnt(struct n_tty_data *ldata) 122static inline size_t read_cnt(struct n_tty_data *ldata)
@@ -333,10 +332,7 @@ static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
333static void reset_buffer_flags(struct n_tty_data *ldata) 332static void reset_buffer_flags(struct n_tty_data *ldata)
334{ 333{
335 ldata->read_head = ldata->canon_head = ldata->read_tail = 0; 334 ldata->read_head = ldata->canon_head = ldata->read_tail = 0;
336 335 ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0;
337 mutex_lock(&ldata->echo_lock);
338 ldata->echo_head = ldata->echo_tail = 0;
339 mutex_unlock(&ldata->echo_lock);
340 336
341 ldata->erasing = 0; 337 ldata->erasing = 0;
342 bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); 338 bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
@@ -642,8 +638,7 @@ break_out:
642 * are prioritized. Also, when control characters are echoed with a 638 * are prioritized. Also, when control characters are echoed with a
643 * prefixed "^", the pair is treated atomically and thus not separated. 639 * prefixed "^", the pair is treated atomically and thus not separated.
644 * 640 *
645 * Locking: output_lock to protect column state and space left, 641 * Locking: output_lock to protect column state and space left
646 * echo_lock to protect the echo buffer
647 */ 642 */
648 643
649static void process_echoes(struct tty_struct *tty) 644static void process_echoes(struct tty_struct *tty)
@@ -653,16 +648,15 @@ static void process_echoes(struct tty_struct *tty)
653 size_t tail; 648 size_t tail;
654 unsigned char c; 649 unsigned char c;
655 650
656 if (ldata->echo_head == ldata->echo_tail) 651 if (ldata->echo_commit == ldata->echo_tail)
657 return; 652 return;
658 653
659 mutex_lock(&ldata->output_lock); 654 mutex_lock(&ldata->output_lock);
660 mutex_lock(&ldata->echo_lock);
661 655
662 space = tty_write_room(tty); 656 space = tty_write_room(tty);
663 657
664 tail = ldata->echo_tail; 658 tail = ldata->echo_tail;
665 nr = ldata->echo_head - ldata->echo_tail; 659 nr = ldata->echo_commit - ldata->echo_tail;
666 while (nr > 0) { 660 while (nr > 0) {
667 c = echo_buf(ldata, tail); 661 c = echo_buf(ldata, tail);
668 if (c == ECHO_OP_START) { 662 if (c == ECHO_OP_START) {
@@ -779,13 +773,21 @@ static void process_echoes(struct tty_struct *tty)
779 773
780 ldata->echo_tail = tail; 774 ldata->echo_tail = tail;
781 775
782 mutex_unlock(&ldata->echo_lock);
783 mutex_unlock(&ldata->output_lock); 776 mutex_unlock(&ldata->output_lock);
784 777
785 if (tty->ops->flush_chars) 778 if (tty->ops->flush_chars)
786 tty->ops->flush_chars(tty); 779 tty->ops->flush_chars(tty);
787} 780}
788 781
782static void commit_echoes(struct tty_struct *tty)
783{
784 struct n_tty_data *ldata = tty->disc_data;
785
786 smp_mb();
787 ldata->echo_commit = ldata->echo_head;
788 process_echoes(tty);
789}
790
789/** 791/**
790 * add_echo_byte - add a byte to the echo buffer 792 * add_echo_byte - add a byte to the echo buffer
791 * @c: unicode byte to echo 793 * @c: unicode byte to echo
@@ -793,13 +795,16 @@ static void process_echoes(struct tty_struct *tty)
793 * 795 *
794 * Add a character or operation byte to the echo buffer. 796 * Add a character or operation byte to the echo buffer.
795 * 797 *
796 * Should be called under the echo lock to protect the echo buffer. 798 * Locks: may claim output_lock to prevent concurrent modify of
799 * echo_tail by process_echoes().
797 */ 800 */
798 801
799static void add_echo_byte(unsigned char c, struct n_tty_data *ldata) 802static void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
800{ 803{
801 if (ldata->echo_head - ldata->echo_tail == N_TTY_BUF_SIZE) { 804 if (ldata->echo_head - ldata->echo_tail == N_TTY_BUF_SIZE) {
802 size_t head = ldata->echo_head; 805 size_t head = ldata->echo_head;
806
807 mutex_lock(&ldata->output_lock);
803 /* 808 /*
804 * Since the buffer start position needs to be advanced, 809 * Since the buffer start position needs to be advanced,
805 * be sure to step by a whole operation byte group. 810 * be sure to step by a whole operation byte group.
@@ -811,6 +816,7 @@ static void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
811 ldata->echo_tail += 2; 816 ldata->echo_tail += 2;
812 } else 817 } else
813 ldata->echo_tail++; 818 ldata->echo_tail++;
819 mutex_unlock(&ldata->output_lock);
814 } 820 }
815 821
816 *echo_buf_addr(ldata, ldata->echo_head++) = c; 822 *echo_buf_addr(ldata, ldata->echo_head++) = c;
@@ -821,16 +827,12 @@ static void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
821 * @ldata: n_tty data 827 * @ldata: n_tty data
822 * 828 *
823 * Add an operation to the echo buffer to move back one column. 829 * Add an operation to the echo buffer to move back one column.
824 *
825 * Locking: echo_lock to protect the echo buffer
826 */ 830 */
827 831
828static void echo_move_back_col(struct n_tty_data *ldata) 832static void echo_move_back_col(struct n_tty_data *ldata)
829{ 833{
830 mutex_lock(&ldata->echo_lock);
831 add_echo_byte(ECHO_OP_START, ldata); 834 add_echo_byte(ECHO_OP_START, ldata);
832 add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata); 835 add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata);
833 mutex_unlock(&ldata->echo_lock);
834} 836}
835 837
836/** 838/**
@@ -839,16 +841,12 @@ static void echo_move_back_col(struct n_tty_data *ldata)
839 * 841 *
840 * Add an operation to the echo buffer to set the canon column 842 * Add an operation to the echo buffer to set the canon column
841 * to the current column. 843 * to the current column.
842 *
843 * Locking: echo_lock to protect the echo buffer
844 */ 844 */
845 845
846static void echo_set_canon_col(struct n_tty_data *ldata) 846static void echo_set_canon_col(struct n_tty_data *ldata)
847{ 847{
848 mutex_lock(&ldata->echo_lock);
849 add_echo_byte(ECHO_OP_START, ldata); 848 add_echo_byte(ECHO_OP_START, ldata);
850 add_echo_byte(ECHO_OP_SET_CANON_COL, ldata); 849 add_echo_byte(ECHO_OP_SET_CANON_COL, ldata);
851 mutex_unlock(&ldata->echo_lock);
852} 850}
853 851
854/** 852/**
@@ -864,15 +862,11 @@ static void echo_set_canon_col(struct n_tty_data *ldata)
864 * of input. This information will be used later, along with 862 * of input. This information will be used later, along with
865 * canon column (if applicable), to go back the correct number 863 * canon column (if applicable), to go back the correct number
866 * of columns. 864 * of columns.
867 *
868 * Locking: echo_lock to protect the echo buffer
869 */ 865 */
870 866
871static void echo_erase_tab(unsigned int num_chars, int after_tab, 867static void echo_erase_tab(unsigned int num_chars, int after_tab,
872 struct n_tty_data *ldata) 868 struct n_tty_data *ldata)
873{ 869{
874 mutex_lock(&ldata->echo_lock);
875
876 add_echo_byte(ECHO_OP_START, ldata); 870 add_echo_byte(ECHO_OP_START, ldata);
877 add_echo_byte(ECHO_OP_ERASE_TAB, ldata); 871 add_echo_byte(ECHO_OP_ERASE_TAB, ldata);
878 872
@@ -884,8 +878,6 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
884 num_chars |= 0x80; 878 num_chars |= 0x80;
885 879
886 add_echo_byte(num_chars, ldata); 880 add_echo_byte(num_chars, ldata);
887
888 mutex_unlock(&ldata->echo_lock);
889} 881}
890 882
891/** 883/**
@@ -897,20 +889,16 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
897 * L_ECHO(tty) is true. Called from the driver receive_buf path. 889 * L_ECHO(tty) is true. Called from the driver receive_buf path.
898 * 890 *
899 * This variant does not treat control characters specially. 891 * This variant does not treat control characters specially.
900 *
901 * Locking: echo_lock to protect the echo buffer
902 */ 892 */
903 893
904static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) 894static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
905{ 895{
906 mutex_lock(&ldata->echo_lock);
907 if (c == ECHO_OP_START) { 896 if (c == ECHO_OP_START) {
908 add_echo_byte(ECHO_OP_START, ldata); 897 add_echo_byte(ECHO_OP_START, ldata);
909 add_echo_byte(ECHO_OP_START, ldata); 898 add_echo_byte(ECHO_OP_START, ldata);
910 } else { 899 } else {
911 add_echo_byte(c, ldata); 900 add_echo_byte(c, ldata);
912 } 901 }
913 mutex_unlock(&ldata->echo_lock);
914} 902}
915 903
916/** 904/**
@@ -923,16 +911,12 @@ static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
923 * 911 *
924 * This variant tags control characters to be echoed as "^X" 912 * This variant tags control characters to be echoed as "^X"
925 * (where X is the letter representing the control char). 913 * (where X is the letter representing the control char).
926 *
927 * Locking: echo_lock to protect the echo buffer
928 */ 914 */
929 915
930static void echo_char(unsigned char c, struct tty_struct *tty) 916static void echo_char(unsigned char c, struct tty_struct *tty)
931{ 917{
932 struct n_tty_data *ldata = tty->disc_data; 918 struct n_tty_data *ldata = tty->disc_data;
933 919
934 mutex_lock(&ldata->echo_lock);
935
936 if (c == ECHO_OP_START) { 920 if (c == ECHO_OP_START) {
937 add_echo_byte(ECHO_OP_START, ldata); 921 add_echo_byte(ECHO_OP_START, ldata);
938 add_echo_byte(ECHO_OP_START, ldata); 922 add_echo_byte(ECHO_OP_START, ldata);
@@ -941,8 +925,6 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
941 add_echo_byte(ECHO_OP_START, ldata); 925 add_echo_byte(ECHO_OP_START, ldata);
942 add_echo_byte(c, ldata); 926 add_echo_byte(c, ldata);
943 } 927 }
944
945 mutex_unlock(&ldata->echo_lock);
946} 928}
947 929
948/** 930/**
@@ -1284,7 +1266,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
1284 if (ldata->canon_head == ldata->read_head) 1266 if (ldata->canon_head == ldata->read_head)
1285 echo_set_canon_col(ldata); 1267 echo_set_canon_col(ldata);
1286 echo_char(c, tty); 1268 echo_char(c, tty);
1287 process_echoes(tty); 1269 commit_echoes(tty);
1288 } 1270 }
1289 if (parmrk) 1271 if (parmrk)
1290 put_tty_queue(c, ldata); 1272 put_tty_queue(c, ldata);
@@ -1295,7 +1277,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
1295 if (I_IXON(tty)) { 1277 if (I_IXON(tty)) {
1296 if (c == START_CHAR(tty)) { 1278 if (c == START_CHAR(tty)) {
1297 start_tty(tty); 1279 start_tty(tty);
1298 process_echoes(tty); 1280 commit_echoes(tty);
1299 return; 1281 return;
1300 } 1282 }
1301 if (c == STOP_CHAR(tty)) { 1283 if (c == STOP_CHAR(tty)) {
@@ -1326,7 +1308,7 @@ send_signal:
1326 start_tty(tty); 1308 start_tty(tty);
1327 if (L_ECHO(tty)) { 1309 if (L_ECHO(tty)) {
1328 echo_char(c, tty); 1310 echo_char(c, tty);
1329 process_echoes(tty); 1311 commit_echoes(tty);
1330 } 1312 }
1331 isig(signal, tty); 1313 isig(signal, tty);
1332 return; 1314 return;
@@ -1345,7 +1327,7 @@ send_signal:
1345 if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || 1327 if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
1346 (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { 1328 (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
1347 eraser(c, tty); 1329 eraser(c, tty);
1348 process_echoes(tty); 1330 commit_echoes(tty);
1349 return; 1331 return;
1350 } 1332 }
1351 if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { 1333 if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
@@ -1355,7 +1337,7 @@ send_signal:
1355 if (L_ECHOCTL(tty)) { 1337 if (L_ECHOCTL(tty)) {
1356 echo_char_raw('^', ldata); 1338 echo_char_raw('^', ldata);
1357 echo_char_raw('\b', ldata); 1339 echo_char_raw('\b', ldata);
1358 process_echoes(tty); 1340 commit_echoes(tty);
1359 } 1341 }
1360 } 1342 }
1361 return; 1343 return;
@@ -1371,7 +1353,7 @@ send_signal:
1371 echo_char(read_buf(ldata, tail), tty); 1353 echo_char(read_buf(ldata, tail), tty);
1372 tail++; 1354 tail++;
1373 } 1355 }
1374 process_echoes(tty); 1356 commit_echoes(tty);
1375 return; 1357 return;
1376 } 1358 }
1377 if (c == '\n') { 1359 if (c == '\n') {
@@ -1382,7 +1364,7 @@ send_signal:
1382 } 1364 }
1383 if (L_ECHO(tty) || L_ECHONL(tty)) { 1365 if (L_ECHO(tty) || L_ECHONL(tty)) {
1384 echo_char_raw('\n', ldata); 1366 echo_char_raw('\n', ldata);
1385 process_echoes(tty); 1367 commit_echoes(tty);
1386 } 1368 }
1387 goto handle_newline; 1369 goto handle_newline;
1388 } 1370 }
@@ -1411,7 +1393,7 @@ send_signal:
1411 if (ldata->canon_head == ldata->read_head) 1393 if (ldata->canon_head == ldata->read_head)
1412 echo_set_canon_col(ldata); 1394 echo_set_canon_col(ldata);
1413 echo_char(c, tty); 1395 echo_char(c, tty);
1414 process_echoes(tty); 1396 commit_echoes(tty);
1415 } 1397 }
1416 /* 1398 /*
1417 * XXX does PARMRK doubling happen for 1399 * XXX does PARMRK doubling happen for
@@ -1448,7 +1430,7 @@ handle_newline:
1448 echo_set_canon_col(ldata); 1430 echo_set_canon_col(ldata);
1449 echo_char(c, tty); 1431 echo_char(c, tty);
1450 } 1432 }
1451 process_echoes(tty); 1433 commit_echoes(tty);
1452 } 1434 }
1453 1435
1454 if (parmrk) 1436 if (parmrk)
@@ -1713,7 +1695,6 @@ static int n_tty_open(struct tty_struct *tty)
1713 ldata->overrun_time = jiffies; 1695 ldata->overrun_time = jiffies;
1714 mutex_init(&ldata->atomic_read_lock); 1696 mutex_init(&ldata->atomic_read_lock);
1715 mutex_init(&ldata->output_lock); 1697 mutex_init(&ldata->output_lock);
1716 mutex_init(&ldata->echo_lock);
1717 1698
1718 /* These are ugly. Currently a malloc failure here can panic */ 1699 /* These are ugly. Currently a malloc failure here can panic */
1719 ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); 1700 ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);