diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 18:53:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 18:53:22 -0400 |
commit | 8c7febe83915332276cab49e89f6580bb963fb9a (patch) | |
tree | c6ffa5fbdef402f8c6e2d75b19dcce813fd21ded /drivers/tty/vt | |
parent | 23908db413eccd77084b09c9b0a4451dfb0524c0 (diff) | |
parent | 71206b9f8120eb513c621d4f31906577bb658df3 (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.c | 60 | ||||
-rw-r--r-- | drivers/tty/vt/vt.c | 92 |
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 | } |
279 | EXPORT_SYMBOL_GPL(inverse_translate); | 282 | EXPORT_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 | ||
112 | struct con_driver { | 113 | struct 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 | ||
139 | struct vc vc_cons [MAX_NR_CONSOLES]; | 141 | struct vc vc_cons [MAX_NR_CONSOLES]; |
140 | 142 | ||
@@ -153,6 +155,7 @@ static int set_vesa_blanking(char __user *p); | |||
153 | static void set_cursor(struct vc_data *vc); | 155 | static void set_cursor(struct vc_data *vc); |
154 | static void hide_cursor(struct vc_data *vc); | 156 | static void hide_cursor(struct vc_data *vc); |
155 | static void console_callback(struct work_struct *ignored); | 157 | static void console_callback(struct work_struct *ignored); |
158 | static void con_driver_unregister_callback(struct work_struct *ignored); | ||
156 | static void blank_screen_t(unsigned long dummy); | 159 | static void blank_screen_t(unsigned long dummy); |
157 | static void set_palette(struct vc_data *vc); | 160 | static void set_palette(struct vc_data *vc); |
158 | 161 | ||
@@ -182,6 +185,7 @@ static int blankinterval = 10*60; | |||
182 | core_param(consoleblank, blankinterval, int, 0444); | 185 | core_param(consoleblank, blankinterval, int, 0444); |
183 | 186 | ||
184 | static DECLARE_WORK(console_work, console_callback); | 187 | static DECLARE_WORK(console_work, console_callback); |
188 | static 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 |
3195 | static 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() */ |
3212 | int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | 3208 | int 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 = ®istered_con_driver[i]; | 3591 | con_driver = ®istered_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 = ®istered_con_driver[i]; | 3653 | struct con_driver *con_driver = ®istered_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 | } |
3677 | EXPORT_SYMBOL_GPL(do_unregister_con_driver); | 3676 | EXPORT_SYMBOL_GPL(do_unregister_con_driver); |
3678 | 3677 | ||
3678 | static 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 = ®istered_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 |