forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/tty/vt/vc_screen.c
....@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: GPL-2.0
22 /*
33 * Provide access to virtual console memory.
4
- * /dev/vcs0: the screen as it is being viewed right now (possibly scrolled)
4
+ * /dev/vcs: the screen as it is being viewed right now (possibly scrolled)
55 * /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63)
66 * [minor: N]
77 *
....@@ -50,11 +50,7 @@
5050 #include <asm/byteorder.h>
5151 #include <asm/unaligned.h>
5252
53
-#undef attr
54
-#undef org
55
-#undef addr
56
-#define HEADER_SIZE 4
57
-
53
+#define HEADER_SIZE 4u
5854 #define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE)
5955
6056 /*
....@@ -80,7 +76,7 @@
8076 struct vcs_poll_data {
8177 struct notifier_block notifier;
8278 unsigned int cons_num;
83
- bool seen_last_update;
79
+ int event;
8480 wait_queue_head_t waitq;
8581 struct fasync_struct *fasync;
8682 };
....@@ -93,9 +89,18 @@
9389 struct vcs_poll_data *poll =
9490 container_of(nb, struct vcs_poll_data, notifier);
9591 int currcons = poll->cons_num;
92
+ int fa_band;
9693
97
- if (code != VT_UPDATE)
94
+ switch (code) {
95
+ case VT_UPDATE:
96
+ fa_band = POLL_PRI;
97
+ break;
98
+ case VT_DEALLOCATE:
99
+ fa_band = POLL_HUP;
100
+ break;
101
+ default:
98102 return NOTIFY_DONE;
103
+ }
99104
100105 if (currcons == 0)
101106 currcons = fg_console;
....@@ -104,9 +109,9 @@
104109 if (currcons != vc->vc_num)
105110 return NOTIFY_DONE;
106111
107
- poll->seen_last_update = false;
112
+ poll->event = code;
108113 wake_up_interruptible(&poll->waitq);
109
- kill_fasync(&poll->fasync, SIGIO, POLL_IN);
114
+ kill_fasync(&poll->fasync, SIGIO, fa_band);
110115 return NOTIFY_OK;
111116 }
112117
....@@ -131,6 +136,15 @@
131136 poll->cons_num = console(file_inode(file));
132137 init_waitqueue_head(&poll->waitq);
133138 poll->notifier.notifier_call = vcs_notifier;
139
+ /*
140
+ * In order not to lose any update event, we must pretend one might
141
+ * have occurred before we have a chance to register our notifier.
142
+ * This is also how user space has come to detect which kernels
143
+ * support POLLPRI on /dev/vcs* devices i.e. using poll() with
144
+ * POLLPRI and a zero timeout.
145
+ */
146
+ poll->event = VT_UPDATE;
147
+
134148 if (register_vt_notifier(&poll->notifier) != 0) {
135149 kfree(poll);
136150 return NULL;
....@@ -159,12 +173,14 @@
159173 return poll;
160174 }
161175
162
-/*
163
- * Returns VC for inode.
176
+/**
177
+ * vcs_vc -- return VC for @inode
178
+ * @inode: inode for which to return a VC
179
+ * @viewed: returns whether this console is currently foreground (viewed)
180
+ *
164181 * Must be called with console_lock.
165182 */
166
-static struct vc_data*
167
-vcs_vc(struct inode *inode, int *viewed)
183
+static struct vc_data *vcs_vc(struct inode *inode, bool *viewed)
168184 {
169185 unsigned int currcons = console(inode);
170186
....@@ -173,54 +189,177 @@
173189 if (currcons == 0) {
174190 currcons = fg_console;
175191 if (viewed)
176
- *viewed = 1;
192
+ *viewed = true;
177193 } else {
178194 currcons--;
179195 if (viewed)
180
- *viewed = 0;
196
+ *viewed = false;
181197 }
182198 return vc_cons[currcons].d;
183199 }
184200
185
-/*
186
- * Returns size for VC carried by inode.
201
+/**
202
+ * vcs_size -- return size for a VC in @vc
203
+ * @vc: which VC
204
+ * @attr: does it use attributes?
205
+ * @unicode: is it unicode?
206
+ *
187207 * Must be called with console_lock.
188208 */
189
-static int
190
-vcs_size(struct inode *inode)
209
+static int vcs_size(const struct vc_data *vc, bool attr, bool unicode)
191210 {
192211 int size;
193
- struct vc_data *vc;
194212
195213 WARN_CONSOLE_UNLOCKED();
196214
197
- vc = vcs_vc(inode, NULL);
198
- if (!vc)
199
- return -ENXIO;
200
-
201215 size = vc->vc_rows * vc->vc_cols;
202216
203
- if (use_attributes(inode)) {
204
- if (use_unicode(inode))
217
+ if (attr) {
218
+ if (unicode)
205219 return -EOPNOTSUPP;
206
- size = 2*size + HEADER_SIZE;
207
- } else if (use_unicode(inode))
220
+
221
+ size = 2 * size + HEADER_SIZE;
222
+ } else if (unicode)
208223 size *= 4;
224
+
209225 return size;
210226 }
211227
212228 static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
213229 {
230
+ struct inode *inode = file_inode(file);
231
+ struct vc_data *vc;
214232 int size;
215233
216234 console_lock();
217
- size = vcs_size(file_inode(file));
235
+ vc = vcs_vc(inode, NULL);
236
+ if (!vc) {
237
+ console_unlock();
238
+ return -ENXIO;
239
+ }
240
+
241
+ size = vcs_size(vc, use_attributes(inode), use_unicode(inode));
218242 console_unlock();
219243 if (size < 0)
220244 return size;
221245 return fixed_size_llseek(file, offset, orig, size);
222246 }
223247
248
+static int vcs_read_buf_uni(struct vc_data *vc, char *con_buf,
249
+ unsigned int pos, unsigned int count, bool viewed)
250
+{
251
+ unsigned int nr, row, col, maxcol = vc->vc_cols;
252
+ int ret;
253
+
254
+ ret = vc_uniscr_check(vc);
255
+ if (ret)
256
+ return ret;
257
+
258
+ pos /= 4;
259
+ row = pos / maxcol;
260
+ col = pos % maxcol;
261
+ nr = maxcol - col;
262
+ do {
263
+ if (nr > count / 4)
264
+ nr = count / 4;
265
+ vc_uniscr_copy_line(vc, con_buf, viewed, row, col, nr);
266
+ con_buf += nr * 4;
267
+ count -= nr * 4;
268
+ row++;
269
+ col = 0;
270
+ nr = maxcol;
271
+ } while (count);
272
+
273
+ return 0;
274
+}
275
+
276
+static void vcs_read_buf_noattr(const struct vc_data *vc, char *con_buf,
277
+ unsigned int pos, unsigned int count, bool viewed)
278
+{
279
+ u16 *org;
280
+ unsigned int col, maxcol = vc->vc_cols;
281
+
282
+ org = screen_pos(vc, pos, viewed);
283
+ col = pos % maxcol;
284
+ pos += maxcol - col;
285
+
286
+ while (count-- > 0) {
287
+ *con_buf++ = (vcs_scr_readw(vc, org++) & 0xff);
288
+ if (++col == maxcol) {
289
+ org = screen_pos(vc, pos, viewed);
290
+ col = 0;
291
+ pos += maxcol;
292
+ }
293
+ }
294
+}
295
+
296
+static unsigned int vcs_read_buf(const struct vc_data *vc, char *con_buf,
297
+ unsigned int pos, unsigned int count, bool viewed,
298
+ unsigned int *skip)
299
+{
300
+ u16 *org, *con_buf16;
301
+ unsigned int col, maxcol = vc->vc_cols;
302
+ unsigned int filled = count;
303
+
304
+ if (pos < HEADER_SIZE) {
305
+ /* clamp header values if they don't fit */
306
+ con_buf[0] = min(vc->vc_rows, 0xFFu);
307
+ con_buf[1] = min(vc->vc_cols, 0xFFu);
308
+ getconsxy(vc, con_buf + 2);
309
+
310
+ *skip += pos;
311
+ count += pos;
312
+ if (count > CON_BUF_SIZE) {
313
+ count = CON_BUF_SIZE;
314
+ filled = count - pos;
315
+ }
316
+
317
+ /* Advance state pointers and move on. */
318
+ count -= min(HEADER_SIZE, count);
319
+ pos = HEADER_SIZE;
320
+ con_buf += HEADER_SIZE;
321
+ /* If count >= 0, then pos is even... */
322
+ } else if (pos & 1) {
323
+ /*
324
+ * Skip first byte for output if start address is odd. Update
325
+ * region sizes up/down depending on free space in buffer.
326
+ */
327
+ (*skip)++;
328
+ if (count < CON_BUF_SIZE)
329
+ count++;
330
+ else
331
+ filled--;
332
+ }
333
+
334
+ if (!count)
335
+ return filled;
336
+
337
+ pos -= HEADER_SIZE;
338
+ pos /= 2;
339
+ col = pos % maxcol;
340
+
341
+ org = screen_pos(vc, pos, viewed);
342
+ pos += maxcol - col;
343
+
344
+ /*
345
+ * Buffer has even length, so we can always copy character + attribute.
346
+ * We do not copy last byte to userspace if count is odd.
347
+ */
348
+ count = (count + 1) / 2;
349
+ con_buf16 = (u16 *)con_buf;
350
+
351
+ while (count) {
352
+ *con_buf16++ = vcs_scr_readw(vc, org++);
353
+ count--;
354
+ if (++col == maxcol) {
355
+ org = screen_pos(vc, pos, viewed);
356
+ col = 0;
357
+ pos += maxcol;
358
+ }
359
+ }
360
+
361
+ return filled;
362
+}
224363
225364 static ssize_t
226365 vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
....@@ -228,11 +367,11 @@
228367 struct inode *inode = file_inode(file);
229368 struct vc_data *vc;
230369 struct vcs_poll_data *poll;
231
- long pos, read;
232
- int attr, uni_mode, row, col, maxcol, viewed;
233
- unsigned short *org = NULL;
370
+ unsigned int read;
234371 ssize_t ret;
235372 char *con_buf;
373
+ loff_t pos;
374
+ bool viewed, attr, uni_mode;
236375
237376 con_buf = (char *) __get_free_page(GFP_KERNEL);
238377 if (!con_buf)
....@@ -247,10 +386,6 @@
247386
248387 uni_mode = use_unicode(inode);
249388 attr = use_attributes(inode);
250
- ret = -ENXIO;
251
- vc = vcs_vc(inode, &viewed);
252
- if (!vc)
253
- goto unlock_out;
254389
255390 ret = -EINVAL;
256391 if (pos < 0)
....@@ -261,25 +396,27 @@
261396
262397 poll = file->private_data;
263398 if (count && poll)
264
- poll->seen_last_update = true;
399
+ poll->event = 0;
265400 read = 0;
266401 ret = 0;
267402 while (count) {
268
- char *con_buf0, *con_buf_start;
269
- long this_round, size;
270
- ssize_t orig_count;
271
- long p = pos;
403
+ unsigned int this_round, skip = 0;
404
+ int size;
405
+
406
+ vc = vcs_vc(inode, &viewed);
407
+ if (!vc) {
408
+ ret = -ENXIO;
409
+ break;
410
+ }
272411
273412 /* Check whether we are above size each round,
274413 * as copy_to_user at the end of this loop
275414 * could sleep.
276415 */
277
- size = vcs_size(inode);
416
+ size = vcs_size(vc, attr, uni_mode);
278417 if (size < 0) {
279
- if (read)
280
- break;
281418 ret = size;
282
- goto unlock_out;
419
+ break;
283420 }
284421 if (pos >= size)
285422 break;
....@@ -295,103 +432,17 @@
295432 * attempt to move it to userspace.
296433 */
297434
298
- con_buf_start = con_buf0 = con_buf;
299
- orig_count = this_round;
300
- maxcol = vc->vc_cols;
301435 if (uni_mode) {
302
- unsigned int nr;
303
-
304
- ret = vc_uniscr_check(vc);
436
+ ret = vcs_read_buf_uni(vc, con_buf, pos, this_round,
437
+ viewed);
305438 if (ret)
306439 break;
307
- p /= 4;
308
- row = p / vc->vc_cols;
309
- col = p % maxcol;
310
- nr = maxcol - col;
311
- do {
312
- if (nr > this_round/4)
313
- nr = this_round/4;
314
- vc_uniscr_copy_line(vc, con_buf0, viewed,
315
- row, col, nr);
316
- con_buf0 += nr * 4;
317
- this_round -= nr * 4;
318
- row++;
319
- col = 0;
320
- nr = maxcol;
321
- } while (this_round);
322440 } else if (!attr) {
323
- org = screen_pos(vc, p, viewed);
324
- col = p % maxcol;
325
- p += maxcol - col;
326
- while (this_round-- > 0) {
327
- *con_buf0++ = (vcs_scr_readw(vc, org++) & 0xff);
328
- if (++col == maxcol) {
329
- org = screen_pos(vc, p, viewed);
330
- col = 0;
331
- p += maxcol;
332
- }
333
- }
441
+ vcs_read_buf_noattr(vc, con_buf, pos, this_round,
442
+ viewed);
334443 } else {
335
- if (p < HEADER_SIZE) {
336
- size_t tmp_count;
337
-
338
- con_buf0[0] = (char)vc->vc_rows;
339
- con_buf0[1] = (char)vc->vc_cols;
340
- getconsxy(vc, con_buf0 + 2);
341
-
342
- con_buf_start += p;
343
- this_round += p;
344
- if (this_round > CON_BUF_SIZE) {
345
- this_round = CON_BUF_SIZE;
346
- orig_count = this_round - p;
347
- }
348
-
349
- tmp_count = HEADER_SIZE;
350
- if (tmp_count > this_round)
351
- tmp_count = this_round;
352
-
353
- /* Advance state pointers and move on. */
354
- this_round -= tmp_count;
355
- p = HEADER_SIZE;
356
- con_buf0 = con_buf + HEADER_SIZE;
357
- /* If this_round >= 0, then p is even... */
358
- } else if (p & 1) {
359
- /* Skip first byte for output if start address is odd
360
- * Update region sizes up/down depending on free
361
- * space in buffer.
362
- */
363
- con_buf_start++;
364
- if (this_round < CON_BUF_SIZE)
365
- this_round++;
366
- else
367
- orig_count--;
368
- }
369
- if (this_round > 0) {
370
- unsigned short *tmp_buf = (unsigned short *)con_buf0;
371
-
372
- p -= HEADER_SIZE;
373
- p /= 2;
374
- col = p % maxcol;
375
-
376
- org = screen_pos(vc, p, viewed);
377
- p += maxcol - col;
378
-
379
- /* Buffer has even length, so we can always copy
380
- * character + attribute. We do not copy last byte
381
- * to userspace if this_round is odd.
382
- */
383
- this_round = (this_round + 1) >> 1;
384
-
385
- while (this_round) {
386
- *tmp_buf++ = vcs_scr_readw(vc, org++);
387
- this_round --;
388
- if (++col == maxcol) {
389
- org = screen_pos(vc, p, viewed);
390
- col = 0;
391
- p += maxcol;
392
- }
393
- }
394
- }
444
+ this_round = vcs_read_buf(vc, con_buf, pos, this_round,
445
+ viewed, &skip);
395446 }
396447
397448 /* Finally, release the console semaphore while we push
....@@ -402,18 +453,18 @@
402453 */
403454
404455 console_unlock();
405
- ret = copy_to_user(buf, con_buf_start, orig_count);
456
+ ret = copy_to_user(buf, con_buf + skip, this_round);
406457 console_lock();
407458
408459 if (ret) {
409
- read += (orig_count - ret);
460
+ read += this_round - ret;
410461 ret = -EFAULT;
411462 break;
412463 }
413
- buf += orig_count;
414
- pos += orig_count;
415
- read += orig_count;
416
- count -= orig_count;
464
+ buf += this_round;
465
+ pos += this_round;
466
+ read += this_round;
467
+ count -= this_round;
417468 }
418469 *ppos += read;
419470 if (read)
....@@ -424,18 +475,129 @@
424475 return ret;
425476 }
426477
478
+static u16 *vcs_write_buf_noattr(struct vc_data *vc, const char *con_buf,
479
+ unsigned int pos, unsigned int count, bool viewed, u16 **org0)
480
+{
481
+ u16 *org;
482
+ unsigned int col, maxcol = vc->vc_cols;
483
+
484
+ *org0 = org = screen_pos(vc, pos, viewed);
485
+ col = pos % maxcol;
486
+ pos += maxcol - col;
487
+
488
+ while (count > 0) {
489
+ unsigned char c = *con_buf++;
490
+
491
+ count--;
492
+ vcs_scr_writew(vc,
493
+ (vcs_scr_readw(vc, org) & 0xff00) | c, org);
494
+ org++;
495
+ if (++col == maxcol) {
496
+ org = screen_pos(vc, pos, viewed);
497
+ col = 0;
498
+ pos += maxcol;
499
+ }
500
+ }
501
+
502
+ return org;
503
+}
504
+
505
+/*
506
+ * Compilers (gcc 10) are unable to optimize the swap in cpu_to_le16. So do it
507
+ * the poor man way.
508
+ */
509
+static inline u16 vc_compile_le16(u8 hi, u8 lo)
510
+{
511
+#ifdef __BIG_ENDIAN
512
+ return (lo << 8u) | hi;
513
+#else
514
+ return (hi << 8u) | lo;
515
+#endif
516
+}
517
+
518
+static u16 *vcs_write_buf(struct vc_data *vc, const char *con_buf,
519
+ unsigned int pos, unsigned int count, bool viewed, u16 **org0)
520
+{
521
+ u16 *org;
522
+ unsigned int col, maxcol = vc->vc_cols;
523
+ unsigned char c;
524
+
525
+ /* header */
526
+ if (pos < HEADER_SIZE) {
527
+ char header[HEADER_SIZE];
528
+
529
+ getconsxy(vc, header + 2);
530
+ while (pos < HEADER_SIZE && count > 0) {
531
+ count--;
532
+ header[pos++] = *con_buf++;
533
+ }
534
+ if (!viewed)
535
+ putconsxy(vc, header + 2);
536
+ }
537
+
538
+ if (!count)
539
+ return NULL;
540
+
541
+ pos -= HEADER_SIZE;
542
+ col = (pos/2) % maxcol;
543
+
544
+ *org0 = org = screen_pos(vc, pos/2, viewed);
545
+
546
+ /* odd pos -- the first single character */
547
+ if (pos & 1) {
548
+ count--;
549
+ c = *con_buf++;
550
+ vcs_scr_writew(vc, vc_compile_le16(c, vcs_scr_readw(vc, org)),
551
+ org);
552
+ org++;
553
+ pos++;
554
+ if (++col == maxcol) {
555
+ org = screen_pos(vc, pos/2, viewed);
556
+ col = 0;
557
+ }
558
+ }
559
+
560
+ pos /= 2;
561
+ pos += maxcol - col;
562
+
563
+ /* even pos -- handle attr+character pairs */
564
+ while (count > 1) {
565
+ unsigned short w;
566
+
567
+ w = get_unaligned(((unsigned short *)con_buf));
568
+ vcs_scr_writew(vc, w, org++);
569
+ con_buf += 2;
570
+ count -= 2;
571
+ if (++col == maxcol) {
572
+ org = screen_pos(vc, pos, viewed);
573
+ col = 0;
574
+ pos += maxcol;
575
+ }
576
+ }
577
+
578
+ if (!count)
579
+ return org;
580
+
581
+ /* odd pos -- the remaining character */
582
+ c = *con_buf++;
583
+ vcs_scr_writew(vc, vc_compile_le16(vcs_scr_readw(vc, org) >> 8, c),
584
+ org);
585
+
586
+ return org;
587
+}
588
+
427589 static ssize_t
428590 vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
429591 {
430592 struct inode *inode = file_inode(file);
431593 struct vc_data *vc;
432
- long pos;
433
- long attr, size, written;
434
- char *con_buf0;
435
- int col, maxcol, viewed;
436
- u16 *org0 = NULL, *org = NULL;
437
- size_t ret;
438594 char *con_buf;
595
+ u16 *org0, *org;
596
+ unsigned int written;
597
+ int size;
598
+ ssize_t ret;
599
+ loff_t pos;
600
+ bool viewed, attr;
439601
440602 if (use_unicode(inode))
441603 return -EOPNOTSUPP;
....@@ -457,7 +619,11 @@
457619 if (!vc)
458620 goto unlock_out;
459621
460
- size = vcs_size(inode);
622
+ size = vcs_size(vc, attr, false);
623
+ if (size < 0) {
624
+ ret = size;
625
+ goto unlock_out;
626
+ }
461627 ret = -EINVAL;
462628 if (pos < 0 || pos > size)
463629 goto unlock_out;
....@@ -465,9 +631,7 @@
465631 count = size - pos;
466632 written = 0;
467633 while (count) {
468
- long this_round = count;
469
- size_t orig_count;
470
- long p;
634
+ unsigned int this_round = count;
471635
472636 if (this_round > CON_BUF_SIZE)
473637 this_round = CON_BUF_SIZE;
....@@ -492,11 +656,18 @@
492656 }
493657 }
494658
495
- /* The vcs_size might have changed while we slept to grab
496
- * the user buffer, so recheck.
659
+ /* The vc might have been freed or vcs_size might have changed
660
+ * while we slept to grab the user buffer, so recheck.
497661 * Return data written up to now on failure.
498662 */
499
- size = vcs_size(inode);
663
+ vc = vcs_vc(inode, &viewed);
664
+ if (!vc) {
665
+ if (written)
666
+ break;
667
+ ret = -ENXIO;
668
+ goto unlock_out;
669
+ }
670
+ size = vcs_size(vc, attr, false);
500671 if (size < 0) {
501672 if (written)
502673 break;
....@@ -512,95 +683,18 @@
512683 * under the lock using the local kernel buffer.
513684 */
514685
515
- con_buf0 = con_buf;
516
- orig_count = this_round;
517
- maxcol = vc->vc_cols;
518
- p = pos;
519
- if (!attr) {
520
- org0 = org = screen_pos(vc, p, viewed);
521
- col = p % maxcol;
522
- p += maxcol - col;
686
+ if (attr)
687
+ org = vcs_write_buf(vc, con_buf, pos, this_round,
688
+ viewed, &org0);
689
+ else
690
+ org = vcs_write_buf_noattr(vc, con_buf, pos, this_round,
691
+ viewed, &org0);
523692
524
- while (this_round > 0) {
525
- unsigned char c = *con_buf0++;
526
-
527
- this_round--;
528
- vcs_scr_writew(vc,
529
- (vcs_scr_readw(vc, org) & 0xff00) | c, org);
530
- org++;
531
- if (++col == maxcol) {
532
- org = screen_pos(vc, p, viewed);
533
- col = 0;
534
- p += maxcol;
535
- }
536
- }
537
- } else {
538
- if (p < HEADER_SIZE) {
539
- char header[HEADER_SIZE];
540
-
541
- getconsxy(vc, header + 2);
542
- while (p < HEADER_SIZE && this_round > 0) {
543
- this_round--;
544
- header[p++] = *con_buf0++;
545
- }
546
- if (!viewed)
547
- putconsxy(vc, header + 2);
548
- }
549
- p -= HEADER_SIZE;
550
- col = (p/2) % maxcol;
551
- if (this_round > 0) {
552
- org0 = org = screen_pos(vc, p/2, viewed);
553
- if ((p & 1) && this_round > 0) {
554
- char c;
555
-
556
- this_round--;
557
- c = *con_buf0++;
558
-#ifdef __BIG_ENDIAN
559
- vcs_scr_writew(vc, c |
560
- (vcs_scr_readw(vc, org) & 0xff00), org);
561
-#else
562
- vcs_scr_writew(vc, (c << 8) |
563
- (vcs_scr_readw(vc, org) & 0xff), org);
564
-#endif
565
- org++;
566
- p++;
567
- if (++col == maxcol) {
568
- org = screen_pos(vc, p/2, viewed);
569
- col = 0;
570
- }
571
- }
572
- p /= 2;
573
- p += maxcol - col;
574
- }
575
- while (this_round > 1) {
576
- unsigned short w;
577
-
578
- w = get_unaligned(((unsigned short *)con_buf0));
579
- vcs_scr_writew(vc, w, org++);
580
- con_buf0 += 2;
581
- this_round -= 2;
582
- if (++col == maxcol) {
583
- org = screen_pos(vc, p, viewed);
584
- col = 0;
585
- p += maxcol;
586
- }
587
- }
588
- if (this_round > 0) {
589
- unsigned char c;
590
-
591
- c = *con_buf0++;
592
-#ifdef __BIG_ENDIAN
593
- vcs_scr_writew(vc, (vcs_scr_readw(vc, org) & 0xff) | (c << 8), org);
594
-#else
595
- vcs_scr_writew(vc, (vcs_scr_readw(vc, org) & 0xff00) | c, org);
596
-#endif
597
- }
598
- }
599
- count -= orig_count;
600
- written += orig_count;
601
- buf += orig_count;
602
- pos += orig_count;
603
- if (org0)
693
+ count -= this_round;
694
+ written += this_round;
695
+ buf += this_round;
696
+ pos += this_round;
697
+ if (org)
604698 update_region(vc, (unsigned long)(org0), org - org0);
605699 }
606700 *ppos += written;
....@@ -618,12 +712,21 @@
618712 vcs_poll(struct file *file, poll_table *wait)
619713 {
620714 struct vcs_poll_data *poll = vcs_poll_data_get(file);
621
- __poll_t ret = DEFAULT_POLLMASK|EPOLLERR|EPOLLPRI;
715
+ __poll_t ret = DEFAULT_POLLMASK|EPOLLERR;
622716
623717 if (poll) {
624718 poll_wait(file, &poll->waitq, wait);
625
- if (poll->seen_last_update)
719
+ switch (poll->event) {
720
+ case VT_UPDATE:
721
+ ret = DEFAULT_POLLMASK|EPOLLPRI;
722
+ break;
723
+ case VT_DEALLOCATE:
724
+ ret = DEFAULT_POLLMASK|EPOLLHUP|EPOLLERR;
725
+ break;
726
+ case 0:
626727 ret = DEFAULT_POLLMASK;
728
+ break;
729
+ }
627730 }
628731 return ret;
629732 }