aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/vt
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-26 18:53:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-26 18:53:22 -0400
commit8c7febe83915332276cab49e89f6580bb963fb9a (patch)
treec6ffa5fbdef402f8c6e2d75b19dcce813fd21ded /drivers/tty/vt
parent23908db413eccd77084b09c9b0a4451dfb0524c0 (diff)
parent71206b9f8120eb513c621d4f31906577bb658df3 (diff)
Merge tag 'tty-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here's the tty and serial driver patches for 4.2-rc1. A number of individual driver updates, some code cleanups, and other minor things, full details in the shortlog. All have been in linux-next for a while with no reported issues" * tag 'tty-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (152 commits) Doc: serial-rs485.txt: update RS485 driver interface Doc: tty.txt: remove mention of the BKL MAINTAINERS: tty: add serial docs directory serial: sprd: check for NULL after calling devm_clk_get serial: 8250_pci: Correct uartclk for xr17v35x expansion chips serial: 8250_pci: Add support for 12 port Exar boards serial: 8250_uniphier: add bindings document for UniPhier UART serial: core: cleanup in uart_get_baud_rate() serial: stm32-usart: Add STM32 USART Driver tty/serial: kill off set_irq_flags usage tty: move linux/gsmmux.h to uapi doc: dt: add documentation for nxp,lpc1850-uart serial: 8250: add LPC18xx/43xx UART driver serial: 8250_uniphier: add UniPhier serial driver serial: 8250_dw: support ACPI platforms with integrated DMA engine serial: of_serial: check the return value of clk_prepare_enable() serial: of_serial: use devm_clk_get() instead of clk_get() serial: earlycon: Add support for big-endian MMIO accesses serial: sirf: use hrtimer for data rx serial: sirf: correct the fifo empty_bit ...
Diffstat (limited to 'drivers/tty/vt')
-rw-r--r--drivers/tty/vt/consolemap.c60
-rw-r--r--drivers/tty/vt/vt.c92
2 files changed, 99 insertions, 53 deletions
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 59b25e039968..c8c91f0476a2 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -261,19 +261,22 @@ u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
261 int m; 261 int m;
262 if (glyph < 0 || glyph >= MAX_GLYPH) 262 if (glyph < 0 || glyph >= MAX_GLYPH)
263 return 0; 263 return 0;
264 else if (!(p = *conp->vc_uni_pagedir_loc)) 264 else {
265 return glyph; 265 p = *conp->vc_uni_pagedir_loc;
266 else if (use_unicode) { 266 if (!p)
267 if (!p->inverse_trans_unicode)
268 return glyph; 267 return glyph;
269 else 268 else if (use_unicode) {
270 return p->inverse_trans_unicode[glyph]; 269 if (!p->inverse_trans_unicode)
271 } else { 270 return glyph;
272 m = inv_translate[conp->vc_num]; 271 else
273 if (!p->inverse_translations[m]) 272 return p->inverse_trans_unicode[glyph];
274 return glyph; 273 } else {
275 else 274 m = inv_translate[conp->vc_num];
276 return p->inverse_translations[m][glyph]; 275 if (!p->inverse_translations[m])
276 return glyph;
277 else
278 return p->inverse_translations[m][glyph];
279 }
277 } 280 }
278} 281}
279EXPORT_SYMBOL_GPL(inverse_translate); 282EXPORT_SYMBOL_GPL(inverse_translate);
@@ -397,7 +400,8 @@ static void con_release_unimap(struct uni_pagedir *p)
397 400
398 if (p == dflt) dflt = NULL; 401 if (p == dflt) dflt = NULL;
399 for (i = 0; i < 32; i++) { 402 for (i = 0; i < 32; i++) {
400 if ((p1 = p->uni_pgdir[i]) != NULL) { 403 p1 = p->uni_pgdir[i];
404 if (p1 != NULL) {
401 for (j = 0; j < 32; j++) 405 for (j = 0; j < 32; j++)
402 kfree(p1[j]); 406 kfree(p1[j]);
403 kfree(p1); 407 kfree(p1);
@@ -473,14 +477,16 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
473 int i, n; 477 int i, n;
474 u16 **p1, *p2; 478 u16 **p1, *p2;
475 479
476 if (!(p1 = p->uni_pgdir[n = unicode >> 11])) { 480 p1 = p->uni_pgdir[n = unicode >> 11];
481 if (!p1) {
477 p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL); 482 p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
478 if (!p1) return -ENOMEM; 483 if (!p1) return -ENOMEM;
479 for (i = 0; i < 32; i++) 484 for (i = 0; i < 32; i++)
480 p1[i] = NULL; 485 p1[i] = NULL;
481 } 486 }
482 487
483 if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) { 488 p2 = p1[n = (unicode >> 6) & 0x1f];
489 if (!p2) {
484 p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL); 490 p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
485 if (!p2) return -ENOMEM; 491 if (!p2) return -ENOMEM;
486 memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */ 492 memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
@@ -569,10 +575,12 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
569 * entries from "p" (old) to "q" (new). 575 * entries from "p" (old) to "q" (new).
570 */ 576 */
571 l = 0; /* unicode value */ 577 l = 0; /* unicode value */
572 for (i = 0; i < 32; i++) 578 for (i = 0; i < 32; i++) {
573 if ((p1 = p->uni_pgdir[i])) 579 p1 = p->uni_pgdir[i];
574 for (j = 0; j < 32; j++) 580 if (p1)
575 if ((p2 = p1[j])) { 581 for (j = 0; j < 32; j++) {
582 p2 = p1[j];
583 if (p2) {
576 for (k = 0; k < 64; k++, l++) 584 for (k = 0; k < 64; k++, l++)
577 if (p2[k] != 0xffff) { 585 if (p2[k] != 0xffff) {
578 /* 586 /*
@@ -593,9 +601,11 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
593 /* Account for row of 64 empty entries */ 601 /* Account for row of 64 empty entries */
594 l += 64; 602 l += 64;
595 } 603 }
604 }
596 else 605 else
597 /* Account for empty table */ 606 /* Account for empty table */
598 l += 32 * 64; 607 l += 32 * 64;
608 }
599 609
600 /* 610 /*
601 * Finished copying font table, set vc_uni_pagedir to new table 611 * Finished copying font table, set vc_uni_pagedir to new table
@@ -735,10 +745,12 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct uni
735 ect = 0; 745 ect = 0;
736 if (*vc->vc_uni_pagedir_loc) { 746 if (*vc->vc_uni_pagedir_loc) {
737 p = *vc->vc_uni_pagedir_loc; 747 p = *vc->vc_uni_pagedir_loc;
738 for (i = 0; i < 32; i++) 748 for (i = 0; i < 32; i++) {
739 if ((p1 = p->uni_pgdir[i])) 749 p1 = p->uni_pgdir[i];
740 for (j = 0; j < 32; j++) 750 if (p1)
741 if ((p2 = *(p1++))) 751 for (j = 0; j < 32; j++) {
752 p2 = *(p1++);
753 if (p2)
742 for (k = 0; k < 64; k++) { 754 for (k = 0; k < 64; k++) {
743 if (*p2 < MAX_GLYPH && ect++ < ct) { 755 if (*p2 < MAX_GLYPH && ect++ < ct) {
744 __put_user((u_short)((i<<11)+(j<<6)+k), 756 __put_user((u_short)((i<<11)+(j<<6)+k),
@@ -749,6 +761,8 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct uni
749 } 761 }
750 p2++; 762 p2++;
751 } 763 }
764 }
765 }
752 } 766 }
753 __put_user(ect, uct); 767 __put_user(ect, uct);
754 console_unlock(); 768 console_unlock();
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4a24eb2b0ede..8fe52989b380 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -108,6 +108,7 @@
108#define CON_DRIVER_FLAG_MODULE 1 108#define CON_DRIVER_FLAG_MODULE 1
109#define CON_DRIVER_FLAG_INIT 2 109#define CON_DRIVER_FLAG_INIT 2
110#define CON_DRIVER_FLAG_ATTR 4 110#define CON_DRIVER_FLAG_ATTR 4
111#define CON_DRIVER_FLAG_ZOMBIE 8
111 112
112struct con_driver { 113struct con_driver {
113 const struct consw *con; 114 const struct consw *con;
@@ -135,6 +136,7 @@ const struct consw *conswitchp;
135 */ 136 */
136#define DEFAULT_BELL_PITCH 750 137#define DEFAULT_BELL_PITCH 750
137#define DEFAULT_BELL_DURATION (HZ/8) 138#define DEFAULT_BELL_DURATION (HZ/8)
139#define DEFAULT_CURSOR_BLINK_MS 200
138 140
139struct vc vc_cons [MAX_NR_CONSOLES]; 141struct vc vc_cons [MAX_NR_CONSOLES];
140 142
@@ -153,6 +155,7 @@ static int set_vesa_blanking(char __user *p);
153static void set_cursor(struct vc_data *vc); 155static void set_cursor(struct vc_data *vc);
154static void hide_cursor(struct vc_data *vc); 156static void hide_cursor(struct vc_data *vc);
155static void console_callback(struct work_struct *ignored); 157static void console_callback(struct work_struct *ignored);
158static void con_driver_unregister_callback(struct work_struct *ignored);
156static void blank_screen_t(unsigned long dummy); 159static void blank_screen_t(unsigned long dummy);
157static void set_palette(struct vc_data *vc); 160static void set_palette(struct vc_data *vc);
158 161
@@ -182,6 +185,7 @@ static int blankinterval = 10*60;
182core_param(consoleblank, blankinterval, int, 0444); 185core_param(consoleblank, blankinterval, int, 0444);
183 186
184static DECLARE_WORK(console_work, console_callback); 187static DECLARE_WORK(console_work, console_callback);
188static DECLARE_WORK(con_driver_unregister_work, con_driver_unregister_callback);
185 189
186/* 190/*
187 * fg_console is the current virtual console, 191 * fg_console is the current virtual console,
@@ -1590,6 +1594,13 @@ static void setterm_command(struct vc_data *vc)
1590 case 15: /* activate the previous console */ 1594 case 15: /* activate the previous console */
1591 set_console(last_console); 1595 set_console(last_console);
1592 break; 1596 break;
1597 case 16: /* set cursor blink duration in msec */
1598 if (vc->vc_npar >= 1 && vc->vc_par[1] >= 50 &&
1599 vc->vc_par[1] <= USHRT_MAX)
1600 vc->vc_cur_blink_ms = vc->vc_par[1];
1601 else
1602 vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
1603 break;
1593 } 1604 }
1594} 1605}
1595 1606
@@ -1717,6 +1728,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
1717 1728
1718 vc->vc_bell_pitch = DEFAULT_BELL_PITCH; 1729 vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
1719 vc->vc_bell_duration = DEFAULT_BELL_DURATION; 1730 vc->vc_bell_duration = DEFAULT_BELL_DURATION;
1731 vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
1720 1732
1721 gotoxy(vc, 0, 0); 1733 gotoxy(vc, 0, 0);
1722 save_cur(vc); 1734 save_cur(vc);
@@ -3192,22 +3204,6 @@ err:
3192 3204
3193 3205
3194#ifdef CONFIG_VT_HW_CONSOLE_BINDING 3206#ifdef CONFIG_VT_HW_CONSOLE_BINDING
3195static int con_is_graphics(const struct consw *csw, int first, int last)
3196{
3197 int i, retval = 0;
3198
3199 for (i = first; i <= last; i++) {
3200 struct vc_data *vc = vc_cons[i].d;
3201
3202 if (vc && vc->vc_mode == KD_GRAPHICS) {
3203 retval = 1;
3204 break;
3205 }
3206 }
3207
3208 return retval;
3209}
3210
3211/* unlocked version of unbind_con_driver() */ 3207/* unlocked version of unbind_con_driver() */
3212int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) 3208int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
3213{ 3209{
@@ -3293,8 +3289,7 @@ static int vt_bind(struct con_driver *con)
3293 const struct consw *defcsw = NULL, *csw = NULL; 3289 const struct consw *defcsw = NULL, *csw = NULL;
3294 int i, more = 1, first = -1, last = -1, deflt = 0; 3290 int i, more = 1, first = -1, last = -1, deflt = 0;
3295 3291
3296 if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) || 3292 if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE))
3297 con_is_graphics(con->con, con->first, con->last))
3298 goto err; 3293 goto err;
3299 3294
3300 csw = con->con; 3295 csw = con->con;
@@ -3345,8 +3340,7 @@ static int vt_unbind(struct con_driver *con)
3345 int i, more = 1, first = -1, last = -1, deflt = 0; 3340 int i, more = 1, first = -1, last = -1, deflt = 0;
3346 int ret; 3341 int ret;
3347 3342
3348 if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) || 3343 if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE))
3349 con_is_graphics(con->con, con->first, con->last))
3350 goto err; 3344 goto err;
3351 3345
3352 csw = con->con; 3346 csw = con->con;
@@ -3596,7 +3590,8 @@ static int do_register_con_driver(const struct consw *csw, int first, int last)
3596 for (i = 0; i < MAX_NR_CON_DRIVER; i++) { 3590 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
3597 con_driver = &registered_con_driver[i]; 3591 con_driver = &registered_con_driver[i];
3598 3592
3599 if (con_driver->con == NULL) { 3593 if (con_driver->con == NULL &&
3594 !(con_driver->flag & CON_DRIVER_FLAG_ZOMBIE)) {
3600 con_driver->con = csw; 3595 con_driver->con = csw;
3601 con_driver->desc = desc; 3596 con_driver->desc = desc;
3602 con_driver->node = i; 3597 con_driver->node = i;
@@ -3658,16 +3653,20 @@ int do_unregister_con_driver(const struct consw *csw)
3658 struct con_driver *con_driver = &registered_con_driver[i]; 3653 struct con_driver *con_driver = &registered_con_driver[i];
3659 3654
3660 if (con_driver->con == csw) { 3655 if (con_driver->con == csw) {
3661 vtconsole_deinit_device(con_driver); 3656 /*
3662 device_destroy(vtconsole_class, 3657 * Defer the removal of the sysfs entries since that
3663 MKDEV(0, con_driver->node)); 3658 * will acquire the kernfs s_active lock and we can't
3659 * acquire this lock while holding the console lock:
3660 * the unbind sysfs entry imposes already the opposite
3661 * order. Reset con already here to prevent any later
3662 * lookup to succeed and mark this slot as zombie, so
3663 * it won't get reused until we complete the removal
3664 * in the deferred work.
3665 */
3664 con_driver->con = NULL; 3666 con_driver->con = NULL;
3665 con_driver->desc = NULL; 3667 con_driver->flag = CON_DRIVER_FLAG_ZOMBIE;
3666 con_driver->dev = NULL; 3668 schedule_work(&con_driver_unregister_work);
3667 con_driver->node = 0; 3669
3668 con_driver->flag = 0;
3669 con_driver->first = 0;
3670 con_driver->last = 0;
3671 return 0; 3670 return 0;
3672 } 3671 }
3673 } 3672 }
@@ -3676,6 +3675,39 @@ int do_unregister_con_driver(const struct consw *csw)
3676} 3675}
3677EXPORT_SYMBOL_GPL(do_unregister_con_driver); 3676EXPORT_SYMBOL_GPL(do_unregister_con_driver);
3678 3677
3678static void con_driver_unregister_callback(struct work_struct *ignored)
3679{
3680 int i;
3681
3682 console_lock();
3683
3684 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
3685 struct con_driver *con_driver = &registered_con_driver[i];
3686
3687 if (!(con_driver->flag & CON_DRIVER_FLAG_ZOMBIE))
3688 continue;
3689
3690 console_unlock();
3691
3692 vtconsole_deinit_device(con_driver);
3693 device_destroy(vtconsole_class, MKDEV(0, con_driver->node));
3694
3695 console_lock();
3696
3697 if (WARN_ON_ONCE(con_driver->con))
3698 con_driver->con = NULL;
3699 con_driver->desc = NULL;
3700 con_driver->dev = NULL;
3701 con_driver->node = 0;
3702 WARN_ON_ONCE(con_driver->flag != CON_DRIVER_FLAG_ZOMBIE);
3703 con_driver->flag = 0;
3704 con_driver->first = 0;
3705 con_driver->last = 0;
3706 }
3707
3708 console_unlock();
3709}
3710
3679/* 3711/*
3680 * If we support more console drivers, this function is used 3712 * If we support more console drivers, this function is used
3681 * when a driver wants to take over some existing consoles 3713 * when a driver wants to take over some existing consoles