DF-4415 / fix.diff
diff --git a/sys/dev/misc/kbd/atkbdc.c b/sys/dev/misc/kbd/atkbdc.c --- a/sys/dev/misc/kbd/atkbdc.c +++ b/sys/dev/misc/kbd/atkbdc.c @@ -856,9 +856,11 @@ empty_kbd_buffer(KBDC p, int wait) #endif int delta = 2; + int waited = 0; for (t = wait; t > 0;) { if ((f = read_status(p)) & KBDS_ANY_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); b = read_data(p); @@ -879,7 +881,13 @@ empty_kbd_buffer(KBDC p, int wait) } else { t -= delta; } + /* + * A flooding controller resets `t' forever; cap total time + * like empty_both_buffers() does for the Intel blades. + */ + waited += (delta * 1000); + if (waited >= (delta * 1000000)) + return; DELAY(delta * 1000); } @@ -895,9 +903,11 @@ empty_aux_buffer(KBDC p, int wait) #endif int delta = 2; + int waited = 0; for (t = wait; t > 0;) { if ((f = read_status(p)) & KBDS_ANY_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); b = read_data(p); @@ -918,7 +928,13 @@ empty_aux_buffer(KBDC p, int wait) } else { t -= delta; } + waited += (delta * 1000); + if (waited >= (delta * 1000000)) + return; DELAY(delta * 1000); } @@ -796,7 +812,11 @@ read_kbd_data_no_wait(KBDC p) f = read_status(p) & KBDS_BUFFER_FULL; while (f == KBDS_AUX_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); b = read_data(p); addq(&p->aux, b); f = read_status(p) & KBDS_BUFFER_FULL; + if (++drain > KBDQ_BUFSIZE) { /* bounded drain */ + f = 0; + break; + } } @@ -835,7 +855,11 @@ read_aux_data_no_wait(KBDC p) f = read_status(p) & KBDS_BUFFER_FULL; while (f == KBDS_KBD_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); b = read_data(p); addq(&p->kbd, b); f = read_status(p) & KBDS_BUFFER_FULL; + if (++drain > KBDQ_BUFSIZE) { /* bounded drain */ + f = 0; + break; + } } |