summaryrefslogtreecommitdiffstats
path: root/drivers/macintosh
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2020-06-28 14:23:12 +1000
committerMichael Ellerman <mpe@ellerman.id.au>2020-07-26 23:34:25 +1000
commit624cf5b538b507293ec761797bd8ce0702fefe64 (patch)
treec07f0cc27a6863a4c29183e088c5d5b858513d71 /drivers/macintosh
parentb16b67689baa01a5616b651356df7ad3e47a8763 (diff)
downloadlinux-stable-624cf5b538b507293ec761797bd8ce0702fefe64.tar.gz
linux-stable-624cf5b538b507293ec761797bd8ce0702fefe64.tar.bz2
linux-stable-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.c20
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;
}