Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fbcon: Move fbcon callbacks into struct fbcon_bitops

Depending on rotation settings, fbcon sets different callback
functions in struct fbcon_par from within fbcon_set_bitops(). Declare
the callback functions in the new type struct fbcon_bitops. Then
only replace the single bitops pointer in struct fbcon_par.

Keeping callbacks in constant instances of struct fbcon_bitops
makes it harder to exploit the callbacks. Also makes the code slightly
easier to maintain.

For tile-based consoles, there's a separate instance of the bitops
structure.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
Link: https://lore.kernel.org/r/20250909124616.143365-5-tzimmermann@suse.de

+94 -67
+10 -7
drivers/video/fbdev/core/bitblit.c
··· 384 384 return err; 385 385 } 386 386 387 + static const struct fbcon_bitops bit_fbcon_bitops = { 388 + .bmove = bit_bmove, 389 + .clear = bit_clear, 390 + .putcs = bit_putcs, 391 + .clear_margins = bit_clear_margins, 392 + .cursor = bit_cursor, 393 + .update_start = bit_update_start, 394 + }; 395 + 387 396 void fbcon_set_bitops(struct fbcon_par *par) 388 397 { 389 - par->bmove = bit_bmove; 390 - par->clear = bit_clear; 391 - par->putcs = bit_putcs; 392 - par->clear_margins = bit_clear_margins; 393 - par->cursor = bit_cursor; 394 - par->update_start = bit_update_start; 395 - par->rotate_font = NULL; 398 + par->bitops = &bit_fbcon_bitops; 396 399 397 400 if (par->rotate) 398 401 fbcon_set_rotate(par);
+35 -32
drivers/video/fbdev/core/fbcon.c
··· 405 405 406 406 c = scr_readw((u16 *) vc->vc_pos); 407 407 enable = par->cursor_flash && !par->cursor_state.enable; 408 - par->cursor(vc, info, enable, 409 - get_fg_color(vc, info, c), 410 - get_bg_color(vc, info, c)); 408 + par->bitops->cursor(vc, info, enable, 409 + get_fg_color(vc, info, c), 410 + get_bg_color(vc, info, c)); 411 411 console_unlock(); 412 412 413 413 queue_delayed_work(system_power_efficient_wq, &par->cursor_work, ··· 1162 1162 if (logo) 1163 1163 fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows); 1164 1164 1165 - if (par->rotate_font && par->rotate_font(info, vc)) { 1165 + if (par->bitops->rotate_font && par->bitops->rotate_font(info, vc)) { 1166 1166 par->rotate = FB_ROTATE_UR; 1167 1167 set_blitting_type(vc, info); 1168 1168 } ··· 1303 1303 y_break = p->vrows - p->yscroll; 1304 1304 if (sy < y_break && sy + height - 1 >= y_break) { 1305 1305 u_int b = y_break - sy; 1306 - par->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg); 1307 - par->clear(vc, info, real_y(p, sy + b), sx, height - b, width, fg, bg); 1306 + par->bitops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg); 1307 + par->bitops->clear(vc, info, real_y(p, sy + b), sx, height - b, 1308 + width, fg, bg); 1308 1309 } else 1309 - par->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg); 1310 + par->bitops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg); 1310 1311 } 1311 1312 1312 1313 static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, ··· 1324 1323 struct fbcon_par *par = info->fbcon_par; 1325 1324 1326 1325 if (fbcon_is_active(vc, info)) 1327 - par->putcs(vc, info, s, count, real_y(p, ypos), xpos, 1328 - get_fg_color(vc, info, scr_readw(s)), 1329 - get_bg_color(vc, info, scr_readw(s))); 1326 + par->bitops->putcs(vc, info, s, count, real_y(p, ypos), xpos, 1327 + get_fg_color(vc, info, scr_readw(s)), 1328 + get_bg_color(vc, info, scr_readw(s))); 1330 1329 } 1331 1330 1332 1331 static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) ··· 1335 1334 struct fbcon_par *par = info->fbcon_par; 1336 1335 1337 1336 if (fbcon_is_active(vc, info)) 1338 - par->clear_margins(vc, info, margin_color, bottom_only); 1337 + par->bitops->clear_margins(vc, info, margin_color, bottom_only); 1339 1338 } 1340 1339 1341 1340 static void fbcon_cursor(struct vc_data *vc, bool enable) ··· 1356 1355 1357 1356 par->cursor_flash = enable; 1358 1357 1359 - if (!par->cursor) 1358 + if (!par->bitops->cursor) 1360 1359 return; 1361 1360 1362 - par->cursor(vc, info, enable, 1363 - get_fg_color(vc, info, c), 1364 - get_bg_color(vc, info, c)); 1361 + par->bitops->cursor(vc, info, enable, 1362 + get_fg_color(vc, info, c), 1363 + get_bg_color(vc, info, c)); 1365 1364 } 1366 1365 1367 1366 static int scrollback_phys_max = 0; ··· 1445 1444 par->var.xoffset = 0; 1446 1445 par->var.yoffset = p->yscroll * vc->vc_font.height; 1447 1446 par->var.vmode |= FB_VMODE_YWRAP; 1448 - par->update_start(info); 1447 + par->bitops->update_start(info); 1449 1448 scrollback_max += count; 1450 1449 if (scrollback_max > scrollback_phys_max) 1451 1450 scrollback_max = scrollback_phys_max; ··· 1464 1463 par->var.xoffset = 0; 1465 1464 par->var.yoffset = p->yscroll * vc->vc_font.height; 1466 1465 par->var.vmode |= FB_VMODE_YWRAP; 1467 - par->update_start(info); 1466 + par->bitops->update_start(info); 1468 1467 scrollback_max -= count; 1469 1468 if (scrollback_max < 0) 1470 1469 scrollback_max = 0; ··· 1479 1478 1480 1479 p->yscroll += count; 1481 1480 if (p->yscroll > p->vrows - vc->vc_rows) { 1482 - par->bmove(vc, info, p->vrows - vc->vc_rows, 1483 - 0, 0, 0, vc->vc_rows, vc->vc_cols); 1481 + par->bitops->bmove(vc, info, p->vrows - vc->vc_rows, 1482 + 0, 0, 0, vc->vc_rows, vc->vc_cols); 1484 1483 p->yscroll -= p->vrows - vc->vc_rows; 1485 1484 } 1486 1485 1487 1486 par->var.xoffset = 0; 1488 1487 par->var.yoffset = p->yscroll * vc->vc_font.height; 1489 1488 par->var.vmode &= ~FB_VMODE_YWRAP; 1490 - par->update_start(info); 1489 + par->bitops->update_start(info); 1491 1490 fbcon_clear_margins(vc, 1); 1492 1491 scrollback_max += count; 1493 1492 if (scrollback_max > scrollback_phys_max) ··· 1511 1510 par->var.xoffset = 0; 1512 1511 par->var.yoffset = p->yscroll * vc->vc_font.height; 1513 1512 par->var.vmode &= ~FB_VMODE_YWRAP; 1514 - par->update_start(info); 1513 + par->bitops->update_start(info); 1515 1514 fbcon_clear_margins(vc, 1); 1516 1515 scrollback_max += count; 1517 1516 if (scrollback_max > scrollback_phys_max) ··· 1527 1526 1528 1527 p->yscroll -= count; 1529 1528 if (p->yscroll < 0) { 1530 - par->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows, 1531 - 0, vc->vc_rows, vc->vc_cols); 1529 + par->bitops->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows, 1530 + 0, vc->vc_rows, vc->vc_cols); 1532 1531 p->yscroll += p->vrows - vc->vc_rows; 1533 1532 } 1534 1533 1535 1534 par->var.xoffset = 0; 1536 1535 par->var.yoffset = p->yscroll * vc->vc_font.height; 1537 1536 par->var.vmode &= ~FB_VMODE_YWRAP; 1538 - par->update_start(info); 1537 + par->bitops->update_start(info); 1539 1538 fbcon_clear_margins(vc, 1); 1540 1539 scrollback_max -= count; 1541 1540 if (scrollback_max < 0) ··· 1559 1558 par->var.xoffset = 0; 1560 1559 par->var.yoffset = p->yscroll * vc->vc_font.height; 1561 1560 par->var.vmode &= ~FB_VMODE_YWRAP; 1562 - par->update_start(info); 1561 + par->bitops->update_start(info); 1563 1562 fbcon_clear_margins(vc, 1); 1564 1563 scrollback_max -= count; 1565 1564 if (scrollback_max < 0) ··· 1621 1620 1622 1621 if (c == scr_readw(d)) { 1623 1622 if (s > start) { 1624 - par->bmove(vc, info, line + ycount, x, 1625 - line, x, 1, s - start); 1623 + par->bitops->bmove(vc, info, line + ycount, x, 1624 + line, x, 1, s - start); 1626 1625 x += s - start + 1; 1627 1626 start = s + 1; 1628 1627 } else { ··· 1637 1636 d++; 1638 1637 } while (s < le); 1639 1638 if (s > start) 1640 - par->bmove(vc, info, line + ycount, x, line, x, 1, s - start); 1639 + par->bitops->bmove(vc, info, line + ycount, x, line, x, 1, 1640 + s - start); 1641 1641 console_conditional_schedule(); 1642 1642 if (ycount > 0) 1643 1643 line++; ··· 1743 1741 } 1744 1742 return; 1745 1743 } 1746 - par->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, height, width); 1744 + par->bitops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, 1745 + height, width); 1747 1746 } 1748 1747 1749 1748 static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, ··· 2164 2161 set_blitting_type(vc, info); 2165 2162 par->cursor_reset = 1; 2166 2163 2167 - if (par->rotate_font && par->rotate_font(info, vc)) { 2164 + if (par->bitops->rotate_font && par->bitops->rotate_font(info, vc)) { 2168 2165 par->rotate = FB_ROTATE_UR; 2169 2166 set_blitting_type(vc, info); 2170 2167 } ··· 2197 2194 2198 2195 if (fbcon_is_active(vc, info)) { 2199 2196 par->var.xoffset = par->var.yoffset = p->yscroll = 0; 2200 - par->update_start(info); 2197 + par->bitops->update_start(info); 2201 2198 } 2202 2199 2203 2200 fbcon_set_palette(vc, color_table); ··· 2696 2693 2697 2694 if (fbcon_is_active(vc, info)) { 2698 2695 par->var.xoffset = par->var.yoffset = p->yscroll = 0; 2699 - par->update_start(info); 2696 + par->bitops->update_start(info); 2700 2697 } 2701 2698 2702 2699 fbcon_set_palette(vc, color_table);
+6 -1
drivers/video/fbdev/core/fbcon.h
··· 51 51 const struct fb_videomode *mode; 52 52 }; 53 53 54 - struct fbcon_par { 54 + struct fbcon_bitops { 55 55 void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, 56 56 int sx, int dy, int dx, int height, int width); 57 57 void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, ··· 65 65 bool enable, int fg, int bg); 66 66 int (*update_start)(struct fb_info *info); 67 67 int (*rotate_font)(struct fb_info *info, struct vc_data *vc); 68 + }; 69 + 70 + struct fbcon_par { 68 71 struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ 69 72 struct delayed_work cursor_work; /* Cursor timer */ 70 73 struct fb_cursor cursor_state; ··· 89 86 u8 *cursor_src; 90 87 u32 cursor_size; 91 88 u32 fd_size; 89 + 90 + const struct fbcon_bitops *bitops; 92 91 }; 93 92 94 93 /*
+11 -7
drivers/video/fbdev/core/fbcon_ccw.c
··· 390 390 return err; 391 391 } 392 392 393 + static const struct fbcon_bitops ccw_fbcon_bitops = { 394 + .bmove = ccw_bmove, 395 + .clear = ccw_clear, 396 + .putcs = ccw_putcs, 397 + .clear_margins = ccw_clear_margins, 398 + .cursor = ccw_cursor, 399 + .update_start = ccw_update_start, 400 + .rotate_font = fbcon_rotate_font, 401 + }; 402 + 393 403 void fbcon_rotate_ccw(struct fbcon_par *par) 394 404 { 395 - par->bmove = ccw_bmove; 396 - par->clear = ccw_clear; 397 - par->putcs = ccw_putcs; 398 - par->clear_margins = ccw_clear_margins; 399 - par->cursor = ccw_cursor; 400 - par->update_start = ccw_update_start; 401 - par->rotate_font = fbcon_rotate_font; 405 + par->bitops = &ccw_fbcon_bitops; 402 406 }
+11 -7
drivers/video/fbdev/core/fbcon_cw.c
··· 373 373 return err; 374 374 } 375 375 376 + static const struct fbcon_bitops cw_fbcon_bitops = { 377 + .bmove = cw_bmove, 378 + .clear = cw_clear, 379 + .putcs = cw_putcs, 380 + .clear_margins = cw_clear_margins, 381 + .cursor = cw_cursor, 382 + .update_start = cw_update_start, 383 + .rotate_font = fbcon_rotate_font, 384 + }; 385 + 376 386 void fbcon_rotate_cw(struct fbcon_par *par) 377 387 { 378 - par->bmove = cw_bmove; 379 - par->clear = cw_clear; 380 - par->putcs = cw_putcs; 381 - par->clear_margins = cw_clear_margins; 382 - par->cursor = cw_cursor; 383 - par->update_start = cw_update_start; 384 - par->rotate_font = fbcon_rotate_font; 388 + par->bitops = &cw_fbcon_bitops; 385 389 }
+11 -7
drivers/video/fbdev/core/fbcon_ud.c
··· 417 417 return err; 418 418 } 419 419 420 + static const struct fbcon_bitops ud_fbcon_bitops = { 421 + .bmove = ud_bmove, 422 + .clear = ud_clear, 423 + .putcs = ud_putcs, 424 + .clear_margins = ud_clear_margins, 425 + .cursor = ud_cursor, 426 + .update_start = ud_update_start, 427 + .rotate_font = fbcon_rotate_font, 428 + }; 429 + 420 430 void fbcon_rotate_ud(struct fbcon_par *par) 421 431 { 422 - par->bmove = ud_bmove; 423 - par->clear = ud_clear; 424 - par->putcs = ud_putcs; 425 - par->clear_margins = ud_clear_margins; 426 - par->cursor = ud_cursor; 427 - par->update_start = ud_update_start; 428 - par->rotate_font = fbcon_rotate_font; 432 + par->bitops = &ud_fbcon_bitops; 429 433 }
+10 -6
drivers/video/fbdev/core/tileblit.c
··· 161 161 return err; 162 162 } 163 163 164 + static const struct fbcon_bitops tile_fbcon_bitops = { 165 + .bmove = tile_bmove, 166 + .clear = tile_clear, 167 + .putcs = tile_putcs, 168 + .clear_margins = tile_clear_margins, 169 + .cursor = tile_cursor, 170 + .update_start = tile_update_start, 171 + }; 172 + 164 173 void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info) 165 174 { 166 175 struct fb_tilemap map; 167 176 struct fbcon_par *par = info->fbcon_par; 168 177 169 - par->bmove = tile_bmove; 170 - par->clear = tile_clear; 171 - par->putcs = tile_putcs; 172 - par->clear_margins = tile_clear_margins; 173 - par->cursor = tile_cursor; 174 - par->update_start = tile_update_start; 178 + par->bitops = &tile_fbcon_bitops; 175 179 176 180 if (par->p) { 177 181 map.width = vc->vc_font.width;