From 28bc24fc46f9c9f39ddefb424d6072041805b563 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:33 +0200 Subject: vc: separate state There are two copies of some members of struct vc_data. This is because we need to save them and restore later. Move these memebers to a separate structure called vc_state. So now instead of members like: vc_x, vc_y and vc_saved_x, vc_saved_y we have state and saved_state (of type: struct vc_state) containing state.x, state.y and saved_state.x, saved_state.y This change: * makes clear what is saved & restored * eases save & restore by using memcpy (see save_cur and restore_cur) Finally, we document the newly added struct vc_state using kernel-doc. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-1-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/accessibility/braille/braille_console.c | 10 +- drivers/staging/speakup/main.c | 28 +- drivers/tty/vt/vt.c | 327 ++++++++++++------------ drivers/video/console/mdacon.c | 2 +- drivers/video/console/sticon.c | 6 +- drivers/video/console/vgacon.c | 22 +- drivers/video/fbdev/core/bitblit.c | 6 +- drivers/video/fbdev/core/fbcon.c | 8 +- drivers/video/fbdev/core/fbcon_ccw.c | 4 +- drivers/video/fbdev/core/fbcon_cw.c | 4 +- drivers/video/fbdev/core/fbcon_ud.c | 4 +- drivers/video/fbdev/core/tileblit.c | 4 +- 12 files changed, 206 insertions(+), 219 deletions(-) (limited to 'drivers') diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c index a8f7c278b691..c2b452af6806 100644 --- a/drivers/accessibility/braille/braille_console.c +++ b/drivers/accessibility/braille/braille_console.c @@ -109,16 +109,16 @@ static void braille_write(u16 *buf) /* Follow the VC cursor*/ static void vc_follow_cursor(struct vc_data *vc) { - vc_x = vc->vc_x - (vc->vc_x % WIDTH); - vc_y = vc->vc_y; - lastvc_x = vc->vc_x; - lastvc_y = vc->vc_y; + vc_x = vc->state.x - (vc->state.x % WIDTH); + vc_y = vc->state.y; + lastvc_x = vc->state.x; + lastvc_y = vc->state.y; } /* Maybe the VC cursor moved, if so follow it */ static void vc_maybe_cursor_moved(struct vc_data *vc) { - if (vc->vc_x != lastvc_x || vc->vc_y != lastvc_y) + if (vc->state.x != lastvc_x || vc->state.y != lastvc_y) vc_follow_cursor(vc); } diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 02471d932d71..ddfd12afe3b9 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -263,8 +263,8 @@ static unsigned char get_attributes(struct vc_data *vc, u16 *pos) static void speakup_date(struct vc_data *vc) { - spk_x = spk_cx = vc->vc_x; - spk_y = spk_cy = vc->vc_y; + spk_x = spk_cx = vc->state.x; + spk_y = spk_cy = vc->state.y; spk_pos = spk_cp = vc->vc_pos; spk_old_attr = spk_attr; spk_attr = get_attributes(vc, (u_short *)spk_pos); @@ -1551,9 +1551,9 @@ static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag) */ is_cursor = value + 1; old_cursor_pos = vc->vc_pos; - old_cursor_x = vc->vc_x; - old_cursor_y = vc->vc_y; - speakup_console[vc->vc_num]->ht.cy = vc->vc_y; + old_cursor_x = vc->state.x; + old_cursor_y = vc->state.y; + speakup_console[vc->vc_num]->ht.cy = vc->state.y; cursor_con = vc->vc_num; if (cursor_track == CT_Highlight) reset_highlight_buffers(vc); @@ -1574,8 +1574,8 @@ static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len) i = 0; if (speakup_console[vc_num]->ht.highsize[bi] == 0) { speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos; - speakup_console[vc_num]->ht.rx[bi] = vc->vc_x; - speakup_console[vc_num]->ht.ry[bi] = vc->vc_y; + speakup_console[vc_num]->ht.rx[bi] = vc->state.x; + speakup_console[vc_num]->ht.ry[bi] = vc->state.y; } while ((hi < COLOR_BUFFER_SIZE) && (i < len)) { if (ic[i] > 32) { @@ -1664,9 +1664,9 @@ static int speak_highlight(struct vc_data *vc) return 0; hc = get_highlight_color(vc); if (hc != -1) { - d = vc->vc_y - speakup_console[vc_num]->ht.cy; + d = vc->state.y - speakup_console[vc_num]->ht.cy; if ((d == 1) || (d == -1)) - if (speakup_console[vc_num]->ht.ry[hc] != vc->vc_y) + if (speakup_console[vc_num]->ht.ry[hc] != vc->state.y) return 0; spk_parked |= 0x01; spk_do_flush(); @@ -1693,8 +1693,8 @@ static void cursor_done(struct timer_list *unused) } speakup_date(vc); if (win_enabled) { - if (vc->vc_x >= win_left && vc->vc_x <= win_right && - vc->vc_y >= win_top && vc->vc_y <= win_bottom) { + if (vc->state.x >= win_left && vc->state.x <= win_right && + vc->state.y >= win_top && vc->state.y <= win_bottom) { spk_keydown = 0; is_cursor = 0; goto out; @@ -1757,7 +1757,7 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len) if (!spin_trylock_irqsave(&speakup_info.spinlock, flags)) /* Speakup output, discard */ return; - if (spk_bell_pos && spk_keydown && (vc->vc_x == spk_bell_pos - 1)) + if (spk_bell_pos && spk_keydown && (vc->state.x == spk_bell_pos - 1)) bleep(3); if ((is_cursor) || (cursor_track == read_all_mode)) { if (cursor_track == CT_Highlight) @@ -1766,8 +1766,8 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len) return; } if (win_enabled) { - if (vc->vc_x >= win_left && vc->vc_x <= win_right && - vc->vc_y >= win_top && vc->vc_y <= win_bottom) { + if (vc->state.x >= win_left && vc->state.x <= win_right && + vc->state.y >= win_top && vc->state.y <= win_bottom) { spin_unlock_irqrestore(&speakup_info.spinlock, flags); return; } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 48a8199f7845..76f52935e0c8 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -381,7 +381,7 @@ static void vc_uniscr_putc(struct vc_data *vc, char32_t uc) struct uni_screen *uniscr = get_vc_uniscr(vc); if (uniscr) - uniscr->lines[vc->vc_y][vc->vc_x] = uc; + uniscr->lines[vc->state.y][vc->state.x] = uc; } static void vc_uniscr_insert(struct vc_data *vc, unsigned int nr) @@ -389,8 +389,8 @@ static void vc_uniscr_insert(struct vc_data *vc, unsigned int nr) struct uni_screen *uniscr = get_vc_uniscr(vc); if (uniscr) { - char32_t *ln = uniscr->lines[vc->vc_y]; - unsigned int x = vc->vc_x, cols = vc->vc_cols; + char32_t *ln = uniscr->lines[vc->state.y]; + unsigned int x = vc->state.x, cols = vc->vc_cols; memmove(&ln[x + nr], &ln[x], (cols - x - nr) * sizeof(*ln)); memset32(&ln[x], ' ', nr); @@ -402,8 +402,8 @@ static void vc_uniscr_delete(struct vc_data *vc, unsigned int nr) struct uni_screen *uniscr = get_vc_uniscr(vc); if (uniscr) { - char32_t *ln = uniscr->lines[vc->vc_y]; - unsigned int x = vc->vc_x, cols = vc->vc_cols; + char32_t *ln = uniscr->lines[vc->state.y]; + unsigned int x = vc->state.x, cols = vc->vc_cols; memcpy(&ln[x], &ln[x + nr], (cols - x - nr) * sizeof(*ln)); memset32(&ln[cols - nr], ' ', nr); @@ -416,7 +416,7 @@ static void vc_uniscr_clear_line(struct vc_data *vc, unsigned int x, struct uni_screen *uniscr = get_vc_uniscr(vc); if (uniscr) { - char32_t *ln = uniscr->lines[vc->vc_y]; + char32_t *ln = uniscr->lines[vc->state.y]; memset32(&ln[x], ' ', nr); } @@ -750,10 +750,11 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, static void update_attr(struct vc_data *vc) { - vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, - vc->vc_blink, vc->vc_underline, - vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic); - vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' '; + vc->vc_attr = build_attr(vc, vc->state.color, vc->state.intensity, + vc->state.blink, vc->state.underline, + vc->state.reverse ^ vc->vc_decscnm, vc->state.italic); + vc->vc_video_erase_char = ' ' | (build_attr(vc, vc->state.color, 1, + vc->state.blink, 0, vc->vc_decscnm, 0) << 8); } /* Note: inverting the screen twice should revert to the original state */ @@ -842,12 +843,12 @@ static void insert_char(struct vc_data *vc, unsigned int nr) unsigned short *p = (unsigned short *) vc->vc_pos; vc_uniscr_insert(vc, nr); - scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2); + scr_memmovew(p + nr, p, (vc->vc_cols - vc->state.x - nr) * 2); scr_memsetw(p, vc->vc_video_erase_char, nr * 2); vc->vc_need_wrap = 0; if (con_should_update(vc)) do_update_region(vc, (unsigned long) p, - vc->vc_cols - vc->vc_x); + vc->vc_cols - vc->state.x); } static void delete_char(struct vc_data *vc, unsigned int nr) @@ -855,13 +856,13 @@ static void delete_char(struct vc_data *vc, unsigned int nr) unsigned short *p = (unsigned short *) vc->vc_pos; vc_uniscr_delete(vc, nr); - scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2); - scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char, + scr_memcpyw(p, p + nr, (vc->vc_cols - vc->state.x - nr) * 2); + scr_memsetw(p + vc->vc_cols - vc->state.x - nr, vc->vc_video_erase_char, nr * 2); vc->vc_need_wrap = 0; if (con_should_update(vc)) do_update_region(vc, (unsigned long) p, - vc->vc_cols - vc->vc_x); + vc->vc_cols - vc->state.x); } static int softcursor_original = -1; @@ -880,7 +881,7 @@ static void add_softcursor(struct vc_data *vc) if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700; scr_writew(i, (u16 *) vc->vc_pos); if (con_should_update(vc)) - vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x); + vc->vc_sw->con_putc(vc, i, vc->state.y, vc->state.x); } static void hide_softcursor(struct vc_data *vc) @@ -889,7 +890,7 @@ static void hide_softcursor(struct vc_data *vc) scr_writew(softcursor_original, (u16 *)vc->vc_pos); if (con_should_update(vc)) vc->vc_sw->con_putc(vc, softcursor_original, - vc->vc_y, vc->vc_x); + vc->state.y, vc->state.x); softcursor_original = -1; } } @@ -927,7 +928,8 @@ static void set_origin(struct vc_data *vc) vc->vc_origin = (unsigned long)vc->vc_screenbuf; vc->vc_visible_origin = vc->vc_origin; vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size; - vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x; + vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->state.y + + 2 * vc->state.x; } static void save_screen(struct vc_data *vc) @@ -1250,8 +1252,8 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, new_origin = (long) newscreen; new_scr_end = new_origin + new_screen_size; - if (vc->vc_y > new_rows) { - if (old_rows - vc->vc_y < new_rows) { + if (vc->state.y > new_rows) { + if (old_rows - vc->state.y < new_rows) { /* * Cursor near the bottom, copy contents from the * bottom of buffer @@ -1262,7 +1264,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, * Cursor is in no man's land, copy 1/2 screenful * from the top and bottom of cursor position */ - first_copied_row = (vc->vc_y - new_rows/2); + first_copied_row = (vc->state.y - new_rows/2); } old_origin += first_copied_row * old_row_size; } else @@ -1296,7 +1298,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, /* do part of a reset_terminal() */ vc->vc_top = 0; vc->vc_bottom = vc->vc_rows; - gotoxy(vc, vc->vc_x, vc->vc_y); + gotoxy(vc, vc->state.x, vc->state.y); save_cur(vc); if (tty) { @@ -1431,12 +1433,12 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y) int min_y, max_y; if (new_x < 0) - vc->vc_x = 0; + vc->state.x = 0; else { if (new_x >= vc->vc_cols) - vc->vc_x = vc->vc_cols - 1; + vc->state.x = vc->vc_cols - 1; else - vc->vc_x = new_x; + vc->state.x = new_x; } if (vc->vc_decom) { @@ -1447,12 +1449,13 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y) max_y = vc->vc_rows; } if (new_y < min_y) - vc->vc_y = min_y; + vc->state.y = min_y; else if (new_y >= max_y) - vc->vc_y = max_y - 1; + vc->state.y = max_y - 1; else - vc->vc_y = new_y; - vc->vc_pos = vc->vc_origin + vc->vc_y * vc->vc_size_row + (vc->vc_x<<1); + vc->state.y = new_y; + vc->vc_pos = vc->vc_origin + vc->state.y * vc->vc_size_row + + (vc->state.x << 1); vc->vc_need_wrap = 0; } @@ -1479,10 +1482,10 @@ static void lf(struct vc_data *vc) /* don't scroll if above bottom of scrolling region, or * if below scrolling region */ - if (vc->vc_y + 1 == vc->vc_bottom) + if (vc->state.y + 1 == vc->vc_bottom) con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_UP, 1); - else if (vc->vc_y < vc->vc_rows - 1) { - vc->vc_y++; + else if (vc->state.y < vc->vc_rows - 1) { + vc->state.y++; vc->vc_pos += vc->vc_size_row; } vc->vc_need_wrap = 0; @@ -1494,10 +1497,10 @@ static void ri(struct vc_data *vc) /* don't scroll if below top of scrolling region, or * if above scrolling region */ - if (vc->vc_y == vc->vc_top) + if (vc->state.y == vc->vc_top) con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_DOWN, 1); - else if (vc->vc_y > 0) { - vc->vc_y--; + else if (vc->state.y > 0) { + vc->state.y--; vc->vc_pos -= vc->vc_size_row; } vc->vc_need_wrap = 0; @@ -1505,16 +1508,16 @@ static void ri(struct vc_data *vc) static inline void cr(struct vc_data *vc) { - vc->vc_pos -= vc->vc_x << 1; - vc->vc_need_wrap = vc->vc_x = 0; + vc->vc_pos -= vc->state.x << 1; + vc->vc_need_wrap = vc->state.x = 0; notify_write(vc, '\r'); } static inline void bs(struct vc_data *vc) { - if (vc->vc_x) { + if (vc->state.x) { vc->vc_pos -= 2; - vc->vc_x--; + vc->state.x--; vc->vc_need_wrap = 0; notify_write(vc, '\b'); } @@ -1532,16 +1535,16 @@ static void csi_J(struct vc_data *vc, int vpar) switch (vpar) { case 0: /* erase from cursor to end of display */ - vc_uniscr_clear_line(vc, vc->vc_x, - vc->vc_cols - vc->vc_x); - vc_uniscr_clear_lines(vc, vc->vc_y + 1, - vc->vc_rows - vc->vc_y - 1); + vc_uniscr_clear_line(vc, vc->state.x, + vc->vc_cols - vc->state.x); + vc_uniscr_clear_lines(vc, vc->state.y + 1, + vc->vc_rows - vc->state.y - 1); count = (vc->vc_scr_end - vc->vc_pos) >> 1; start = (unsigned short *)vc->vc_pos; break; case 1: /* erase from start to cursor */ - vc_uniscr_clear_line(vc, 0, vc->vc_x + 1); - vc_uniscr_clear_lines(vc, 0, vc->vc_y); + vc_uniscr_clear_line(vc, 0, vc->state.x + 1); + vc_uniscr_clear_lines(vc, 0, vc->state.y); count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; start = (unsigned short *)vc->vc_origin; break; @@ -1571,20 +1574,20 @@ static void csi_K(struct vc_data *vc, int vpar) switch (vpar) { case 0: /* erase from cursor to end of line */ offset = 0; - count = vc->vc_cols - vc->vc_x; + count = vc->vc_cols - vc->state.x; break; case 1: /* erase from start of line to cursor */ - offset = -vc->vc_x; - count = vc->vc_x + 1; + offset = -vc->state.x; + count = vc->state.x + 1; break; case 2: /* erase whole line */ - offset = -vc->vc_x; + offset = -vc->state.x; count = vc->vc_cols; break; default: return; } - vc_uniscr_clear_line(vc, vc->vc_x + offset, count); + vc_uniscr_clear_line(vc, vc->state.x + offset, count); scr_memsetw(start + offset, vc->vc_video_erase_char, 2 * count); vc->vc_need_wrap = 0; if (con_should_update(vc)) @@ -1597,23 +1600,23 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi if (!vpar) vpar++; - count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar; + count = (vpar > vc->vc_cols - vc->state.x) ? (vc->vc_cols - vc->state.x) : vpar; - vc_uniscr_clear_line(vc, vc->vc_x, count); + vc_uniscr_clear_line(vc, vc->state.x, count); scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count); if (con_should_update(vc)) - vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count); + vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, 1, count); vc->vc_need_wrap = 0; } static void default_attr(struct vc_data *vc) { - vc->vc_intensity = 1; - vc->vc_italic = 0; - vc->vc_underline = 0; - vc->vc_reverse = 0; - vc->vc_blink = 0; - vc->vc_color = vc->vc_def_color; + vc->state.intensity = 1; + vc->state.italic = 0; + vc->state.underline = 0; + vc->state.reverse = 0; + vc->state.blink = 0; + vc->state.color = vc->vc_def_color; } struct rgb { u8 r; u8 g; u8 b; }; @@ -1649,19 +1652,19 @@ static void rgb_foreground(struct vc_data *vc, const struct rgb *c) if (hue == 7 && max <= 0x55) { hue = 0; - vc->vc_intensity = 2; + vc->state.intensity = 2; } else if (max > 0xaa) - vc->vc_intensity = 2; + vc->state.intensity = 2; else - vc->vc_intensity = 1; + vc->state.intensity = 1; - vc->vc_color = (vc->vc_color & 0xf0) | hue; + vc->state.color = (vc->state.color & 0xf0) | hue; } static void rgb_background(struct vc_data *vc, const struct rgb *c) { /* For backgrounds, err on the dark side. */ - vc->vc_color = (vc->vc_color & 0x0f) + vc->state.color = (vc->state.color & 0x0f) | (c->r&0x80) >> 1 | (c->g&0x80) >> 2 | (c->b&0x80) >> 3; } @@ -1712,13 +1715,13 @@ static void csi_m(struct vc_data *vc) default_attr(vc); break; case 1: - vc->vc_intensity = 2; + vc->state.intensity = 2; break; case 2: - vc->vc_intensity = 0; + vc->state.intensity = 0; break; case 3: - vc->vc_italic = 1; + vc->state.italic = 1; break; case 21: /* @@ -1726,21 +1729,21 @@ static void csi_m(struct vc_data *vc) * convert it to a single underline. */ case 4: - vc->vc_underline = 1; + vc->state.underline = 1; break; case 5: - vc->vc_blink = 1; + vc->state.blink = 1; break; case 7: - vc->vc_reverse = 1; + vc->state.reverse = 1; break; case 10: /* ANSI X3.64-1979 (SCO-ish?) * Select primary font, don't display control chars if * defined, don't set bit 8 on output. */ - vc->vc_translate = set_translate(vc->vc_charset == 0 - ? vc->vc_G0_charset - : vc->vc_G1_charset, vc); + vc->vc_translate = set_translate(vc->state.charset == 0 + ? vc->state.G0_charset + : vc->state.G1_charset, vc); vc->vc_disp_ctrl = 0; vc->vc_toggle_meta = 0; break; @@ -1761,19 +1764,19 @@ static void csi_m(struct vc_data *vc) vc->vc_toggle_meta = 1; break; case 22: - vc->vc_intensity = 1; + vc->state.intensity = 1; break; case 23: - vc->vc_italic = 0; + vc->state.italic = 0; break; case 24: - vc->vc_underline = 0; + vc->state.underline = 0; break; case 25: - vc->vc_blink = 0; + vc->state.blink = 0; break; case 27: - vc->vc_reverse = 0; + vc->state.reverse = 0; break; case 38: i = vc_t416_color(vc, i, rgb_foreground); @@ -1782,25 +1785,25 @@ static void csi_m(struct vc_data *vc) i = vc_t416_color(vc, i, rgb_background); break; case 39: - vc->vc_color = (vc->vc_def_color & 0x0f) | - (vc->vc_color & 0xf0); + vc->state.color = (vc->vc_def_color & 0x0f) | + (vc->state.color & 0xf0); break; case 49: - vc->vc_color = (vc->vc_def_color & 0xf0) | - (vc->vc_color & 0x0f); + vc->state.color = (vc->vc_def_color & 0xf0) | + (vc->state.color & 0x0f); break; default: if (vc->vc_par[i] >= 90 && vc->vc_par[i] <= 107) { if (vc->vc_par[i] < 100) - vc->vc_intensity = 2; + vc->state.intensity = 2; vc->vc_par[i] -= 60; } if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37) - vc->vc_color = color_table[vc->vc_par[i] - 30] - | (vc->vc_color & 0xf0); + vc->state.color = color_table[vc->vc_par[i] - 30] + | (vc->state.color & 0xf0); else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47) - vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4) - | (vc->vc_color & 0x0f); + vc->state.color = (color_table[vc->vc_par[i] - 40] << 4) + | (vc->state.color & 0x0f); break; } update_attr(vc); @@ -1819,7 +1822,7 @@ static void cursor_report(struct vc_data *vc, struct tty_struct *tty) { char buf[40]; - sprintf(buf, "\033[%d;%dR", vc->vc_y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->vc_x + 1); + sprintf(buf, "\033[%d;%dR", vc->state.y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->state.x + 1); respond_string(buf, tty->port); } @@ -1924,14 +1927,14 @@ static void setterm_command(struct vc_data *vc) case 1: /* set color for underline mode */ if (vc->vc_can_do_color && vc->vc_par[1] < 16) { vc->vc_ulcolor = color_table[vc->vc_par[1]]; - if (vc->vc_underline) + if (vc->state.underline) update_attr(vc); } break; case 2: /* set color for half intensity mode */ if (vc->vc_can_do_color && vc->vc_par[1] < 16) { vc->vc_halfcolor = color_table[vc->vc_par[1]]; - if (vc->vc_intensity == 0) + if (vc->state.intensity == 0) update_attr(vc); } break; @@ -1985,8 +1988,8 @@ static void setterm_command(struct vc_data *vc) /* console_lock is held */ static void csi_at(struct vc_data *vc, unsigned int nr) { - if (nr > vc->vc_cols - vc->vc_x) - nr = vc->vc_cols - vc->vc_x; + if (nr > vc->vc_cols - vc->state.x) + nr = vc->vc_cols - vc->state.x; else if (!nr) nr = 1; insert_char(vc, nr); @@ -1995,19 +1998,19 @@ static void csi_at(struct vc_data *vc, unsigned int nr) /* console_lock is held */ static void csi_L(struct vc_data *vc, unsigned int nr) { - if (nr > vc->vc_rows - vc->vc_y) - nr = vc->vc_rows - vc->vc_y; + if (nr > vc->vc_rows - vc->state.y) + nr = vc->vc_rows - vc->state.y; else if (!nr) nr = 1; - con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_DOWN, nr); + con_scroll(vc, vc->state.y, vc->vc_bottom, SM_DOWN, nr); vc->vc_need_wrap = 0; } /* console_lock is held */ static void csi_P(struct vc_data *vc, unsigned int nr) { - if (nr > vc->vc_cols - vc->vc_x) - nr = vc->vc_cols - vc->vc_x; + if (nr > vc->vc_cols - vc->state.x) + nr = vc->vc_cols - vc->state.x; else if (!nr) nr = 1; delete_char(vc, nr); @@ -2016,44 +2019,28 @@ static void csi_P(struct vc_data *vc, unsigned int nr) /* console_lock is held */ static void csi_M(struct vc_data *vc, unsigned int nr) { - if (nr > vc->vc_rows - vc->vc_y) - nr = vc->vc_rows - vc->vc_y; + if (nr > vc->vc_rows - vc->state.y) + nr = vc->vc_rows - vc->state.y; else if (!nr) nr=1; - con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_UP, nr); + con_scroll(vc, vc->state.y, vc->vc_bottom, SM_UP, nr); vc->vc_need_wrap = 0; } /* console_lock is held (except via vc_init->reset_terminal */ static void save_cur(struct vc_data *vc) { - vc->vc_saved_x = vc->vc_x; - vc->vc_saved_y = vc->vc_y; - vc->vc_s_intensity = vc->vc_intensity; - vc->vc_s_italic = vc->vc_italic; - vc->vc_s_underline = vc->vc_underline; - vc->vc_s_blink = vc->vc_blink; - vc->vc_s_reverse = vc->vc_reverse; - vc->vc_s_charset = vc->vc_charset; - vc->vc_s_color = vc->vc_color; - vc->vc_saved_G0 = vc->vc_G0_charset; - vc->vc_saved_G1 = vc->vc_G1_charset; + memcpy(&vc->saved_state, &vc->state, sizeof(vc->state)); } /* console_lock is held */ static void restore_cur(struct vc_data *vc) { - gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y); - vc->vc_intensity = vc->vc_s_intensity; - vc->vc_italic = vc->vc_s_italic; - vc->vc_underline = vc->vc_s_underline; - vc->vc_blink = vc->vc_s_blink; - vc->vc_reverse = vc->vc_s_reverse; - vc->vc_charset = vc->vc_s_charset; - vc->vc_color = vc->vc_s_color; - vc->vc_G0_charset = vc->vc_saved_G0; - vc->vc_G1_charset = vc->vc_saved_G1; - vc->vc_translate = set_translate(vc->vc_charset ? vc->vc_G1_charset : vc->vc_G0_charset, vc); + memcpy(&vc->state, &vc->saved_state, sizeof(vc->state)); + + gotoxy(vc, vc->state.x, vc->state.y); + vc->vc_translate = set_translate(vc->state.charset ? vc->state.G1_charset : + vc->state.G0_charset, vc); update_attr(vc); vc->vc_need_wrap = 0; } @@ -2070,9 +2057,9 @@ static void reset_terminal(struct vc_data *vc, int do_clear) vc->vc_state = ESnormal; vc->vc_priv = EPecma; vc->vc_translate = set_translate(LAT1_MAP, vc); - vc->vc_G0_charset = LAT1_MAP; - vc->vc_G1_charset = GRAF_MAP; - vc->vc_charset = 0; + vc->state.G0_charset = LAT1_MAP; + vc->state.G1_charset = GRAF_MAP; + vc->state.charset = 0; vc->vc_need_wrap = 0; vc->vc_report_mouse = 0; vc->vc_utf = default_utf8; @@ -2136,13 +2123,13 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) bs(vc); return; case 9: - vc->vc_pos -= (vc->vc_x << 1); - while (vc->vc_x < vc->vc_cols - 1) { - vc->vc_x++; - if (vc->vc_tab_stop[7 & (vc->vc_x >> 5)] & (1 << (vc->vc_x & 31))) + vc->vc_pos -= (vc->state.x << 1); + while (vc->state.x < vc->vc_cols - 1) { + vc->state.x++; + if (vc->vc_tab_stop[7 & (vc->state.x >> 5)] & (1 << (vc->state.x & 31))) break; } - vc->vc_pos += (vc->vc_x << 1); + vc->vc_pos += (vc->state.x << 1); notify_write(vc, '\t'); return; case 10: case 11: case 12: @@ -2154,13 +2141,13 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) cr(vc); return; case 14: - vc->vc_charset = 1; - vc->vc_translate = set_translate(vc->vc_G1_charset, vc); + vc->state.charset = 1; + vc->vc_translate = set_translate(vc->state.G1_charset, vc); vc->vc_disp_ctrl = 1; return; case 15: - vc->vc_charset = 0; - vc->vc_translate = set_translate(vc->vc_G0_charset, vc); + vc->state.charset = 0; + vc->vc_translate = set_translate(vc->state.G0_charset, vc); vc->vc_disp_ctrl = 0; return; case 24: case 26: @@ -2200,7 +2187,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) lf(vc); return; case 'H': - vc->vc_tab_stop[7 & (vc->vc_x >> 5)] |= (1 << (vc->vc_x & 31)); + vc->vc_tab_stop[7 & (vc->state.x >> 5)] |= (1 << (vc->state.x & 31)); return; case 'Z': respond_ID(tty); @@ -2347,42 +2334,42 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) case 'G': case '`': if (vc->vc_par[0]) vc->vc_par[0]--; - gotoxy(vc, vc->vc_par[0], vc->vc_y); + gotoxy(vc, vc->vc_par[0], vc->state.y); return; case 'A': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, vc->vc_x, vc->vc_y - vc->vc_par[0]); + gotoxy(vc, vc->state.x, vc->state.y - vc->vc_par[0]); return; case 'B': case 'e': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, vc->vc_x, vc->vc_y + vc->vc_par[0]); + gotoxy(vc, vc->state.x, vc->state.y + vc->vc_par[0]); return; case 'C': case 'a': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, vc->vc_x + vc->vc_par[0], vc->vc_y); + gotoxy(vc, vc->state.x + vc->vc_par[0], vc->state.y); return; case 'D': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, vc->vc_x - vc->vc_par[0], vc->vc_y); + gotoxy(vc, vc->state.x - vc->vc_par[0], vc->state.y); return; case 'E': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, 0, vc->vc_y + vc->vc_par[0]); + gotoxy(vc, 0, vc->state.y + vc->vc_par[0]); return; case 'F': if (!vc->vc_par[0]) vc->vc_par[0]++; - gotoxy(vc, 0, vc->vc_y - vc->vc_par[0]); + gotoxy(vc, 0, vc->state.y - vc->vc_par[0]); return; case 'd': if (vc->vc_par[0]) vc->vc_par[0]--; - gotoxay(vc, vc->vc_x ,vc->vc_par[0]); + gotoxay(vc, vc->state.x ,vc->vc_par[0]); return; case 'H': case 'f': if (vc->vc_par[0]) @@ -2412,7 +2399,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) return; case 'g': if (!vc->vc_par[0]) - vc->vc_tab_stop[7 & (vc->vc_x >> 5)] &= ~(1 << (vc->vc_x & 31)); + vc->vc_tab_stop[7 & (vc->state.x >> 5)] &= ~(1 << (vc->state.x & 31)); else if (vc->vc_par[0] == 3) { vc->vc_tab_stop[0] = vc->vc_tab_stop[1] = @@ -2497,28 +2484,28 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) return; case ESsetG0: if (c == '0') - vc->vc_G0_charset = GRAF_MAP; + vc->state.G0_charset = GRAF_MAP; else if (c == 'B') - vc->vc_G0_charset = LAT1_MAP; + vc->state.G0_charset = LAT1_MAP; else if (c == 'U') - vc->vc_G0_charset = IBMPC_MAP; + vc->state.G0_charset = IBMPC_MAP; else if (c == 'K') - vc->vc_G0_charset = USER_MAP; - if (vc->vc_charset == 0) - vc->vc_translate = set_translate(vc->vc_G0_charset, vc); + vc->state.G0_charset = USER_MAP; + if (vc->state.charset == 0) + vc->vc_translate = set_translate(vc->state.G0_charset, vc); vc->vc_state = ESnormal; return; case ESsetG1: if (c == '0') - vc->vc_G1_charset = GRAF_MAP; + vc->state.G1_charset = GRAF_MAP; else if (c == 'B') - vc->vc_G1_charset = LAT1_MAP; + vc->state.G1_charset = LAT1_MAP; else if (c == 'U') - vc->vc_G1_charset = IBMPC_MAP; + vc->state.G1_charset = IBMPC_MAP; else if (c == 'K') - vc->vc_G1_charset = USER_MAP; - if (vc->vc_charset == 1) - vc->vc_translate = set_translate(vc->vc_G1_charset, vc); + vc->state.G1_charset = USER_MAP; + if (vc->state.charset == 1) + vc->vc_translate = set_translate(vc->state.G1_charset, vc); vc->vc_state = ESnormal; return; case ESosc: @@ -2572,7 +2559,7 @@ static void con_flush(struct vc_data *vc, unsigned long draw_from, return; vc->vc_sw->con_putcs(vc, (u16 *)draw_from, - (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, *draw_x); + (u16 *)draw_to - (u16 *)draw_from, vc->state.y, *draw_x); *draw_x = -1; } @@ -2788,14 +2775,14 @@ rescan_last_byte: (vc_attr << 8) + tc, (u16 *) vc->vc_pos); if (con_should_update(vc) && draw_x < 0) { - draw_x = vc->vc_x; + draw_x = vc->state.x; draw_from = vc->vc_pos; } - if (vc->vc_x == vc->vc_cols - 1) { + if (vc->state.x == vc->vc_cols - 1) { vc->vc_need_wrap = vc->vc_decawm; draw_to = vc->vc_pos + 2; } else { - vc->vc_x++; + vc->state.x++; draw_to = (vc->vc_pos += 2); } @@ -2972,25 +2959,25 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) hide_cursor(vc); start = (ushort *)vc->vc_pos; - start_x = vc->vc_x; + start_x = vc->state.x; cnt = 0; while (count--) { c = *b++; if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) { if (cnt && con_is_visible(vc)) - vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x); + vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x); cnt = 0; if (c == 8) { /* backspace */ bs(vc); start = (ushort *)vc->vc_pos; - start_x = vc->vc_x; + start_x = vc->state.x; continue; } if (c != 13) lf(vc); cr(vc); start = (ushort *)vc->vc_pos; - start_x = vc->vc_x; + start_x = vc->state.x; if (c == 10 || c == 13) continue; } @@ -2998,15 +2985,15 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos); notify_write(vc, c); cnt++; - if (vc->vc_x == vc->vc_cols - 1) { + if (vc->state.x == vc->vc_cols - 1) { vc->vc_need_wrap = 1; } else { vc->vc_pos += 2; - vc->vc_x++; + vc->state.x++; } } if (cnt && con_is_visible(vc)) - vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x); + vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x); set_cursor(vc); notify_update(vc); @@ -3401,7 +3388,7 @@ static int __init con_init(void) master_display_fg = vc = vc_cons[currcons].d; set_origin(vc); save_screen(vc); - gotoxy(vc, vc->vc_x, vc->vc_y); + gotoxy(vc, vc->state.x, vc->state.y); csi_J(vc, 0); update_screen(vc); pr_info("Console: %s %s %dx%d\n", @@ -4680,8 +4667,8 @@ EXPORT_SYMBOL_GPL(screen_pos); void getconsxy(struct vc_data *vc, unsigned char *p) { /* clamp values if they don't fit */ - p[0] = min(vc->vc_x, 0xFFu); - p[1] = min(vc->vc_y, 0xFFu); + p[0] = min(vc->state.x, 0xFFu); + p[1] = min(vc->state.y, 0xFFu); } void putconsxy(struct vc_data *vc, unsigned char *p) diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index d0d427a2f1a3..d64c5ce84125 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -488,7 +488,7 @@ static void mdacon_cursor(struct vc_data *c, int mode) return; } - mda_set_cursor(c->vc_y*mda_num_columns*2 + c->vc_x*2); + mda_set_cursor(c->state.y * mda_num_columns * 2 + c->state.x * 2); switch (c->vc_cursor_type & 0x0f) { diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 79c9bd8d3025..90083eb80515 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -132,10 +132,10 @@ static void sticon_cursor(struct vc_data *conp, int mode) { unsigned short car1; - car1 = conp->vc_screenbuf[conp->vc_x + conp->vc_y * conp->vc_cols]; + car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; switch (mode) { case CM_ERASE: - sti_putc(sticon_sti, car1, conp->vc_y, conp->vc_x); + sti_putc(sticon_sti, car1, conp->state.y, conp->state.x); break; case CM_MOVE: case CM_DRAW: @@ -146,7 +146,7 @@ static void sticon_cursor(struct vc_data *conp, int mode) case CUR_TWO_THIRDS: case CUR_BLOCK: sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), - conp->vc_y, conp->vc_x); + conp->state.y, conp->state.x); break; } break; diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 998b0de1812f..d073fa167e87 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -718,9 +718,9 @@ static void vgacon_cursor(struct vc_data *c, int mode) case CM_ERASE: write_vga(14, (c->vc_pos - vga_vram_base) / 2); if (vga_video_type >= VIDEO_TYPE_VGAC) - vgacon_set_cursor_size(c->vc_x, 31, 30); + vgacon_set_cursor_size(c->state.x, 31, 30); else - vgacon_set_cursor_size(c->vc_x, 31, 31); + vgacon_set_cursor_size(c->state.x, 31, 31); break; case CM_MOVE: @@ -728,7 +728,7 @@ static void vgacon_cursor(struct vc_data *c, int mode) write_vga(14, (c->vc_pos - vga_vram_base) / 2); switch (c->vc_cursor_type & 0x0f) { case CUR_UNDERLINE: - vgacon_set_cursor_size(c->vc_x, + vgacon_set_cursor_size(c->state.x, c->vc_font.height - (c->vc_font.height < 10 ? 2 : 3), @@ -737,21 +737,21 @@ static void vgacon_cursor(struct vc_data *c, int mode) 10 ? 1 : 2)); break; case CUR_TWO_THIRDS: - vgacon_set_cursor_size(c->vc_x, + vgacon_set_cursor_size(c->state.x, c->vc_font.height / 3, c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2)); break; case CUR_LOWER_THIRD: - vgacon_set_cursor_size(c->vc_x, + vgacon_set_cursor_size(c->state.x, (c->vc_font.height * 2) / 3, c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2)); break; case CUR_LOWER_HALF: - vgacon_set_cursor_size(c->vc_x, + vgacon_set_cursor_size(c->state.x, c->vc_font.height / 2, c->vc_font.height - (c->vc_font.height < @@ -759,12 +759,12 @@ static void vgacon_cursor(struct vc_data *c, int mode) break; case CUR_NONE: if (vga_video_type >= VIDEO_TYPE_VGAC) - vgacon_set_cursor_size(c->vc_x, 31, 30); + vgacon_set_cursor_size(c->state.x, 31, 30); else - vgacon_set_cursor_size(c->vc_x, 31, 31); + vgacon_set_cursor_size(c->state.x, 31, 31); break; default: - vgacon_set_cursor_size(c->vc_x, 1, + vgacon_set_cursor_size(c->state.x, 1, c->vc_font.height); break; } @@ -1352,8 +1352,8 @@ static void vgacon_save_screen(struct vc_data *c) * console initialization routines. */ vga_bootup_console = 1; - c->vc_x = screen_info.orig_x; - c->vc_y = screen_info.orig_y; + c->state.x = screen_info.orig_x; + c->state.y = screen_info.orig_y; } /* We can't copy in more than the size of the video buffer, diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index ca935c09a261..c750470a31ec 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -240,7 +240,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = DIV_ROUND_UP(vc->vc_font.width, 8), c; - int y = real_y(ops->p, vc->vc_y); + int y = real_y(ops->p, vc->state.y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1; char *src; @@ -286,10 +286,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, cursor.set |= FB_CUR_SETCMAP; } - if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->vc_x)) || + if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) || (ops->cursor_state.image.dy != (vc->vc_font.height * y)) || ops->cursor_reset) { - ops->cursor_state.image.dx = vc->vc_font.width * vc->vc_x; + ops->cursor_state.image.dx = vc->vc_font.width * vc->state.x; ops->cursor_state.image.dy = vc->vc_font.height * y; cursor.set |= FB_CUR_SETPOS; } diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 9d28a8e3328f..38d2a00b0ccf 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -655,11 +655,11 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, } if (!save) { int lines; - if (vc->vc_y + logo_lines >= rows) - lines = rows - vc->vc_y - 1; + if (vc->state.y + logo_lines >= rows) + lines = rows - vc->state.y - 1; else lines = logo_lines; - vc->vc_y += lines; + vc->state.y += lines; vc->vc_pos += lines * vc->vc_size_row; } } @@ -677,7 +677,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, vc->vc_size_row * rows); scr_memcpyw(q, save, logo_lines * new_cols * 2); - vc->vc_y += logo_lines; + vc->state.y += logo_lines; vc->vc_pos += logo_lines * vc->vc_size_row; kfree(save); } diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c index dfa9a8aa4509..9d06446a1a3b 100644 --- a/drivers/video/fbdev/core/fbcon_ccw.c +++ b/drivers/video/fbdev/core/fbcon_ccw.c @@ -225,7 +225,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; - int y = real_y(ops->p, vc->vc_y); + int y = real_y(ops->p, vc->state.y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1, dx, dy; char *src; @@ -284,7 +284,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, } dx = y * vc->vc_font.height; - dy = vyres - ((vc->vc_x + 1) * vc->vc_font.width); + dy = vyres - ((vc->state.x + 1) * vc->vc_font.width); if (ops->cursor_state.image.dx != dx || ops->cursor_state.image.dy != dy || diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c index ce08251bfd38..4b5f76bb01e5 100644 --- a/drivers/video/fbdev/core/fbcon_cw.c +++ b/drivers/video/fbdev/core/fbcon_cw.c @@ -208,7 +208,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; - int y = real_y(ops->p, vc->vc_y); + int y = real_y(ops->p, vc->state.y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1, dx, dy; char *src; @@ -267,7 +267,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, } dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height); - dy = vc->vc_x * vc->vc_font.width; + dy = vc->state.x * vc->vc_font.width; if (ops->cursor_state.image.dx != dx || ops->cursor_state.image.dy != dy || diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c index 1936afc78fec..7e0ae3549dc7 100644 --- a/drivers/video/fbdev/core/fbcon_ud.c +++ b/drivers/video/fbdev/core/fbcon_ud.c @@ -255,7 +255,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.width + 7) >> 3, c; - int y = real_y(ops->p, vc->vc_y); + int y = real_y(ops->p, vc->state.y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1, dx, dy; char *src; @@ -315,7 +315,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, } dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height); - dx = vxres - ((vc->vc_x * vc->vc_font.width) + vc->vc_font.width); + dx = vxres - ((vc->state.x * vc->vc_font.width) + vc->vc_font.width); if (ops->cursor_state.image.dx != dx || ops->cursor_state.image.dy != dy || diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c index 93390312957f..ac51425687e4 100644 --- a/drivers/video/fbdev/core/tileblit.c +++ b/drivers/video/fbdev/core/tileblit.c @@ -85,8 +85,8 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fb_tilecursor cursor; int use_sw = (vc->vc_cursor_type & 0x10); - cursor.sx = vc->vc_x; - cursor.sy = vc->vc_y; + cursor.sx = vc->state.x; + cursor.sy = vc->state.y; cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1; cursor.fg = fg; cursor.bg = bg; -- cgit v1.2.3 From b84ae3dc70fedf4bdee2dbfa487fd23b606fbb82 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:34 +0200 Subject: vt: introduce enum vc_intensity for intensity Introduce names (en enum) for 0, 1, and 2 constants. We now have VCI_HALF_BRIGHT, VCI_NORMAL, and VCI_BOLD instead. Apart from the cleanup, 1) the enum allows for better type checking, and 2) this saves some code. No more fiddling with bits is needed in assembly now. (OTOH, the structure is larger.) Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-2-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 32 +++++++++++++++++--------------- drivers/usb/misc/sisusbvga/sisusb_con.c | 6 +++--- drivers/video/console/mdacon.c | 5 +++-- drivers/video/console/sticon.c | 3 ++- drivers/video/console/vgacon.c | 9 +++++---- include/linux/console.h | 5 ++++- include/linux/console_struct.h | 11 +++++++++-- 7 files changed, 43 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 76f52935e0c8..71bf483e5640 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -705,8 +705,9 @@ void update_region(struct vc_data *vc, unsigned long start, int count) /* Structure of attributes is hardware-dependent */ -static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, - u8 _underline, u8 _reverse, u8 _italic) +static u8 build_attr(struct vc_data *vc, u8 _color, + enum vc_intensity _intensity, u8 _blink, u8 _underline, + u8 _reverse, u8 _italic) { if (vc->vc_sw->con_build_attr) return vc->vc_sw->con_build_attr(vc, _color, _intensity, @@ -734,13 +735,13 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, a = (a & 0xF0) | vc->vc_itcolor; else if (_underline) a = (a & 0xf0) | vc->vc_ulcolor; - else if (_intensity == 0) + else if (_intensity == VCI_HALF_BRIGHT) a = (a & 0xf0) | vc->vc_halfcolor; if (_reverse) a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77); if (_blink) a ^= 0x80; - if (_intensity == 2) + if (_intensity == VCI_BOLD) a ^= 0x08; if (vc->vc_hi_font_mask == 0x100) a <<= 1; @@ -753,8 +754,9 @@ static void update_attr(struct vc_data *vc) vc->vc_attr = build_attr(vc, vc->state.color, vc->state.intensity, vc->state.blink, vc->state.underline, vc->state.reverse ^ vc->vc_decscnm, vc->state.italic); - vc->vc_video_erase_char = ' ' | (build_attr(vc, vc->state.color, 1, - vc->state.blink, 0, vc->vc_decscnm, 0) << 8); + vc->vc_video_erase_char = ' ' | (build_attr(vc, vc->state.color, + VCI_NORMAL, vc->state.blink, 0, vc->vc_decscnm, + 0) << 8); } /* Note: inverting the screen twice should revert to the original state */ @@ -1611,7 +1613,7 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi static void default_attr(struct vc_data *vc) { - vc->state.intensity = 1; + vc->state.intensity = VCI_NORMAL; vc->state.italic = 0; vc->state.underline = 0; vc->state.reverse = 0; @@ -1652,11 +1654,11 @@ static void rgb_foreground(struct vc_data *vc, const struct rgb *c) if (hue == 7 && max <= 0x55) { hue = 0; - vc->state.intensity = 2; + vc->state.intensity = VCI_BOLD; } else if (max > 0xaa) - vc->state.intensity = 2; + vc->state.intensity = VCI_BOLD; else - vc->state.intensity = 1; + vc->state.intensity = VCI_NORMAL; vc->state.color = (vc->state.color & 0xf0) | hue; } @@ -1715,10 +1717,10 @@ static void csi_m(struct vc_data *vc) default_attr(vc); break; case 1: - vc->state.intensity = 2; + vc->state.intensity = VCI_BOLD; break; case 2: - vc->state.intensity = 0; + vc->state.intensity = VCI_HALF_BRIGHT; break; case 3: vc->state.italic = 1; @@ -1764,7 +1766,7 @@ static void csi_m(struct vc_data *vc) vc->vc_toggle_meta = 1; break; case 22: - vc->state.intensity = 1; + vc->state.intensity = VCI_NORMAL; break; case 23: vc->state.italic = 0; @@ -1795,7 +1797,7 @@ static void csi_m(struct vc_data *vc) default: if (vc->vc_par[i] >= 90 && vc->vc_par[i] <= 107) { if (vc->vc_par[i] < 100) - vc->state.intensity = 2; + vc->state.intensity = VCI_BOLD; vc->vc_par[i] -= 60; } if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37) @@ -1934,7 +1936,7 @@ static void setterm_command(struct vc_data *vc) case 2: /* set color for half intensity mode */ if (vc->vc_can_do_color && vc->vc_par[1] < 16) { vc->vc_halfcolor = color_table[vc->vc_par[1]]; - if (vc->state.intensity == 0) + if (vc->state.intensity == VCI_HALF_BRIGHT) update_attr(vc); } break; diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index cd0155310fea..c59fe641b8b5 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -302,14 +302,14 @@ sisusbcon_deinit(struct vc_data *c) /* interface routine */ static u8 -sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity, +sisusbcon_build_attr(struct vc_data *c, u8 color, enum vc_intensity intensity, u8 blink, u8 underline, u8 reverse, u8 unused) { u8 attr = color; if (underline) attr = (attr & 0xf0) | c->vc_ulcolor; - else if (intensity == 0) + else if (intensity == VCI_HALF_BRIGHT) attr = (attr & 0xf0) | c->vc_halfcolor; if (reverse) @@ -320,7 +320,7 @@ sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity, if (blink) attr ^= 0x80; - if (intensity == 2) + if (intensity == VCI_BOLD) attr ^= 0x08; return attr; diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index d64c5ce84125..e3da664df16c 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -394,7 +394,8 @@ static inline u16 mda_convert_attr(u16 ch) (ch & 0x00ff) | attr; } -static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, +static u8 mdacon_build_attr(struct vc_data *c, u8 color, + enum vc_intensity intensity, u8 blink, u8 underline, u8 reverse, u8 italic) { /* The attribute is just a bit vector: @@ -405,7 +406,7 @@ static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, * Bit 7 : blink */ - return (intensity & 3) | + return (intensity & VCI_MASK) | ((underline & 1) << 2) | ((reverse & 1) << 3) | (!!italic << 4) | diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 90083eb80515..a847067abbe5 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -288,7 +288,8 @@ static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, return ret; } -static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, +static u8 sticon_build_attr(struct vc_data *conp, u8 color, + enum vc_intensity intens, u8 blink, u8 underline, u8 reverse, u8 italic) { u8 attr = ((color & 0x70) >> 1) | ((color & 7)); diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index d073fa167e87..d0b26e2318d3 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -629,7 +629,8 @@ static void vgacon_deinit(struct vc_data *c) con_set_default_unimap(c); } -static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, +static u8 vgacon_build_attr(struct vc_data *c, u8 color, + enum vc_intensity intensity, u8 blink, u8 underline, u8 reverse, u8 italic) { u8 attr = color; @@ -639,7 +640,7 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, attr = (attr & 0xF0) | c->vc_itcolor; else if (underline) attr = (attr & 0xf0) | c->vc_ulcolor; - else if (intensity == 0) + else if (intensity == VCI_HALF_BRIGHT) attr = (attr & 0xf0) | c->vc_halfcolor; } if (reverse) @@ -648,14 +649,14 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, 0x77); if (blink) attr ^= 0x80; - if (intensity == 2) + if (intensity == VCI_BOLD) attr ^= 0x08; if (!vga_can_do_color) { if (italic) attr = (attr & 0xF8) | 0x02; else if (underline) attr = (attr & 0xf8) | 0x01; - else if (intensity == 0) + else if (intensity == VCI_HALF_BRIGHT) attr = (attr & 0xf0) | 0x08; } return attr; diff --git a/include/linux/console.h b/include/linux/console.h index 75dd20650fbe..10c04779ae49 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -35,6 +35,8 @@ enum con_scroll { SM_DOWN, }; +enum vc_intensity; + /** * struct consw - callbacks for consoles * @@ -74,7 +76,8 @@ struct consw { void (*con_scrolldelta)(struct vc_data *vc, int lines); int (*con_set_origin)(struct vc_data *vc); void (*con_save_screen)(struct vc_data *vc); - u8 (*con_build_attr)(struct vc_data *vc, u8 color, u8 intensity, + u8 (*con_build_attr)(struct vc_data *vc, u8 color, + enum vc_intensity intensity, u8 blink, u8 underline, u8 reverse, u8 italic); void (*con_invert_region)(struct vc_data *vc, u16 *p, int count); u16 *(*con_screen_pos)(struct vc_data *vc, int offset); diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 162f4337c767..e901d98790bf 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -22,6 +22,13 @@ struct uni_screen; #define NPAR 16 +enum vc_intensity { + VCI_HALF_BRIGHT, + VCI_NORMAL, + VCI_BOLD, + VCI_MASK = 0x3, +}; + /** * struct vc_state -- state of a VC * @x: cursor's x-position @@ -30,7 +37,7 @@ struct uni_screen; * @G0_charset: what's G0 slot set to (like GRAF_MAP, LAT1_MAP) * @G1_charset: what's G1 slot set to (like GRAF_MAP, LAT1_MAP) * @charset: what character set to use (0=G0 or 1=G1) - * @intensity: 0=half-bright, 1=normal, 2=bold + * @intensity: see enum vc_intensity for values * @reverse: reversed foreground/background colors * * These members are defined separately from struct vc_data as we save & @@ -46,7 +53,7 @@ struct vc_state { unsigned int charset : 1; /* attribute flags */ - unsigned int intensity : 2; + enum vc_intensity intensity; unsigned int italic : 1; unsigned int underline : 1; unsigned int blink : 1; -- cgit v1.2.3 From 77bc14f273c2dfecbf87f41fdc00345d99597e13 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:35 +0200 Subject: vc: switch state to bool The code currently uses bitfields to store true-false values. Switch all of that to bools. Apart from the cleanup, it saves 20B of code as many shifts, ANDs, and ORs became simple movzb's. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-3-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 32 ++++++++++++++++---------------- drivers/usb/misc/sisusbvga/sisusb_con.c | 3 ++- drivers/video/console/mdacon.c | 11 ++++++----- drivers/video/console/sticon.c | 3 ++- drivers/video/console/vgacon.c | 3 ++- include/linux/console.h | 2 +- include/linux/console_struct.h | 8 ++++---- 7 files changed, 33 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 71bf483e5640..26cb1fc48b27 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -706,8 +706,8 @@ void update_region(struct vc_data *vc, unsigned long start, int count) /* Structure of attributes is hardware-dependent */ static u8 build_attr(struct vc_data *vc, u8 _color, - enum vc_intensity _intensity, u8 _blink, u8 _underline, - u8 _reverse, u8 _italic) + enum vc_intensity _intensity, bool _blink, bool _underline, + bool _reverse, bool _italic) { if (vc->vc_sw->con_build_attr) return vc->vc_sw->con_build_attr(vc, _color, _intensity, @@ -755,8 +755,8 @@ static void update_attr(struct vc_data *vc) vc->state.blink, vc->state.underline, vc->state.reverse ^ vc->vc_decscnm, vc->state.italic); vc->vc_video_erase_char = ' ' | (build_attr(vc, vc->state.color, - VCI_NORMAL, vc->state.blink, 0, vc->vc_decscnm, - 0) << 8); + VCI_NORMAL, vc->state.blink, false, + vc->vc_decscnm, false) << 8); } /* Note: inverting the screen twice should revert to the original state */ @@ -1614,10 +1614,10 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi static void default_attr(struct vc_data *vc) { vc->state.intensity = VCI_NORMAL; - vc->state.italic = 0; - vc->state.underline = 0; - vc->state.reverse = 0; - vc->state.blink = 0; + vc->state.italic = false; + vc->state.underline = false; + vc->state.reverse = false; + vc->state.blink = false; vc->state.color = vc->vc_def_color; } @@ -1723,7 +1723,7 @@ static void csi_m(struct vc_data *vc) vc->state.intensity = VCI_HALF_BRIGHT; break; case 3: - vc->state.italic = 1; + vc->state.italic = true; break; case 21: /* @@ -1731,13 +1731,13 @@ static void csi_m(struct vc_data *vc) * convert it to a single underline. */ case 4: - vc->state.underline = 1; + vc->state.underline = true; break; case 5: - vc->state.blink = 1; + vc->state.blink = true; break; case 7: - vc->state.reverse = 1; + vc->state.reverse = true; break; case 10: /* ANSI X3.64-1979 (SCO-ish?) * Select primary font, don't display control chars if @@ -1769,16 +1769,16 @@ static void csi_m(struct vc_data *vc) vc->state.intensity = VCI_NORMAL; break; case 23: - vc->state.italic = 0; + vc->state.italic = false; break; case 24: - vc->state.underline = 0; + vc->state.underline = false; break; case 25: - vc->state.blink = 0; + vc->state.blink = false; break; case 27: - vc->state.reverse = 0; + vc->state.reverse = false; break; case 38: i = vc_t416_color(vc, i, rgb_foreground); diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index c59fe641b8b5..80657c49310a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -303,7 +303,8 @@ sisusbcon_deinit(struct vc_data *c) /* interface routine */ static u8 sisusbcon_build_attr(struct vc_data *c, u8 color, enum vc_intensity intensity, - u8 blink, u8 underline, u8 reverse, u8 unused) + bool blink, bool underline, bool reverse, + bool unused) { u8 attr = color; diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index e3da664df16c..00cb6245fbef 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -396,7 +396,8 @@ static inline u16 mda_convert_attr(u16 ch) static u8 mdacon_build_attr(struct vc_data *c, u8 color, enum vc_intensity intensity, - u8 blink, u8 underline, u8 reverse, u8 italic) + bool blink, bool underline, bool reverse, + bool italic) { /* The attribute is just a bit vector: * @@ -407,10 +408,10 @@ static u8 mdacon_build_attr(struct vc_data *c, u8 color, */ return (intensity & VCI_MASK) | - ((underline & 1) << 2) | - ((reverse & 1) << 3) | - (!!italic << 4) | - ((blink & 1) << 7); + (underline << 2) | + (reverse << 3) | + (italic << 4) | + (blink << 7); } static void mdacon_invert_region(struct vc_data *c, u16 *p, int count) diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index a847067abbe5..bbcdfd312c36 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -290,7 +290,8 @@ static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, static u8 sticon_build_attr(struct vc_data *conp, u8 color, enum vc_intensity intens, - u8 blink, u8 underline, u8 reverse, u8 italic) + bool blink, bool underline, bool reverse, + bool italic) { u8 attr = ((color & 0x70) >> 1) | ((color & 7)); diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index d0b26e2318d3..c1c4ce28ac5e 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -631,7 +631,8 @@ static void vgacon_deinit(struct vc_data *c) static u8 vgacon_build_attr(struct vc_data *c, u8 color, enum vc_intensity intensity, - u8 blink, u8 underline, u8 reverse, u8 italic) + bool blink, bool underline, bool reverse, + bool italic) { u8 attr = color; diff --git a/include/linux/console.h b/include/linux/console.h index 10c04779ae49..964b67912b04 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -78,7 +78,7 @@ struct consw { void (*con_save_screen)(struct vc_data *vc); u8 (*con_build_attr)(struct vc_data *vc, u8 color, enum vc_intensity intensity, - u8 blink, u8 underline, u8 reverse, u8 italic); + bool blink, bool underline, bool reverse, bool italic); void (*con_invert_region)(struct vc_data *vc, u16 *p, int count); u16 *(*con_screen_pos)(struct vc_data *vc, int offset); unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position, diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index e901d98790bf..fa1abffe64be 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -54,10 +54,10 @@ struct vc_state { /* attribute flags */ enum vc_intensity intensity; - unsigned int italic : 1; - unsigned int underline : 1; - unsigned int blink : 1; - unsigned int reverse : 1; + bool italic; + bool underline; + bool blink; + bool reverse; }; /* -- cgit v1.2.3 From b4d92b6575ac3c2d0ed8310d6b8279968dca10b8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:36 +0200 Subject: vt: deduplicate setGx code The code for setting G0 and G1 is duplicated -- for each of them. Move the code to a separate function (vc_setGx) and distinguish the two cases by a parameter. Change if-else-if to switch which allows for slightly better optimization (decision tree). Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-4-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 26cb1fc48b27..729c7c8c682b 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2103,6 +2103,30 @@ static void reset_terminal(struct vc_data *vc, int do_clear) csi_J(vc, 2); } +static void vc_setGx(struct vc_data *vc, unsigned int which, int c) +{ + unsigned char *charset = which == 0 ? &vc->state.G0_charset : + &vc->state.G1_charset; + + switch (c) { + case '0': + *charset = GRAF_MAP; + break; + case 'B': + *charset = LAT1_MAP; + break; + case 'U': + *charset = IBMPC_MAP; + break; + case 'K': + *charset = USER_MAP; + break; + } + + if (vc->state.charset == which) + vc->vc_translate = set_translate(*charset, vc); +} + /* console_lock is held */ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) { @@ -2485,29 +2509,11 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) } return; case ESsetG0: - if (c == '0') - vc->state.G0_charset = GRAF_MAP; - else if (c == 'B') - vc->state.G0_charset = LAT1_MAP; - else if (c == 'U') - vc->state.G0_charset = IBMPC_MAP; - else if (c == 'K') - vc->state.G0_charset = USER_MAP; - if (vc->state.charset == 0) - vc->vc_translate = set_translate(vc->state.G0_charset, vc); + vc_setGx(vc, 0, c); vc->vc_state = ESnormal; return; case ESsetG1: - if (c == '0') - vc->state.G1_charset = GRAF_MAP; - else if (c == 'B') - vc->state.G1_charset = LAT1_MAP; - else if (c == 'U') - vc->state.G1_charset = IBMPC_MAP; - else if (c == 'K') - vc->state.G1_charset = USER_MAP; - if (vc->state.charset == 1) - vc->vc_translate = set_translate(vc->state.G1_charset, vc); + vc_setGx(vc, 1, c); vc->vc_state = ESnormal; return; case ESosc: -- cgit v1.2.3 From b70ec4d97f4cc4f6f804ca57419d070b80a9874e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:37 +0200 Subject: vt: switch G0/1_charset to an array Declare Gx_charset[2] instead of G0_charset and G1_charset. It makes the code simpler (without ternary operators). Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-5-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 19 ++++++++----------- include/linux/console_struct.h | 6 ++---- 2 files changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 729c7c8c682b..4e79cda0c2be 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1743,9 +1743,7 @@ static void csi_m(struct vc_data *vc) * Select primary font, don't display control chars if * defined, don't set bit 8 on output. */ - vc->vc_translate = set_translate(vc->state.charset == 0 - ? vc->state.G0_charset - : vc->state.G1_charset, vc); + vc->vc_translate = set_translate(vc->state.Gx_charset[vc->state.charset], vc); vc->vc_disp_ctrl = 0; vc->vc_toggle_meta = 0; break; @@ -2041,8 +2039,8 @@ static void restore_cur(struct vc_data *vc) memcpy(&vc->state, &vc->saved_state, sizeof(vc->state)); gotoxy(vc, vc->state.x, vc->state.y); - vc->vc_translate = set_translate(vc->state.charset ? vc->state.G1_charset : - vc->state.G0_charset, vc); + vc->vc_translate = set_translate(vc->state.Gx_charset[vc->state.charset], + vc); update_attr(vc); vc->vc_need_wrap = 0; } @@ -2059,8 +2057,8 @@ static void reset_terminal(struct vc_data *vc, int do_clear) vc->vc_state = ESnormal; vc->vc_priv = EPecma; vc->vc_translate = set_translate(LAT1_MAP, vc); - vc->state.G0_charset = LAT1_MAP; - vc->state.G1_charset = GRAF_MAP; + vc->state.Gx_charset[0] = LAT1_MAP; + vc->state.Gx_charset[1] = GRAF_MAP; vc->state.charset = 0; vc->vc_need_wrap = 0; vc->vc_report_mouse = 0; @@ -2105,8 +2103,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear) static void vc_setGx(struct vc_data *vc, unsigned int which, int c) { - unsigned char *charset = which == 0 ? &vc->state.G0_charset : - &vc->state.G1_charset; + unsigned char *charset = &vc->state.Gx_charset[which]; switch (c) { case '0': @@ -2168,12 +2165,12 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) return; case 14: vc->state.charset = 1; - vc->vc_translate = set_translate(vc->state.G1_charset, vc); + vc->vc_translate = set_translate(vc->state.Gx_charset[1], vc); vc->vc_disp_ctrl = 1; return; case 15: vc->state.charset = 0; - vc->vc_translate = set_translate(vc->state.G0_charset, vc); + vc->vc_translate = set_translate(vc->state.Gx_charset[0], vc); vc->vc_disp_ctrl = 0; return; case 24: case 26: diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index fa1abffe64be..623e86689c3a 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -34,8 +34,7 @@ enum vc_intensity { * @x: cursor's x-position * @y: cursor's y-position * @color: foreground & background colors - * @G0_charset: what's G0 slot set to (like GRAF_MAP, LAT1_MAP) - * @G1_charset: what's G1 slot set to (like GRAF_MAP, LAT1_MAP) + * @Gx_charset: what's G0/G1 slot set to (like GRAF_MAP, LAT1_MAP) * @charset: what character set to use (0=G0 or 1=G1) * @intensity: see enum vc_intensity for values * @reverse: reversed foreground/background colors @@ -48,8 +47,7 @@ struct vc_state { unsigned char color; - unsigned char G0_charset; - unsigned char G1_charset; + unsigned char Gx_charset[2]; unsigned int charset : 1; /* attribute flags */ -- cgit v1.2.3 From dbee4cffa1bfe23263edde1d17cdbef0de3a6ac0 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:38 +0200 Subject: vt: convert vc_tab_stop to bitmap vc_tab_stop is used as a bitmap, but defined as an unsigned int array. Switch it to bitmap and convert all users to the bitmap interface. Note the difference in behavior! We no longer mask the top 24 bits away from x, hence we do not wrap tabs at 256th column. Instead, we silently drop attempts to set a tab behind 256 columns. And we will also seek by '\t' to the rightmost column, when behind that boundary. I do not think the original behavior was desired and that someone relies on that. If this turns out to be the case, we can change the added 'if's back to masks here and there instead... (Or we can increase the limit as fb consoles now have 240 chars here. And they could have more with higher than my resolution, of course.) Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-6-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 44 +++++++++++++++++------------------------- include/linux/console_struct.h | 3 ++- 2 files changed, 20 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 4e79cda0c2be..3adb7f409524 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2052,6 +2052,8 @@ enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey, /* console_lock is held (except via vc_init()) */ static void reset_terminal(struct vc_data *vc, int do_clear) { + unsigned int i; + vc->vc_top = 0; vc->vc_bottom = vc->vc_rows; vc->vc_state = ESnormal; @@ -2082,14 +2084,9 @@ static void reset_terminal(struct vc_data *vc, int do_clear) default_attr(vc); update_attr(vc); - vc->vc_tab_stop[0] = - vc->vc_tab_stop[1] = - vc->vc_tab_stop[2] = - vc->vc_tab_stop[3] = - vc->vc_tab_stop[4] = - vc->vc_tab_stop[5] = - vc->vc_tab_stop[6] = - vc->vc_tab_stop[7] = 0x01010101; + bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT); + for (i = 0; i < VC_TABSTOPS_COUNT; i += 8) + set_bit(i, vc->vc_tab_stop); vc->vc_bell_pitch = DEFAULT_BELL_PITCH; vc->vc_bell_duration = DEFAULT_BELL_DURATION; @@ -2147,11 +2144,13 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) return; case 9: vc->vc_pos -= (vc->state.x << 1); - while (vc->state.x < vc->vc_cols - 1) { - vc->state.x++; - if (vc->vc_tab_stop[7 & (vc->state.x >> 5)] & (1 << (vc->state.x & 31))) - break; - } + + vc->state.x = find_next_bit(vc->vc_tab_stop, + min(vc->vc_cols - 1, VC_TABSTOPS_COUNT), + vc->state.x + 1); + if (vc->state.x >= VC_TABSTOPS_COUNT) + vc->state.x = vc->vc_cols - 1; + vc->vc_pos += (vc->state.x << 1); notify_write(vc, '\t'); return; @@ -2210,7 +2209,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) lf(vc); return; case 'H': - vc->vc_tab_stop[7 & (vc->state.x >> 5)] |= (1 << (vc->state.x & 31)); + if (vc->state.x < VC_TABSTOPS_COUNT) + set_bit(vc->state.x, vc->vc_tab_stop); return; case 'Z': respond_ID(tty); @@ -2421,18 +2421,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) respond_ID(tty); return; case 'g': - if (!vc->vc_par[0]) - vc->vc_tab_stop[7 & (vc->state.x >> 5)] &= ~(1 << (vc->state.x & 31)); - else if (vc->vc_par[0] == 3) { - vc->vc_tab_stop[0] = - vc->vc_tab_stop[1] = - vc->vc_tab_stop[2] = - vc->vc_tab_stop[3] = - vc->vc_tab_stop[4] = - vc->vc_tab_stop[5] = - vc->vc_tab_stop[6] = - vc->vc_tab_stop[7] = 0; - } + if (!vc->vc_par[0] && vc->state.x < VC_TABSTOPS_COUNT) + set_bit(vc->state.x, vc->vc_tab_stop); + else if (vc->vc_par[0] == 3) + bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT); return; case 'm': csi_m(vc); diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 623e86689c3a..81f7afcd061a 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -21,6 +21,7 @@ struct uni_pagedir; struct uni_screen; #define NPAR 16 +#define VC_TABSTOPS_COUNT 256U enum vc_intensity { VCI_HALF_BRIGHT, @@ -147,7 +148,7 @@ struct vc_data { unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */ unsigned char vc_utf_count; int vc_utf_char; - unsigned int vc_tab_stop[8]; /* Tab stops. 256 columns. */ + DECLARE_BITMAP(vc_tab_stop, VC_TABSTOPS_COUNT); /* Tab stops. 256 columns. */ unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */ unsigned short * vc_translate; unsigned int vc_resize_user; /* resize request from user */ -- cgit v1.2.3 From de53ce0427cd20886b0d53555dc576702cbb1ff8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:40 +0200 Subject: vt: use tty_insert_flip_string in respond_string Pass the length of a string to respond_string and use tty_insert_flip_string instead of a loop with tty_insert_flip_char. This simplifies the processing on the tty side. The added strlens are optimized during constant folding and propagation and the result are proper constants in assembly. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-8-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 3adb7f409524..49c9d1e4067c 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1809,40 +1809,43 @@ static void csi_m(struct vc_data *vc) update_attr(vc); } -static void respond_string(const char *p, struct tty_port *port) +static void respond_string(const char *p, size_t len, struct tty_port *port) { - while (*p) { - tty_insert_flip_char(port, *p, 0); - p++; - } + tty_insert_flip_string(port, p, len); tty_schedule_flip(port); } static void cursor_report(struct vc_data *vc, struct tty_struct *tty) { char buf[40]; + int len; - sprintf(buf, "\033[%d;%dR", vc->state.y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->state.x + 1); - respond_string(buf, tty->port); + len = sprintf(buf, "\033[%d;%dR", vc->state.y + + (vc->vc_decom ? vc->vc_top + 1 : 1), + vc->state.x + 1); + respond_string(buf, len, tty->port); } static inline void status_report(struct tty_struct *tty) { - respond_string("\033[0n", tty->port); /* Terminal ok */ + static const char teminal_ok[] = "\033[0n"; + + respond_string(teminal_ok, strlen(teminal_ok), tty->port); } static inline void respond_ID(struct tty_struct *tty) { - respond_string(VT102ID, tty->port); + respond_string(VT102ID, strlen(VT102ID), tty->port); } void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry) { char buf[8]; + int len; - sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx), - (char)('!' + mry)); - respond_string(buf, tty->port); + len = sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), + (char)('!' + mrx), (char)('!' + mry)); + respond_string(buf, len, tty->port); } /* invoked via ioctl(TIOCLINUX) and through set_selection_user */ -- cgit v1.2.3 From 9a6f72d9b6c121415bc2867329fe77b0d2a52dc1 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:41 +0200 Subject: vt: get rid of VT10.ID macros VT100ID is unused, but defined twice. Kill it. VT102ID is used only in respond_ID. Define there a variable with proper type and use that instead. Then drop both defines of VT102ID too. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-9-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 11 ++++------- include/linux/console.h | 6 ------ 2 files changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 49c9d1e4067c..8d9e532f050a 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1397,12 +1397,6 @@ enum { EPecma = 0, EPdec, EPeq, EPgt, EPlt}; #define kbdapplic VC_APPLIC #define lnm VC_CRLF -/* - * this is what the terminal answers to a ESC-Z or csi0c query. - */ -#define VT100ID "\033[?1;2c" -#define VT102ID "\033[?6c" - const unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7, 8,12,10,14, 9,13,11,15 }; @@ -1835,7 +1829,10 @@ static inline void status_report(struct tty_struct *tty) static inline void respond_ID(struct tty_struct *tty) { - respond_string(VT102ID, strlen(VT102ID), tty->port); + /* terminal answer to an ESC-Z or csi0c query. */ + static const char vt102_id[] = "\033[?6c"; + + respond_string(vt102_id, strlen(vt102_id), tty->port); } void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry) diff --git a/include/linux/console.h b/include/linux/console.h index 964b67912b04..0670d3491e0e 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -24,12 +24,6 @@ struct module; struct tty_struct; struct notifier_block; -/* - * this is what the terminal answers to a ESC-Z or csi0c query. - */ -#define VT100ID "\033[?1;2c" -#define VT102ID "\033[?6c" - enum con_scroll { SM_UP, SM_DOWN, -- cgit v1.2.3 From a018180cc3485e71f7912e36bf93caa635e0e4af Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:42 +0200 Subject: vt: move vc_translate to vt.c and rename it vc_translate is used only in vt.c, so move the definition from a header there. Also, it used to be a macro, so be modern and make a static inline from it. This makes the code actually readable. And as a preparation for next patches, rename it to vc_translate_ascii. vc_translate will be a wrapper for both unicode and this one. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-10-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 14 +++++++++++++- include/linux/vt_kern.h | 3 --- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 8d9e532f050a..b86639351dd2 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2560,6 +2560,18 @@ static void con_flush(struct vc_data *vc, unsigned long draw_from, *draw_x = -1; } +static inline int vc_translate_ascii(const struct vc_data *vc, int c) +{ + if (IS_ENABLED(CONFIG_CONSOLE_TRANSLATIONS)) { + if (vc->vc_toggle_meta) + c |= 0x80; + + return vc->vc_translate[c]; + } + + return c; +} + /* acquires console_lock */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { @@ -2687,7 +2699,7 @@ rescan_last_byte: c = 0xfffd; tc = c; } else { /* no utf or alternate charset mode */ - tc = vc_translate(vc, c); + tc = vc_translate_ascii(vc, c); } param.c = tc; diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index abf5bccf906a..349e39c3ab60 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -74,8 +74,6 @@ int con_set_default_unimap(struct vc_data *vc); void con_free_unimap(struct vc_data *vc); int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); -#define vc_translate(vc, c) ((vc)->vc_translate[(c) | \ - ((vc)->vc_toggle_meta ? 0x80 : 0)]) #else static inline int con_set_trans_old(unsigned char __user *table) { @@ -124,7 +122,6 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc) return 0; } -#define vc_translate(vc, c) (c) #endif /* vt.c */ -- cgit v1.2.3 From da823b2dc03749f0d1b2d051b37f222e5a3918d7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:43 +0200 Subject: vt: use modern types in do_con_write Use bools for rescan and inverse. And true/false accordingly. Use u8 for width instead of uint8_t. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-11-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index b86639351dd2..a9e4924fa675 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2581,10 +2581,10 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co struct vc_data *vc; unsigned char vc_attr; struct vt_notifier_param param; - uint8_t rescan; - uint8_t inverse; - uint8_t width; u16 himask, charmask; + u8 width; + bool rescan; + bool inverse; if (in_interrupt()) return count; @@ -2620,8 +2620,8 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co buf++; n++; count--; - rescan = 0; - inverse = 0; + rescan = false; + inverse = false; width = 1; /* Do no translation at all in control states */ @@ -2660,7 +2660,7 @@ rescan_last_byte: /* Single ASCII byte or first byte of a sequence received */ if (vc->vc_utf_count) { /* Continuation byte expected */ - rescan = 1; + rescan = true; vc->vc_utf_count = 0; c = 0xfffd; } else if (c > 0x7f) { @@ -2746,7 +2746,7 @@ rescan_last_byte: /* Display U+FFFD. If it's not found, display an inverse question mark. */ tc = conv_uni_to_pc(vc, 0xfffd); if (tc < 0) { - inverse = 1; + inverse = true; tc = conv_uni_to_pc(vc, '?'); if (tc < 0) tc = '?'; } @@ -2807,8 +2807,8 @@ rescan_last_byte: con_flush(vc, draw_from, draw_to, &draw_x); if (rescan) { - rescan = 0; - inverse = 0; + rescan = false; + inverse = false; width = 1; c = orig; goto rescan_last_byte; -- cgit v1.2.3 From 694d8a487c8bc2a0b35b9da951b0635c6a256ea6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:44 +0200 Subject: vt: separate unicode handling into vc_translate_unicode do_con_write is complicated enough. Extract unicode handling to a separate function. For do_con_write, 249 LOCs lowered to 183 lines. Use diff -w -b to see the difference is neligible -- mostly whitespace and use of 'return's instead of 'continue's. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-12-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 149 ++++++++++++++++++++++++++++------------------------ 1 file changed, 81 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index a9e4924fa675..caaad820413a 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2572,6 +2572,85 @@ static inline int vc_translate_ascii(const struct vc_data *vc, int c) return c; } +/** + * vc_translate_unicode -- Combine UTF-8 into Unicode in @vc_utf_char + * + * @vc_utf_char is the being-constructed unicode character. + * @vc_utf_count is the number of continuation bytes still expected to arrive. + * @vc_npar is the number of continuation bytes arrived so far. + */ +static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan) +{ + static const u32 utf8_length_changes[] = { + 0x0000007f, 0x000007ff, 0x0000ffff, + 0x001fffff, 0x03ffffff, 0x7fffffff + }; + + if ((c & 0xc0) == 0x80) { + /* Continuation byte received */ + if (vc->vc_utf_count) { + vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); + vc->vc_npar++; + if (--vc->vc_utf_count) { + /* Still need some bytes */ + return -1; + } + /* Got a whole character */ + c = vc->vc_utf_char; + /* Reject overlong sequences */ + if (c <= utf8_length_changes[vc->vc_npar - 1] || + c > utf8_length_changes[vc->vc_npar]) + return 0xfffd; + } else { + /* Unexpected continuation byte */ + vc->vc_utf_count = 0; + return 0xfffd; + } + } else { + /* Single ASCII byte or first byte of a sequence received */ + if (vc->vc_utf_count) { + /* Continuation byte expected */ + *rescan = true; + vc->vc_utf_count = 0; + return 0xfffd; + } else if (c > 0x7f) { + /* First byte of a multibyte sequence received */ + vc->vc_npar = 0; + if ((c & 0xe0) == 0xc0) { + vc->vc_utf_count = 1; + vc->vc_utf_char = (c & 0x1f); + } else if ((c & 0xf0) == 0xe0) { + vc->vc_utf_count = 2; + vc->vc_utf_char = (c & 0x0f); + } else if ((c & 0xf8) == 0xf0) { + vc->vc_utf_count = 3; + vc->vc_utf_char = (c & 0x07); + } else if ((c & 0xfc) == 0xf8) { + vc->vc_utf_count = 4; + vc->vc_utf_char = (c & 0x03); + } else if ((c & 0xfe) == 0xfc) { + vc->vc_utf_count = 5; + vc->vc_utf_char = (c & 0x01); + } else { + /* 254 and 255 are invalid */ + return 0xfffd; + } + if (vc->vc_utf_count) { + /* Still need some bytes */ + return -1; + } + } + /* Nothing to do if an ASCII byte was received */ + } + /* End of UTF-8 decoding. */ + /* c is the received character, or U+FFFD for invalid sequences. */ + /* Replace invalid Unicode code points with U+FFFD too */ + if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) + return 0xfffd; + + return c; +} + /* acquires console_lock */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { @@ -2628,76 +2707,10 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co if (vc->vc_state != ESnormal) { tc = c; } else if (vc->vc_utf && !vc->vc_disp_ctrl) { - /* Combine UTF-8 into Unicode in vc_utf_char. - * vc_utf_count is the number of continuation bytes still - * expected to arrive. - * vc_npar is the number of continuation bytes arrived so - * far - */ rescan_last_byte: - if ((c & 0xc0) == 0x80) { - /* Continuation byte received */ - static const uint32_t utf8_length_changes[] = { 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff }; - if (vc->vc_utf_count) { - vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); - vc->vc_npar++; - if (--vc->vc_utf_count) { - /* Still need some bytes */ - continue; - } - /* Got a whole character */ - c = vc->vc_utf_char; - /* Reject overlong sequences */ - if (c <= utf8_length_changes[vc->vc_npar - 1] || - c > utf8_length_changes[vc->vc_npar]) - c = 0xfffd; - } else { - /* Unexpected continuation byte */ - vc->vc_utf_count = 0; - c = 0xfffd; - } - } else { - /* Single ASCII byte or first byte of a sequence received */ - if (vc->vc_utf_count) { - /* Continuation byte expected */ - rescan = true; - vc->vc_utf_count = 0; - c = 0xfffd; - } else if (c > 0x7f) { - /* First byte of a multibyte sequence received */ - vc->vc_npar = 0; - if ((c & 0xe0) == 0xc0) { - vc->vc_utf_count = 1; - vc->vc_utf_char = (c & 0x1f); - } else if ((c & 0xf0) == 0xe0) { - vc->vc_utf_count = 2; - vc->vc_utf_char = (c & 0x0f); - } else if ((c & 0xf8) == 0xf0) { - vc->vc_utf_count = 3; - vc->vc_utf_char = (c & 0x07); - } else if ((c & 0xfc) == 0xf8) { - vc->vc_utf_count = 4; - vc->vc_utf_char = (c & 0x03); - } else if ((c & 0xfe) == 0xfc) { - vc->vc_utf_count = 5; - vc->vc_utf_char = (c & 0x01); - } else { - /* 254 and 255 are invalid */ - c = 0xfffd; - } - if (vc->vc_utf_count) { - /* Still need some bytes */ + tc = c = vc_translate_unicode(vc, c, &rescan); + if (tc == -1) continue; - } - } - /* Nothing to do if an ASCII byte was received */ - } - /* End of UTF-8 decoding. */ - /* c is the received character, or U+FFFD for invalid sequences. */ - /* Replace invalid Unicode code points with U+FFFD too */ - if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) - c = 0xfffd; - tc = c; } else { /* no utf or alternate charset mode */ tc = vc_translate_ascii(vc, c); } -- cgit v1.2.3 From ede98d12b6c2bdb34efcd64369ca3ab2af304e16 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:45 +0200 Subject: vt: rearrange vc_translate_unicode The code was too overcomplicated. Extract vc_sanitize_unicode to a separate function and flatten the code. I believe the code is straightforward now. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-13-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 121 +++++++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index caaad820413a..5004242d601b 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2572,6 +2572,19 @@ static inline int vc_translate_ascii(const struct vc_data *vc, int c) return c; } + +/** + * vc_sanitize_unicode -- Replace invalid Unicode code points with U+FFFD + * @c: the received character, or U+FFFD for invalid sequences. + */ +static inline int vc_sanitize_unicode(const int c) +{ + if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) + return 0xfffd; + + return c; +} + /** * vc_translate_unicode -- Combine UTF-8 into Unicode in @vc_utf_char * @@ -2586,69 +2599,63 @@ static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan) 0x001fffff, 0x03ffffff, 0x7fffffff }; + /* Continuation byte received */ if ((c & 0xc0) == 0x80) { - /* Continuation byte received */ - if (vc->vc_utf_count) { - vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); - vc->vc_npar++; - if (--vc->vc_utf_count) { - /* Still need some bytes */ - return -1; - } - /* Got a whole character */ - c = vc->vc_utf_char; - /* Reject overlong sequences */ - if (c <= utf8_length_changes[vc->vc_npar - 1] || - c > utf8_length_changes[vc->vc_npar]) - return 0xfffd; - } else { - /* Unexpected continuation byte */ - vc->vc_utf_count = 0; + /* Unexpected continuation byte? */ + if (!vc->vc_utf_count) return 0xfffd; - } - } else { - /* Single ASCII byte or first byte of a sequence received */ - if (vc->vc_utf_count) { - /* Continuation byte expected */ - *rescan = true; - vc->vc_utf_count = 0; + + vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); + vc->vc_npar++; + if (--vc->vc_utf_count) + goto need_more_bytes; + + /* Got a whole character */ + c = vc->vc_utf_char; + /* Reject overlong sequences */ + if (c <= utf8_length_changes[vc->vc_npar - 1] || + c > utf8_length_changes[vc->vc_npar]) return 0xfffd; - } else if (c > 0x7f) { - /* First byte of a multibyte sequence received */ - vc->vc_npar = 0; - if ((c & 0xe0) == 0xc0) { - vc->vc_utf_count = 1; - vc->vc_utf_char = (c & 0x1f); - } else if ((c & 0xf0) == 0xe0) { - vc->vc_utf_count = 2; - vc->vc_utf_char = (c & 0x0f); - } else if ((c & 0xf8) == 0xf0) { - vc->vc_utf_count = 3; - vc->vc_utf_char = (c & 0x07); - } else if ((c & 0xfc) == 0xf8) { - vc->vc_utf_count = 4; - vc->vc_utf_char = (c & 0x03); - } else if ((c & 0xfe) == 0xfc) { - vc->vc_utf_count = 5; - vc->vc_utf_char = (c & 0x01); - } else { - /* 254 and 255 are invalid */ - return 0xfffd; - } - if (vc->vc_utf_count) { - /* Still need some bytes */ - return -1; - } - } - /* Nothing to do if an ASCII byte was received */ + + return vc_sanitize_unicode(c); } - /* End of UTF-8 decoding. */ - /* c is the received character, or U+FFFD for invalid sequences. */ - /* Replace invalid Unicode code points with U+FFFD too */ - if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) + + /* Single ASCII byte or first byte of a sequence received */ + if (vc->vc_utf_count) { + /* Continuation byte expected */ + *rescan = true; + vc->vc_utf_count = 0; return 0xfffd; + } - return c; + /* Nothing to do if an ASCII byte was received */ + if (c <= 0x7f) + return c; + + /* First byte of a multibyte sequence received */ + vc->vc_npar = 0; + if ((c & 0xe0) == 0xc0) { + vc->vc_utf_count = 1; + vc->vc_utf_char = (c & 0x1f); + } else if ((c & 0xf0) == 0xe0) { + vc->vc_utf_count = 2; + vc->vc_utf_char = (c & 0x0f); + } else if ((c & 0xf8) == 0xf0) { + vc->vc_utf_count = 3; + vc->vc_utf_char = (c & 0x07); + } else if ((c & 0xfc) == 0xf8) { + vc->vc_utf_count = 4; + vc->vc_utf_char = (c & 0x03); + } else if ((c & 0xfe) == 0xfc) { + vc->vc_utf_count = 5; + vc->vc_utf_char = (c & 0x01); + } else { + /* 254 and 255 are invalid */ + return 0xfffd; + } + +need_more_bytes: + return -1; } /* acquires console_lock */ -- cgit v1.2.3 From 881c8783e9608be9f86d67705dc7b5adeb3e4808 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:46 +0200 Subject: vt: extract attribute inversion to vc_invert_attr We continue cleaning up do_con_write. This (hopefully) makes the inversion code obvious. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-14-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 5004242d601b..bf171bb1d2fd 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2658,6 +2658,21 @@ need_more_bytes: return -1; } +static inline unsigned char vc_invert_attr(const struct vc_data *vc) +{ + if (!vc->vc_can_do_color) + return vc->vc_attr ^ 0x08; + + if (vc->vc_hi_font_mask == 0x100) + return (vc->vc_attr & 0x11) | + ((vc->vc_attr & 0xe0) >> 4) | + ((vc->vc_attr & 0x0e) << 4); + + return (vc->vc_attr & 0x88) | + ((vc->vc_attr & 0x70) >> 4) | + ((vc->vc_attr & 0x07) << 4); +} + /* acquires console_lock */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { @@ -2776,14 +2791,7 @@ rescan_last_byte: if (!inverse) { vc_attr = vc->vc_attr; } else { - /* invert vc_attr */ - if (!vc->vc_can_do_color) { - vc_attr = (vc->vc_attr) ^ 0x08; - } else if (vc->vc_hi_font_mask == 0x100) { - vc_attr = ((vc->vc_attr) & 0x11) | (((vc->vc_attr) & 0xe0) >> 4) | (((vc->vc_attr) & 0x0e) << 4); - } else { - vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4); - } + vc_attr = vc_invert_attr(vc); con_flush(vc, draw_from, draw_to, &draw_x); } -- cgit v1.2.3 From 0d1ffef5782628aede95d5390c658c2027c53c55 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:47 +0200 Subject: vt: move rescan_last_byte label earlier This removes duplicated initialization of variables (after reordering 'c' initialization). It will also allow for eliminating whole translation into a separate function in the next patch. Note that vc_state, vc_utf etc. are checked with every rescan now. But they are immutable for non-control characters where rescan might be only necessary. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-15-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index bf171bb1d2fd..93ad7e004900 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2717,10 +2717,11 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co while (!tty->stopped && count) { int orig = *buf; - c = orig; buf++; n++; count--; +rescan_last_byte: + c = orig; rescan = false; inverse = false; width = 1; @@ -2729,7 +2730,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co if (vc->vc_state != ESnormal) { tc = c; } else if (vc->vc_utf && !vc->vc_disp_ctrl) { -rescan_last_byte: tc = c = vc_translate_unicode(vc, c, &rescan); if (tc == -1) continue; @@ -2834,13 +2834,9 @@ rescan_last_byte: if (inverse) con_flush(vc, draw_from, draw_to, &draw_x); - if (rescan) { - rescan = false; - inverse = false; - width = 1; - c = orig; + if (rescan) goto rescan_last_byte; - } + continue; } con_flush(vc, draw_from, draw_to, &draw_x); -- cgit v1.2.3 From a4236348f4ada19e7f88b631149561bbec275d75 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:48 +0200 Subject: vc: move translation out of do_con_write Now that we reordered the code and the label, we can eliminate the translation into a separate function. We call it vc_translate here. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-16-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 93ad7e004900..0f61dc360067 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2658,6 +2658,19 @@ need_more_bytes: return -1; } +static int vc_translate(struct vc_data *vc, int *c, bool *rescan) +{ + /* Do no translation at all in control states */ + if (vc->vc_state != ESnormal) + return *c; + + if (vc->vc_utf && !vc->vc_disp_ctrl) + return *c = vc_translate_unicode(vc, *c, rescan); + + /* no utf or alternate charset mode */ + return vc_translate_ascii(vc, *c); +} + static inline unsigned char vc_invert_attr(const struct vc_data *vc) { if (!vc->vc_can_do_color) @@ -2726,16 +2739,9 @@ rescan_last_byte: inverse = false; width = 1; - /* Do no translation at all in control states */ - if (vc->vc_state != ESnormal) { - tc = c; - } else if (vc->vc_utf && !vc->vc_disp_ctrl) { - tc = c = vc_translate_unicode(vc, c, &rescan); - if (tc == -1) - continue; - } else { /* no utf or alternate charset mode */ - tc = vc_translate_ascii(vc, c); - } + tc = vc_translate(vc, &c, &rescan); + if (tc == -1) + continue; param.c = tc; if (atomic_notifier_call_chain(&vt_notifier_list, VT_PREWRITE, -- cgit v1.2.3 From 917ae1a9907bf33fe41fdfe68c6fcb03dfa07ed2 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:49 +0200 Subject: vc: introduce struct vc_draw_region For passing of draw area among functions. This makes next patches simpler. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-17-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 0f61dc360067..0c663054ab79 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2549,15 +2549,20 @@ static int is_double_width(uint32_t ucs) sizeof(struct interval), ucs_cmp) != NULL; } -static void con_flush(struct vc_data *vc, unsigned long draw_from, - unsigned long draw_to, int *draw_x) +struct vc_draw_region { + unsigned long from, to; + int x; +}; + +static void con_flush(struct vc_data *vc, struct vc_draw_region *draw) { - if (*draw_x < 0) + if (draw->x < 0) return; - vc->vc_sw->con_putcs(vc, (u16 *)draw_from, - (u16 *)draw_to - (u16 *)draw_from, vc->state.y, *draw_x); - *draw_x = -1; + vc->vc_sw->con_putcs(vc, (u16 *)draw->from, + (u16 *)draw->to - (u16 *)draw->from, vc->state.y, + draw->x); + draw->x = -1; } static inline int vc_translate_ascii(const struct vc_data *vc, int c) @@ -2689,9 +2694,11 @@ static inline unsigned char vc_invert_attr(const struct vc_data *vc) /* acquires console_lock */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { - int c, next_c, tc, ok, n = 0, draw_x = -1; + struct vc_draw_region draw = { + .x = -1, + }; + int c, next_c, tc, ok, n = 0; unsigned int currcons; - unsigned long draw_from = 0, draw_to = 0; struct vc_data *vc; unsigned char vc_attr; struct vt_notifier_param param; @@ -2798,14 +2805,13 @@ rescan_last_byte: vc_attr = vc->vc_attr; } else { vc_attr = vc_invert_attr(vc); - con_flush(vc, draw_from, draw_to, &draw_x); + con_flush(vc, &draw); } next_c = c; while (1) { if (vc->vc_need_wrap || vc->vc_decim) - con_flush(vc, draw_from, draw_to, - &draw_x); + con_flush(vc, &draw); if (vc->vc_need_wrap) { cr(vc); lf(vc); @@ -2817,16 +2823,16 @@ rescan_last_byte: ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : (vc_attr << 8) + tc, (u16 *) vc->vc_pos); - if (con_should_update(vc) && draw_x < 0) { - draw_x = vc->state.x; - draw_from = vc->vc_pos; + if (con_should_update(vc) && draw.x < 0) { + draw.x = vc->state.x; + draw.from = vc->vc_pos; } if (vc->state.x == vc->vc_cols - 1) { vc->vc_need_wrap = vc->vc_decawm; - draw_to = vc->vc_pos + 2; + draw.to = vc->vc_pos + 2; } else { vc->state.x++; - draw_to = (vc->vc_pos += 2); + draw.to = (vc->vc_pos += 2); } if (!--width) break; @@ -2838,17 +2844,17 @@ rescan_last_byte: notify_write(vc, c); if (inverse) - con_flush(vc, draw_from, draw_to, &draw_x); + con_flush(vc, &draw); if (rescan) goto rescan_last_byte; continue; } - con_flush(vc, draw_from, draw_to, &draw_x); + con_flush(vc, &draw); do_con_trol(tty, vc, orig); } - con_flush(vc, draw_from, draw_to, &draw_x); + con_flush(vc, &draw); vc_uniscr_debug_check(vc); console_conditional_schedule(); notify_update(vc); -- cgit v1.2.3 From 754bda9807f2fcc0fe32ebeaef9f6443b2151059 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:50 +0200 Subject: vc: extract detecting control characters from do_con_write Move the control characters detection to a separate function dubbed vc_is_control. It makes the 14 subexpressions a "bit" more readable. And also simplifies next patches. It moves also CTRL_ACTION and CTRL_ALWAYS to this new function, as they are used exclusively here. While at it, these are converted to static const variables. And we use "& BIT()" instead of ">>" and "& 1". Checked using symbolic execution (klee), that the old and new behaviors are the same. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-18-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 71 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 0c663054ab79..45d32844e61b 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -127,14 +127,6 @@ struct con_driver { static struct con_driver registered_con_driver[MAX_NR_CON_DRIVER]; const struct consw *conswitchp; -/* A bitmap for codes <32. A bit of 1 indicates that the code - * corresponding to that bit number invokes some special action - * (such as cursor movement) and should not be displayed as a - * glyph unless the disp_ctrl mode is explicitly enabled. - */ -#define CTRL_ACTION 0x0d00ff81 -#define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */ - /* * Here is the default bell parameters: 750HZ, 1/8th of a second */ @@ -2691,13 +2683,56 @@ static inline unsigned char vc_invert_attr(const struct vc_data *vc) ((vc->vc_attr & 0x07) << 4); } +static bool vc_is_control(struct vc_data *vc, int tc, int c) +{ + /* + * A bitmap for codes <32. A bit of 1 indicates that the code + * corresponding to that bit number invokes some special action (such + * as cursor movement) and should not be displayed as a glyph unless + * the disp_ctrl mode is explicitly enabled. + */ + static const u32 CTRL_ACTION = 0x0d00ff81; + /* Cannot be overridden by disp_ctrl */ + static const u32 CTRL_ALWAYS = 0x0800f501; + + if (vc->vc_state != ESnormal) + return true; + + if (!tc) + return true; + + /* + * If the original code was a control character we only allow a glyph + * to be displayed if the code is not normally used (such as for cursor + * movement) or if the disp_ctrl mode has been explicitly enabled. + * Certain characters (as given by the CTRL_ALWAYS bitmap) are always + * displayed as control characters, as the console would be pretty + * useless without them; to display an arbitrary font position use the + * direct-to-font zone in UTF-8 mode. + */ + if (c < 32) { + if (vc->vc_disp_ctrl) + return CTRL_ALWAYS & BIT(c); + else + return vc->vc_utf || (CTRL_ACTION & BIT(c)); + } + + if (c == 127 && !vc->vc_disp_ctrl) + return true; + + if (c == 128 + 27) + return true; + + return false; +} + /* acquires console_lock */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct vc_draw_region draw = { .x = -1, }; - int c, next_c, tc, ok, n = 0; + int c, next_c, tc, n = 0; unsigned int currcons; struct vc_data *vc; unsigned char vc_attr; @@ -2755,23 +2790,7 @@ rescan_last_byte: ¶m) == NOTIFY_STOP) continue; - /* If the original code was a control character we - * only allow a glyph to be displayed if the code is - * not normally used (such as for cursor movement) or - * if the disp_ctrl mode has been explicitly enabled. - * Certain characters (as given by the CTRL_ALWAYS - * bitmap) are always displayed as control characters, - * as the console would be pretty useless without - * them; to display an arbitrary font position use the - * direct-to-font zone in UTF-8 mode. - */ - ok = tc && (c >= 32 || - !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 : - vc->vc_utf || ((CTRL_ACTION >> c) & 1))) - && (c != 127 || vc->vc_disp_ctrl) - && (c != 128+27); - - if (vc->vc_state == ESnormal && ok) { + if (!vc_is_control(vc, tc, c)) { if (vc->vc_utf && !vc->vc_disp_ctrl) { if (is_double_width(c)) width = 2; -- cgit v1.2.3 From 391536ab775bf7d17e20e11c6f24f88d605449b2 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:51 +0200 Subject: vc: move normal char processing from do_con_write vc_con_write_normal now handles the complex normal characters processing. It is no longer a part of do_con_write. So this patch makes do_con_write pretty clean and obvious. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-19-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 198 +++++++++++++++++++++++++++++----------------------- 1 file changed, 109 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 45d32844e61b..893f72dc812c 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2726,21 +2726,116 @@ static bool vc_is_control(struct vc_data *vc, int tc, int c) return false; } +static int vc_con_write_normal(struct vc_data *vc, int tc, int c, + struct vc_draw_region *draw) +{ + int next_c; + unsigned char vc_attr; + u16 himask = vc->vc_hi_font_mask, charmask = himask ? 0x1ff : 0xff; + u8 width = 1; + bool inverse = false; + + if (vc->vc_utf && !vc->vc_disp_ctrl) { + if (is_double_width(c)) + width = 2; + } + + /* Now try to find out how to display it */ + tc = conv_uni_to_pc(vc, tc); + if (tc & ~charmask) { + if (tc == -1 || tc == -2) + return -1; /* nothing to display */ + + /* Glyph not found */ + if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && + !(c & ~charmask)) { + /* + * In legacy mode use the glyph we get by a 1:1 + * mapping. + * This would make absolutely no sense with Unicode in + * mind, but do this for ASCII characters since a font + * may lack Unicode mapping info and we don't want to + * end up with having question marks only. + */ + tc = c; + } else { + /* + * Display U+FFFD. If it's not found, display an inverse + * question mark. + */ + tc = conv_uni_to_pc(vc, 0xfffd); + if (tc < 0) { + inverse = true; + tc = conv_uni_to_pc(vc, '?'); + if (tc < 0) + tc = '?'; + } + } + } + + if (!inverse) { + vc_attr = vc->vc_attr; + } else { + vc_attr = vc_invert_attr(vc); + con_flush(vc, draw); + } + + next_c = c; + while (1) { + if (vc->vc_need_wrap || vc->vc_decim) + con_flush(vc, draw); + if (vc->vc_need_wrap) { + cr(vc); + lf(vc); + } + if (vc->vc_decim) + insert_char(vc, 1); + vc_uniscr_putc(vc, next_c); + scr_writew(himask ? + ((vc_attr << 8) & ~himask) + + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : + (vc_attr << 8) + tc, + (u16 *)vc->vc_pos); + if (con_should_update(vc) && draw->x < 0) { + draw->x = vc->state.x; + draw->from = vc->vc_pos; + } + if (vc->state.x == vc->vc_cols - 1) { + vc->vc_need_wrap = vc->vc_decawm; + draw->to = vc->vc_pos + 2; + } else { + vc->state.x++; + draw->to = (vc->vc_pos += 2); + } + + if (!--width) + break; + + /* A space is printed in the second column */ + tc = conv_uni_to_pc(vc, ' '); + if (tc < 0) + tc = ' '; + next_c = ' '; + } + notify_write(vc, c); + + if (inverse) + con_flush(vc, draw); + + return 0; +} + /* acquires console_lock */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct vc_draw_region draw = { .x = -1, }; - int c, next_c, tc, n = 0; + int c, tc, n = 0; unsigned int currcons; struct vc_data *vc; - unsigned char vc_attr; struct vt_notifier_param param; - u16 himask, charmask; - u8 width; bool rescan; - bool inverse; if (in_interrupt()) return count; @@ -2761,8 +2856,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co return 0; } - himask = vc->vc_hi_font_mask; - charmask = himask ? 0x1ff : 0xff; /* undraw cursor first */ if (con_is_fg(vc)) @@ -2778,8 +2871,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co rescan_last_byte: c = orig; rescan = false; - inverse = false; - width = 1; tc = vc_translate(vc, &c, &rescan); if (tc == -1) @@ -2790,88 +2881,17 @@ rescan_last_byte: ¶m) == NOTIFY_STOP) continue; - if (!vc_is_control(vc, tc, c)) { - if (vc->vc_utf && !vc->vc_disp_ctrl) { - if (is_double_width(c)) - width = 2; - } - /* Now try to find out how to display it */ - tc = conv_uni_to_pc(vc, tc); - if (tc & ~charmask) { - if (tc == -1 || tc == -2) { - continue; /* nothing to display */ - } - /* Glyph not found */ - if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) { - /* In legacy mode use the glyph we get by a 1:1 mapping. - This would make absolutely no sense with Unicode in mind, - but do this for ASCII characters since a font may lack - Unicode mapping info and we don't want to end up with - having question marks only. */ - tc = c; - } else { - /* Display U+FFFD. If it's not found, display an inverse question mark. */ - tc = conv_uni_to_pc(vc, 0xfffd); - if (tc < 0) { - inverse = true; - tc = conv_uni_to_pc(vc, '?'); - if (tc < 0) tc = '?'; - } - } - } - - if (!inverse) { - vc_attr = vc->vc_attr; - } else { - vc_attr = vc_invert_attr(vc); - con_flush(vc, &draw); - } - - next_c = c; - while (1) { - if (vc->vc_need_wrap || vc->vc_decim) - con_flush(vc, &draw); - if (vc->vc_need_wrap) { - cr(vc); - lf(vc); - } - if (vc->vc_decim) - insert_char(vc, 1); - vc_uniscr_putc(vc, next_c); - scr_writew(himask ? - ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : - (vc_attr << 8) + tc, - (u16 *) vc->vc_pos); - if (con_should_update(vc) && draw.x < 0) { - draw.x = vc->state.x; - draw.from = vc->vc_pos; - } - if (vc->state.x == vc->vc_cols - 1) { - vc->vc_need_wrap = vc->vc_decawm; - draw.to = vc->vc_pos + 2; - } else { - vc->state.x++; - draw.to = (vc->vc_pos += 2); - } - - if (!--width) break; - - tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */ - if (tc < 0) tc = ' '; - next_c = ' '; - } - notify_write(vc, c); - - if (inverse) - con_flush(vc, &draw); - - if (rescan) - goto rescan_last_byte; - + if (vc_is_control(vc, tc, c)) { + con_flush(vc, &draw); + do_con_trol(tty, vc, orig); continue; } - con_flush(vc, &draw); - do_con_trol(tty, vc, orig); + + if (vc_con_write_normal(vc, tc, c, &draw) < 0) + continue; + + if (rescan) + goto rescan_last_byte; } con_flush(vc, &draw); vc_uniscr_debug_check(vc); -- cgit v1.2.3 From 6923e2d793213283d808e60c390fe0b5e9090c7e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:52 +0200 Subject: vc: simplify condition in vc_con_write_normal Convert (!(A && !B) || C) into (!A || B || C) to improve readability. No functional changes, as was just proven by objdump. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-20-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 893f72dc812c..d3cd256ba0fa 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2747,7 +2747,7 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c, return -1; /* nothing to display */ /* Glyph not found */ - if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && + if ((!vc->vc_utf || vc->vc_disp_ctrl || c < 128) && !(c & ~charmask)) { /* * In legacy mode use the glyph we get by a 1:1 -- cgit v1.2.3 From f3205b29be7a18a198491004d058f3fc9d6eaf79 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:53 +0200 Subject: vt: simplify vc_attr handling in vc_con_write_normal Invert the attribute on the only place, without the need of checking 'inverse'. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-21-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index d3cd256ba0fa..72ae8ede1ac9 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2730,7 +2730,7 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c, struct vc_draw_region *draw) { int next_c; - unsigned char vc_attr; + unsigned char vc_attr = vc->vc_attr; u16 himask = vc->vc_hi_font_mask, charmask = himask ? 0x1ff : 0xff; u8 width = 1; bool inverse = false; @@ -2769,17 +2769,13 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c, tc = conv_uni_to_pc(vc, '?'); if (tc < 0) tc = '?'; + + vc_attr = vc_invert_attr(vc); + con_flush(vc, draw); } } } - if (!inverse) { - vc_attr = vc->vc_attr; - } else { - vc_attr = vc_invert_attr(vc); - con_flush(vc, draw); - } - next_c = c; while (1) { if (vc->vc_need_wrap || vc->vc_decim) -- cgit v1.2.3 From f1bcbe141381a9f715f90d61003d6b47fe084d04 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:54 +0200 Subject: vt: make tc write more obvious in vc_con_write_normal Nested ternary operators spread over 4 lines are really evil for reading. Turn the outer one to proper 'if'. Now, we see, there is a common path, so the code can be simplified. This way, the code is understandable now. Checked using symbolic execution (klee), that the old and new behaviors are the same. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-22-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 72ae8ede1ac9..4686f8b9251d 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2787,11 +2787,14 @@ static int vc_con_write_normal(struct vc_data *vc, int tc, int c, if (vc->vc_decim) insert_char(vc, 1); vc_uniscr_putc(vc, next_c); - scr_writew(himask ? - ((vc_attr << 8) & ~himask) + - ((tc & 0x100) ? himask : 0) + (tc & 0xff) : - (vc_attr << 8) + tc, - (u16 *)vc->vc_pos); + + if (himask) + tc = ((tc & 0x100) ? himask : 0) | + (tc & 0xff); + tc |= (vc_attr << 8) & ~himask; + + scr_writew(tc, (u16 *)vc->vc_pos); + if (con_should_update(vc) && draw->x < 0) { draw->x = vc->state.x; draw->from = vc->vc_pos; -- cgit v1.2.3 From e8548296d27fc5944e4d98f830dc0cb71a9da5e5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:55 +0200 Subject: vt: synchronize types and use min in csi_X All the types are unsinged ints -- even the vpar passed to the function. So unify them and use min() to compute count instead of explicit comparison. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-23-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 4686f8b9251d..b1fdbf119755 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1582,13 +1582,15 @@ static void csi_K(struct vc_data *vc, int vpar) do_update_region(vc, (unsigned long)(start + offset), count); } -static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */ +/* erase the following vpar positions */ +static void csi_X(struct vc_data *vc, unsigned int vpar) { /* not vt100? */ - int count; + unsigned int count; if (!vpar) vpar++; - count = (vpar > vc->vc_cols - vc->state.x) ? (vc->vc_cols - vc->state.x) : vpar; + + count = min(vpar, vc->vc_cols - vc->state.x); vc_uniscr_clear_line(vc, vc->state.x, count); scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count); -- cgit v1.2.3 From dc219db66ada76669b8ca23a1a9fbef703c9f6bd Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:56 +0200 Subject: vt: whitespace and paren cleanup in add_softcursor Format add_softcursor according to CodingStyle. Until now, it was a mess of letters. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-24-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index b1fdbf119755..f7d5a3c3845f 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -866,14 +866,18 @@ static void add_softcursor(struct vc_data *vc) int i = scr_readw((u16 *) vc->vc_pos); u32 type = vc->vc_cursor_type; - if (! (type & 0x10)) return; - if (softcursor_original != -1) return; + if (!(type & 0x10)) + return; + if (softcursor_original != -1) + return; softcursor_original = i; - i |= ((type >> 8) & 0xff00 ); - i ^= ((type) & 0xff00 ); - if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000; - if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700; - scr_writew(i, (u16 *) vc->vc_pos); + i |= (type >> 8) & 0xff00; + i ^= type & 0xff00; + if ((type & 0x20) && (softcursor_original & 0x7000) == (i & 0x7000)) + i ^= 0x7000; + if ((type & 0x40) && (i & 0x700) == ((i & 0x7000) >> 4)) + i ^= 0x0700; + scr_writew(i, (u16 *)vc->vc_pos); if (con_should_update(vc)) vc->vc_sw->con_putc(vc, i, vc->state.y, vc->state.x); } -- cgit v1.2.3 From 4dfa3c54f908d7ec20b88671329d6a3205d37d36 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:57 +0200 Subject: vt: redefine world of cursor macros The cursor code used to use magic constants, ANDs, ORs, and some macros. Redefine all this to make some sense. In particular: * Drop CUR_DEFAULT, which is CUR_UNDERLINE. CUR_DEFAULT was used only for cur_default variable initialization, so use CUR_UNDERLINE there to make obvious what's the default. * Drop CUR_HWMASK. Instead, define CUR_SIZE() which explains it more. And use it all over the places. * Define few more masks and bits which will be used in next patches instead of magic constants. * Define CUR_MAKE to build up cursor value. Signed-off-by: Jiri Slaby Cc: Bartlomiej Zolnierkiewicz Cc: dri-devel@lists.freedesktop.org Cc: linux-fbdev@vger.kernel.org Link: https://lore.kernel.org/r/20200615074910.19267-25-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 2 +- drivers/video/fbdev/core/bitblit.c | 2 +- drivers/video/fbdev/core/fbcon_ccw.c | 2 +- drivers/video/fbdev/core/fbcon_cw.c | 2 +- drivers/video/fbdev/core/fbcon_ud.c | 2 +- include/linux/console_struct.h | 28 +++++++++++++++++----------- 6 files changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index f7d5a3c3845f..af1ef717f416 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -163,7 +163,7 @@ module_param(default_utf8, int, S_IRUGO | S_IWUSR); int global_cursor_default = -1; module_param(global_cursor_default, int, S_IRUGO | S_IWUSR); -static int cur_default = CUR_DEFAULT; +static int cur_default = CUR_UNDERLINE; module_param(cur_default, int, S_IRUGO | S_IWUSR); /* diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index c750470a31ec..3b002b365a5a 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -325,7 +325,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (ops->p->cursor_shape & CUR_HWMASK) { + switch (CUR_SIZE(ops->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c index 9d06446a1a3b..5b67bcebe34c 100644 --- a/drivers/video/fbdev/core/fbcon_ccw.c +++ b/drivers/video/fbdev/core/fbcon_ccw.c @@ -325,7 +325,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (ops->p->cursor_shape & CUR_HWMASK) { + switch (CUR_SIZE(ops->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c index 4b5f76bb01e5..f1aab3ae3bc9 100644 --- a/drivers/video/fbdev/core/fbcon_cw.c +++ b/drivers/video/fbdev/core/fbcon_cw.c @@ -308,7 +308,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (ops->p->cursor_shape & CUR_HWMASK) { + switch (CUR_SIZE(ops->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c index 7e0ae3549dc7..81ed6f6bed67 100644 --- a/drivers/video/fbdev/core/fbcon_ud.c +++ b/drivers/video/fbdev/core/fbcon_ud.c @@ -348,7 +348,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, ops->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (ops->p->cursor_shape & CUR_HWMASK) { + switch (CUR_SIZE(ops->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 40ed52f67bc5..153734816b49 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -173,17 +173,23 @@ struct vc { extern struct vc vc_cons [MAX_NR_CONSOLES]; extern void vc_SAK(struct work_struct *work); -#define CUR_DEF 0 -#define CUR_NONE 1 -#define CUR_UNDERLINE 2 -#define CUR_LOWER_THIRD 3 -#define CUR_LOWER_HALF 4 -#define CUR_TWO_THIRDS 5 -#define CUR_BLOCK 6 -#define CUR_HWMASK 0x0f -#define CUR_SWMASK 0xfff0 - -#define CUR_DEFAULT CUR_UNDERLINE +#define CUR_MAKE(size, change, set) ((size) | ((change) << 8) | \ + ((set) << 16)) +#define CUR_SIZE(c) ((c) & 0x00000f) +# define CUR_DEF 0 +# define CUR_NONE 1 +# define CUR_UNDERLINE 2 +# define CUR_LOWER_THIRD 3 +# define CUR_LOWER_HALF 4 +# define CUR_TWO_THIRDS 5 +# define CUR_BLOCK 6 +#define CUR_SW 0x000010 +#define CUR_ALWAYS_BG 0x000020 +#define CUR_INVERT_FG_BG 0x000040 +#define CUR_FG 0x000700 +#define CUR_BG 0x007000 +#define CUR_CHANGE(c) ((c) & 0x00ff00) +#define CUR_SET(c) (((c) & 0xff0000) >> 8) bool con_is_visible(const struct vc_data *vc); -- cgit v1.2.3 From c0e4b3ad67997a6756ce0d22335b190baaa9914a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:58 +0200 Subject: vt: use newly defined CUR_* macros We defined macros for all the magic constants in the previous patch. So let us use the macro in the code now. No functional change intended. Signed-off-by: Jiri Slaby Cc: Thomas Winischhofer Cc: Bartlomiej Zolnierkiewicz Cc: "James E.J. Bottomley" Cc: Helge Deller Cc: linux-usb@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-fbdev@vger.kernel.org Cc: linux-parisc@vger.kernel.org Acked-by: Helge Deller Link: https://lore.kernel.org/r/20200615074910.19267-26-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 22 +++++++++++++--------- drivers/usb/misc/sisusbvga/sisusb_con.c | 2 +- drivers/video/console/mdacon.c | 2 +- drivers/video/console/sticon.c | 2 +- drivers/video/console/vgacon.c | 2 +- drivers/video/fbdev/core/bitblit.c | 2 +- drivers/video/fbdev/core/fbcon.c | 2 +- drivers/video/fbdev/core/fbcon_ccw.c | 2 +- drivers/video/fbdev/core/fbcon_cw.c | 2 +- drivers/video/fbdev/core/fbcon_ud.c | 2 +- drivers/video/fbdev/core/tileblit.c | 2 +- 11 files changed, 23 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index af1ef717f416..2b9fc628f05b 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -866,17 +866,18 @@ static void add_softcursor(struct vc_data *vc) int i = scr_readw((u16 *) vc->vc_pos); u32 type = vc->vc_cursor_type; - if (!(type & 0x10)) + if (!(type & CUR_SW)) return; if (softcursor_original != -1) return; softcursor_original = i; - i |= (type >> 8) & 0xff00; - i ^= type & 0xff00; - if ((type & 0x20) && (softcursor_original & 0x7000) == (i & 0x7000)) - i ^= 0x7000; - if ((type & 0x40) && (i & 0x700) == ((i & 0x7000) >> 4)) - i ^= 0x0700; + i |= CUR_SET(type); + i ^= CUR_CHANGE(type); + if ((type & CUR_ALWAYS_BG) && + (softcursor_original & CUR_BG) == (i & CUR_BG)) + i ^= CUR_BG; + if ((type & CUR_INVERT_FG_BG) && (i & CUR_FG) == ((i & CUR_BG) >> 4)) + i ^= CUR_FG; scr_writew(i, (u16 *)vc->vc_pos); if (con_should_update(vc)) vc->vc_sw->con_putc(vc, i, vc->state.y, vc->state.x); @@ -910,7 +911,7 @@ static void set_cursor(struct vc_data *vc) if (vc_is_sel(vc)) clear_selection(); add_softcursor(vc); - if ((vc->vc_cursor_type & 0x0f) != 1) + if (CUR_SIZE(vc->vc_cursor_type) != CUR_NONE) vc->vc_sw->con_cursor(vc, CM_DRAW); } else hide_cursor(vc); @@ -2322,7 +2323,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) case 'c': if (vc->vc_priv == EPdec) { if (vc->vc_par[0]) - vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16); + vc->vc_cursor_type = + CUR_MAKE(vc->vc_par[0], + vc->vc_par[1], + vc->vc_par[2]); else vc->vc_cursor_type = cur_default; return; diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 80657c49310a..1058eaba3084 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -727,7 +727,7 @@ sisusbcon_cursor(struct vc_data *c, int mode) baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2); - switch (c->vc_cursor_type & 0x0f) { + switch (CUR_SIZE(c->vc_cursor_type)) { case CUR_BLOCK: from = 1; to = c->vc_font.height; break; diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 00cb6245fbef..ef29b321967f 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -492,7 +492,7 @@ static void mdacon_cursor(struct vc_data *c, int mode) mda_set_cursor(c->state.y * mda_num_columns * 2 + c->state.x * 2); - switch (c->vc_cursor_type & 0x0f) { + switch (CUR_SIZE(c->vc_cursor_type)) { case CUR_LOWER_THIRD: mda_set_cursor_size(10, 13); break; case CUR_LOWER_HALF: mda_set_cursor_size(7, 13); break; diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index bbcdfd312c36..21a5c280c8c9 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -139,7 +139,7 @@ static void sticon_cursor(struct vc_data *conp, int mode) break; case CM_MOVE: case CM_DRAW: - switch (conp->vc_cursor_type & 0x0f) { + switch (CUR_SIZE(conp->vc_cursor_type)) { case CUR_UNDERLINE: case CUR_LOWER_THIRD: case CUR_LOWER_HALF: diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index c1c4ce28ac5e..f0f3d573f848 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -728,7 +728,7 @@ static void vgacon_cursor(struct vc_data *c, int mode) case CM_MOVE: case CM_DRAW: write_vga(14, (c->vc_pos - vga_vram_base) / 2); - switch (c->vc_cursor_type & 0x0f) { + switch (CUR_SIZE(c->vc_cursor_type)) { case CUR_UNDERLINE: vgacon_set_cursor_size(c->state.x, c->vc_font.height - diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index 3b002b365a5a..dde8004d8610 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -241,7 +241,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = DIV_ROUND_UP(vc->vc_font.width, 8), c; int y = real_y(ops->p, vc->state.y); - int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1; char *src; diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 38d2a00b0ccf..86fe41b1deb8 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -1393,7 +1393,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode) if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1) return; - if (vc->vc_cursor_type & 0x10) + if (vc->vc_cursor_type & CUR_SW) fbcon_del_cursor_timer(info); else fbcon_add_cursor_timer(info); diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c index 5b67bcebe34c..b5dd8317086d 100644 --- a/drivers/video/fbdev/core/fbcon_ccw.c +++ b/drivers/video/fbdev/core/fbcon_ccw.c @@ -226,7 +226,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; int y = real_y(ops->p, vc->state.y); - int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1, dx, dy; char *src; u32 vyres = GETVYRES(ops->p->scrollmode, info); diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c index f1aab3ae3bc9..dbb5dbf3dd01 100644 --- a/drivers/video/fbdev/core/fbcon_cw.c +++ b/drivers/video/fbdev/core/fbcon_cw.c @@ -209,7 +209,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; int y = real_y(ops->p, vc->state.y); - int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1, dx, dy; char *src; u32 vxres = GETVXRES(ops->p->scrollmode, info); diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c index 81ed6f6bed67..b2c9cdbcc9e4 100644 --- a/drivers/video/fbdev/core/fbcon_ud.c +++ b/drivers/video/fbdev/core/fbcon_ud.c @@ -256,7 +256,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.width + 7) >> 3, c; int y = real_y(ops->p, vc->state.y); - int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1, dx, dy; char *src; u32 vyres = GETVYRES(ops->p->scrollmode, info); diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c index ac51425687e4..1dfaff0881fb 100644 --- a/drivers/video/fbdev/core/tileblit.c +++ b/drivers/video/fbdev/core/tileblit.c @@ -83,7 +83,7 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode, int softback_lines, int fg, int bg) { struct fb_tilecursor cursor; - int use_sw = (vc->vc_cursor_type & 0x10); + int use_sw = vc->vc_cursor_type & CUR_SW; cursor.sx = vc->state.x; cursor.sy = vc->state.y; -- cgit v1.2.3 From faace51b63ea258e95c2a168f65af193d41279d0 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:48:59 +0200 Subject: vt: remove superfluous parens in invert_screen and build_attr There were too many parentheses in invert_screen, remove them and align the code in invert_screen a bit. No functional change intended. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-27-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 2b9fc628f05b..3aff2e3cf5a6 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -730,7 +730,7 @@ static u8 build_attr(struct vc_data *vc, u8 _color, else if (_intensity == VCI_HALF_BRIGHT) a = (a & 0xf0) | vc->vc_halfcolor; if (_reverse) - a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77); + a = (a & 0x88) | (((a >> 4) | (a << 4)) & 0x77); if (_blink) a ^= 0x80; if (_intensity == VCI_BOLD) @@ -777,14 +777,18 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed) } else if (vc->vc_hi_font_mask == 0x100) { while (cnt--) { a = scr_readw(q); - a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4); + a = (a & 0x11ff) | + ((a & 0xe000) >> 4) | + ((a & 0x0e00) << 4); scr_writew(a, q); q++; } } else { while (cnt--) { a = scr_readw(q); - a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4); + a = (a & 0x88ff) | + ((a & 0x7000) >> 4) | + ((a & 0x0700) << 4); scr_writew(a, q); q++; } -- cgit v1.2.3 From c5c717e7a593558160b939dba4091e1ebbaf3778 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:00 +0200 Subject: vt: simplify noncolor attributes in build_attr All the attributes are bools, so do a simple shift instead of tests and constants as bool is either 0 or 1. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-28-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 3aff2e3cf5a6..673177d4e859 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -719,10 +719,10 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 a = _color; if (!vc->vc_can_do_color) return _intensity | - (_italic ? 2 : 0) | - (_underline ? 4 : 0) | - (_reverse ? 8 : 0) | - (_blink ? 0x80 : 0); + (_italic << 1) | + (_underline << 2) | + (_reverse << 3) | + (_blink << 7); if (_italic) a = (a & 0xF0) | vc->vc_itcolor; else if (_underline) -- cgit v1.2.3 From 0ce8179e248023606980823d970252e715f9f504 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:01 +0200 Subject: vt_ioctl: eliminate ret & breaks in vt_ioctl This is still a leftover from BKL, when we locked it around vt_ioctl's code. We can return instead of breaks in the switch loop. And we can return in case of errors too. This allows for sifting of the code to the left in some cases. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-29-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 318 +++++++++++++++++++--------------------------- 1 file changed, 133 insertions(+), 185 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index daf61c28ba76..87fe088c3eb4 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -357,7 +357,7 @@ int vt_ioctl(struct tty_struct *tty, unsigned int uival; void __user *up = (void __user *)arg; int i, perm; - int ret = 0; + int ret; /* * To have permissions to do most of the vt ioctls, we either have @@ -369,8 +369,7 @@ int vt_ioctl(struct tty_struct *tty, switch (cmd) { case TIOCLINUX: - ret = tioclinux(tty, arg); - break; + return tioclinux(tty, arg); case KIOCSOUND: if (!perm) return -EPERM; @@ -408,8 +407,7 @@ int vt_ioctl(struct tty_struct *tty, * this is naïve. */ ucval = KB_101; - ret = put_user(ucval, (char __user *)arg); - break; + return put_user(ucval, (char __user *)arg); /* * These cannot be implemented on any machine that implements @@ -426,18 +424,15 @@ int vt_ioctl(struct tty_struct *tty, * * These are locked internally via sys_ioperm */ - if (arg < GPFIRST || arg > GPLAST) { - ret = -EINVAL; - break; - } - ret = ksys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; - break; + if (arg < GPFIRST || arg > GPLAST) + return -EINVAL; + + return ksys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; case KDENABIO: case KDDISABIO: - ret = ksys_ioperm(GPFIRST, GPNUM, + return ksys_ioperm(GPFIRST, GPNUM, (cmd == KDENABIO)) ? -ENXIO : 0; - break; #endif /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */ @@ -449,15 +444,14 @@ int vt_ioctl(struct tty_struct *tty, if (!capable(CAP_SYS_TTY_CONFIG)) return -EPERM; - if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) { - ret = -EFAULT; - break; - } + if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) + return -EFAULT; + ret = kbd_rate(&kbrep); if (ret) - break; + return ret; if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat))) - ret = -EFAULT; + return -EFAULT; break; } @@ -481,8 +475,7 @@ int vt_ioctl(struct tty_struct *tty, case KD_TEXT: break; default: - ret = -EINVAL; - goto out; + return -EINVAL; } /* FIXME: this needs the console lock extending */ if (vc->vc_mode == (unsigned char) arg) @@ -511,51 +504,45 @@ int vt_ioctl(struct tty_struct *tty, * these work like a combination of mmap and KDENABIO. * this could be easily finished. */ - ret = -EINVAL; - break; + return -EINVAL; case KDSKBMODE: if (!perm) return -EPERM; ret = vt_do_kdskbmode(console, arg); - if (ret == 0) - tty_ldisc_flush(tty); + if (ret) + return ret; + tty_ldisc_flush(tty); break; case KDGKBMODE: uival = vt_do_kdgkbmode(console); - ret = put_user(uival, (int __user *)arg); - break; + return put_user(uival, (int __user *)arg); /* this could be folded into KDSKBMODE, but for compatibility reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ case KDSKBMETA: - ret = vt_do_kdskbmeta(console, arg); - break; + return vt_do_kdskbmeta(console, arg); case KDGKBMETA: /* FIXME: should review whether this is worth locking */ uival = vt_do_kdgkbmeta(console); setint: - ret = put_user(uival, (int __user *)arg); - break; + return put_user(uival, (int __user *)arg); case KDGETKEYCODE: case KDSETKEYCODE: if(!capable(CAP_SYS_TTY_CONFIG)) perm = 0; - ret = vt_do_kbkeycode_ioctl(cmd, up, perm); - break; + return vt_do_kbkeycode_ioctl(cmd, up, perm); case KDGKBENT: case KDSKBENT: - ret = vt_do_kdsk_ioctl(cmd, up, perm, console); - break; + return vt_do_kdsk_ioctl(cmd, up, perm, console); case KDGKBSENT: case KDSKBSENT: - ret = vt_do_kdgkb_ioctl(cmd, up, perm); - break; + return vt_do_kdgkb_ioctl(cmd, up, perm); /* Diacritical processing. Handled in keyboard.c as it has to operate on the keyboard locks and structures */ @@ -563,8 +550,7 @@ int vt_ioctl(struct tty_struct *tty, case KDGKBDIACRUC: case KDSKBDIACR: case KDSKBDIACRUC: - ret = vt_do_diacrit(cmd, up, perm); - break; + return vt_do_diacrit(cmd, up, perm); /* the ioctls below read/set the flags usually shown in the leds */ /* don't use them - they will go away without warning */ @@ -572,8 +558,7 @@ int vt_ioctl(struct tty_struct *tty, case KDSKBLED: case KDGETLED: case KDSETLED: - ret = vt_do_kdskled(console, cmd, arg, perm); - break; + return vt_do_kdskled(console, cmd, arg, perm); /* * A process can indicate its willingness to accept signals @@ -583,20 +568,17 @@ int vt_ioctl(struct tty_struct *tty, * See also the kbrequest field of inittab(5). */ case KDSIGACCEPT: - { if (!perm || !capable(CAP_KILL)) return -EPERM; if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) - ret = -EINVAL; - else { - spin_lock_irq(&vt_spawn_con.lock); - put_pid(vt_spawn_con.pid); - vt_spawn_con.pid = get_pid(task_pid(current)); - vt_spawn_con.sig = arg; - spin_unlock_irq(&vt_spawn_con.lock); - } + return -EINVAL; + + spin_lock_irq(&vt_spawn_con.lock); + put_pid(vt_spawn_con.pid); + vt_spawn_con.pid = get_pid(task_pid(current)); + vt_spawn_con.sig = arg; + spin_unlock_irq(&vt_spawn_con.lock); break; - } case VT_SETMODE: { @@ -604,14 +586,11 @@ int vt_ioctl(struct tty_struct *tty, if (!perm) return -EPERM; - if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) { - ret = -EFAULT; - goto out; - } - if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) { - ret = -EINVAL; - goto out; - } + if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) + return -EFAULT; + if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) + return -EINVAL; + console_lock(); vc->vt_mode = tmp; /* the frsig is ignored, so we set it to 0 */ @@ -635,7 +614,7 @@ int vt_ioctl(struct tty_struct *tty, rc = copy_to_user(up, &tmp, sizeof(struct vt_mode)); if (rc) - ret = -EFAULT; + return -EFAULT; break; } @@ -650,18 +629,16 @@ int vt_ioctl(struct tty_struct *tty, unsigned short state, mask; if (put_user(fg_console + 1, &vtstat->v_active)) - ret = -EFAULT; - else { - state = 1; /* /dev/tty0 is always open */ - console_lock(); /* required by vt_in_use() */ - for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; - ++i, mask <<= 1) - if (vt_in_use(i)) - state |= mask; - console_unlock(); - ret = put_user(state, &vtstat->v_state); - } - break; + return -EFAULT; + + state = 1; /* /dev/tty0 is always open */ + console_lock(); /* required by vt_in_use() */ + for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; + ++i, mask <<= 1) + if (vt_in_use(i)) + state |= mask; + console_unlock(); + return put_user(state, &vtstat->v_state); } /* @@ -685,56 +662,54 @@ int vt_ioctl(struct tty_struct *tty, if (!perm) return -EPERM; if (arg == 0 || arg > MAX_NR_CONSOLES) - ret = -ENXIO; - else { - arg--; - console_lock(); - ret = vc_allocate(arg); - console_unlock(); - if (ret) - break; - set_console(arg); - } + return -ENXIO; + + arg--; + console_lock(); + ret = vc_allocate(arg); + console_unlock(); + if (ret) + return ret; + set_console(arg); break; case VT_SETACTIVATE: { struct vt_setactivate vsa; + struct vc_data *nvc; if (!perm) return -EPERM; if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg, - sizeof(struct vt_setactivate))) { - ret = -EFAULT; - goto out; - } + sizeof(struct vt_setactivate))) + return -EFAULT; if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) - ret = -ENXIO; - else { - vsa.console = array_index_nospec(vsa.console, - MAX_NR_CONSOLES + 1); - vsa.console--; - console_lock(); - ret = vc_allocate(vsa.console); - if (ret == 0) { - struct vc_data *nvc; - /* This is safe providing we don't drop the - console sem between vc_allocate and - finishing referencing nvc */ - nvc = vc_cons[vsa.console].d; - nvc->vt_mode = vsa.mode; - nvc->vt_mode.frsig = 0; - put_pid(nvc->vt_pid); - nvc->vt_pid = get_pid(task_pid(current)); - } + return -ENXIO; + + vsa.console = array_index_nospec(vsa.console, + MAX_NR_CONSOLES + 1); + vsa.console--; + console_lock(); + ret = vc_allocate(vsa.console); + if (ret) { console_unlock(); - if (ret) - break; - /* Commence switch and lock */ - /* Review set_console locks */ - set_console(vsa.console); + return ret; } + + /* This is safe providing we don't drop the + console sem between vc_allocate and + finishing referencing nvc */ + nvc = vc_cons[vsa.console].d; + nvc->vt_mode = vsa.mode; + nvc->vt_mode.frsig = 0; + put_pid(nvc->vt_pid); + nvc->vt_pid = get_pid(task_pid(current)); + console_unlock(); + + /* Commence switch and lock */ + /* Review set_console locks */ + set_console(vsa.console); break; } @@ -745,10 +720,8 @@ int vt_ioctl(struct tty_struct *tty, if (!perm) return -EPERM; if (arg == 0 || arg > MAX_NR_CONSOLES) - ret = -ENXIO; - else - ret = vt_waitactive(arg); - break; + return -ENXIO; + return vt_waitactive(arg); /* * If a vt is under process control, the kernel will not switch to it @@ -767,8 +740,7 @@ int vt_ioctl(struct tty_struct *tty, console_lock(); if (vc->vt_mode.mode != VT_PROCESS) { console_unlock(); - ret = -EINVAL; - break; + return -EINVAL; } /* * Switching-from response @@ -792,7 +764,7 @@ int vt_ioctl(struct tty_struct *tty, ret = vc_allocate(newvt); if (ret) { console_unlock(); - break; + return ret; } /* * When we actually do the console switch, @@ -808,8 +780,10 @@ int vt_ioctl(struct tty_struct *tty, /* * If it's just an ACK, ignore it */ - if (arg != VT_ACKACQ) - ret = -EINVAL; + if (arg != VT_ACKACQ) { + console_unlock(); + return -EINVAL; + } } console_unlock(); break; @@ -818,40 +792,38 @@ int vt_ioctl(struct tty_struct *tty, * Disallocate memory associated to VT (but leave VT1) */ case VT_DISALLOCATE: - if (arg > MAX_NR_CONSOLES) { - ret = -ENXIO; - break; - } + if (arg > MAX_NR_CONSOLES) + return -ENXIO; + if (arg == 0) vt_disallocate_all(); else - ret = vt_disallocate(--arg); + return vt_disallocate(--arg); break; case VT_RESIZE: { struct vt_sizes __user *vtsizes = up; struct vc_data *vc; - ushort ll,cc; + if (!perm) return -EPERM; if (get_user(ll, &vtsizes->v_rows) || get_user(cc, &vtsizes->v_cols)) - ret = -EFAULT; - else { - console_lock(); - for (i = 0; i < MAX_NR_CONSOLES; i++) { - vc = vc_cons[i].d; + return -EFAULT; - if (vc) { - vc->vc_resize_user = 1; - /* FIXME: review v tty lock */ - vc_resize(vc_cons[i].d, cc, ll); - } + console_lock(); + for (i = 0; i < MAX_NR_CONSOLES; i++) { + vc = vc_cons[i].d; + + if (vc) { + vc->vc_resize_user = 1; + /* FIXME: review v tty lock */ + vc_resize(vc_cons[i].d, cc, ll); } - console_unlock(); } + console_unlock(); break; } @@ -905,7 +877,7 @@ int vt_ioctl(struct tty_struct *tty, break; } - case PIO_FONT: { + case PIO_FONT: if (!perm) return -EPERM; op.op = KD_FONT_OP_SET; @@ -914,98 +886,77 @@ int vt_ioctl(struct tty_struct *tty, op.height = 0; op.charcount = 256; op.data = up; - ret = con_font_op(vc_cons[fg_console].d, &op); - break; - } + return con_font_op(vc_cons[fg_console].d, &op); - case GIO_FONT: { + case GIO_FONT: op.op = KD_FONT_OP_GET; op.flags = KD_FONT_FLAG_OLD; op.width = 8; op.height = 32; op.charcount = 256; op.data = up; - ret = con_font_op(vc_cons[fg_console].d, &op); - break; - } + return con_font_op(vc_cons[fg_console].d, &op); case PIO_CMAP: if (!perm) - ret = -EPERM; - else - ret = con_set_cmap(up); - break; + return -EPERM; + return con_set_cmap(up); case GIO_CMAP: - ret = con_get_cmap(up); - break; + return con_get_cmap(up); case PIO_FONTX: case GIO_FONTX: - ret = do_fontx_ioctl(cmd, up, perm, &op); - break; + return do_fontx_ioctl(cmd, up, perm, &op); case PIO_FONTRESET: - { if (!perm) return -EPERM; #ifdef BROKEN_GRAPHICS_PROGRAMS /* With BROKEN_GRAPHICS_PROGRAMS defined, the default font is not saved. */ - ret = -ENOSYS; - break; + return -ENOSYS; #else - { op.op = KD_FONT_OP_SET_DEFAULT; op.data = NULL; ret = con_font_op(vc_cons[fg_console].d, &op); if (ret) - break; + return ret; console_lock(); con_set_default_unimap(vc_cons[fg_console].d); console_unlock(); break; - } #endif - } case KDFONTOP: { - if (copy_from_user(&op, up, sizeof(op))) { - ret = -EFAULT; - break; - } + if (copy_from_user(&op, up, sizeof(op))) + return -EFAULT; if (!perm && op.op != KD_FONT_OP_GET) return -EPERM; ret = con_font_op(vc, &op); if (ret) - break; + return ret; if (copy_to_user(up, &op, sizeof(op))) - ret = -EFAULT; + return -EFAULT; break; } case PIO_SCRNMAP: if (!perm) - ret = -EPERM; - else - ret = con_set_trans_old(up); - break; + return -EPERM; + return con_set_trans_old(up); case GIO_SCRNMAP: - ret = con_get_trans_old(up); - break; + return con_get_trans_old(up); case PIO_UNISCRNMAP: if (!perm) - ret = -EPERM; - else - ret = con_set_trans_new(up); - break; + return -EPERM; + return con_set_trans_new(up); case GIO_UNISCRNMAP: - ret = con_get_trans_new(up); - break; + return con_get_trans_new(up); case PIO_UNIMAPCLR: if (!perm) @@ -1015,8 +966,7 @@ int vt_ioctl(struct tty_struct *tty, case PIO_UNIMAP: case GIO_UNIMAP: - ret = do_unimap_ioctl(cmd, up, perm, vc); - break; + return do_unimap_ioctl(cmd, up, perm, vc); case VT_LOCKSWITCH: if (!capable(CAP_SYS_TTY_CONFIG)) @@ -1029,17 +979,15 @@ int vt_ioctl(struct tty_struct *tty, vt_dont_switch = false; break; case VT_GETHIFONTMASK: - ret = put_user(vc->vc_hi_font_mask, + return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg); - break; case VT_WAITEVENT: - ret = vt_event_wait_ioctl((struct vt_event __user *)arg); - break; + return vt_event_wait_ioctl((struct vt_event __user *)arg); default: - ret = -ENOIOCTLCMD; + return -ENOIOCTLCMD; } -out: - return ret; + + return 0; } void reset_vc(struct vc_data *vc) -- cgit v1.2.3 From eca734d8f0043e9597c9426f829d48c381dbb388 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:02 +0200 Subject: vt_ioctl: eliminate use of uival and ucval They were used for the first parameter of put_user. But put_user accepts constants in the parameter and also determines the type only by the second parameter. So we can safely drop these helpers and simplify the code a bit. Including the removal of set_int label. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-30-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 87fe088c3eb4..911edd8d1272 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -353,8 +353,6 @@ int vt_ioctl(struct tty_struct *tty, struct vc_data *vc = tty->driver_data; struct console_font_op op; /* used in multiple places here */ unsigned int console = vc->vc_num; - unsigned char ucval; - unsigned int uival; void __user *up = (void __user *)arg; int i, perm; int ret; @@ -406,8 +404,7 @@ int vt_ioctl(struct tty_struct *tty, /* * this is naïve. */ - ucval = KB_101; - return put_user(ucval, (char __user *)arg); + return put_user(KB_101, (char __user *)arg); /* * These cannot be implemented on any machine that implements @@ -495,8 +492,7 @@ int vt_ioctl(struct tty_struct *tty, break; case KDGETMODE: - uival = vc->vc_mode; - goto setint; + return put_user(vc->vc_mode, (int __user *)arg); case KDMAPDISP: case KDUNMAPDISP: @@ -516,8 +512,7 @@ int vt_ioctl(struct tty_struct *tty, break; case KDGKBMODE: - uival = vt_do_kdgkbmode(console); - return put_user(uival, (int __user *)arg); + return put_user(vt_do_kdgkbmode(console), (int __user *)arg); /* this could be folded into KDSKBMODE, but for compatibility reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ @@ -526,9 +521,7 @@ int vt_ioctl(struct tty_struct *tty, case KDGKBMETA: /* FIXME: should review whether this is worth locking */ - uival = vt_do_kdgkbmeta(console); - setint: - return put_user(uival, (int __user *)arg); + return put_user(vt_do_kdgkbmeta(console), (int __user *)arg); case KDGETKEYCODE: case KDSETKEYCODE: @@ -650,8 +643,8 @@ int vt_ioctl(struct tty_struct *tty, if (!vt_in_use(i)) break; console_unlock(); - uival = i < MAX_NR_CONSOLES ? (i+1) : -1; - goto setint; + i = i < MAX_NR_CONSOLES ? (i+1) : -1; + return put_user(i, (int __user *)arg); /* * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num, -- cgit v1.2.3 From 832a62ab6b7d32243266f1829bfa4ea85c95065a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:03 +0200 Subject: vt_ioctl: move K* ioctls to a separate function We create a new vt_k_ioctl here and move there all the K* ioctls. This makes vt_ioctl significantly smaller. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-31-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 294 +++++++++++++++++++++++++--------------------- 1 file changed, 157 insertions(+), 137 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 911edd8d1272..1b423bdc488e 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -241,133 +241,15 @@ int vt_waitactive(int n) #define GPLAST 0x3df #define GPNUM (GPLAST - GPFIRST + 1) - - -static inline int -do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) -{ - struct consolefontdesc cfdarg; - int i; - - if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) - return -EFAULT; - - switch (cmd) { - case PIO_FONTX: - if (!perm) - return -EPERM; - op->op = KD_FONT_OP_SET; - op->flags = KD_FONT_FLAG_OLD; - op->width = 8; - op->height = cfdarg.charheight; - op->charcount = cfdarg.charcount; - op->data = cfdarg.chardata; - return con_font_op(vc_cons[fg_console].d, op); - case GIO_FONTX: { - op->op = KD_FONT_OP_GET; - op->flags = KD_FONT_FLAG_OLD; - op->width = 8; - op->height = cfdarg.charheight; - op->charcount = cfdarg.charcount; - op->data = cfdarg.chardata; - i = con_font_op(vc_cons[fg_console].d, op); - if (i) - return i; - cfdarg.charheight = op->height; - cfdarg.charcount = op->charcount; - if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) - return -EFAULT; - return 0; - } - } - return -EINVAL; -} - -static inline int -do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc) -{ - struct unimapdesc tmp; - - if (copy_from_user(&tmp, user_ud, sizeof tmp)) - return -EFAULT; - switch (cmd) { - case PIO_UNIMAP: - if (!perm) - return -EPERM; - return con_set_unimap(vc, tmp.entry_ct, tmp.entries); - case GIO_UNIMAP: - if (!perm && fg_console != vc->vc_num) - return -EPERM; - return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries); - } - return 0; -} - -/* deallocate a single console, if possible (leave 0) */ -static int vt_disallocate(unsigned int vc_num) -{ - struct vc_data *vc = NULL; - int ret = 0; - - console_lock(); - if (vt_busy(vc_num)) - ret = -EBUSY; - else if (vc_num) - vc = vc_deallocate(vc_num); - console_unlock(); - - if (vc && vc_num >= MIN_NR_CONSOLES) - tty_port_put(&vc->port); - - return ret; -} - -/* deallocate all unused consoles, but leave 0 */ -static void vt_disallocate_all(void) -{ - struct vc_data *vc[MAX_NR_CONSOLES]; - int i; - - console_lock(); - for (i = 1; i < MAX_NR_CONSOLES; i++) - if (!vt_busy(i)) - vc[i] = vc_deallocate(i); - else - vc[i] = NULL; - console_unlock(); - - for (i = 1; i < MAX_NR_CONSOLES; i++) { - if (vc[i] && i >= MIN_NR_CONSOLES) - tty_port_put(&vc[i]->port); - } -} - - -/* - * We handle the console-specific ioctl's here. We allow the - * capability to modify any console, not just the fg_console. - */ -int vt_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) +static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd, + unsigned long arg, bool perm) { struct vc_data *vc = tty->driver_data; - struct console_font_op op; /* used in multiple places here */ - unsigned int console = vc->vc_num; void __user *up = (void __user *)arg; - int i, perm; + unsigned int console = vc->vc_num; int ret; - /* - * To have permissions to do most of the vt ioctls, we either have - * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. - */ - perm = 0; - if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) - perm = 1; - switch (cmd) { - case TIOCLINUX: - return tioclinux(tty, arg); case KIOCSOUND: if (!perm) return -EPERM; @@ -387,7 +269,7 @@ int vt_ioctl(struct tty_struct *tty, return -EPERM; { unsigned int ticks, count; - + /* * Generate the tone for the appropriate number of ticks. * If the time is zero, turn off sound ourselves. @@ -433,11 +315,11 @@ int vt_ioctl(struct tty_struct *tty, #endif /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */ - + case KDKBDREP: { struct kbd_repeat kbrep; - + if (!capable(CAP_SYS_TTY_CONFIG)) return -EPERM; @@ -573,6 +455,157 @@ int vt_ioctl(struct tty_struct *tty, spin_unlock_irq(&vt_spawn_con.lock); break; + case KDFONTOP: { + struct console_font_op op; + + if (copy_from_user(&op, up, sizeof(op))) + return -EFAULT; + if (!perm && op.op != KD_FONT_OP_GET) + return -EPERM; + ret = con_font_op(vc, &op); + if (ret) + return ret; + if (copy_to_user(up, &op, sizeof(op))) + return -EFAULT; + break; + } + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static inline int do_fontx_ioctl(int cmd, + struct consolefontdesc __user *user_cfd, int perm, + struct console_font_op *op) +{ + struct consolefontdesc cfdarg; + int i; + + if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) + return -EFAULT; + + switch (cmd) { + case PIO_FONTX: + if (!perm) + return -EPERM; + op->op = KD_FONT_OP_SET; + op->flags = KD_FONT_FLAG_OLD; + op->width = 8; + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = cfdarg.chardata; + return con_font_op(vc_cons[fg_console].d, op); + case GIO_FONTX: { + op->op = KD_FONT_OP_GET; + op->flags = KD_FONT_FLAG_OLD; + op->width = 8; + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = cfdarg.chardata; + i = con_font_op(vc_cons[fg_console].d, op); + if (i) + return i; + cfdarg.charheight = op->height; + cfdarg.charcount = op->charcount; + if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) + return -EFAULT; + return 0; + } + } + return -EINVAL; +} + +static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, + int perm, struct vc_data *vc) +{ + struct unimapdesc tmp; + + if (copy_from_user(&tmp, user_ud, sizeof tmp)) + return -EFAULT; + switch (cmd) { + case PIO_UNIMAP: + if (!perm) + return -EPERM; + return con_set_unimap(vc, tmp.entry_ct, tmp.entries); + case GIO_UNIMAP: + if (!perm && fg_console != vc->vc_num) + return -EPERM; + return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), + tmp.entries); + } + return 0; +} + +/* deallocate a single console, if possible (leave 0) */ +static int vt_disallocate(unsigned int vc_num) +{ + struct vc_data *vc = NULL; + int ret = 0; + + console_lock(); + if (vt_busy(vc_num)) + ret = -EBUSY; + else if (vc_num) + vc = vc_deallocate(vc_num); + console_unlock(); + + if (vc && vc_num >= MIN_NR_CONSOLES) + tty_port_put(&vc->port); + + return ret; +} + +/* deallocate all unused consoles, but leave 0 */ +static void vt_disallocate_all(void) +{ + struct vc_data *vc[MAX_NR_CONSOLES]; + int i; + + console_lock(); + for (i = 1; i < MAX_NR_CONSOLES; i++) + if (!vt_busy(i)) + vc[i] = vc_deallocate(i); + else + vc[i] = NULL; + console_unlock(); + + for (i = 1; i < MAX_NR_CONSOLES; i++) { + if (vc[i] && i >= MIN_NR_CONSOLES) + tty_port_put(&vc[i]->port); + } +} + +/* + * We handle the console-specific ioctl's here. We allow the + * capability to modify any console, not just the fg_console. + */ +int vt_ioctl(struct tty_struct *tty, + unsigned int cmd, unsigned long arg) +{ + struct vc_data *vc = tty->driver_data; + struct console_font_op op; /* used in multiple places here */ + void __user *up = (void __user *)arg; + int i, perm; + int ret; + + /* + * To have permissions to do most of the vt ioctls, we either have + * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. + */ + perm = 0; + if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) + perm = 1; + + ret = vt_k_ioctl(tty, cmd, arg, perm); + if (ret != -ENOIOCTLCMD) + return ret; + + switch (cmd) { + case TIOCLINUX: + return tioclinux(tty, arg); case VT_SETMODE: { struct vt_mode tmp; @@ -922,19 +955,6 @@ int vt_ioctl(struct tty_struct *tty, break; #endif - case KDFONTOP: { - if (copy_from_user(&op, up, sizeof(op))) - return -EFAULT; - if (!perm && op.op != KD_FONT_OP_GET) - return -EPERM; - ret = con_font_op(vc, &op); - if (ret) - return ret; - if (copy_to_user(up, &op, sizeof(op))) - return -EFAULT; - break; - } - case PIO_SCRNMAP: if (!perm) return -EPERM; -- cgit v1.2.3 From bfbbdfa4de133ed235359693dae8468c1dc98cf1 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:04 +0200 Subject: vt_ioctl: move io ioctls to a separate function We create a new vt_io_ioctl here and move there all the IO ioctls. This makes vt_ioctl significantly smaller. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-32-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 177 +++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 1b423bdc488e..978c33ad6619 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -539,6 +539,100 @@ static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, return 0; } +static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, + bool perm) +{ + struct console_font_op op; /* used in multiple places here */ + + switch (cmd) { + case PIO_FONT: + if (!perm) + return -EPERM; + op.op = KD_FONT_OP_SET; + op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ + op.width = 8; + op.height = 0; + op.charcount = 256; + op.data = up; + return con_font_op(vc_cons[fg_console].d, &op); + + case GIO_FONT: + op.op = KD_FONT_OP_GET; + op.flags = KD_FONT_FLAG_OLD; + op.width = 8; + op.height = 32; + op.charcount = 256; + op.data = up; + return con_font_op(vc_cons[fg_console].d, &op); + + case PIO_CMAP: + if (!perm) + return -EPERM; + return con_set_cmap(up); + + case GIO_CMAP: + return con_get_cmap(up); + + case PIO_FONTX: + case GIO_FONTX: + return do_fontx_ioctl(cmd, up, perm, &op); + + case PIO_FONTRESET: + if (!perm) + return -EPERM; + +#ifdef BROKEN_GRAPHICS_PROGRAMS + /* With BROKEN_GRAPHICS_PROGRAMS defined, the default + font is not saved. */ + return -ENOSYS; +#else + { + int ret; + op.op = KD_FONT_OP_SET_DEFAULT; + op.data = NULL; + ret = con_font_op(vc_cons[fg_console].d, &op); + if (ret) + return ret; + console_lock(); + con_set_default_unimap(vc_cons[fg_console].d); + console_unlock(); + break; + } +#endif + + case PIO_SCRNMAP: + if (!perm) + return -EPERM; + return con_set_trans_old(up); + + case GIO_SCRNMAP: + return con_get_trans_old(up); + + case PIO_UNISCRNMAP: + if (!perm) + return -EPERM; + return con_set_trans_new(up); + + case GIO_UNISCRNMAP: + return con_get_trans_new(up); + + case PIO_UNIMAPCLR: + if (!perm) + return -EPERM; + con_clear_unimap(vc); + break; + + case PIO_UNIMAP: + case GIO_UNIMAP: + return do_unimap_ioctl(cmd, up, perm, vc); + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + /* deallocate a single console, if possible (leave 0) */ static int vt_disallocate(unsigned int vc_num) { @@ -586,7 +680,6 @@ int vt_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct vc_data *vc = tty->driver_data; - struct console_font_op op; /* used in multiple places here */ void __user *up = (void __user *)arg; int i, perm; int ret; @@ -603,6 +696,10 @@ int vt_ioctl(struct tty_struct *tty, if (ret != -ENOIOCTLCMD) return ret; + ret = vt_io_ioctl(vc, cmd, up, perm); + if (ret != -ENOIOCTLCMD) + return ret; + switch (cmd) { case TIOCLINUX: return tioclinux(tty, arg); @@ -903,84 +1000,6 @@ int vt_ioctl(struct tty_struct *tty, break; } - case PIO_FONT: - if (!perm) - return -EPERM; - op.op = KD_FONT_OP_SET; - op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ - op.width = 8; - op.height = 0; - op.charcount = 256; - op.data = up; - return con_font_op(vc_cons[fg_console].d, &op); - - case GIO_FONT: - op.op = KD_FONT_OP_GET; - op.flags = KD_FONT_FLAG_OLD; - op.width = 8; - op.height = 32; - op.charcount = 256; - op.data = up; - return con_font_op(vc_cons[fg_console].d, &op); - - case PIO_CMAP: - if (!perm) - return -EPERM; - return con_set_cmap(up); - - case GIO_CMAP: - return con_get_cmap(up); - - case PIO_FONTX: - case GIO_FONTX: - return do_fontx_ioctl(cmd, up, perm, &op); - - case PIO_FONTRESET: - if (!perm) - return -EPERM; - -#ifdef BROKEN_GRAPHICS_PROGRAMS - /* With BROKEN_GRAPHICS_PROGRAMS defined, the default - font is not saved. */ - return -ENOSYS; -#else - op.op = KD_FONT_OP_SET_DEFAULT; - op.data = NULL; - ret = con_font_op(vc_cons[fg_console].d, &op); - if (ret) - return ret; - console_lock(); - con_set_default_unimap(vc_cons[fg_console].d); - console_unlock(); - break; -#endif - - case PIO_SCRNMAP: - if (!perm) - return -EPERM; - return con_set_trans_old(up); - - case GIO_SCRNMAP: - return con_get_trans_old(up); - - case PIO_UNISCRNMAP: - if (!perm) - return -EPERM; - return con_set_trans_new(up); - - case GIO_UNISCRNMAP: - return con_get_trans_new(up); - - case PIO_UNIMAPCLR: - if (!perm) - return -EPERM; - con_clear_unimap(vc); - break; - - case PIO_UNIMAP: - case GIO_UNIMAP: - return do_unimap_ioctl(cmd, up, perm, vc); - case VT_LOCKSWITCH: if (!capable(CAP_SYS_TTY_CONFIG)) return -EPERM; -- cgit v1.2.3 From ebf1efbb1a7f79bafcde703cf5f74fa55242ea83 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:05 +0200 Subject: vt_ioctl: move vt_setactivate out of vt_ioctl It's too long to be inlined. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-33-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 74 +++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 978c33ad6619..e8bcfcdbedbb 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -633,6 +633,44 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, return 0; } +static int vt_setactivate(struct vt_setactivate __user *sa) +{ + struct vt_setactivate vsa; + struct vc_data *nvc; + int ret; + + if (copy_from_user(&vsa, sa, sizeof(vsa))) + return -EFAULT; + if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) + return -ENXIO; + + vsa.console = array_index_nospec(vsa.console, MAX_NR_CONSOLES + 1); + vsa.console--; + console_lock(); + ret = vc_allocate(vsa.console); + if (ret) { + console_unlock(); + return ret; + } + + /* + * This is safe providing we don't drop the console sem between + * vc_allocate and finishing referencing nvc. + */ + nvc = vc_cons[vsa.console].d; + nvc->vt_mode = vsa.mode; + nvc->vt_mode.frsig = 0; + put_pid(nvc->vt_pid); + nvc->vt_pid = get_pid(task_pid(current)); + console_unlock(); + + /* Commence switch and lock */ + /* Review set_console locks */ + set_console(vsa.console); + + return 0; +} + /* deallocate a single console, if possible (leave 0) */ static int vt_disallocate(unsigned int vc_num) { @@ -797,44 +835,10 @@ int vt_ioctl(struct tty_struct *tty, break; case VT_SETACTIVATE: - { - struct vt_setactivate vsa; - struct vc_data *nvc; - if (!perm) return -EPERM; - if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg, - sizeof(struct vt_setactivate))) - return -EFAULT; - if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) - return -ENXIO; - - vsa.console = array_index_nospec(vsa.console, - MAX_NR_CONSOLES + 1); - vsa.console--; - console_lock(); - ret = vc_allocate(vsa.console); - if (ret) { - console_unlock(); - return ret; - } - - /* This is safe providing we don't drop the - console sem between vc_allocate and - finishing referencing nvc */ - nvc = vc_cons[vsa.console].d; - nvc->vt_mode = vsa.mode; - nvc->vt_mode.frsig = 0; - put_pid(nvc->vt_pid); - nvc->vt_pid = get_pid(task_pid(current)); - console_unlock(); - - /* Commence switch and lock */ - /* Review set_console locks */ - set_console(vsa.console); - break; - } + return vt_setactivate(up); /* * wait until the specified VT has been activated -- cgit v1.2.3 From 535082d9078d0b161a730696c495043afcabaf8a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:06 +0200 Subject: vt_ioctl: move vt_reldisp out of vt_ioctl It's too long to be inlined. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-34-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 88 +++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index e8bcfcdbedbb..cdb7f0370ca9 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -633,6 +633,42 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, return 0; } +static int vt_reldisp(struct vc_data *vc, unsigned int swtch) +{ + int newvt, ret; + + if (vc->vt_mode.mode != VT_PROCESS) + return -EINVAL; + + /* Switched-to response */ + if (vc->vt_newvt < 0) { + /* If it's just an ACK, ignore it */ + return swtch == VT_ACKACQ ? 0 : -EINVAL; + } + + /* Switching-from response */ + if (swtch == 0) { + /* Switch disallowed, so forget we were trying to do it. */ + vc->vt_newvt = -1; + return 0; + } + + /* The current vt has been released, so complete the switch. */ + newvt = vc->vt_newvt; + vc->vt_newvt = -1; + ret = vc_allocate(newvt); + if (ret) + return ret; + + /* + * When we actually do the console switch, make sure we are atomic with + * respect to other console switches.. + */ + complete_change_console(vc_cons[newvt].d); + + return 0; +} + static int vt_setactivate(struct vt_setactivate __user *sa) { struct vt_setactivate vsa; @@ -865,55 +901,11 @@ int vt_ioctl(struct tty_struct *tty, return -EPERM; console_lock(); - if (vc->vt_mode.mode != VT_PROCESS) { - console_unlock(); - return -EINVAL; - } - /* - * Switching-from response - */ - if (vc->vt_newvt >= 0) { - if (arg == 0) - /* - * Switch disallowed, so forget we were trying - * to do it. - */ - vc->vt_newvt = -1; - - else { - /* - * The current vt has been released, so - * complete the switch. - */ - int newvt; - newvt = vc->vt_newvt; - vc->vt_newvt = -1; - ret = vc_allocate(newvt); - if (ret) { - console_unlock(); - return ret; - } - /* - * When we actually do the console switch, - * make sure we are atomic with respect to - * other console switches.. - */ - complete_change_console(vc_cons[newvt].d); - } - } else { - /* - * Switched-to response - */ - /* - * If it's just an ACK, ignore it - */ - if (arg != VT_ACKACQ) { - console_unlock(); - return -EINVAL; - } - } + ret = vt_reldisp(vc, arg); console_unlock(); - break; + + return ret; + /* * Disallocate memory associated to VT (but leave VT1) -- cgit v1.2.3 From 5422337d569eade4e79a98d22bbc757285d8872d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:07 +0200 Subject: vt_ioctl: move vt_resizex out of vt_ioctl It's too long to be inlined. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-35-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 100 +++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index cdb7f0370ca9..f671e94a94a9 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -746,6 +746,60 @@ static void vt_disallocate_all(void) } } +static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs) +{ + struct vt_consize v; + int i; + + if (copy_from_user(&v, cs, sizeof(struct vt_consize))) + return -EFAULT; + + /* FIXME: Should check the copies properly */ + if (!v.v_vlin) + v.v_vlin = vc->vc_scan_lines; + + if (v.v_clin) { + int rows = v.v_vlin / v.v_clin; + if (v.v_rows != rows) { + if (v.v_rows) /* Parameters don't add up */ + return -EINVAL; + v.v_rows = rows; + } + } + + if (v.v_vcol && v.v_ccol) { + int cols = v.v_vcol / v.v_ccol; + if (v.v_cols != cols) { + if (v.v_cols) + return -EINVAL; + v.v_cols = cols; + } + } + + if (v.v_clin > 32) + return -EINVAL; + + for (i = 0; i < MAX_NR_CONSOLES; i++) { + struct vc_data *vcp; + + if (!vc_cons[i].d) + continue; + console_lock(); + vcp = vc_cons[i].d; + if (vcp) { + if (v.v_vlin) + vcp->vc_scan_lines = v.v_vlin; + if (v.v_clin) + vcp->vc_font.height = v.v_clin; + vcp->vc_resize_user = 1; + vc_resize(vcp, v.v_cols, v.v_rows); + } + console_unlock(); + } + + return 0; +} + /* * We handle the console-specific ioctl's here. We allow the * capability to modify any console, not just the fg_console. @@ -947,54 +1001,10 @@ int vt_ioctl(struct tty_struct *tty, } case VT_RESIZEX: - { - struct vt_consize v; if (!perm) return -EPERM; - if (copy_from_user(&v, up, sizeof(struct vt_consize))) - return -EFAULT; - /* FIXME: Should check the copies properly */ - if (!v.v_vlin) - v.v_vlin = vc->vc_scan_lines; - if (v.v_clin) { - int rows = v.v_vlin/v.v_clin; - if (v.v_rows != rows) { - if (v.v_rows) /* Parameters don't add up */ - return -EINVAL; - v.v_rows = rows; - } - } - if (v.v_vcol && v.v_ccol) { - int cols = v.v_vcol/v.v_ccol; - if (v.v_cols != cols) { - if (v.v_cols) - return -EINVAL; - v.v_cols = cols; - } - } - if (v.v_clin > 32) - return -EINVAL; - - for (i = 0; i < MAX_NR_CONSOLES; i++) { - struct vc_data *vcp; - - if (!vc_cons[i].d) - continue; - console_lock(); - vcp = vc_cons[i].d; - if (vcp) { - if (v.v_vlin) - vcp->vc_scan_lines = v.v_vlin; - if (v.v_clin) - vcp->vc_font.height = v.v_clin; - vcp->vc_resize_user = 1; - vc_resize(vcp, v.v_cols, v.v_rows); - } - console_unlock(); - } - break; - } + return vt_resizex(vc, up); case VT_LOCKSWITCH: if (!capable(CAP_SYS_TTY_CONFIG)) -- cgit v1.2.3 From 7a0ac4b17f15fcd687498380da0ba28945cc6ece Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:08 +0200 Subject: vt_ioctl: move vt_io_fontreset out of vt_io_ioctl This also eliminates the ifdeffery by using if and __is_defined. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-36-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index f671e94a94a9..ecf96f5e616d 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -518,6 +518,31 @@ static inline int do_fontx_ioctl(int cmd, return -EINVAL; } +static int vt_io_fontreset(struct console_font_op *op) +{ + int ret; + + if (__is_defined(BROKEN_GRAPHICS_PROGRAMS)) { + /* + * With BROKEN_GRAPHICS_PROGRAMS defined, the default font is + * not saved. + */ + return -ENOSYS; + } + + op->op = KD_FONT_OP_SET_DEFAULT; + op->data = NULL; + ret = con_font_op(vc_cons[fg_console].d, op); + if (ret) + return ret; + + console_lock(); + con_set_default_unimap(vc_cons[fg_console].d); + console_unlock(); + + return 0; +} + static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc) { @@ -581,24 +606,7 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, if (!perm) return -EPERM; -#ifdef BROKEN_GRAPHICS_PROGRAMS - /* With BROKEN_GRAPHICS_PROGRAMS defined, the default - font is not saved. */ - return -ENOSYS; -#else - { - int ret; - op.op = KD_FONT_OP_SET_DEFAULT; - op.data = NULL; - ret = con_font_op(vc_cons[fg_console].d, &op); - if (ret) - return ret; - console_lock(); - con_set_default_unimap(vc_cons[fg_console].d); - console_unlock(); - break; - } -#endif + return vt_io_fontreset(&op); case PIO_SCRNMAP: if (!perm) -- cgit v1.2.3 From a4c53c830b2722f7cd30f58740fd9955ea4eed2c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:09 +0200 Subject: vt_ioctl: move vt_kdsetmode out of vt_k_ioctl It's too long to be inlined. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-37-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 78 ++++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index ecf96f5e616d..224f2a564e13 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -241,6 +241,47 @@ int vt_waitactive(int n) #define GPLAST 0x3df #define GPNUM (GPLAST - GPFIRST + 1) +/* + * currently, setting the mode from KD_TEXT to KD_GRAPHICS doesn't do a whole + * lot. i'm not sure if it should do any restoration of modes or what... + * + * XXX It should at least call into the driver, fbdev's definitely need to + * restore their engine state. --BenH + */ +static int vt_kdsetmode(struct vc_data *vc, unsigned long mode) +{ + switch (mode) { + case KD_GRAPHICS: + break; + case KD_TEXT0: + case KD_TEXT1: + mode = KD_TEXT; + fallthrough; + case KD_TEXT: + break; + default: + return -EINVAL; + } + + /* FIXME: this needs the console lock extending */ + if (vc->vc_mode == mode) + return 0; + + vc->vc_mode = mode; + if (vc->vc_num != fg_console) + return 0; + + /* explicitly blank/unblank the screen if switching modes */ + console_lock(); + if (mode == KD_TEXT) + do_unblank_screen(1); + else + do_blank_screen(1); + console_unlock(); + + return 0; +} + static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg, bool perm) { @@ -335,43 +376,10 @@ static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd, } case KDSETMODE: - /* - * currently, setting the mode from KD_TEXT to KD_GRAPHICS - * doesn't do a whole lot. i'm not sure if it should do any - * restoration of modes or what... - * - * XXX It should at least call into the driver, fbdev's definitely - * need to restore their engine state. --BenH - */ if (!perm) return -EPERM; - switch (arg) { - case KD_GRAPHICS: - break; - case KD_TEXT0: - case KD_TEXT1: - arg = KD_TEXT; - case KD_TEXT: - break; - default: - return -EINVAL; - } - /* FIXME: this needs the console lock extending */ - if (vc->vc_mode == (unsigned char) arg) - break; - vc->vc_mode = (unsigned char) arg; - if (console != fg_console) - break; - /* - * explicitly blank/unblank the screen if switching modes - */ - console_lock(); - if (arg == KD_TEXT) - do_unblank_screen(1); - else - do_blank_screen(1); - console_unlock(); - break; + + return vt_kdsetmode(vc, arg); case KDGETMODE: return put_user(vc->vc_mode, (int __user *)arg); -- cgit v1.2.3 From 5ba1278787225629fb0b58de768e744714215678 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 15 Jun 2020 09:49:10 +0200 Subject: vt_ioctl: move perm checks level up Synchronize with others and check perm directly in vt_k_ioctl. We do not need to pass perm to do_fontx_ioctl and do_unimap_ioctl then. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20200615074910.19267-38-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 224f2a564e13..91c301775047 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -486,7 +486,7 @@ static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd, } static inline int do_fontx_ioctl(int cmd, - struct consolefontdesc __user *user_cfd, int perm, + struct consolefontdesc __user *user_cfd, struct console_font_op *op) { struct consolefontdesc cfdarg; @@ -497,8 +497,6 @@ static inline int do_fontx_ioctl(int cmd, switch (cmd) { case PIO_FONTX: - if (!perm) - return -EPERM; op->op = KD_FONT_OP_SET; op->flags = KD_FONT_FLAG_OLD; op->width = 8; @@ -552,7 +550,7 @@ static int vt_io_fontreset(struct console_font_op *op) } static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, - int perm, struct vc_data *vc) + struct vc_data *vc) { struct unimapdesc tmp; @@ -560,11 +558,9 @@ static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, return -EFAULT; switch (cmd) { case PIO_UNIMAP: - if (!perm) - return -EPERM; return con_set_unimap(vc, tmp.entry_ct, tmp.entries); case GIO_UNIMAP: - if (!perm && fg_console != vc->vc_num) + if (fg_console != vc->vc_num) return -EPERM; return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries); @@ -607,8 +603,12 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, return con_get_cmap(up); case PIO_FONTX: + if (!perm) + return -EPERM; + + fallthrough; case GIO_FONTX: - return do_fontx_ioctl(cmd, up, perm, &op); + return do_fontx_ioctl(cmd, up, &op); case PIO_FONTRESET: if (!perm) @@ -640,7 +640,10 @@ static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up, case PIO_UNIMAP: case GIO_UNIMAP: - return do_unimap_ioctl(cmd, up, perm, vc); + if (!perm) + return -EPERM; + + return do_unimap_ioctl(cmd, up, vc); default: return -ENOIOCTLCMD; -- cgit v1.2.3 From 5de30b286e7166164f9e45de991bde26f5db8298 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Wed, 3 Jun 2020 13:28:04 +0300 Subject: tty/vt: check allocation size in con_set_unimap() The vmemdup_user() function has no 2-factor argument form. Use array_size() to check for the overflow. Signed-off-by: Denis Efremov Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/20200603102804.2110817-1-efremov@linux.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/consolemap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c index c1be96bb3ecf..5947b54d92be 100644 --- a/drivers/tty/vt/consolemap.c +++ b/drivers/tty/vt/consolemap.c @@ -542,7 +542,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) if (!ct) return 0; - unilist = vmemdup_user(list, ct * sizeof(struct unipair)); + unilist = vmemdup_user(list, array_size(sizeof(struct unipair), ct)); if (IS_ERR(unilist)) return PTR_ERR(unilist); -- cgit v1.2.3 From 695b847b247cff47be4cc23bc7ed62d527233135 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 17 Jun 2020 17:28:56 +0200 Subject: serial: samsung: Minor whitespace cleanups Make the code slightly more readable by removing unneeded line breaks, adding missing line breaks and white spaces. This also fixes few strict checkpatch suggestions: CHECK: spaces preferred around that '-' (ctx:VxV) CHECK: Unbalanced braces around else statement CHECK: Lines should not end with a '(' Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200617152856.18086-1-krzk@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung_tty.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index d913d9b2762a..7be9579216b8 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -327,7 +327,6 @@ static void s3c24xx_serial_tx_dma_complete(void *args) unsigned long flags; int count; - dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state); count = dma->tx_bytes_requested - state.residue; async_tx_ack(dma->tx_desc); @@ -409,7 +408,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, struct circ_buf *xmit = &port->state->xmit; struct s3c24xx_uart_dma *dma = ourport->dma; - if (ourport->tx_mode != S3C24XX_TX_DMA) enable_tx_dma(ourport); @@ -816,7 +814,6 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id) return IRQ_HANDLED; } - static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id) { struct s3c24xx_uart_port *ourport = dev_id; @@ -842,8 +839,8 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) count >= ourport->min_dma_size) { int align = dma_get_cache_alignment() - (xmit->tail & (dma_get_cache_alignment() - 1)); - if (count-align >= ourport->min_dma_size) { - dma_count = count-align; + if (count - align >= ourport->min_dma_size) { + dma_count = count - align; count = align; } } @@ -1589,7 +1586,6 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser) return 0; } - #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE static struct console s3c24xx_serial_console; @@ -1672,7 +1668,6 @@ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { } }, #if CONFIG_SERIAL_SAMSUNG_UARTS > 2 - [2] = { .port = { .lock = __PORT_LOCK_UNLOCKED(2), @@ -1728,7 +1723,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port, udelay(1); } - #ifdef CONFIG_ARM_S3C24XX_CPUFREQ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, @@ -1903,9 +1897,9 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, port->mapbase = res->start; ret = platform_get_irq(platdev, 0); - if (ret < 0) + if (ret < 0) { port->irq = 0; - else { + } else { port->irq = ret; ourport->rx_irq = ret; ourport->tx_irq = ret + 1; @@ -1977,8 +1971,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[]; static int probe_index; -static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data( - struct platform_device *pdev) +static inline struct s3c24xx_serial_drv_data * +s3c24xx_get_driver_data(struct platform_device *pdev) { #ifdef CONFIG_OF if (pdev->dev.of_node) { @@ -2329,7 +2323,6 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, *baud = rate / (16 * (ubrdiv + 1)); dev_dbg(port->dev, "calculated baud %d\n", *baud); } - } static int __init @@ -2696,6 +2689,7 @@ static int __init s3c2410_early_console_setup(struct earlycon_device *device, device->port.private_data = &s3c2410_early_console_data; return samsung_early_console_setup(device, opt); } + OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart", s3c2410_early_console_setup); @@ -2710,6 +2704,7 @@ static int __init s3c2440_early_console_setup(struct earlycon_device *device, device->port.private_data = &s3c2440_early_console_data; return samsung_early_console_setup(device, opt); } + OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart", s3c2440_early_console_setup); OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart", @@ -2728,6 +2723,7 @@ static int __init s5pv210_early_console_setup(struct earlycon_device *device, device->port.private_data = &s5pv210_early_console_data; return samsung_early_console_setup(device, opt); } + OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart", s5pv210_early_console_setup); OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart", -- cgit v1.2.3 From c89511f61c34aa8e52055fc704cee09c8e459dee Mon Sep 17 00:00:00 2001 From: Tamseel Shams Date: Wed, 17 Jun 2020 16:29:07 +0530 Subject: serial: samsung: fix spelling mistake There is a spelling mistake in a comment. Fix it. Signed-off-by: Tamseel Shams Reviewed-by: Alim Akhtar Link: https://lore.kernel.org/r/20200617105907.7143-1-m.shams@samsung.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index 7be9579216b8..8ed3482d2e1e 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -6,7 +6,7 @@ * http://armlinux.simtec.co.uk/ */ -/* Hote on 2410 error handling +/* Note on 2410 error handling * * The s3c2410 manual has a love/hate affair with the contents of the * UERSTAT register in the UART blocks, and keeps marking some of the -- cgit v1.2.3 From 3550f8979a7bb2f28940aa26aab77314ec8840bd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 24 Jun 2020 16:27:44 +0300 Subject: tty: serial: qcom_geni_serial: Clean up an ARRAY_SIZE() vs sizeof() The ARRAY_SIZE() is the number of elements but we want the number of bytes so sizeof() is more appropriate. Fortunately, it's the same thing here because this is an array of u8 so this doesn't change runtime. Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20200624132744.GD9972@mwanda Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/qcom_geni_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 457c0bf8cbf8..1ed3d354e16d 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -718,7 +718,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, u8 buf[sizeof(u32)]; int c; - memset(buf, 0, ARRAY_SIZE(buf)); + memset(buf, 0, sizeof(buf)); tx_bytes = min_t(size_t, remaining, port->tx_bytes_pw); for (c = 0; c < tx_bytes ; c++) { -- cgit v1.2.3 From d10ee1d1917b082f0008a840cde5aeaad11b396b Mon Sep 17 00:00:00 2001 From: Vabhav Sharma Date: Fri, 26 Jun 2020 16:50:34 +0530 Subject: tty: serial: fsl_lpuart: minimum baud rate support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The formula for the baud rate is baud rate = "baud clock / ((OSR+1) × SBR) Algorithm used in function lpuart32_serial_setbrg() only changes the SBR. Even with maxmum value put in, OSR stays at 0x7 and the lowest baud rate would be ~ 2600 bps Update the algorithm to allow driver operation at 1200,2400 or 600 bps Signed-off-by: Vabhav Sharma Link: https://lore.kernel.org/r/1593170434-13524-1-git-send-email-vabhav.sharma@oss.nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 90298c403042..7ca642249224 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1925,6 +1925,9 @@ static void __lpuart32_serial_setbrg(struct uart_port *port, tmp_sbr++; } + if (tmp_sbr > UARTBAUD_SBR_MASK) + continue; + if (tmp_diff <= baud_diff) { baud_diff = tmp_diff; osr = tmp_osr; -- cgit v1.2.3 From 167cbce27444be3203081b97ea65178c4088b062 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 10 Jun 2020 17:51:21 +0200 Subject: serial: core: drop unnecessary gpio include Drop the recently added gpio include from the serial-core header in favour of a forward declaration and instead include the gpio header only where needed. Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20200610155121.14014-1-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 1 + drivers/tty/serial/serial_core.c | 1 + include/linux/serial_core.h | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 1632f7d25acc..d64ca77d9cfa 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 57840cf90388..5750f3628357 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 9fd550e7946a..653c653ad0c2 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -30,6 +29,7 @@ struct uart_port; struct serial_struct; struct device; +struct gpio_desc; /* * This structure describes all the operations that can be done on the -- cgit v1.2.3 From 894b867ac9dc6906022c27ace2339418db666002 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sat, 6 Jun 2020 17:11:46 +0200 Subject: 8250-men-mcb: fix signed/unsigned confusion get_num_ports returns -ENODEV, and the result is stored in int, so it should not be unsigned. Zero ports does not seem to make sense, so make that check consistent. Signed-off-by: Pavel Machek (CIP) Link: https://lore.kernel.org/r/20200606151146.GA10940@amd Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_men_mcb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c index e985f344b2dd..737c4c31e8a0 100644 --- a/drivers/tty/serial/8250/8250_men_mcb.c +++ b/drivers/tty/serial/8250/8250_men_mcb.c @@ -51,7 +51,7 @@ static u32 men_lookup_uartclk(struct mcb_device *mdev) return clkval; } -static unsigned int get_num_ports(struct mcb_device *mdev, +static int get_num_ports(struct mcb_device *mdev, void __iomem *membase) { switch (mdev->id) { @@ -140,7 +140,7 @@ static void serial_8250_men_mcb_remove(struct mcb_device *mdev) return; num_ports = get_num_ports(mdev, data[0].uart.port.membase); - if (num_ports < 0 || num_ports > 4) { + if (num_ports <= 0 || num_ports > 4) { dev_err(&mdev->dev, "error retrieving number of ports!\n"); return; } -- cgit v1.2.3 From f1681a9a2a62d7e6232832d6780cc65ce63f5396 Mon Sep 17 00:00:00 2001 From: Randolph Maaßen Date: Fri, 5 Jun 2020 16:57:14 +0200 Subject: serial: serial-tegra: reduce irq-latency after rx errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since dev_err() calls can lead to synchronous writes to another serial console these calls can provide significant latency during irq-handling in tegra_uart_isr(). With this latency another interrupt is likely to apper during handling of the first interrupt, which might lock up the kernel completely. These errors are reported to the error counters so converting the dev_err() to dev_dbg() is appropriate. Signed-off-by: Randolph Maaßen Link: https://lore.kernel.org/r/20200605145714.9964-1-gaireg@gaireg.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial-tegra.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 8de8bac9c6c7..d3fef5ab289a 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -439,16 +439,16 @@ static char tegra_uart_decode_rx_error(struct tegra_uart_port *tup, /* Overrrun error */ flag = TTY_OVERRUN; tup->uport.icount.overrun++; - dev_err(tup->uport.dev, "Got overrun errors\n"); + dev_dbg(tup->uport.dev, "Got overrun errors\n"); } else if (lsr & UART_LSR_PE) { /* Parity error */ flag = TTY_PARITY; tup->uport.icount.parity++; - dev_err(tup->uport.dev, "Got Parity errors\n"); + dev_dbg(tup->uport.dev, "Got Parity errors\n"); } else if (lsr & UART_LSR_FE) { flag = TTY_FRAME; tup->uport.icount.frame++; - dev_err(tup->uport.dev, "Got frame errors\n"); + dev_dbg(tup->uport.dev, "Got frame errors\n"); } else if (lsr & UART_LSR_BI) { /* * Break error -- cgit v1.2.3 From 5b36146eac22153f57cf28278bbe8c642533a9be Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 2 Jun 2020 12:40:48 -0700 Subject: serial: kgdboc: Fix bad line wrapping in comment In commit a4912303ac6f ("serial: kgdboc: Allow earlycon initialization to be deferred") it looks like Daniel really took Linus's new suggestion about not needing to wrap at 80 columns to heart and he jammed two full lines of comments into one line. Either that or he just somehow accidentally deleted a carriage return when doing final edits on the patch. In either case let's make it look prettier. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200602124044.1.Iee31247bc080d42a02e167454b1225a1b4283705@changeid Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/kgdboc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index 41396982e9e0..fe6ae98360a2 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -538,7 +538,8 @@ static int __init kgdboc_earlycon_init(char *opt) if (!con) { /* - * Both earlycon and kgdboc_earlycon are initialized during * early parameter parsing. We cannot guarantee earlycon gets + * Both earlycon and kgdboc_earlycon are initialized during + * early parameter parsing. We cannot guarantee earlycon gets * in first and, in any case, on ACPI systems earlycon may * defer its own initialization (usually to somewhere within * setup_arch() ). To cope with either of these situations -- cgit v1.2.3 From 2a1dbd259e631a56784e5f72aebe5d6b2f5c5c87 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 18 Jun 2020 12:51:44 +0300 Subject: serial: 8250_em: Switch to use platform_get_irq() platform_get_irq() provides an established error code and error message. Also, it's better to use dedicated API to retrieve Linux IRQ resource. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200618095144.73852-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_em.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index 2a76e22d2ec0..db88dee3a399 100644 --- a/drivers/tty/serial/8250/8250_em.c +++ b/drivers/tty/serial/8250/8250_em.c @@ -78,14 +78,18 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value) static int serial8250_em_probe(struct platform_device *pdev) { - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct serial8250_em_priv *priv; struct uart_8250_port up; - int ret; + struct resource *regs; + int irq, ret; - if (!regs || !irq) { - dev_err(&pdev->dev, "missing registers or irq\n"); + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "missing registers\n"); return -EINVAL; } @@ -101,7 +105,7 @@ static int serial8250_em_probe(struct platform_device *pdev) memset(&up, 0, sizeof(up)); up.port.mapbase = regs->start; - up.port.irq = irq->start; + up.port.irq = irq; up.port.type = PORT_UNKNOWN; up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP; up.port.dev = &pdev->dev; -- cgit v1.2.3 From 9167cc78bd3f615f0df03859b2aae668ba8f8cec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 18 Jun 2020 15:20:24 +0300 Subject: serial: 8250_omap: Switch to use platform_get_irq() platform_get_irq() provides an established error code and error message. Also, it's better to use dedicated API to retrieve Linux IRQ resource. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200618122024.87170-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 16cfb887c5a3..562087df7d33 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1209,17 +1209,21 @@ MODULE_DEVICE_TABLE(of, omap8250_dt_ids); static int omap8250_probe(struct platform_device *pdev) { - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct device_node *np = pdev->dev.of_node; struct omap8250_priv *priv; const struct omap8250_platdata *pdata; struct uart_8250_port up; - int ret; + struct resource *regs; void __iomem *membase; + int irq, ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; - if (!regs || !irq) { - dev_err(&pdev->dev, "missing registers or irq\n"); + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "missing registers\n"); return -EINVAL; } @@ -1236,7 +1240,7 @@ static int omap8250_probe(struct platform_device *pdev) up.port.dev = &pdev->dev; up.port.mapbase = regs->start; up.port.membase = membase; - up.port.irq = irq->start; + up.port.irq = irq; /* * It claims to be 16C750 compatible however it is a little different. * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to -- cgit v1.2.3 From e914072cacb60c48f20c240ebe28414b8fbbf135 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 18 Jun 2020 15:27:44 +0300 Subject: serial: 8250_pxa: Switch to use platform_get_irq() platform_get_irq() provides an established error code and error message. Also, it's better to use dedicated API to retrieve Linux IRQ resource. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200618122744.88204-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pxa.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c index 11612d174716..33ca98bfa5b3 100644 --- a/drivers/tty/serial/8250/8250_pxa.c +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -93,12 +92,15 @@ static int serial_pxa_probe(struct platform_device *pdev) { struct uart_8250_port uart = {}; struct pxa8250_data *data; - struct resource *mmres, *irqres; - int ret; + struct resource *mmres; + int irq, ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!mmres || !irqres) + if (!mmres) return -ENODEV; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); @@ -121,7 +123,7 @@ static int serial_pxa_probe(struct platform_device *pdev) uart.port.iotype = UPIO_MEM32; uart.port.mapbase = mmres->start; uart.port.regshift = 2; - uart.port.irq = irqres->start; + uart.port.irq = irq; uart.port.fifosize = 64; uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE; uart.port.dev = &pdev->dev; -- cgit v1.2.3 From 451a73c68014528e2e5f80af6c64bcc477b8864a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 18 Jun 2020 15:33:20 +0300 Subject: serial: 8250_ingenic: Switch to use platform_get_irq() platform_get_irq() provides an established error code and error message. Also, it's better to use dedicated API to retrieve Linux IRQ resource. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200618123320.88612-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_ingenic.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 424c07c5f629..dde766fa465f 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -207,12 +207,11 @@ static unsigned int ingenic_uart_serial_in(struct uart_port *p, int offset) static int ingenic_uart_probe(struct platform_device *pdev) { struct uart_8250_port uart = {}; - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct ingenic_uart_data *data; const struct ingenic_uart_config *cdata; const struct of_device_id *match; - int err, line; + struct resource *regs; + int irq, err, line; match = of_match_device(of_match, &pdev->dev); if (!match) { @@ -221,8 +220,13 @@ static int ingenic_uart_probe(struct platform_device *pdev) } cdata = match->data; - if (!regs || !irq) { - dev_err(&pdev->dev, "no registers/irq defined\n"); + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "no registers defined\n"); return -EINVAL; } @@ -238,7 +242,7 @@ static int ingenic_uart_probe(struct platform_device *pdev) uart.port.regshift = 2; uart.port.serial_out = ingenic_uart_serial_out; uart.port.serial_in = ingenic_uart_serial_in; - uart.port.irq = irq->start; + uart.port.irq = irq; uart.port.dev = &pdev->dev; uart.port.fifosize = cdata->fifosize; uart.tx_loadsz = cdata->tx_loadsz; -- cgit v1.2.3 From 1b1eef6863cdbf35f1abbe9207da36a8dc71e06e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 18 Jun 2020 15:29:52 +0300 Subject: serial: 8250_mtk: Switch to use platform_get_irq() platform_get_irq() provides an established error code and error message. Also, it's better to use dedicated API to retrieve Linux IRQ resource. Signed-off-by: Andy Shevchenko Reviewed-by: Matthias Brugger Link: https://lore.kernel.org/r/20200618122952.88265-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_mtk.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index f839380c2f4c..685ded99fa6d 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -494,13 +494,17 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p, static int mtk8250_probe(struct platform_device *pdev) { struct uart_8250_port uart = {}; - struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct mtk8250_data *data; - int err; + struct resource *regs; + int irq, err; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; - if (!regs || !irq) { - dev_err(&pdev->dev, "no registers/irq defined\n"); + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "no registers defined\n"); return -EINVAL; } @@ -524,7 +528,7 @@ static int mtk8250_probe(struct platform_device *pdev) spin_lock_init(&uart.port.lock); uart.port.mapbase = regs->start; - uart.port.irq = irq->start; + uart.port.irq = irq; uart.port.pm = mtk8250_do_pm; uart.port.type = PORT_16550; uart.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT; -- cgit v1.2.3 From 890814504eeb930c15a1e238c3fff7dfc238b8c9 Mon Sep 17 00:00:00 2001 From: Flavio Suligoi Date: Tue, 9 Jun 2020 18:02:49 +0200 Subject: tty: fix spelling mistake Fix typo: "tigger" --> "trigger" Signed-off-by: Flavio Suligoi Link: https://lore.kernel.org/r/20200609160249.31329-1-f.suligoi@asem.it Signed-off-by: Greg Kroah-Hartman --- drivers/tty/moxa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/moxa.h b/drivers/tty/moxa.h index 563d2dce80b3..f0a4381b6861 100644 --- a/drivers/tty/moxa.h +++ b/drivers/tty/moxa.h @@ -138,7 +138,7 @@ #define IntrQuit 0x40 /* received QUIT code */ #define IntrEOF 0x80 /* received EOF code */ -#define IntrRxTrigger 0x100 /* rx data count reach tigger value */ +#define IntrRxTrigger 0x100 /* rx data count reach trigger value */ #define IntrTxTrigger 0x200 /* tx data count below trigger value */ #define Magic_no (Config_base + 0) -- cgit v1.2.3 From 6fd9fffb6ff54fdb19b57ecb927fe15e99b0b24d Mon Sep 17 00:00:00 2001 From: Erwan Le Ray Date: Wed, 20 May 2020 15:39:32 +0200 Subject: serial: stm32: Use generic DT binding for announcing RTS/CTS lines Add support of generic DT binding for annoucing RTS/CTS lines. The initial binding 'st,hw-flow-control' is not needed anymore since generic binding is available, but is kept for backward compatibility. Signed-off-by: Erwan Le Ray Link: https://lore.kernel.org/r/20200520133932.30441-3-erwan.leray@st.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 8602ff357321..d1c5e536a167 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -1033,8 +1033,9 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev) if (WARN_ON(id >= STM32_MAX_PORTS)) return NULL; - stm32_ports[id].hw_flow_control = of_property_read_bool(np, - "st,hw-flow-ctrl"); + stm32_ports[id].hw_flow_control = + of_property_read_bool (np, "st,hw-flow-ctrl") /*deprecated*/ || + of_property_read_bool (np, "uart-has-rtscts"); stm32_ports[id].port.line = id; stm32_ports[id].cr1_irq = USART_CR1_RXNEIE; stm32_ports[id].cr3_irq = 0; -- cgit v1.2.3 From 44c413d9a51752056d606bf6f312003ac1740fab Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Wed, 17 Jun 2020 17:04:44 +1000 Subject: tty/vt: Do not warn when huge selection requested The tty TIOCL_SETSEL ioctl allocates a memory buffer big enough for text selection area. The maximum allowed console size is VC_RESIZE_MAXCOL * VC_RESIZE_MAXROW == 32767*32767 == ~1GB and typical MAX_ORDER is set to allow allocations lot less than than (circa 16MB). So it is quite possible to trigger huge allocation (and syzkaller just did that) which is going to fail (which is fine) with a backtrace in mm/page_alloc.c at WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN)) and this may trigger panic (if panic_on_warn is enabled) and leak kernel addresses to dmesg. This passes __GFP_NOWARN to kmalloc_array to avoid unnecessary user- triggered WARN_ON. Note that the error is not ignored and the warning is still printed. Signed-off-by: Alexey Kardashevskiy Link: https://lore.kernel.org/r/20200617070444.116704-1-aik@ozlabs.ru Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/selection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 31bb3647a99c..8e74654c1b27 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -193,7 +193,7 @@ static int vc_selection_store_chars(struct vc_data *vc, bool unicode) /* Allocate a new buffer before freeing the old one ... */ /* chars can take up to 4 bytes with unicode */ bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1, - GFP_KERNEL); + GFP_KERNEL | __GFP_NOWARN); if (!bp) { printk(KERN_WARNING "selection: kmalloc() failed\n"); clear_selection(); -- cgit v1.2.3 From 30336ef6f13e41097dd26c8e693ba75e802fcb21 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 11 Jul 2020 16:53:42 +0300 Subject: Revert "serial: sunhv: Initialize lock for non-registered console" This reverts commit 0f87aa66e8c314f95c00eeff978c8a0b41e05d50. There has been a quick fix against uninitialised lock revealed by the commit f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()"). Since we have now better fix in serial core, this may be safely reverted. Fixes: 0f87aa66e8c3 ("serial: sunhv: Initialize lock for non-registered console") Depends-on: f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()") Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200711135346.71171-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sunhv.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index e35073e93a5b..eafada8fb6fa 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -567,9 +567,6 @@ static int hv_probe(struct platform_device *op) sunserial_console_match(&sunhv_console, op->dev.of_node, &sunhv_reg, port->line, false); - /* We need to initialize lock even for non-registered console */ - spin_lock_init(&port->lock); - err = uart_add_one_port(&sunhv_reg, port); if (err) goto out_unregister_driver; -- cgit v1.2.3 From 6a63ba971edbbfae280ea0cc4502e7ba4354125b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 11 Jul 2020 16:53:43 +0300 Subject: Revert "serial: amba-pl011: Make sure we initialize the port.lock spinlock" This reverts commit 8508f4cba308f785b2fd4b8c38849c117b407297. There has been a quick fix against uninitialised lock revealed by the commit f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()"). Since we have now better fix in serial core, this may be safely reverted. Fixes: 8508f4cba308 ("serial: amba-pl011: Make sure we initialize the port.lock spinlock") Depends-on: f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()") Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200711135346.71171-2-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 8efd7c2a34fe..c010f639298d 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2607,7 +2607,6 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE); uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = index; - spin_lock_init(&uap->port.lock); amba_ports[index] = uap; -- cgit v1.2.3 From c6e45ae511b192807376fdd8f9020d5301aeec6d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 11 Jul 2020 16:53:44 +0300 Subject: Revert "tty: serial: add missing spin_lock_init for SiFive serial console" This reverts commit 17b4efdf4e4867079012a48ca10d965fe9d68822. There has been a quick fix against uninitialised lock revealed by the commit f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()"). Since we have now better fix in serial core, this may be safely reverted. Fixes: 17b4efdf4e48 ("tty: serial: add missing spin_lock_init for SiFive serial console") Depends-on: f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()") Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200711135346.71171-3-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sifive.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c index 0b5110dad051..13eadcb8aec4 100644 --- a/drivers/tty/serial/sifive.c +++ b/drivers/tty/serial/sifive.c @@ -883,7 +883,6 @@ console_initcall(sifive_console_init); static void __ssp_add_console_port(struct sifive_serial_port *ssp) { - spin_lock_init(&ssp->port.lock); sifive_serial_console_ports[ssp->port.line] = ssp; } -- cgit v1.2.3 From dfe51d97776ef926749362f34625cd36657845d8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 11 Jul 2020 16:53:45 +0300 Subject: Revert "serial: imx: Initialize lock for non-registered console" This reverts commit 8f065acec7573672dd15916e31d1e9b2e785566c. There has been a quick fix against uninitialised lock revealed by the commit f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()"). Since we have now better fix in serial core, this may be safely reverted. Fixes: 8f065acec757 ("serial: imx: Initialize lock for non-registered console") Depends-on: f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()") Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200711135346.71171-4-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 1265e8d86d8a..6175f8398130 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2406,9 +2406,6 @@ static int imx_uart_probe(struct platform_device *pdev) } } - /* We need to initialize lock even for non-registered console */ - spin_lock_init(&sport->port.lock); - imx_uart_ports[sport->port.line] = sport; platform_set_drvdata(pdev, sport); -- cgit v1.2.3 From 71614e1c21cdc5dc90a50127ac843416c26dce7e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 11 Jul 2020 16:53:46 +0300 Subject: Revert "serial: sh-sci: Initialize spinlock for uart console" This reverts commit f38278e9b810b06aff2981d505267be984423ba3. There has been a quick fix against uninitialised lock revealed by the commit f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()"). Since we have now better fix in serial core, this may be safely reverted. Fixes: f38278e9b810 ("serial: sh-sci: Initialize spinlock for uart console") Depends-on: f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()") Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200711135346.71171-5-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 204bb68ce3ca..e1179e74a2b8 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -3301,9 +3301,6 @@ static int sci_probe_single(struct platform_device *dev, sciport->port.flags |= UPF_HARD_FLOW; } - if (sci_uart_driver.cons->index == sciport->port.line) - spin_lock_init(&sciport->port.lock); - ret = uart_add_one_port(&sci_uart_driver, &sciport->port); if (ret) { sci_cleanup_single(sciport); -- cgit v1.2.3 From a6fdf0c77154a29883f5b46f1137d1d76aaf5f6c Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Sat, 18 Jul 2020 15:34:52 +0200 Subject: tty: vt: Replace HTTP links with HTTPS ones Rationale: Reduces attack surface on kernel devs opening the links for MITM as HTTPS traffic is much harder to manipulate. Deterministic algorithm: For each file: If not .svg: For each line: If doesn't contain `\bxmlns\b`: For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`: If neither `\bgnu\.org/license`, nor `\bmozilla\.org/MPL\b`: If both the HTTP and HTTPS versions return 200 OK and serve the same content: Replace HTTP with HTTPS. Signed-off-by: Alexander A. Klimov Link: https://lore.kernel.org/r/20200718133452.24290-1-grandmaster@al2klimov.de Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/n_gsm.rst | 2 +- drivers/tty/vt/vt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/driver-api/serial/n_gsm.rst b/Documentation/driver-api/serial/n_gsm.rst index 286e7ff4d2d9..87dfcd54a96b 100644 --- a/Documentation/driver-api/serial/n_gsm.rst +++ b/Documentation/driver-api/serial/n_gsm.rst @@ -5,7 +5,7 @@ GSM 0710 tty multiplexor HOWTO This line discipline implements the GSM 07.10 multiplexing protocol detailed in the following 3GPP document: - http://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip + https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip This document give some hints on how to use this driver with GPRS and 3G modems connected to a physical serial port. diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 673177d4e859..6a2f4c66fe02 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2520,7 +2520,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) /* is_double_width() is based on the wcwidth() implementation by * Markus Kuhn -- 2007-05-26 (Unicode 5.0) - * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c + * Latest version: https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */ struct interval { uint32_t first; -- cgit v1.2.3 From d4c2b4e730e8bdfe818b222e018fe891a1db52ee Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Sat, 18 Jul 2020 14:38:40 +0200 Subject: tty: serial: Replace HTTP links with HTTPS ones Rationale: Reduces attack surface on kernel devs opening the links for MITM as HTTPS traffic is much harder to manipulate. Deterministic algorithm: For each file: If not .svg: For each line: If doesn't contain `\bxmlns\b`: For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`: If neither `\bgnu\.org/license`, nor `\bmozilla\.org/MPL\b`: If both the HTTP and HTTPS versions return 200 OK and serve the same content: Replace HTTP with HTTPS. Signed-off-by: Alexander A. Klimov Link: https://lore.kernel.org/r/20200718123840.19957-1-grandmaster@al2klimov.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/Kconfig | 4 ++-- drivers/tty/serial/jsm/jsm_driver.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index d2ae033aea40..603137da4736 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -222,7 +222,7 @@ config SERIAL_8250_MANY_PORTS Say Y here if you have dumb serial boards other than the four standard COM 1/2/3/4 ports. This may happen if you have an AST FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available - from ), or other custom + from ), or other custom serial port hardware which acts similar to standard serial port hardware. If you only use the standard COM 1/2/3/4 ports, you can say N here to save some memory. You can also say Y if you have an @@ -266,7 +266,7 @@ config SERIAL_8250_BOCA depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS help Say Y here if you have a Boca serial board. Please read the Boca - mini-HOWTO, available from + mini-HOWTO, available from To compile this driver as a module, choose M here: the module will be called 8250_boca. diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index 592e51d8944e..cd30da0ef083 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c @@ -16,7 +16,7 @@ #include "jsm.h" -MODULE_AUTHOR("Digi International, http://www.digi.com"); +MODULE_AUTHOR("Digi International, https://www.digi.com"); MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("jsm"); -- cgit v1.2.3 From 82ee0b147cac6111498ae841ab2afbe046a304f1 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Sat, 18 Jul 2020 12:08:07 +0200 Subject: tty: serial: uartlite: Replace HTTP links with HTTPS ones Rationale: Reduces attack surface on kernel devs opening the links for MITM as HTTPS traffic is much harder to manipulate. Deterministic algorithm: For each file: If not .svg: For each line: If doesn't contain `\bxmlns\b`: For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`: If neither `\bgnu\.org/license`, nor `\bmozilla\.org/MPL\b`: If both the HTTP and HTTPS versions return 200 OK and serve the same content: Replace HTTP with HTTPS. Signed-off-by: Alexander A. Klimov Link: https://lore.kernel.org/r/20200718100807.983-1-grandmaster@al2klimov.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/uartlite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 7dbd0c471d92..09379db613d8 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -32,7 +32,7 @@ * Register definitions * * For register details see datasheet: - * http://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf + * https://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf */ #define ULITE_RX 0x00 -- cgit v1.2.3 From 4ed71addf51a627397826f11328d6ce0f69d6d34 Mon Sep 17 00:00:00 2001 From: Tamseel Shams Date: Thu, 16 Jul 2020 17:24:38 +0530 Subject: serial: core: Fix Coding Style This patch fixes the following checkpatch error and warning: 1. space required after ',' 2. Missing a blank line after declarations Signed-off-by: Tamseel Shams Link: https://lore.kernel.org/r/20200716115438.9967-1-m.shams@samsung.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 309fa42b0861..3403dd790517 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1121,7 +1121,7 @@ out: return ret; } -static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state) +static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state) { struct tty_port *port = &state->port; struct uart_port *uport; @@ -1524,6 +1524,7 @@ static void uart_set_termios(struct tty_struct *tty, /* Handle transition away from B0 status */ else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { unsigned int mask = TIOCM_DTR; + if (!(cflag & CRTSCTS) || !tty_throttled(tty)) mask |= TIOCM_RTS; uart_set_mctrl(uport, mask); @@ -2280,6 +2281,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) if (console_suspend_enabled || !uart_console(uport)) { /* Protected by port mutex for now */ struct tty_struct *tty = port->tty; + ret = ops->startup(uport); if (ret == 0) { if (tty) -- cgit v1.2.3 From aaad2940c754ee186609f5f46cb1ec2ff3072c3f Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Sat, 18 Jul 2020 12:30:18 +0200 Subject: serial: altera_jtaguart: Replace HTTP links with HTTPS ones Rationale: Reduces attack surface on kernel devs opening the links for MITM as HTTPS traffic is much harder to manipulate. Deterministic algorithm: For each file: If not .svg: For each line: If doesn't contain `\bxmlns\b`: For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`: If neither `\bgnu\.org/license`, nor `\bmozilla\.org/MPL\b`: If both the HTTP and HTTPS versions return 200 OK and serve the same content: Replace HTTP with HTTPS. Signed-off-by: Alexander A. Klimov Acked-by: Tobias Klauser Link: https://lore.kernel.org/r/20200718103018.3164-1-grandmaster@al2klimov.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/altera_jtaguart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index c90e503d6b57..d0ca9cf29b62 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c @@ -27,7 +27,7 @@ /* * Altera JTAG UART register definitions according to the Altera JTAG UART - * datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf + * datasheet: https://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf */ #define ALTERA_JTAGUART_SIZE 8 -- cgit v1.2.3 From 23a98b6eb808e2080d6d4acba931b5db3aac9a16 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 20 Jul 2020 17:34:15 +0530 Subject: serial: pch_uart: use generic power management Drivers using legacy PM have to manage PCI states and device's PM states themselves. They also need to take care of configuration registers. With improved and powerful support of generic PM, PCI Core takes care of above mentioned, device-independent, jobs. This driver makes use of PCI helper functions like pci_save/restore_state(), pci_enable_device() and pci_set_power_state() to do required operations. In generic mode, they are no longer needed. Change function parameter in both .suspend() and .resume() to "struct device*" type. Use dev_get_drvdata() to get drv data. Compile-tested only. Signed-off-by: Vaibhav Gupta Link: https://lore.kernel.org/r/20200720120414.399961-1-vaibhavgupta40@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 40fa7a27722d..67aca8cb9cd4 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1857,41 +1857,24 @@ static void pch_uart_pci_remove(struct pci_dev *pdev) kfree(priv); return; } -#ifdef CONFIG_PM -static int pch_uart_pci_suspend(struct pci_dev *pdev, pm_message_t state) + +static int __maybe_unused pch_uart_pci_suspend(struct device *dev) { - struct eg20t_port *priv = pci_get_drvdata(pdev); + struct eg20t_port *priv = dev_get_drvdata(dev); uart_suspend_port(&pch_uart_driver, &priv->port); - pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } -static int pch_uart_pci_resume(struct pci_dev *pdev) +static int __maybe_unused pch_uart_pci_resume(struct device *dev) { - struct eg20t_port *priv = pci_get_drvdata(pdev); - int ret; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, - "%s-pci_enable_device failed(ret=%d) ", __func__, ret); - return ret; - } + struct eg20t_port *priv = dev_get_drvdata(dev); uart_resume_port(&pch_uart_driver, &priv->port); return 0; } -#else -#define pch_uart_pci_suspend NULL -#define pch_uart_pci_resume NULL -#endif static const struct pci_device_id pch_uart_pci_id[] = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811), @@ -1945,13 +1928,16 @@ probe_error: return ret; } +static SIMPLE_DEV_PM_OPS(pch_uart_pci_pm_ops, + pch_uart_pci_suspend, + pch_uart_pci_resume); + static struct pci_driver pch_uart_pci_driver = { .name = "pch_uart", .id_table = pch_uart_pci_id, .probe = pch_uart_pci_probe, .remove = pch_uart_pci_remove, - .suspend = pch_uart_pci_suspend, - .resume = pch_uart_pci_resume, + .driver.pm = &pch_uart_pci_pm_ops, }; static int __init pch_uart_module_init(void) -- cgit v1.2.3 From cb1a609236096c278ecbfb7be678a693a70283f1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 14 Jul 2020 11:30:11 +0200 Subject: serial: imx: implement rts delaying for rs485 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for delays between assertion of RTS (which is supposed to enable the rs485 transmitter) and sending as well as between the last send char and deassertionof RTS. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20200714093012.21621-2-uwe@kleine-koenig.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 157 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 121 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 6175f8398130..81f2824379c8 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -188,6 +188,13 @@ struct imx_uart_data { enum imx_uart_type devtype; }; +enum imx_tx_state { + OFF, + WAIT_AFTER_RTS, + SEND, + WAIT_AFTER_SEND, +}; + struct imx_port { struct uart_port port; struct timer_list timer; @@ -224,6 +231,11 @@ struct imx_port { unsigned int dma_tx_nents; unsigned int saved_reg[10]; bool context_saved; + + enum imx_tx_state tx_state; + unsigned long tx_state_next_change; + struct timer_list trigger_start_tx; + struct timer_list trigger_stop_tx; }; struct imx_port_ucrs { @@ -427,7 +439,10 @@ static void imx_uart_start_rx(struct uart_port *port) static void imx_uart_stop_tx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - u32 ucr1; + u32 ucr1, ucr4, usr2; + + if (sport->tx_state == OFF) + return; /* * We are maybe in the SMP context, so if the DMA TX thread is running @@ -439,21 +454,46 @@ static void imx_uart_stop_tx(struct uart_port *port) ucr1 = imx_uart_readl(sport, UCR1); imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1); - /* in rs485 mode disable transmitter if shifter is empty */ - if (port->rs485.flags & SER_RS485_ENABLED && - imx_uart_readl(sport, USR2) & USR2_TXDC) { - u32 ucr2 = imx_uart_readl(sport, UCR2), ucr4; - if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) - imx_uart_rts_active(sport, &ucr2); - else - imx_uart_rts_inactive(sport, &ucr2); - imx_uart_writel(sport, ucr2, UCR2); + usr2 = imx_uart_readl(sport, USR2); + if (!(usr2 & USR2_TXDC)) { + /* The shifter is still busy, so retry once TC triggers */ + return; + } - imx_uart_start_rx(port); + ucr4 = imx_uart_readl(sport, UCR4); + ucr4 &= ~UCR4_TCEN; + imx_uart_writel(sport, ucr4, UCR4); - ucr4 = imx_uart_readl(sport, UCR4); - ucr4 &= ~UCR4_TCEN; - imx_uart_writel(sport, ucr4, UCR4); + /* in rs485 mode disable transmitter */ + if (port->rs485.flags & SER_RS485_ENABLED) { + if (sport->tx_state == SEND) { + sport->tx_state = WAIT_AFTER_SEND; + sport->tx_state_next_change = + jiffies + DIV_ROUND_UP(port->rs485.delay_rts_after_send * HZ, 1000); + } + + if (sport->tx_state == WAIT_AFTER_RTS || + (sport->tx_state == WAIT_AFTER_SEND && + time_after_eq(jiffies, sport->tx_state_next_change))) { + u32 ucr2; + + del_timer(&sport->trigger_start_tx); + + ucr2 = imx_uart_readl(sport, UCR2); + if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) + imx_uart_rts_active(sport, &ucr2); + else + imx_uart_rts_inactive(sport, &ucr2); + imx_uart_writel(sport, ucr2, UCR2); + + imx_uart_start_rx(port); + + sport->tx_state = OFF; + } else if (sport->tx_state == WAIT_AFTER_SEND) { + mod_timer(&sport->trigger_stop_tx, sport->tx_state_next_change); + } + } else { + sport->tx_state = OFF; } } @@ -651,28 +691,53 @@ static void imx_uart_start_tx(struct uart_port *port) if (!sport->port.x_char && uart_circ_empty(&port->state->xmit)) return; + /* + * We cannot simply do nothing here if sport->tx_state == SEND already + * because UCR1_TXMPTYEN might already have been cleared in + * imx_uart_stop_tx(), but tx_state is still SEND. + */ + if (port->rs485.flags & SER_RS485_ENABLED) { - u32 ucr2; + if (sport->tx_state == OFF) { + u32 ucr2 = imx_uart_readl(sport, UCR2); + if (port->rs485.flags & SER_RS485_RTS_ON_SEND) + imx_uart_rts_active(sport, &ucr2); + else + imx_uart_rts_inactive(sport, &ucr2); + imx_uart_writel(sport, ucr2, UCR2); - ucr2 = imx_uart_readl(sport, UCR2); - if (port->rs485.flags & SER_RS485_RTS_ON_SEND) - imx_uart_rts_active(sport, &ucr2); - else - imx_uart_rts_inactive(sport, &ucr2); - imx_uart_writel(sport, ucr2, UCR2); + if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) + imx_uart_stop_rx(port); - if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) - imx_uart_stop_rx(port); + sport->tx_state = WAIT_AFTER_RTS; + sport->tx_state_next_change = + jiffies + DIV_ROUND_UP(port->rs485.delay_rts_before_send * HZ, 1000); + } - /* - * Enable transmitter and shifter empty irq only if DMA is off. - * In the DMA case this is done in the tx-callback. - */ - if (!sport->dma_is_enabled) { - u32 ucr4 = imx_uart_readl(sport, UCR4); - ucr4 |= UCR4_TCEN; - imx_uart_writel(sport, ucr4, UCR4); + if (sport->tx_state == WAIT_AFTER_SEND || + (sport->tx_state == WAIT_AFTER_RTS && + time_after_eq(jiffies, sport->tx_state_next_change))) { + + del_timer(&sport->trigger_stop_tx); + /* + * Enable transmitter and shifter empty irq only if DMA + * is off. In the DMA case this is done in the + * tx-callback. + */ + if (!sport->dma_is_enabled) { + u32 ucr4 = imx_uart_readl(sport, UCR4); + ucr4 |= UCR4_TCEN; + imx_uart_writel(sport, ucr4, UCR4); + } + + sport->tx_state = SEND; + + } else if (sport->tx_state == WAIT_AFTER_RTS) { + mod_timer(&sport->trigger_start_tx, sport->tx_state_next_change); + return; } + } else { + sport->tx_state = SEND; } if (!sport->dma_is_enabled) { @@ -1630,7 +1695,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_cflag & CRTSCTS) ucr2 &= ~UCR2_IRTS; - if (termios->c_cflag & CSTOPB) ucr2 |= UCR2_STPB; if (termios->c_cflag & PARENB) { @@ -1857,10 +1921,6 @@ static int imx_uart_rs485_config(struct uart_port *port, struct imx_port *sport = (struct imx_port *)port; u32 ucr2; - /* unimplemented */ - rs485conf->delay_rts_before_send = 0; - rs485conf->delay_rts_after_send = 0; - /* RTS is required to control the transmitter */ if (!sport->have_rtscts && !sport->have_rtsgpio) rs485conf->flags &= ~SER_RS485_ENABLED; @@ -2223,6 +2283,28 @@ static void imx_uart_probe_pdata(struct imx_port *sport, sport->have_rtscts = 1; } +static void imx_trigger_start_tx(struct timer_list *t) +{ + struct imx_port *sport = from_timer(sport, t, trigger_start_tx); + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); + if (sport->tx_state == WAIT_AFTER_RTS) + imx_uart_start_tx(&sport->port); + spin_unlock_irqrestore(&sport->port.lock, flags); +} + +static void imx_trigger_stop_tx(struct timer_list *t) +{ + struct imx_port *sport = from_timer(sport, t, trigger_stop_tx); + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); + if (sport->tx_state == WAIT_AFTER_SEND) + imx_uart_stop_tx(&sport->port); + spin_unlock_irqrestore(&sport->port.lock, flags); +} + static int imx_uart_probe(struct platform_device *pdev) { struct imx_port *sport; @@ -2369,6 +2451,9 @@ static int imx_uart_probe(struct platform_device *pdev) clk_disable_unprepare(sport->clk_ipg); + timer_setup(&sport->trigger_start_tx, imx_trigger_start_tx, 0); + timer_setup(&sport->trigger_stop_tx, imx_trigger_stop_tx, 0); + /* * Allocate the IRQ(s) i.MX1 has three interrupts whereas later * chips only have one interrupt. -- cgit v1.2.3 From bd78ecd6056d9987067db5b100d3667da6b85467 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Tue, 14 Jul 2020 11:30:12 +0200 Subject: serial: imx: use hrtimers for rs485 delays This patch imitates 6e0a5de213 ("serial: 8250: Use hrtimers for rs485 delays") in replacing the previously used classic timers with hrtimers. The old way provided a too coarse resolution on systems with configs of less than 1000 HZ. Use of hrtimers addresses this and can be easily extended to support microsecond resolution in future when support for this arrives upstream. Signed-off-by: Ahmad Fatoum Link: https://lore.kernel.org/r/20200714093012.21621-3-uwe@kleine-koenig.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 62 ++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 81f2824379c8..ba4e35229b36 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -233,9 +234,8 @@ struct imx_port { bool context_saved; enum imx_tx_state tx_state; - unsigned long tx_state_next_change; - struct timer_list trigger_start_tx; - struct timer_list trigger_stop_tx; + struct hrtimer trigger_start_tx; + struct hrtimer trigger_stop_tx; }; struct imx_port_ucrs { @@ -412,6 +412,15 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2) mctrl_gpio_set(sport->gpios, sport->port.mctrl); } +static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec) +{ + long sec = msec / MSEC_PER_SEC; + long nsec = (msec % MSEC_PER_SEC) * 1000000; + ktime_t t = ktime_set(sec, nsec); + + hrtimer_start(hrt, t, HRTIMER_MODE_REL); +} + /* called with port.lock taken and irqs off */ static void imx_uart_start_rx(struct uart_port *port) { @@ -468,16 +477,16 @@ static void imx_uart_stop_tx(struct uart_port *port) if (port->rs485.flags & SER_RS485_ENABLED) { if (sport->tx_state == SEND) { sport->tx_state = WAIT_AFTER_SEND; - sport->tx_state_next_change = - jiffies + DIV_ROUND_UP(port->rs485.delay_rts_after_send * HZ, 1000); + start_hrtimer_ms(&sport->trigger_stop_tx, + port->rs485.delay_rts_after_send); + return; } if (sport->tx_state == WAIT_AFTER_RTS || - (sport->tx_state == WAIT_AFTER_SEND && - time_after_eq(jiffies, sport->tx_state_next_change))) { + sport->tx_state == WAIT_AFTER_SEND) { u32 ucr2; - del_timer(&sport->trigger_start_tx); + hrtimer_try_to_cancel(&sport->trigger_start_tx); ucr2 = imx_uart_readl(sport, UCR2); if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) @@ -489,8 +498,6 @@ static void imx_uart_stop_tx(struct uart_port *port) imx_uart_start_rx(port); sport->tx_state = OFF; - } else if (sport->tx_state == WAIT_AFTER_SEND) { - mod_timer(&sport->trigger_stop_tx, sport->tx_state_next_change); } } else { sport->tx_state = OFF; @@ -710,15 +717,16 @@ static void imx_uart_start_tx(struct uart_port *port) imx_uart_stop_rx(port); sport->tx_state = WAIT_AFTER_RTS; - sport->tx_state_next_change = - jiffies + DIV_ROUND_UP(port->rs485.delay_rts_before_send * HZ, 1000); + start_hrtimer_ms(&sport->trigger_start_tx, + port->rs485.delay_rts_before_send); + return; } - if (sport->tx_state == WAIT_AFTER_SEND || - (sport->tx_state == WAIT_AFTER_RTS && - time_after_eq(jiffies, sport->tx_state_next_change))) { + if (sport->tx_state == WAIT_AFTER_SEND + || sport->tx_state == WAIT_AFTER_RTS) { + + hrtimer_try_to_cancel(&sport->trigger_stop_tx); - del_timer(&sport->trigger_stop_tx); /* * Enable transmitter and shifter empty irq only if DMA * is off. In the DMA case this is done in the @@ -731,10 +739,6 @@ static void imx_uart_start_tx(struct uart_port *port) } sport->tx_state = SEND; - - } else if (sport->tx_state == WAIT_AFTER_RTS) { - mod_timer(&sport->trigger_start_tx, sport->tx_state_next_change); - return; } } else { sport->tx_state = SEND; @@ -2283,26 +2287,30 @@ static void imx_uart_probe_pdata(struct imx_port *sport, sport->have_rtscts = 1; } -static void imx_trigger_start_tx(struct timer_list *t) +static enum hrtimer_restart imx_trigger_start_tx(struct hrtimer *t) { - struct imx_port *sport = from_timer(sport, t, trigger_start_tx); + struct imx_port *sport = container_of(t, struct imx_port, trigger_start_tx); unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); if (sport->tx_state == WAIT_AFTER_RTS) imx_uart_start_tx(&sport->port); spin_unlock_irqrestore(&sport->port.lock, flags); + + return HRTIMER_NORESTART; } -static void imx_trigger_stop_tx(struct timer_list *t) +static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t) { - struct imx_port *sport = from_timer(sport, t, trigger_stop_tx); + struct imx_port *sport = container_of(t, struct imx_port, trigger_stop_tx); unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); if (sport->tx_state == WAIT_AFTER_SEND) imx_uart_stop_tx(&sport->port); spin_unlock_irqrestore(&sport->port.lock, flags); + + return HRTIMER_NORESTART; } static int imx_uart_probe(struct platform_device *pdev) @@ -2451,8 +2459,10 @@ static int imx_uart_probe(struct platform_device *pdev) clk_disable_unprepare(sport->clk_ipg); - timer_setup(&sport->trigger_start_tx, imx_trigger_start_tx, 0); - timer_setup(&sport->trigger_stop_tx, imx_trigger_stop_tx, 0); + hrtimer_init(&sport->trigger_start_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&sport->trigger_stop_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + sport->trigger_start_tx.function = imx_trigger_start_tx; + sport->trigger_stop_tx.function = imx_trigger_stop_tx; /* * Allocate the IRQ(s) i.MX1 has three interrupts whereas later -- cgit v1.2.3 From 118499e70ecec5ca816ebeb6119b9aa16aefb66c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 24 Jul 2020 08:27:35 +0200 Subject: newport_con: vc_color is now in state Since commit 28bc24fc46f9 (vc: separate state), vc->vc_color is known as vc->state.color. Somehow both me and 0-day bot missed this driver during the conversion. So fix the driver now. Reported-by: kernel test robot Fixes: 28bc24fc46f9 ("vc: separate state") Signed-off-by: Jiri Slaby Cc: Bartlomiej Zolnierkiewicz Cc: dri-devel@lists.freedesktop.org Cc: linux-fbdev@vger.kernel.org Cc: linux-mips@vger.kernel.org Link: https://lore.kernel.org/r/20200724062735.18229-1-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/video/console/newport_con.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 504cda38763e..d9fa6b5317ab 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -359,12 +359,12 @@ static void newport_clear(struct vc_data *vc, int sy, int sx, int height, if (ystart < yend) { newport_clear_screen(sx << 3, ystart, xend, yend, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); } else { newport_clear_screen(sx << 3, ystart, xend, 1023, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); newport_clear_screen(sx << 3, 0, xend, yend, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); } } @@ -588,11 +588,11 @@ static bool newport_scroll(struct vc_data *vc, unsigned int t, unsigned int b, topscan = (topscan + (lines << 4)) & 0x3ff; newport_clear_lines(vc->vc_rows - lines, vc->vc_rows - 1, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); } else { topscan = (topscan + (-lines << 4)) & 0x3ff; newport_clear_lines(0, lines - 1, - (vc->vc_color & 0xf0) >> 4); + (vc->state.color & 0xf0) >> 4); } npregs->cset.topscan = (topscan - 1) & 0x3ff; return false; -- cgit v1.2.3 From de5b2c9d16924ad0d9e2bfd9a5da16fe6ea54f22 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 23 Jul 2020 14:33:26 +0200 Subject: serial: pmac_zilog: add sparse context annotation Add sparse context annotation to the receive handler, which releases and reacquires the port lock, to silence a sparse warning: drivers/tty/serial/pmac_zilog.c:255:36: sparse: sparse: context imbalance in 'pmz_receive_chars' - unexpected unlock Reported-by: kernel test robot Signed-off-by: Johan Hovold Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200723123327.5843-2-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pmac_zilog.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index ba65a3bbd72a..96e7aa479961 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -213,6 +213,7 @@ static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable) } static bool pmz_receive_chars(struct uart_pmac_port *uap) + __must_hold(&uap->port.lock) { struct tty_port *port; unsigned char ch, r1, drop, flag; -- cgit v1.2.3 From ca45b5cd55d2ea2e4f2ddec1175cc9bdb5b74e07 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 23 Jul 2020 14:33:27 +0200 Subject: serial: msm_serial: add sparse context annotation Add sparse context annotation to the receive handlers, which release and reacquire the port lock, to silence sparse warnings: drivers/tty/serial/msm_serial.c:748:25: warning: context imbalance in 'msm_handle_rx_dm' - unexpected unlock drivers/tty/serial/msm_serial.c:814:28: warning: context imbalance in 'msm_handle_rx' - unexpected unlock Signed-off-by: Johan Hovold Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200723123327.5843-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 60a9c53fa7cb..87f005e5d2af 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -696,6 +696,7 @@ static void msm_enable_ms(struct uart_port *port) } static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) + __must_hold(&port->lock) { struct tty_port *tport = &port->state->port; unsigned int sr; @@ -771,6 +772,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) } static void msm_handle_rx(struct uart_port *port) + __must_hold(&port->lock) { struct tty_port *tport = &port->state->port; unsigned int sr; -- cgit v1.2.3 From e5b9f4b1dc3e73f8a327b242c783551c4bf15bbd Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 Jul 2020 17:31:27 -0500 Subject: tty: Avoid the use of one-element arrays One-element arrays are being deprecated[1]. Replace the one-element arrays with simple value types 'char reserved_char' and 'compat_int_t reserved'[2], once it seems these are just placeholders for alignment. [1] https://github.com/KSPP/linux/issues/79 [2] https://github.com/KSPP/linux/issues/86 Tested-by: kernel test robot Link: https://github.com/GustavoARSilva/linux-hardening/blob/master/cii/0-day/tty-20200716.md Acked-by: Jiri Slaby Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/f49bf0e27eaac396c96d21392c8c284f9f5ef52a.1595543280.git.gustavoars@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 5a6f36b391d9..3b6e5ec3ba54 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2683,7 +2683,7 @@ struct serial_struct32 { compat_int_t baud_base; unsigned short close_delay; char io_type; - char reserved_char[1]; + char reserved_char; compat_int_t hub6; unsigned short closing_wait; /* time to wait before closing */ unsigned short closing_wait2; /* no longer used... */ @@ -2691,7 +2691,7 @@ struct serial_struct32 { unsigned short iomem_reg_shift; unsigned int port_high; /* compat_ulong_t iomap_base FIXME */ - compat_int_t reserved[1]; + compat_int_t reserved; }; static int compat_tty_tiocsserial(struct tty_struct *tty, -- cgit v1.2.3 From 52b52e91899bc5a76a77b42ec1bdf245aee0286e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 Jul 2020 17:32:25 -0500 Subject: tty: Fix identation issues in struct serial_struct32 Fix the following checkpatch.pl warnings together with all the identation issues in struct serial_struct32: ERROR: code indent should use tabs where possible + char reserved_char;$ WARNING: please, no spaces at the start of a line + char reserved_char;$ ERROR: code indent should use tabs where possible + compat_int_t reserved;$ WARNING: please, no spaces at the start of a line + compat_int_t reserved;$ Acked-by: Jiri Slaby Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/77576843397aeab0af8aa0423a9768f3ca8dedfb.1595543280.git.gustavoars@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 3b6e5ec3ba54..629fbafc9b7e 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2673,25 +2673,25 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #ifdef CONFIG_COMPAT struct serial_struct32 { - compat_int_t type; - compat_int_t line; - compat_uint_t port; - compat_int_t irq; - compat_int_t flags; - compat_int_t xmit_fifo_size; - compat_int_t custom_divisor; - compat_int_t baud_base; - unsigned short close_delay; - char io_type; - char reserved_char; - compat_int_t hub6; - unsigned short closing_wait; /* time to wait before closing */ - unsigned short closing_wait2; /* no longer used... */ - compat_uint_t iomem_base; - unsigned short iomem_reg_shift; - unsigned int port_high; - /* compat_ulong_t iomap_base FIXME */ - compat_int_t reserved; + compat_int_t type; + compat_int_t line; + compat_uint_t port; + compat_int_t irq; + compat_int_t flags; + compat_int_t xmit_fifo_size; + compat_int_t custom_divisor; + compat_int_t baud_base; + unsigned short close_delay; + char io_type; + char reserved_char; + compat_int_t hub6; + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + compat_uint_t iomem_base; + unsigned short iomem_reg_shift; + unsigned int port_high; + /* compat_ulong_t iomap_base FIXME */ + compat_int_t reserved; }; static int compat_tty_tiocsserial(struct tty_struct *tty, -- cgit v1.2.3 From a32418919dd5e863ce47db1bac9051a5364e44a0 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 23 Jul 2020 17:34:22 -0500 Subject: tty: Use the preferred form for passing the size of a structure type Use the preferred form for passing the size of a structure type. The alternative form where the structure type is spelled out hurts readability and introduces an opportunity for a bug when the object type is changed but the corresponding object identifier to which the sizeof operator is applied is not. Signed-off-by: Gustavo A. R. Silva Acked-by: Jiri Slaby Link: https://lore.kernel.org/r/b04dd8cdd67bd6ffde3fd12940aeef35fdb824a6.1595543280.git.gustavoars@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 629fbafc9b7e..ceed72c9a88f 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1405,7 +1405,7 @@ void tty_save_termios(struct tty_struct *tty) /* Stash the termios data */ tp = tty->driver->termios[idx]; if (tp == NULL) { - tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); + tp = kmalloc(sizeof(*tp), GFP_KERNEL); if (tp == NULL) return; tty->driver->termios[idx] = tp; @@ -2489,7 +2489,7 @@ static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user * struct serial_struct v; int flags; - if (copy_from_user(&v, ss, sizeof(struct serial_struct))) + if (copy_from_user(&v, ss, sizeof(*ss))) return -EFAULT; flags = v.flags & ASYNC_DEPRECATED; @@ -2507,11 +2507,11 @@ static int tty_tiocgserial(struct tty_struct *tty, struct serial_struct __user * struct serial_struct v; int err; - memset(&v, 0, sizeof(struct serial_struct)); + memset(&v, 0, sizeof(v)); if (!tty->ops->get_serial) return -ENOTTY; err = tty->ops->get_serial(tty, &v); - if (!err && copy_to_user(ss, &v, sizeof(struct serial_struct))) + if (!err && copy_to_user(ss, &v, sizeof(v))) err = -EFAULT; return err; } @@ -2705,7 +2705,7 @@ static int compat_tty_tiocsserial(struct tty_struct *tty, struct serial_struct v; int flags; - if (copy_from_user(&v32, ss, sizeof(struct serial_struct32))) + if (copy_from_user(&v32, ss, sizeof(*ss))) return -EFAULT; memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base)); @@ -2743,7 +2743,7 @@ static int compat_tty_tiocgserial(struct tty_struct *tty, 0xfffffff : ptr_to_compat(v.iomem_base); v32.iomem_reg_shift = v.iomem_reg_shift; v32.port_high = v.port_high; - if (copy_to_user(ss, &v32, sizeof(struct serial_struct32))) + if (copy_to_user(ss, &v32, sizeof(v32))) err = -EFAULT; } return err; @@ -3215,7 +3215,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1)) return ERR_PTR(-EINVAL); - driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); + driver = kzalloc(sizeof(*driver), GFP_KERNEL); if (!driver) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From a5e0691fd9f610eb46ab4cd070fa7b08ee780bf4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 27 Jul 2020 15:05:01 +0200 Subject: tty/synclink: remove leftover bits of non-PCI card support Since commit 1355cba9c3ba ("tty/synclink: remove ISA support"), the synlink driver only supports PCI card. Remove any leftover dead code to support other cards. Signed-off-by: Christoph Hellwig Link: https://lore.kernel.org/r/20200727130501.31005-1-hch@lst.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/synclink.c | 350 +++++++++++++++---------------------------------- 1 file changed, 109 insertions(+), 241 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 08d2976593d5..0dba40eace46 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -252,7 +252,6 @@ struct mgsl_struct { char device_name[25]; /* device instance name */ - unsigned int bus_type; /* expansion bus type (ISA,EISA,PCI) */ unsigned char bus; /* expansion bus number (zero based) */ unsigned char function; /* PCI device number */ @@ -3432,15 +3431,9 @@ static inline void line_info(struct seq_file *m, struct mgsl_struct *info) char stat_buf[30]; unsigned long flags; - if (info->bus_type == MGSL_BUS_TYPE_PCI) { - seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", - info->device_name, info->io_base, info->irq_level, - info->phys_memory_base, info->phys_lcr_base); - } else { - seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d", - info->device_name, info->io_base, - info->irq_level, info->dma_level); - } + seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", + info->device_name, info->io_base, info->irq_level, + info->phys_memory_base, info->phys_lcr_base); /* output current serial signal states */ spin_lock_irqsave(&info->irq_spinlock,flags); @@ -3556,54 +3549,27 @@ static int mgsl_allocate_dma_buffers(struct mgsl_struct *info) if ( info->max_frame_size % DMABUFFERSIZE ) BuffersPerFrame++; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* - * The PCI adapter has 256KBytes of shared memory to use. - * This is 64 PAGE_SIZE buffers. - * - * The first page is used for padding at this time so the - * buffer list does not begin at offset 0 of the PCI - * adapter's shared memory. - * - * The 2nd page is used for the buffer list. A 4K buffer - * list can hold 128 DMA_BUFFER structures at 32 bytes - * each. - * - * This leaves 62 4K pages. - * - * The next N pages are used for transmit frame(s). We - * reserve enough 4K page blocks to hold the required - * number of transmit dma buffers (num_tx_dma_buffers), - * each of MaxFrameSize size. - * - * Of the remaining pages (62-N), determine how many can - * be used to receive full MaxFrameSize inbound frames - */ - info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; - info->rx_buffer_count = 62 - info->tx_buffer_count; - } else { - /* Calculate the number of PAGE_SIZE buffers needed for */ - /* receive and transmit DMA buffers. */ - - - /* Calculate the number of DMA buffers necessary to */ - /* hold 7 max size receive frames and one max size transmit frame. */ - /* The receive buffer count is bumped by one so we avoid an */ - /* End of List condition if all receive buffers are used when */ - /* using linked list DMA buffers. */ - - info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; - info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6; - - /* - * limit total TxBuffers & RxBuffers to 62 4K total - * (ala PCI Allocation) - */ - - if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 ) - info->rx_buffer_count = 62 - info->tx_buffer_count; - - } + /* + * The PCI adapter has 256KBytes of shared memory to use. This is 64 + * PAGE_SIZE buffers. + * + * The first page is used for padding at this time so the buffer list + * does not begin at offset 0 of the PCI adapter's shared memory. + * + * The 2nd page is used for the buffer list. A 4K buffer list can hold + * 128 DMA_BUFFER structures at 32 bytes each. + * + * This leaves 62 4K pages. + * + * The next N pages are used for transmit frame(s). We reserve enough + * 4K page blocks to hold the required number of transmit dma buffers + * (num_tx_dma_buffers), each of MaxFrameSize size. + * + * Of the remaining pages (62-N), determine how many can be used to + * receive full MaxFrameSize inbound frames + */ + info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame; + info->rx_buffer_count = 62 - info->tx_buffer_count; if ( debug_level >= DEBUG_LEVEL_INFO ) printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n", @@ -3652,23 +3618,10 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) { unsigned int i; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* PCI adapter uses shared memory. */ - info->buffer_list = info->memory_base + info->last_mem_alloc; - info->buffer_list_phys = info->last_mem_alloc; - info->last_mem_alloc += BUFFERLISTSIZE; - } else { - /* ISA adapter uses system memory. */ - /* The buffer lists are allocated as a common buffer that both */ - /* the processor and adapter can access. This allows the driver to */ - /* inspect portions of the buffer while other portions are being */ - /* updated by the adapter using Bus Master DMA. */ - - info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL); - if (info->buffer_list == NULL) - return -ENOMEM; - info->buffer_list_phys = (u32)(info->buffer_list_dma_addr); - } + /* PCI adapter uses shared memory. */ + info->buffer_list = info->memory_base + info->last_mem_alloc; + info->buffer_list_phys = info->last_mem_alloc; + info->last_mem_alloc += BUFFERLISTSIZE; /* We got the memory for the buffer entry lists. */ /* Initialize the memory block to all zeros. */ @@ -3734,9 +3687,6 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) */ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) { - if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI) - dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr); - info->buffer_list = NULL; info->rx_buffer_list = NULL; info->tx_buffer_list = NULL; @@ -3762,24 +3712,13 @@ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) { int i; - u32 phys_addr; /* Allocate page sized buffers for the receive buffer list */ for ( i = 0; i < Buffercount; i++ ) { - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* PCI adapter uses shared memory buffers. */ - BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc; - phys_addr = info->last_mem_alloc; - info->last_mem_alloc += DMABUFFERSIZE; - } else { - /* ISA adapter uses system memory. */ - BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL); - if (BufferList[i].virt_addr == NULL) - return -ENOMEM; - phys_addr = (u32)(BufferList[i].dma_addr); - } - BufferList[i].phys_addr = phys_addr; + BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc; + BufferList[i].phys_addr = info->last_mem_alloc; + info->last_mem_alloc += DMABUFFERSIZE; } return 0; @@ -3807,8 +3746,6 @@ static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *Buf if ( BufferList ) { for ( i = 0 ; i < Buffercount ; i++ ) { if ( BufferList[i].virt_addr ) { - if ( info->bus_type != MGSL_BUS_TYPE_PCI ) - dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr); BufferList[i].virt_addr = NULL; } } @@ -4040,58 +3977,40 @@ static int mgsl_claim_resources(struct mgsl_struct *info) } info->irq_requested = true; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { - printk( "%s(%d):mem addr conflict device %s Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base); - goto errout; - } - info->shared_mem_requested = true; - if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) { - printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset); - goto errout; - } - info->lcr_mem_requested = true; - - info->memory_base = ioremap(info->phys_memory_base, - 0x40000); - if (!info->memory_base) { - printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - goto errout; - } - - if ( !mgsl_memory_test(info) ) { - printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - goto errout; - } - - info->lcr_base = ioremap(info->phys_lcr_base, - PAGE_SIZE); - if (!info->lcr_base) { - printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n", - __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); - goto errout; - } - info->lcr_base += info->lcr_offset; + if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { + printk( "%s(%d):mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base); + goto errout; + } + info->shared_mem_requested = true; + if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) { + printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset); + goto errout; + } + info->lcr_mem_requested = true; + + info->memory_base = ioremap(info->phys_memory_base, 0x40000); + if (!info->memory_base) { + printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + goto errout; + } - } else { - /* claim DMA channel */ + if ( !mgsl_memory_test(info) ) { + printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base ); + goto errout; + } - if (request_dma(info->dma_level,info->device_name) < 0){ - printk( "%s(%d):Can't request DMA channel on device %s DMA=%d\n", - __FILE__,__LINE__,info->device_name, info->dma_level ); - goto errout; - } - info->dma_requested = true; - - /* ISA adapter uses bus master DMA */ - set_dma_mode(info->dma_level,DMA_MODE_CASCADE); - enable_dma(info->dma_level); + info->lcr_base = ioremap(info->phys_lcr_base, PAGE_SIZE); + if (!info->lcr_base) { + printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); + goto errout; } - + info->lcr_base += info->lcr_offset; + if ( mgsl_allocate_dma_buffers(info) < 0 ) { printk( "%s(%d):Can't allocate DMA buffers on device %s DMA=%d\n", __FILE__,__LINE__,info->device_name, info->dma_level ); @@ -4200,16 +4119,10 @@ static void mgsl_add_device( struct mgsl_struct *info ) else if ( info->max_frame_size > 65535 ) info->max_frame_size = 65535; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n", - info->hw_version + 1, info->device_name, info->io_base, info->irq_level, - info->phys_memory_base, info->phys_lcr_base, - info->max_frame_size ); - } else { - printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n", - info->device_name, info->io_base, info->irq_level, info->dma_level, - info->max_frame_size ); - } + printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n", + info->hw_version + 1, info->device_name, info->io_base, info->irq_level, + info->phys_memory_base, info->phys_lcr_base, + info->max_frame_size ); #if SYNCLINK_GENERIC_HDLC hdlcdev_init(info); @@ -4420,8 +4333,7 @@ static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ) outw( Cmd + info->loopback_bits, info->io_base + CCAR ); /* Read to flush write to CCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base + CCAR ); + inw( info->io_base + CCAR ); } /* end of usc_RTCmd() */ @@ -4445,8 +4357,7 @@ static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ) outw( Cmd + info->mbre_bit, info->io_base ); /* Read to flush write to DCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base ); + inw( info->io_base ); } /* end of usc_DmaCmd() */ @@ -4475,8 +4386,7 @@ static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) outw( RegValue, info->io_base ); /* Read to flush write to DCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base ); + inw( info->io_base ); } /* end of usc_OutDmaReg() */ @@ -4528,8 +4438,7 @@ static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) outw( RegValue, info->io_base + CCAR ); /* Read to flush write to CCAR */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - inw( info->io_base + CCAR ); + inw( info->io_base + CCAR ); } /* end of usc_OutReg() */ @@ -4728,10 +4637,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) RegValue = usc_InReg( info, RICR ) & 0xc0; - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - usc_OutReg( info, RICR, (u16)(0x030a | RegValue) ); - else - usc_OutReg( info, RICR, (u16)(0x140a | RegValue) ); + usc_OutReg( info, RICR, (u16)(0x030a | RegValue) ); /* Unlatch all Rx status bits and clear Rx status IRQ Pending */ @@ -4792,10 +4698,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) * 0000 0000 0011 0110 = 0x0036 */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - usc_OutReg( info, TICR, 0x0736 ); - else - usc_OutReg( info, TICR, 0x1436 ); + usc_OutReg( info, TICR, 0x0736 ); usc_UnlatchTxstatusBits( info, TXSTATUS_ALL ); usc_ClearIrqPendingBits( info, TRANSMIT_STATUS ); @@ -4885,10 +4788,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) /* DPLL is enabled. Use BRG1 to provide continuous reference clock */ /* for DPLL. DPLL mode in HCR is dependent on the encoding used. */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - XtalSpeed = 11059200; - else - XtalSpeed = 14745600; + XtalSpeed = 11059200; if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) { DpllDivisor = 16; @@ -5011,13 +4911,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) * 0110 0000 0000 1011 = 0x600b */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* PCI adapter does not need DMA wait state */ - usc_OutDmaReg( info, DCR, 0xa00b ); - } - else - usc_OutDmaReg( info, DCR, 0x800b ); - + /* PCI adapter does not need DMA wait state */ + usc_OutDmaReg( info, DCR, 0xa00b ); /* Receive DMA mode Register (RDMR) * @@ -5109,12 +5004,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) * <7..0> 0x00 Maximum number of clock cycles per bus grant */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* don't limit bus occupancy on PCI adapter */ - usc_OutDmaReg( info, BDCR, 0x0000 ); - } - else - usc_OutDmaReg( info, BDCR, 0x2000 ); + /* don't limit bus occupancy on PCI adapter */ + usc_OutDmaReg( info, BDCR, 0x0000 ); usc_stop_transmitter(info); usc_stop_receiver(info); @@ -5155,10 +5046,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable) /* Write 16-bit Time Constant for BRG0 */ /* use clock speed if available, otherwise use 8 for diagnostics */ if (info->params.clock_speed) { - if (info->bus_type == MGSL_BUS_TYPE_PCI) - usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1)); - else - usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1)); + usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1)); } else usc_OutReg(info, TC0R, (u16)8); @@ -5201,10 +5089,7 @@ static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate ) u16 Tc; if ( data_rate ) { - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - XtalSpeed = 11059200; - else - XtalSpeed = 14745600; + XtalSpeed = 11059200; /* Tc = (Xtal/Speed) - 1 */ @@ -5682,44 +5567,38 @@ static void usc_load_txfifo( struct mgsl_struct *info ) */ static void usc_reset( struct mgsl_struct *info ) { - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - int i; - u32 readval; + int i; + u32 readval; - /* Set BIT30 of Misc Control Register */ - /* (Local Control Register 0x50) to force reset of USC. */ + /* Set BIT30 of Misc Control Register */ + /* (Local Control Register 0x50) to force reset of USC. */ - volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50); - u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28); + volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50); + u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28); - info->misc_ctrl_value |= BIT30; - *MiscCtrl = info->misc_ctrl_value; + info->misc_ctrl_value |= BIT30; + *MiscCtrl = info->misc_ctrl_value; - /* - * Force at least 170ns delay before clearing - * reset bit. Each read from LCR takes at least - * 30ns so 10 times for 300ns to be safe. - */ - for(i=0;i<10;i++) - readval = *MiscCtrl; - - info->misc_ctrl_value &= ~BIT30; - *MiscCtrl = info->misc_ctrl_value; - - *LCR0BRDR = BUS_DESCRIPTOR( - 1, // Write Strobe Hold (0-3) - 2, // Write Strobe Delay (0-3) - 2, // Read Strobe Delay (0-3) - 0, // NWDD (Write data-data) (0-3) - 4, // NWAD (Write Addr-data) (0-31) - 0, // NXDA (Read/Write Data-Addr) (0-3) - 0, // NRDD (Read Data-Data) (0-3) - 5 // NRAD (Read Addr-Data) (0-31) - ); - } else { - /* do HW reset */ - outb( 0,info->io_base + 8 ); - } + /* + * Force at least 170ns delay before clearing reset bit. Each read from + * LCR takes at least 30ns so 10 times for 300ns to be safe. + */ + for(i=0;i<10;i++) + readval = *MiscCtrl; + + info->misc_ctrl_value &= ~BIT30; + *MiscCtrl = info->misc_ctrl_value; + + *LCR0BRDR = BUS_DESCRIPTOR( + 1, // Write Strobe Hold (0-3) + 2, // Write Strobe Delay (0-3) + 2, // Read Strobe Delay (0-3) + 0, // NWDD (Write data-data) (0-3) + 4, // NWAD (Write Addr-data) (0-31) + 0, // NXDA (Read/Write Data-Addr) (0-3) + 0, // NRDD (Read Data-Data) (0-3) + 5 // NRAD (Read Addr-Data) (0-31) + ); info->mbre_bit = 0; info->loopback_bits = 0; @@ -6228,11 +6107,7 @@ static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate ) * ClkSpeed = 921600 (ISA), 691200 (PCI) */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) ); - else - usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) ); - + usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) ); /* * Hardware Configuration Register (HCR) @@ -6837,10 +6712,7 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, /* Actually copy data from source buffer to DMA buffer. */ /* Also set the data count for this individual DMA buffer. */ - if ( info->bus_type == MGSL_BUS_TYPE_PCI ) - mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount); - else - memcpy(pBufEntry->virt_addr, Buffer, Copycount); + mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount); pBufEntry->count = Copycount; @@ -7315,9 +7187,6 @@ static bool mgsl_memory_test( struct mgsl_struct *info ) unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long); unsigned long * TestAddr; - if ( info->bus_type != MGSL_BUS_TYPE_PCI ) - return true; - TestAddr = (unsigned long *)info->memory_base; /* Test data lines with test pattern at one location. */ @@ -8003,7 +7872,6 @@ static int synclink_init_one (struct pci_dev *dev, info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); info->phys_lcr_base &= ~(PAGE_SIZE-1); - info->bus_type = MGSL_BUS_TYPE_PCI; info->io_addr_size = 8; info->irq_flags = IRQF_SHARED; -- cgit v1.2.3 From 0db4f9b91c86bfe9d33e191a31b0150879e2acee Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Fri, 24 Jul 2020 15:08:14 +0800 Subject: tty: serial: imx: enable imx serial console port as module Add support for building i.MX serial driver as module. The changes of the patch: - imx console driver can be built as module. - move out earlycon code to separated driver like imx_earlycon.c, and imx earlycon driver only support build-in. Signed-off-by: Fugang Duan Link: https://lore.kernel.org/r/20200724070815.11445-2-fugang.duan@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 9 ++++----- drivers/tty/serial/imx.c | 37 ++----------------------------------- 2 files changed, 6 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 780908d43557..7fa2c78d1989 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -502,15 +502,14 @@ config SERIAL_IMX can enable its onboard serial port by enabling this option. config SERIAL_IMX_CONSOLE - bool "Console on IMX serial port" - depends on SERIAL_IMX=y + tristate "Console on IMX serial port" + depends on SERIAL_IMX select SERIAL_CORE_CONSOLE - select SERIAL_EARLYCON if OF help If you have enabled the serial port on the Freescale IMX - CPU you can make it the console by answering Y to this option. + CPU you can make it the console by answering Y/M to this option. - Even if you say Y here, the currently visible virtual console + Even if you say Y/M here, the currently visible virtual console (/dev/tty0) will still be used as the system console by default, but you can alter that using a kernel command line option such as "console=ttymxc0". (Try "man bootparam" or see the documentation of diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index ba4e35229b36..ce8c472cf385 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -373,7 +373,7 @@ static inline int imx_uart_is_imx6q(struct imx_port *sport) /* * Save and restore functions for UCR1, UCR2 and UCR3 registers */ -#if defined(CONFIG_SERIAL_IMX_CONSOLE) +#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE) static void imx_uart_ucrs_save(struct imx_port *sport, struct imx_port_ucrs *ucr) { @@ -1979,7 +1979,7 @@ static const struct uart_ops imx_uart_pops = { static struct imx_port *imx_uart_ports[UART_NR]; -#ifdef CONFIG_SERIAL_IMX_CONSOLE +#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE) static void imx_uart_console_putchar(struct uart_port *port, int ch) { struct imx_port *sport = (struct imx_port *)port; @@ -2176,39 +2176,6 @@ static struct console imx_uart_console = { #define IMX_CONSOLE &imx_uart_console -#ifdef CONFIG_OF -static void imx_uart_console_early_putchar(struct uart_port *port, int ch) -{ - struct imx_port *sport = (struct imx_port *)port; - - while (imx_uart_readl(sport, IMX21_UTS) & UTS_TXFULL) - cpu_relax(); - - imx_uart_writel(sport, ch, URTX0); -} - -static void imx_uart_console_early_write(struct console *con, const char *s, - unsigned count) -{ - struct earlycon_device *dev = con->data; - - uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar); -} - -static int __init -imx_console_early_setup(struct earlycon_device *dev, const char *opt) -{ - if (!dev->port.membase) - return -ENODEV; - - dev->con->write = imx_uart_console_early_write; - - return 0; -} -OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup); -OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup); -#endif - #else #define IMX_CONSOLE NULL #endif -- cgit v1.2.3 From 699cc4dfd14071e4843e2fde8ce01f09871eb318 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Fri, 24 Jul 2020 15:08:15 +0800 Subject: tty: serial: imx: add imx earlycon driver Split imx earlycon driver from imx serial driver "imx.c" as separated driver. imx serial driver can be built as module, but earlycon driver only support build in. Signed-off-by: Fugang Duan Link: https://lore.kernel.org/r/20200724070815.11445-3-fugang.duan@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 8 +++++++ drivers/tty/serial/imx_earlycon.c | 50 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 drivers/tty/serial/imx_earlycon.c (limited to 'drivers') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 7fa2c78d1989..8a0352eb337c 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -515,6 +515,14 @@ config SERIAL_IMX_CONSOLE "console=ttymxc0". (Try "man bootparam" or see the documentation of your bootloader about how to pass options to the kernel at boot time.) +config SERIAL_IMX_EARLYCON + bool "Earlycon on IMX serial port" + depends on OF + select SERIAL_EARLYCON + help + If you have enabled the earlycon on the Freescale IMX + CPU you can make it the earlycon by answering Y to this option. + config SERIAL_UARTLITE tristate "Xilinx uartlite serial port support" depends on HAS_IOMEM diff --git a/drivers/tty/serial/imx_earlycon.c b/drivers/tty/serial/imx_earlycon.c new file mode 100644 index 000000000000..795606e1a22f --- /dev/null +++ b/drivers/tty/serial/imx_earlycon.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define URTX0 0x40 /* Transmitter Register */ +#define UTS_TXFULL (1<<4) /* TxFIFO full */ +#define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/ + +static void imx_uart_console_early_putchar(struct uart_port *port, int ch) +{ + while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL) + cpu_relax(); + + writel_relaxed(ch, port->membase + URTX0); +} + +static void imx_uart_console_early_write(struct console *con, const char *s, + unsigned count) +{ + struct earlycon_device *dev = con->data; + + uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar); +} + +static int __init +imx_console_early_setup(struct earlycon_device *dev, const char *opt) +{ + if (!dev->port.membase) + return -ENODEV; + + dev->con->write = imx_uart_console_early_write; + + return 0; +} +OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup); +OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup); + +MODULE_AUTHOR("NXP"); +MODULE_DESCRIPTION("IMX earlycon driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 868f3ee6e452bc2b89e68183a1700fcbbe0807b1 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Thu, 23 Jul 2020 03:33:54 +0300 Subject: serial: 8250: Add 8250 port clock update method Some platforms can be designed in a way so the UART port reference clock might be asynchronously changed at some point. In Baikal-T1 SoC this may happen due to the reference clock being shared between two UART ports, on the Allwinner SoC the reference clock is derived from the CPU clock, so any CPU frequency change should get to be known/reflected by/in the UART controller as well. But it's not enough to just update the uart_port->uartclk field of the corresponding UART port, the 8250 controller reference clock divisor should be altered so to preserve current baud rate setting. All of these things is done in a coherent way by calling the serial8250_update_uartclk() method provided in this patch. Though note that it isn't supposed to be called from within the UART port callbacks because the locks using to the protect the UART port data are already taken in there. Signed-off-by: Serge Semin Link: https://lore.kernel.org/r/20200723003357.26897-2-Sergey.Semin@baikalelectronics.ru Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 40 +++++++++++++++++++++++++++++++++++++ include/linux/serial_8250.h | 2 ++ 2 files changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index d64ca77d9cfa..09475695effd 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2632,6 +2632,46 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, (port->uartclk + tolerance) / 16); } +/* + * Note in order to avoid the tty port mutex deadlock don't use the next method + * within the uart port callbacks. Primarily it's supposed to be utilized to + * handle a sudden reference clock rate change. + */ +void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) +{ + struct uart_8250_port *up = up_to_u8250p(port); + unsigned int baud, quot, frac = 0; + struct ktermios *termios; + unsigned long flags; + + mutex_lock(&port->state->port.mutex); + + if (port->uartclk == uartclk) + goto out_lock; + + port->uartclk = uartclk; + termios = &port->state->port.tty->termios; + + baud = serial8250_get_baud_rate(port, termios, NULL); + quot = serial8250_get_divisor(port, baud, &frac); + + serial8250_rpm_get(up); + spin_lock_irqsave(&port->lock, flags); + + uart_update_timeout(port, termios->c_cflag, baud); + + serial8250_set_divisor(port, baud, quot, frac); + serial_port_out(port, UART_LCR, up->lcr); + serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS); + + spin_unlock_irqrestore(&port->lock, flags); + serial8250_rpm_put(up); + +out_lock: + mutex_unlock(&port->state->port.mutex); +} +EXPORT_SYMBOL_GPL(serial8250_update_uartclk); + void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 6545f8cfc8fa..2b70f736b091 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -155,6 +155,8 @@ extern int early_serial_setup(struct uart_port *port); extern int early_serial8250_setup(struct earlycon_device *device, const char *options); +extern void serial8250_update_uartclk(struct uart_port *port, + unsigned int uartclk); extern void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old); extern void serial8250_do_set_ldisc(struct uart_port *port, -- cgit v1.2.3 From 442fdef1b931181a45ce4fce68b7675f7a78ec3a Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Thu, 23 Jul 2020 03:33:55 +0300 Subject: serial: 8250_dw: Simplify the ref clock rate setting procedure Really instead of twice checking the clk_round_rate() return value we could do it once, and if it isn't error the clock rate can be changed. By doing so we decrease a number of ret-value tests and remove a weird goto-based construction implemented in the dw8250_set_termios() method. Signed-off-by: Serge Semin Link: https://lore.kernel.org/r/20200723003357.26897-3-Sergey.Semin@baikalelectronics.ru Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index aab3cccc6789..12866083731d 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -282,20 +282,13 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, clk_disable_unprepare(d->clk); rate = clk_round_rate(d->clk, baud * 16); - if (rate < 0) - ret = rate; - else if (rate == 0) - ret = -ENOENT; - else + if (rate > 0) { ret = clk_set_rate(d->clk, rate); + if (!ret) + p->uartclk = rate; + } clk_prepare_enable(d->clk); - if (ret) - goto out; - - p->uartclk = rate; - -out: p->status &= ~UPSTAT_AUTOCTS; if (termios->c_cflag & CRTSCTS) p->status |= UPSTAT_AUTOCTS; -- cgit v1.2.3 From 0be160cf86f96dbc2d1cb74f9eef3581a2ad7971 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Thu, 23 Jul 2020 03:33:56 +0300 Subject: serial: 8250_dw: Pass the same rate to the clk round and set rate methods Indeed according to the clk API if clk_round_rate() has successfully accepted a rate, then in order setup the clock with value returned by the clk_round_rate() the clk_set_rate() method must be called with the original rate value. Suggested-by: Russell King Signed-off-by: Serge Semin Link: https://lore.kernel.org/r/20200723003357.26897-4-Sergey.Semin@baikalelectronics.ru Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 12866083731d..c1511f9244bb 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -275,15 +275,15 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, struct ktermios *old) { - unsigned int baud = tty_termios_baud_rate(termios); + unsigned long newrate = tty_termios_baud_rate(termios) * 16; struct dw8250_data *d = to_dw8250_data(p->private_data); long rate; int ret; clk_disable_unprepare(d->clk); - rate = clk_round_rate(d->clk, baud * 16); + rate = clk_round_rate(d->clk, newrate); if (rate > 0) { - ret = clk_set_rate(d->clk, rate); + ret = clk_set_rate(d->clk, newrate); if (!ret) p->uartclk = rate; } -- cgit v1.2.3 From cc816969d7b5973d2720d9afd381f06f0eac6885 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Thu, 23 Jul 2020 03:33:57 +0300 Subject: serial: 8250_dw: Fix common clocks usage race condition The race condition may happen if the UART reference clock is shared with some other device (on Baikal-T1 SoC it's another DW UART port). In this case if that device changes the clock rate while serial console is using it the DW 8250 UART port might not only end up with an invalid uartclk value saved, but may also experience a distorted output data since baud-clock could have been changed. In order to fix this lets at least try to adjust the 8250 port setting like UART clock rate in case if the reference clock rate change is discovered. The driver will call the new method to update 8250 UART port clock rate settings. It's done by means of the clock event notifier registered at the port startup and unregistered in the shutdown callback method. Note 1. In order to avoid deadlocks we had to execute the UART port update method in a dedicated deferred work. This is due to (in my opinion redundant) the clock update implemented in the dw8250_set_termios() method. Note 2. Before the ref clock is manually changed by the custom set_termios() function we swap the port uartclk value with new rate adjusted to be suitable for the requested baud. It is necessary in order to effectively disable a functionality of the ref clock events handler for the current UART port, since uartclk update will be done a bit further in the generic serial8250_do_set_termios() function. Signed-off-by: Serge Semin Link: https://lore.kernel.org/r/20200723003357.26897-5-Sergey.Semin@baikalelectronics.ru Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 103 +++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index c1511f9244bb..87f450b7c177 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -43,6 +45,8 @@ struct dw8250_data { int msr_mask_off; struct clk *clk; struct clk *pclk; + struct notifier_block clk_notifier; + struct work_struct clk_work; struct reset_control *rst; unsigned int skip_autocfg:1; @@ -54,6 +58,16 @@ static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data) return container_of(data, struct dw8250_data, data); } +static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb) +{ + return container_of(nb, struct dw8250_data, clk_notifier); +} + +static inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work) +{ + return container_of(work, struct dw8250_data, clk_work); +} + static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) { struct dw8250_data *d = to_dw8250_data(p->private_data); @@ -260,6 +274,46 @@ static int dw8250_handle_irq(struct uart_port *p) return 0; } +static void dw8250_clk_work_cb(struct work_struct *work) +{ + struct dw8250_data *d = work_to_dw8250_data(work); + struct uart_8250_port *up; + unsigned long rate; + + rate = clk_get_rate(d->clk); + if (rate <= 0) + return; + + up = serial8250_get_port(d->data.line); + + serial8250_update_uartclk(&up->port, rate); +} + +static int dw8250_clk_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct dw8250_data *d = clk_to_dw8250_data(nb); + + /* + * We have no choice but to defer the uartclk update due to two + * deadlocks. First one is caused by a recursive mutex lock which + * happens when clk_set_rate() is called from dw8250_set_termios(). + * Second deadlock is more tricky and is caused by an inverted order of + * the clk and tty-port mutexes lock. It happens if clock rate change + * is requested asynchronously while set_termios() is executed between + * tty-port mutex lock and clk_set_rate() function invocation and + * vise-versa. Anyway if we didn't have the reference clock alteration + * in the dw8250_set_termios() method we wouldn't have needed this + * deferred event handling complication. + */ + if (event == POST_RATE_CHANGE) { + queue_work(system_unbound_wq, &d->clk_work); + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} + static void dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) { @@ -283,9 +337,16 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, clk_disable_unprepare(d->clk); rate = clk_round_rate(d->clk, newrate); if (rate > 0) { + /* + * Premilinary set the uartclk to the new clock rate so the + * clock update event handler caused by the clk_set_rate() + * calling wouldn't actually update the UART divisor since + * we about to do this anyway. + */ + swap(p->uartclk, rate); ret = clk_set_rate(d->clk, newrate); - if (!ret) - p->uartclk = rate; + if (ret) + swap(p->uartclk, rate); } clk_prepare_enable(d->clk); @@ -312,6 +373,39 @@ static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios) serial8250_do_set_ldisc(p, termios); } +static int dw8250_startup(struct uart_port *p) +{ + struct dw8250_data *d = to_dw8250_data(p->private_data); + int ret; + + /* + * Some platforms may provide a reference clock shared between several + * devices. In this case before using the serial port first we have to + * make sure that any clock state change is known to the UART port at + * least post factum. + */ + if (d->clk) { + ret = clk_notifier_register(d->clk, &d->clk_notifier); + if (ret) + dev_warn(p->dev, "Failed to set the clock notifier\n"); + } + + return serial8250_do_startup(p); +} + +static void dw8250_shutdown(struct uart_port *p) +{ + struct dw8250_data *d = to_dw8250_data(p->private_data); + + serial8250_do_shutdown(p); + + if (d->clk) { + clk_notifier_unregister(d->clk, &d->clk_notifier); + + flush_work(&d->clk_work); + } +} + /* * dw8250_fallback_dma_filter will prevent the UART from getting just any free * channel on platforms that have DMA engines, but don't have any channels @@ -407,6 +501,8 @@ static int dw8250_probe(struct platform_device *pdev) p->serial_out = dw8250_serial_out; p->set_ldisc = dw8250_set_ldisc; p->set_termios = dw8250_set_termios; + p->startup = dw8250_startup; + p->shutdown = dw8250_shutdown; p->membase = devm_ioremap(dev, regs->start, resource_size(regs)); if (!p->membase) @@ -468,6 +564,9 @@ static int dw8250_probe(struct platform_device *pdev) if (IS_ERR(data->clk)) return PTR_ERR(data->clk); + INIT_WORK(&data->clk_work, dw8250_clk_work_cb); + data->clk_notifier.notifier_call = dw8250_clk_notifier_cb; + err = clk_prepare_enable(data->clk); if (err) dev_warn(dev, "could not enable optional baudclk: %d\n", err); -- cgit v1.2.3 From 7df5081cbf5e1c342acd30850a483ef504519937 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 25 Jul 2020 16:49:47 +0200 Subject: serial: stm32: Add RS485 RTS GPIO control While the STM32 does support RS485 drive-enable control within the UART IP itself, some systems have the drive-enable line connected to a pin which cannot be pinmuxed as RTS. Add support for toggling the RTS GPIO line using the modem control GPIOs to provide at least some sort of emulation. Signed-off-by: Marek Vasut Cc: Alexandre Torgue Cc: Andy Shevchenko Cc: Manivannan Sadhasivam Cc: Fabrice Gasnier Cc: Greg Kroah-Hartman Cc: linux-stm32@st-md-mailman.stormreply.com Link: https://lore.kernel.org/r/20200725144947.537007-1-marex@denx.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index d1c5e536a167..143300a80090 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -129,9 +129,13 @@ static int stm32_config_rs485(struct uart_port *port, if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { cr3 &= ~USART_CR3_DEP; rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; + mctrl_gpio_set(stm32_port->gpios, + stm32_port->port.mctrl & ~TIOCM_RTS); } else { cr3 |= USART_CR3_DEP; rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; + mctrl_gpio_set(stm32_port->gpios, + stm32_port->port.mctrl | TIOCM_RTS); } writel_relaxed(cr3, port->membase + ofs->cr3); @@ -847,9 +851,13 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { cr3 &= ~USART_CR3_DEP; rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND; + mctrl_gpio_set(stm32_port->gpios, + stm32_port->port.mctrl & ~TIOCM_RTS); } else { cr3 |= USART_CR3_DEP; rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; + mctrl_gpio_set(stm32_port->gpios, + stm32_port->port.mctrl | TIOCM_RTS); } } else { -- cgit v1.2.3 From f3af1b68fc96b14b93d1013ce7965723dc53ebbc Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 30 Jul 2020 12:55:46 +0200 Subject: tty: keyboard, do not speculate on func_table index It is very unlikely for processor to speculate on the func_table index. The index is uchar and func_table is of size 256. So the compiler would need to screw up and generate a really bad code. But to stay on the safe side, forbid speculation on this user passed index. Signed-off-by: Jiri Slaby Cc: Jiri Kosina Link: https://lore.kernel.org/r/20200730105546.24268-1-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/keyboard.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 568b2171f335..a768069b0f9a 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -2019,7 +2020,7 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) goto reterr; } kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; - i = kbs->kb_func; + i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC); switch (cmd) { case KDGKBSENT: -- cgit v1.2.3 From 679193b7baf8d88e41cbeb397ca17f797654947d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 31 Jul 2020 15:37:32 +0300 Subject: serial: 8250: Let serial core initialise spin lock Since the serial core handles spin lock initialisation, let the driver rely on it. Depends-on: f743061a85f5 ("serial: core: Initialise spin lock before use in uart_configure_port()") Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200731123733.22754-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 09475695effd..b2d18189d3d9 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -3194,7 +3194,6 @@ void serial8250_init_port(struct uart_8250_port *up) { struct uart_port *port = &up->port; - spin_lock_init(&port->lock); port->ops = &serial8250_pops; port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); -- cgit v1.2.3 From 81f0f78965ebfe48c4997801050f64687cebea48 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 2 Aug 2020 14:16:12 +0300 Subject: Revert "serial: 8250: Let serial core initialise spin lock" This reverts commit 679193b7baf8d88e41cbeb397ca17f797654947d. It appears that in QEmu the lock has been initialised differently (it wasn't obvious on real hardware during testing). Let's revert the change until the better approach will be developed. Reported-by: kernel test robot Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200802111612.36189-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index b2d18189d3d9..09475695effd 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -3194,6 +3194,7 @@ void serial8250_init_port(struct uart_8250_port *up) { struct uart_port *port = &up->port; + spin_lock_init(&port->lock); port->ops = &serial8250_pops; port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); -- cgit v1.2.3 From ebfdfeeae8c01fcb2b3b74ffaf03876e20835d2d Mon Sep 17 00:00:00 2001 From: Yunhai Zhang Date: Tue, 28 Jul 2020 09:58:03 +0800 Subject: vgacon: Fix for missing check in scrollback handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vgacon_scrollback_update() always leaves enbough room in the scrollback buffer for the next call, but if the console size changed that room might not actually be enough, and so we need to re-check. The check should be in the loop since vgacon_scrollback_cur->tail is updated in the loop and count may be more than 1 when triggered by CSI M, as Jiri's PoC: #include #include #include #include #include #include #include int main(int argc, char** argv) { int fd = open("/dev/tty1", O_RDWR); unsigned short size[3] = {25, 200, 0}; ioctl(fd, 0x5609, size); // VT_RESIZE write(fd, "\e[1;1H", 6); for (int i = 0; i < 30; i++) write(fd, "\e[10M", 5); } It leads to various crashes as vgacon_scrollback_update writes out of the buffer: BUG: unable to handle page fault for address: ffffc900001752a0 #PF: supervisor write access in kernel mode #PF: error_code(0x0002) - not-present page RIP: 0010:mutex_unlock+0x13/0x30 ... Call Trace: n_tty_write+0x1a0/0x4d0 tty_write+0x1a0/0x2e0 Or to KASAN reports: BUG: KASAN: slab-out-of-bounds in vgacon_scroll+0x57a/0x8ed This fixes CVE-2020-14331. Reported-by: 张云海 Reported-by: Yang Yingliang Reported-by: Kyungtae Kim Fixes: 15bdab959c9b ([PATCH] vgacon: Add support for soft scrollback) Cc: stable@vger.kernel.org Cc: linux-fbdev@vger.kernel.org Cc: Linus Torvalds Cc: Solar Designer Cc: "Srivatsa S. Bhat" Cc: Anthony Liguori Cc: Yang Yingliang Cc: Bartlomiej Zolnierkiewicz Cc: Jiri Slaby Signed-off-by: Yunhai Zhang Link: https://lore.kernel.org/r/9fb43895-ca91-9b07-ebfd-808cf854ca95@nsfocus.com Signed-off-by: Greg Kroah-Hartman --- drivers/video/console/vgacon.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index f0f3d573f848..a52bb3740073 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -251,6 +251,10 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count) p = (void *) (c->vc_origin + t * c->vc_size_row); while (count--) { + if ((vgacon_scrollback_cur->tail + c->vc_size_row) > + vgacon_scrollback_cur->size) + vgacon_scrollback_cur->tail = 0; + scr_memcpyw(vgacon_scrollback_cur->data + vgacon_scrollback_cur->tail, p, c->vc_size_row); -- cgit v1.2.3