Skip to content

Commit c284cf0

Browse files
committed
Merge tag 'tty-4.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty fixes from Greg KH: "Here are three small HVC tty driver fixes to resolve a reported regression from 4.19-rc1. All of these have been in linux-next for a while with no reported issues" * tag 'tty-4.19-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: tty: hvc: hvc_write() fix break condition tty: hvc: hvc_poll() fix read loop batching tty: hvc: hvc_poll() fix read loop hang
2 parents 45d9ab8 + 7f2bf78 commit c284cf0

File tree

1 file changed

+33
-5
lines changed

1 file changed

+33
-5
lines changed

drivers/tty/hvc/hvc_console.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
522522
return -EIO;
523523

524524
while (count > 0) {
525+
int ret = 0;
526+
525527
spin_lock_irqsave(&hp->lock, flags);
526528

527529
rsize = hp->outbuf_size - hp->n_outbuf;
@@ -537,10 +539,13 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
537539
}
538540

539541
if (hp->n_outbuf > 0)
540-
hvc_push(hp);
542+
ret = hvc_push(hp);
541543

542544
spin_unlock_irqrestore(&hp->lock, flags);
543545

546+
if (!ret)
547+
break;
548+
544549
if (count) {
545550
if (hp->n_outbuf > 0)
546551
hvc_flush(hp);
@@ -623,6 +628,15 @@ static int hvc_chars_in_buffer(struct tty_struct *tty)
623628
#define MAX_TIMEOUT (2000)
624629
static u32 timeout = MIN_TIMEOUT;
625630

631+
/*
632+
* Maximum number of bytes to get from the console driver if hvc_poll is
633+
* called from driver (and can't sleep). Any more than this and we break
634+
* and start polling with khvcd. This value was derived from from an OpenBMC
635+
* console with the OPAL driver that results in about 0.25ms interrupts off
636+
* latency.
637+
*/
638+
#define HVC_ATOMIC_READ_MAX 128
639+
626640
#define HVC_POLL_READ 0x00000001
627641
#define HVC_POLL_WRITE 0x00000002
628642

@@ -669,8 +683,8 @@ static int __hvc_poll(struct hvc_struct *hp, bool may_sleep)
669683
if (!hp->irq_requested)
670684
poll_mask |= HVC_POLL_READ;
671685

686+
read_again:
672687
/* Read data if any */
673-
674688
count = tty_buffer_request_room(&hp->port, N_INBUF);
675689

676690
/* If flip is full, just reschedule a later read */
@@ -717,9 +731,23 @@ static int __hvc_poll(struct hvc_struct *hp, bool may_sleep)
717731
#endif /* CONFIG_MAGIC_SYSRQ */
718732
tty_insert_flip_char(&hp->port, buf[i], 0);
719733
}
720-
if (n == count)
721-
poll_mask |= HVC_POLL_READ;
722-
read_total = n;
734+
read_total += n;
735+
736+
if (may_sleep) {
737+
/* Keep going until the flip is full */
738+
spin_unlock_irqrestore(&hp->lock, flags);
739+
cond_resched();
740+
spin_lock_irqsave(&hp->lock, flags);
741+
goto read_again;
742+
} else if (read_total < HVC_ATOMIC_READ_MAX) {
743+
/* Break and defer if it's a large read in atomic */
744+
goto read_again;
745+
}
746+
747+
/*
748+
* Latency break, schedule another poll immediately.
749+
*/
750+
poll_mask |= HVC_POLL_READ;
723751

724752
out:
725753
/* Wakeup write queue if necessary */

0 commit comments

Comments
 (0)