diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2020-06-28 14:23:12 +1000 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2020-07-26 23:34:25 +1000 |
commit | 624cf5b538b507293ec761797bd8ce0702fefe64 (patch) | |
tree | c07f0cc27a6863a4c29183e088c5d5b858513d71 /drivers/macintosh | |
parent | b16b67689baa01a5616b651356df7ad3e47a8763 (diff) | |
download | lwn-624cf5b538b507293ec761797bd8ce0702fefe64.tar.gz lwn-624cf5b538b507293ec761797bd8ce0702fefe64.zip |
macintosh/via-macii: Handle poll replies correctly
Userspace applications may use /dev/adb to send Talk requests. Such
requests always have req->reply_expected == 1. The same is true of Talk
requests sent by the kernel, except for poll requests queued internally
by the via-macii driver. Those requests have req->reply_expected == 0.
Consequently, poll reply packets get treated like autopoll reply packets.
(It doesn't make sense to try to distinguish them.) Always enter 'reading'
state after a poll request, so that the reply gets collected and passed
to adb_input(), and none go missing.
All Talk replies passed to adb_input() come from polling or autopolling,
so call adb_input() with the autopoll parameter set to 1.
Fixes: d95fd5fce88f0 ("m68k: Mac II ADB fixes") # v5.0+
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Tested-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/754cddfa045e5bfa53e5da199831de02e7d2f27f.1593318192.git.fthain@telegraphics.com.au
Diffstat (limited to 'drivers/macintosh')
-rw-r--r-- | drivers/macintosh/via-macii.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index d29c87943ca4..8d5ef77b4a43 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -463,6 +463,21 @@ static irqreturn_t macii_interrupt(int irq, void *arg) via[ACR] &= ~SR_OUT; x = via[SR]; + } else if ((req->data[1] & OP_MASK) == TALK) { + macii_state = reading; + + reading_reply = 0; + reply_ptr = reply_buf; + *reply_ptr = req->data[1]; + reply_len = 1; + + via[ACR] &= ~SR_OUT; + x = via[SR]; + + req->complete = 1; + current_req = req->next; + if (req->done) + (*req->done)(req); } else { macii_state = idle; @@ -510,8 +525,9 @@ static irqreturn_t macii_interrupt(int irq, void *arg) current_req = req->next; if (req->done) (*req->done)(req); - } else if (reply_len && autopoll_devs) { - adb_input(reply_buf, reply_len, 0); + } else if (reply_len && autopoll_devs && + reply_buf[0] == last_poll_cmd) { + adb_input(reply_buf, reply_len, 1); } break; } |