Commit 32226e81 authored by Finn Thain's avatar Finn Thain Committed by Michael Ellerman

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: default avatarFinn Thain <fthain@telegraphics.com.au>
Tested-by: default avatarStan Johnson <userm57@yahoo.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/dedcdfc62f43e85cc4c2a8d211a7e2fec7bc7c1a.1590880623.git.fthain@telegraphics.com.au
parent 56b732ed
...@@ -54,13 +54,19 @@ struct adb_driver adb_iop_driver = { ...@@ -54,13 +54,19 @@ struct adb_driver adb_iop_driver = {
.reset_bus = adb_iop_reset_bus .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; req->complete = 1;
current_req = req->next; current_req = req->next;
if (req->done) if (req->done)
(*req->done)(req); (*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) ...@@ -94,37 +100,36 @@ static void adb_iop_complete(struct iop_msg *msg)
static void adb_iop_listen(struct iop_msg *msg) static void adb_iop_listen(struct iop_msg *msg)
{ {
struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message; struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message;
struct adb_request *req;
unsigned long flags; unsigned long flags;
bool req_done = false;
local_irq_save(flags); local_irq_save(flags);
req = current_req;
/* Handle a timeout. Timeout packets seem to occur even after /* Handle a timeout. Timeout packets seem to occur even after
* we've gotten a valid reply to a TALK, presumably because of * we've gotten a valid reply to a TALK, presumably because of
* autopolling. * autopolling.
*/ */
if (amsg->flags & ADB_IOP_TIMEOUT) { if (amsg->flags & ADB_IOP_EXPLICIT) {
msg->reply[0] = ADB_IOP_TIMEOUT | ADB_IOP_AUTOPOLL; if (adb_iop_state == awaiting_reply) {
msg->reply[1] = 0; struct adb_request *req = current_req;
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)) {
req->reply_len = amsg->count + 1; req->reply_len = amsg->count + 1;
memcpy(req->reply, &amsg->cmd, req->reply_len); memcpy(req->reply, &amsg->cmd, req->reply_len);
} else {
req_done = true;
}
} else if (!(amsg->flags & ADB_IOP_TIMEOUT)) {
adb_input(&amsg->cmd, amsg->count + 1, adb_input(&amsg->cmd, amsg->count + 1,
amsg->flags & ADB_IOP_AUTOPOLL); amsg->flags & ADB_IOP_AUTOPOLL);
} }
memcpy(msg->reply, msg->message, IOP_MSG_LEN);
} msg->reply[0] = ADB_IOP_AUTOPOLL;
iop_complete_message(msg); iop_complete_message(msg);
if (req_done)
adb_iop_done();
local_irq_restore(flags); local_irq_restore(flags);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment