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 ...
This commit is contained in:
@@ -261,19 +261,22 @@ u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
|
||||
int m;
|
||||
if (glyph < 0 || glyph >= MAX_GLYPH)
|
||||
return 0;
|
||||
else if (!(p = *conp->vc_uni_pagedir_loc))
|
||||
return glyph;
|
||||
else if (use_unicode) {
|
||||
if (!p->inverse_trans_unicode)
|
||||
else {
|
||||
p = *conp->vc_uni_pagedir_loc;
|
||||
if (!p)
|
||||
return glyph;
|
||||
else
|
||||
return p->inverse_trans_unicode[glyph];
|
||||
} else {
|
||||
m = inv_translate[conp->vc_num];
|
||||
if (!p->inverse_translations[m])
|
||||
return glyph;
|
||||
else
|
||||
return p->inverse_translations[m][glyph];
|
||||
else if (use_unicode) {
|
||||
if (!p->inverse_trans_unicode)
|
||||
return glyph;
|
||||
else
|
||||
return p->inverse_trans_unicode[glyph];
|
||||
} else {
|
||||
m = inv_translate[conp->vc_num];
|
||||
if (!p->inverse_translations[m])
|
||||
return glyph;
|
||||
else
|
||||
return p->inverse_translations[m][glyph];
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(inverse_translate);
|
||||
@@ -397,7 +400,8 @@ static void con_release_unimap(struct uni_pagedir *p)
|
||||
|
||||
if (p == dflt) dflt = NULL;
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((p1 = p->uni_pgdir[i]) != NULL) {
|
||||
p1 = p->uni_pgdir[i];
|
||||
if (p1 != NULL) {
|
||||
for (j = 0; j < 32; j++)
|
||||
kfree(p1[j]);
|
||||
kfree(p1);
|
||||
@@ -473,14 +477,16 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
|
||||
int i, n;
|
||||
u16 **p1, *p2;
|
||||
|
||||
if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
|
||||
p1 = p->uni_pgdir[n = unicode >> 11];
|
||||
if (!p1) {
|
||||
p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
|
||||
if (!p1) return -ENOMEM;
|
||||
for (i = 0; i < 32; i++)
|
||||
p1[i] = NULL;
|
||||
}
|
||||
|
||||
if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
|
||||
p2 = p1[n = (unicode >> 6) & 0x1f];
|
||||
if (!p2) {
|
||||
p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
|
||||
if (!p2) return -ENOMEM;
|
||||
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)
|
||||
* entries from "p" (old) to "q" (new).
|
||||
*/
|
||||
l = 0; /* unicode value */
|
||||
for (i = 0; i < 32; i++)
|
||||
if ((p1 = p->uni_pgdir[i]))
|
||||
for (j = 0; j < 32; j++)
|
||||
if ((p2 = p1[j])) {
|
||||
for (i = 0; i < 32; i++) {
|
||||
p1 = p->uni_pgdir[i];
|
||||
if (p1)
|
||||
for (j = 0; j < 32; j++) {
|
||||
p2 = p1[j];
|
||||
if (p2) {
|
||||
for (k = 0; k < 64; k++, l++)
|
||||
if (p2[k] != 0xffff) {
|
||||
/*
|
||||
@@ -593,9 +601,11 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
|
||||
/* Account for row of 64 empty entries */
|
||||
l += 64;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Account for empty table */
|
||||
l += 32 * 64;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
ect = 0;
|
||||
if (*vc->vc_uni_pagedir_loc) {
|
||||
p = *vc->vc_uni_pagedir_loc;
|
||||
for (i = 0; i < 32; i++)
|
||||
if ((p1 = p->uni_pgdir[i]))
|
||||
for (j = 0; j < 32; j++)
|
||||
if ((p2 = *(p1++)))
|
||||
for (i = 0; i < 32; i++) {
|
||||
p1 = p->uni_pgdir[i];
|
||||
if (p1)
|
||||
for (j = 0; j < 32; j++) {
|
||||
p2 = *(p1++);
|
||||
if (p2)
|
||||
for (k = 0; k < 64; k++) {
|
||||
if (*p2 < MAX_GLYPH && ect++ < ct) {
|
||||
__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
|
||||
}
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__put_user(ect, uct);
|
||||
console_unlock();
|
||||
|
@@ -108,6 +108,7 @@
|
||||
#define CON_DRIVER_FLAG_MODULE 1
|
||||
#define CON_DRIVER_FLAG_INIT 2
|
||||
#define CON_DRIVER_FLAG_ATTR 4
|
||||
#define CON_DRIVER_FLAG_ZOMBIE 8
|
||||
|
||||
struct con_driver {
|
||||
const struct consw *con;
|
||||
@@ -135,6 +136,7 @@ const struct consw *conswitchp;
|
||||
*/
|
||||
#define DEFAULT_BELL_PITCH 750
|
||||
#define DEFAULT_BELL_DURATION (HZ/8)
|
||||
#define DEFAULT_CURSOR_BLINK_MS 200
|
||||
|
||||
struct vc vc_cons [MAX_NR_CONSOLES];
|
||||
|
||||
@@ -153,6 +155,7 @@ static int set_vesa_blanking(char __user *p);
|
||||
static void set_cursor(struct vc_data *vc);
|
||||
static void hide_cursor(struct vc_data *vc);
|
||||
static void console_callback(struct work_struct *ignored);
|
||||
static void con_driver_unregister_callback(struct work_struct *ignored);
|
||||
static void blank_screen_t(unsigned long dummy);
|
||||
static void set_palette(struct vc_data *vc);
|
||||
|
||||
@@ -182,6 +185,7 @@ static int blankinterval = 10*60;
|
||||
core_param(consoleblank, blankinterval, int, 0444);
|
||||
|
||||
static DECLARE_WORK(console_work, console_callback);
|
||||
static DECLARE_WORK(con_driver_unregister_work, con_driver_unregister_callback);
|
||||
|
||||
/*
|
||||
* fg_console is the current virtual console,
|
||||
@@ -1590,6 +1594,13 @@ static void setterm_command(struct vc_data *vc)
|
||||
case 15: /* activate the previous console */
|
||||
set_console(last_console);
|
||||
break;
|
||||
case 16: /* set cursor blink duration in msec */
|
||||
if (vc->vc_npar >= 1 && vc->vc_par[1] >= 50 &&
|
||||
vc->vc_par[1] <= USHRT_MAX)
|
||||
vc->vc_cur_blink_ms = vc->vc_par[1];
|
||||
else
|
||||
vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1717,6 +1728,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
|
||||
|
||||
vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
|
||||
vc->vc_bell_duration = DEFAULT_BELL_DURATION;
|
||||
vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
|
||||
|
||||
gotoxy(vc, 0, 0);
|
||||
save_cur(vc);
|
||||
@@ -3192,22 +3204,6 @@ err:
|
||||
|
||||
|
||||
#ifdef CONFIG_VT_HW_CONSOLE_BINDING
|
||||
static int con_is_graphics(const struct consw *csw, int first, int last)
|
||||
{
|
||||
int i, retval = 0;
|
||||
|
||||
for (i = first; i <= last; i++) {
|
||||
struct vc_data *vc = vc_cons[i].d;
|
||||
|
||||
if (vc && vc->vc_mode == KD_GRAPHICS) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* unlocked version of unbind_con_driver() */
|
||||
int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
|
||||
{
|
||||
@@ -3293,8 +3289,7 @@ static int vt_bind(struct con_driver *con)
|
||||
const struct consw *defcsw = NULL, *csw = NULL;
|
||||
int i, more = 1, first = -1, last = -1, deflt = 0;
|
||||
|
||||
if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
|
||||
con_is_graphics(con->con, con->first, con->last))
|
||||
if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE))
|
||||
goto err;
|
||||
|
||||
csw = con->con;
|
||||
@@ -3345,8 +3340,7 @@ static int vt_unbind(struct con_driver *con)
|
||||
int i, more = 1, first = -1, last = -1, deflt = 0;
|
||||
int ret;
|
||||
|
||||
if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
|
||||
con_is_graphics(con->con, con->first, con->last))
|
||||
if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE))
|
||||
goto err;
|
||||
|
||||
csw = con->con;
|
||||
@@ -3596,7 +3590,8 @@ static int do_register_con_driver(const struct consw *csw, int first, int last)
|
||||
for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
|
||||
con_driver = ®istered_con_driver[i];
|
||||
|
||||
if (con_driver->con == NULL) {
|
||||
if (con_driver->con == NULL &&
|
||||
!(con_driver->flag & CON_DRIVER_FLAG_ZOMBIE)) {
|
||||
con_driver->con = csw;
|
||||
con_driver->desc = desc;
|
||||
con_driver->node = i;
|
||||
@@ -3658,16 +3653,20 @@ int do_unregister_con_driver(const struct consw *csw)
|
||||
struct con_driver *con_driver = ®istered_con_driver[i];
|
||||
|
||||
if (con_driver->con == csw) {
|
||||
vtconsole_deinit_device(con_driver);
|
||||
device_destroy(vtconsole_class,
|
||||
MKDEV(0, con_driver->node));
|
||||
/*
|
||||
* Defer the removal of the sysfs entries since that
|
||||
* will acquire the kernfs s_active lock and we can't
|
||||
* acquire this lock while holding the console lock:
|
||||
* the unbind sysfs entry imposes already the opposite
|
||||
* order. Reset con already here to prevent any later
|
||||
* lookup to succeed and mark this slot as zombie, so
|
||||
* it won't get reused until we complete the removal
|
||||
* in the deferred work.
|
||||
*/
|
||||
con_driver->con = NULL;
|
||||
con_driver->desc = NULL;
|
||||
con_driver->dev = NULL;
|
||||
con_driver->node = 0;
|
||||
con_driver->flag = 0;
|
||||
con_driver->first = 0;
|
||||
con_driver->last = 0;
|
||||
con_driver->flag = CON_DRIVER_FLAG_ZOMBIE;
|
||||
schedule_work(&con_driver_unregister_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -3676,6 +3675,39 @@ int do_unregister_con_driver(const struct consw *csw)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(do_unregister_con_driver);
|
||||
|
||||
static void con_driver_unregister_callback(struct work_struct *ignored)
|
||||
{
|
||||
int i;
|
||||
|
||||
console_lock();
|
||||
|
||||
for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
|
||||
struct con_driver *con_driver = ®istered_con_driver[i];
|
||||
|
||||
if (!(con_driver->flag & CON_DRIVER_FLAG_ZOMBIE))
|
||||
continue;
|
||||
|
||||
console_unlock();
|
||||
|
||||
vtconsole_deinit_device(con_driver);
|
||||
device_destroy(vtconsole_class, MKDEV(0, con_driver->node));
|
||||
|
||||
console_lock();
|
||||
|
||||
if (WARN_ON_ONCE(con_driver->con))
|
||||
con_driver->con = NULL;
|
||||
con_driver->desc = NULL;
|
||||
con_driver->dev = NULL;
|
||||
con_driver->node = 0;
|
||||
WARN_ON_ONCE(con_driver->flag != CON_DRIVER_FLAG_ZOMBIE);
|
||||
con_driver->flag = 0;
|
||||
con_driver->first = 0;
|
||||
con_driver->last = 0;
|
||||
}
|
||||
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* If we support more console drivers, this function is used
|
||||
* when a driver wants to take over some existing consoles
|
||||
|
Reference in New Issue
Block a user