summaryrefslogtreecommitdiffstats
path: root/drivers/macintosh/adb-iop.c
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2020-05-31 01:17:03 +0200
committerMichael Ellerman <mpe@ellerman.id.au>2020-07-26 15:34:24 +0200
commit32226e81704398317e1cc5a82d24c0ef3cc25e5e (patch)
treee6e922638dc7e62224cb3ec70db8eea6714c8337 /drivers/macintosh/adb-iop.c
parentmacintosh/adb-iop: Resolve static checker warnings (diff)
downloadlinux-32226e81704398317e1cc5a82d24c0ef3cc25e5e.tar.xz
linux-32226e81704398317e1cc5a82d24c0ef3cc25e5e.zip
macintosh/adb-iop: Implement idle -> sending state transition
In the present algorithm, the 'idle' state transition does not take place until there's a bus timeout. Once idle, the driver does not automatically proceed with the next request. Change the algorithm so that queued ADB requests will be sent as soon as the driver becomes idle. This is to take place after the current IOP message is completed. 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/dedcdfc62f43e85cc4c2a8d211a7e2fec7bc7c1a.1590880623.git.fthain@telegraphics.com.au
Diffstat (limited to 'drivers/macintosh/adb-iop.c')
-rw-r--r--drivers/macintosh/adb-iop.c43
1 files changed, 24 insertions, 19 deletions
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c
index a2b28e09f2ce..f22792c95d4f 100644
--- a/drivers/macintosh/adb-iop.c
+++ b/drivers/macintosh/adb-iop.c
@@ -54,13 +54,19 @@ struct adb_driver adb_iop_driver = {
.reset_bus = adb_iop_reset_bus
};
-static void adb_iop_end_req(struct adb_request *req, int state)
+static void adb_iop_done(void)
{
+ struct adb_request *req = current_req;
+
+ adb_iop_state = idle;
+
req->complete = 1;
current_req = req->next;
if (req->done)
(*req->done)(req);
- adb_iop_state = state;
+
+ if (adb_iop_state == idle)
+ adb_iop_start();
}
/*
@@ -94,37 +100,36 @@ static void adb_iop_complete(struct iop_msg *msg)
static void adb_iop_listen(struct iop_msg *msg)
{
struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
- struct adb_request *req;
unsigned long flags;
+ bool req_done = false;
local_irq_save(flags);
- req = current_req;
-
/* Handle a timeout. Timeout packets seem to occur even after
* we've gotten a valid reply to a TALK, presumably because of
* autopolling.
*/
- if (amsg->flags & ADB_IOP_TIMEOUT) {
- msg->reply[0] = ADB_IOP_TIMEOUT | ADB_IOP_AUTOPOLL;
- msg->reply[1] = 0;
- msg->reply[2] = 0;
- if (req && (adb_iop_state != idle)) {
- adb_iop_end_req(req, idle);
- }
- } else {
- if ((adb_iop_state == awaiting_reply) &&
- (amsg->flags & ADB_IOP_EXPLICIT)) {
+ if (amsg->flags & ADB_IOP_EXPLICIT) {
+ if (adb_iop_state == awaiting_reply) {
+ struct adb_request *req = current_req;
+
req->reply_len = amsg->count + 1;
memcpy(req->reply, &amsg->cmd, req->reply_len);
- } else {
- adb_input(&amsg->cmd, amsg->count + 1,
- amsg->flags & ADB_IOP_AUTOPOLL);
+
+ req_done = true;
}
- memcpy(msg->reply, msg->message, IOP_MSG_LEN);
+ } else if (!(amsg->flags & ADB_IOP_TIMEOUT)) {
+ adb_input(&amsg->cmd, amsg->count + 1,
+ amsg->flags & ADB_IOP_AUTOPOLL);
}
+
+ msg->reply[0] = ADB_IOP_AUTOPOLL;
iop_complete_message(msg);
+
+ if (req_done)
+ adb_iop_done();
+
local_irq_restore(flags);
}