From a7beab413e2e67dd1abe6bdd0001576892a89e81 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 17 Jul 2020 20:35:22 +0200 Subject: macintosh/adb: Replace HTTP links with HTTPS ones Rationale: Reduces attack surface on kernel devs opening the links for MITM as HTTPS traffic is much harder to manipulate. Deterministic algorithm: For each file: If not .svg: For each line: If doesn't contain `\bxmlns\b`: For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`: If neither `\bgnu\.org/license`, nor `\bmozilla\.org/MPL\b`: If both the HTTP and HTTPS versions return 200 OK and serve the same content: Replace HTTP with HTTPS. Signed-off-by: Alexander A. Klimov Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200717183522.77605-1-grandmaster@al2klimov.de --- drivers/macintosh/adb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index e49d1f287a17..73b396189039 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -163,7 +163,7 @@ static int adb_scan_bus(void) * See if anybody actually moved. This is suggested * by HW TechNote 01: * - * http://developer.apple.com/technotes/hw/hw_01.html + * https://developer.apple.com/technotes/hw/hw_01.html */ adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, (highFree << 4) | 0xf); -- cgit v1.2.3 From 1666e5ea2f838f4266e50e4f3d973c0824256429 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 17 Jul 2020 20:29:40 +0200 Subject: macintosh/therm_adt746x: Replace HTTP links with HTTPS ones Rationale: Reduces attack surface on kernel devs opening the links for MITM as HTTPS traffic is much harder to manipulate. Deterministic algorithm: For each file: If not .svg: For each line: If doesn't contain `\bxmlns\b`: For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`: If neither `\bgnu\.org/license`, nor `\bmozilla\.org/MPL\b`: If both the HTTP and HTTPS versions return 200 OK and serve the same content: Replace HTTP with HTTPS. Signed-off-by: Alexander A. Klimov Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20200717182940.75484-1-grandmaster@al2klimov.de --- drivers/macintosh/therm_adt746x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 8f7725dc2166..7e218437730c 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -5,8 +5,8 @@ * Copyright (C) 2003, 2004 Colin Leroy, Rasmus Rohde, Benjamin Herrenschmidt * * Documentation from 115254175ADT7467_pra.pdf and 3686221171167ADT7460_b.pdf - * http://www.onsemi.com/PowerSolutions/product.do?id=ADT7467 - * http://www.onsemi.com/PowerSolutions/product.do?id=ADT7460 + * https://www.onsemi.com/PowerSolutions/product.do?id=ADT7467 + * https://www.onsemi.com/PowerSolutions/product.do?id=ADT7460 * */ -- cgit v1.2.3 From 8384c82ab0860cd7db2ce4ec403e574f4ee54b6e Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 31 May 2020 09:17:03 +1000 Subject: macintosh/adb-iop: Remove dead and redundant code Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/7720ffb559c334504e16b24d9c2f3b8973d2d674.1590880623.git.fthain@telegraphics.com.au --- drivers/macintosh/adb-iop.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index fca31640e3ef..ce28ff40fb9c 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -18,24 +18,16 @@ #include #include #include -#include #include #include #include -#include #include #include -/*#define DEBUG_ADB_IOP*/ - static struct adb_request *current_req; static struct adb_request *last_req; -#if 0 -static unsigned char reply_buff[16]; -static unsigned char *reply_ptr; -#endif static enum adb_iop_state { idle, @@ -104,22 +96,11 @@ 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; -#ifdef DEBUG_ADB_IOP - int i; -#endif local_irq_save(flags); req = current_req; -#ifdef DEBUG_ADB_IOP - printk("adb_iop_listen %p: rcvd packet, %d bytes: %02X %02X", req, - (uint)amsg->count + 2, (uint)amsg->flags, (uint)amsg->cmd); - for (i = 0; i < amsg->count; i++) - printk(" %02X", (uint)amsg->data[i]); - printk("\n"); -#endif - /* Handle a timeout. Timeout packets seem to occur even after */ /* we've gotten a valid reply to a TALK, so I'm assuming that */ /* a "timeout" is actually more like an "end-of-data" signal. */ @@ -163,9 +144,6 @@ static void adb_iop_start(void) unsigned long flags; struct adb_request *req; struct adb_iopmsg amsg; -#ifdef DEBUG_ADB_IOP - int i; -#endif /* get the packet to send */ req = current_req; @@ -174,13 +152,6 @@ static void adb_iop_start(void) local_irq_save(flags); -#ifdef DEBUG_ADB_IOP - printk("adb_iop_start %p: sending packet, %d bytes:", req, req->nbytes); - for (i = 0; i < req->nbytes; i++) - printk(" %02X", (uint)req->data[i]); - printk("\n"); -#endif - /* The IOP takes MacII-style packets, so */ /* strip the initial ADB_PACKET byte. */ -- cgit v1.2.3 From ff785e179faf4bb06a2f73b8dcde6dabb66a83d2 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 31 May 2020 09:17:03 +1000 Subject: macintosh/adb-iop: Correct comment text This patch improves comment style and corrects some misunderstandings in the text. Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/996f835d2f3d90baaaf9ee954e252d06e8886c6f.1590880623.git.fthain@telegraphics.com.au --- drivers/macintosh/adb-iop.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index ce28ff40fb9c..ca3b411b0742 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -101,11 +101,10 @@ static void adb_iop_listen(struct iop_msg *msg) req = current_req; - /* Handle a timeout. Timeout packets seem to occur even after */ - /* we've gotten a valid reply to a TALK, so I'm assuming that */ - /* a "timeout" is actually more like an "end-of-data" signal. */ - /* We need to send back a timeout packet to the IOP to shut */ - /* it up, plus complete the current request, if any. */ + /* 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; @@ -115,9 +114,6 @@ static void adb_iop_listen(struct iop_msg *msg) adb_iop_end_req(req, idle); } } else { - /* TODO: is it possible for more than one chunk of data */ - /* to arrive before the timeout? If so we need to */ - /* use reply_ptr here like the other drivers do. */ if ((adb_iop_state == awaiting_reply) && (amsg->flags & ADB_IOP_EXPLICIT)) { req->reply_len = amsg->count + 1; @@ -152,23 +148,24 @@ static void adb_iop_start(void) local_irq_save(flags); - /* The IOP takes MacII-style packets, so */ - /* strip the initial ADB_PACKET byte. */ - + /* The IOP takes MacII-style packets, so strip the initial + * ADB_PACKET byte. + */ amsg.flags = ADB_IOP_EXPLICIT; amsg.count = req->nbytes - 2; - /* amsg.data immediately follows amsg.cmd, effectively making */ - /* amsg.cmd a pointer to the beginning of a full ADB packet. */ + /* amsg.data immediately follows amsg.cmd, effectively making + * &amsg.cmd a pointer to the beginning of a full ADB packet. + */ memcpy(&amsg.cmd, req->data + 1, req->nbytes - 1); req->sent = 1; adb_iop_state = sending; local_irq_restore(flags); - /* Now send it. The IOP manager will call adb_iop_complete */ - /* when the packet has been sent. */ - + /* Now send it. The IOP manager will call adb_iop_complete + * when the message has been sent. + */ iop_send_message(ADB_IOP, ADB_CHAN, req, sizeof(amsg), (__u8 *)&amsg, adb_iop_complete); } -- cgit v1.2.3 From 303511edb859b1fbf48b3c1d1d53b33a6ebd2a2b Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 31 May 2020 09:17:03 +1000 Subject: macintosh/adb-iop: Adopt bus reset algorithm from via-macii driver This algorithm is slightly shorter and avoids the surprising adb_iop_start() call in adb_iop_poll(). Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/b63d56ecb6e75f11a0bf02231f3b2db656a528a3.1590880623.git.fthain@telegraphics.com.au --- drivers/macintosh/adb-iop.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index ca3b411b0742..c3089dacf2e2 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -238,24 +238,19 @@ int adb_iop_autopoll(int devs) void adb_iop_poll(void) { - if (adb_iop_state == idle) - adb_iop_start(); iop_ism_irq_poll(ADB_IOP); } int adb_iop_reset_bus(void) { - struct adb_request req = { - .reply_expected = 0, - .nbytes = 2, - .data = { ADB_PACKET, 0 }, - }; - - adb_iop_write(&req); - while (!req.complete) { - adb_iop_poll(); - schedule(); - } + struct adb_request req; + + /* Command = 0, Address = ignored */ + adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET); + adb_iop_send_request(&req, 1); + + /* Don't want any more requests during the Global Reset low time. */ + mdelay(3); return 0; } -- cgit v1.2.3 From aac840eca8fec02d594560647130d4e4447e10d9 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 31 May 2020 09:17:03 +1000 Subject: macintosh/adb-iop: Access current_req and adb_iop_state when inside lock Drop the redundant local_irq_save/restore() from adb_iop_start() because the caller has to do it anyway. This is the pattern used in via-macii. Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/bbe32b087c7e04d68e2425f6a2df4a414d167c32.1590880623.git.fthain@telegraphics.com.au --- drivers/macintosh/adb-iop.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index c3089dacf2e2..7ecc41bc7358 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -137,7 +137,6 @@ static void adb_iop_listen(struct iop_msg *msg) static void adb_iop_start(void) { - unsigned long flags; struct adb_request *req; struct adb_iopmsg amsg; @@ -146,8 +145,6 @@ static void adb_iop_start(void) if (!req) return; - local_irq_save(flags); - /* The IOP takes MacII-style packets, so strip the initial * ADB_PACKET byte. */ @@ -161,7 +158,6 @@ static void adb_iop_start(void) req->sent = 1; adb_iop_state = sending; - local_irq_restore(flags); /* Now send it. The IOP manager will call adb_iop_complete * when the message has been sent. @@ -208,13 +204,13 @@ static int adb_iop_write(struct adb_request *req) return -EINVAL; } - local_irq_save(flags); - req->next = NULL; req->sent = 0; req->complete = 0; req->reply_len = 0; + local_irq_save(flags); + if (current_req != 0) { last_req->next = req; last_req = req; @@ -223,10 +219,11 @@ static int adb_iop_write(struct adb_request *req) last_req = req; } - local_irq_restore(flags); - if (adb_iop_state == idle) adb_iop_start(); + + local_irq_restore(flags); + return 0; } -- cgit v1.2.3 From 56b732edda96b1942fff974fd298ea2a2c543b94 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 31 May 2020 09:17:03 +1000 Subject: macintosh/adb-iop: Resolve static checker warnings drivers/macintosh/adb-iop.c:215:28: warning: Using plain integer as NULL pointer drivers/macintosh/adb-iop.c:170:5: warning: symbol 'adb_iop_probe' was not declared. Should it be static? drivers/macintosh/adb-iop.c:177:5: warning: symbol 'adb_iop_init' was not declared. Should it be static? drivers/macintosh/adb-iop.c:184:5: warning: symbol 'adb_iop_send_request' was not declared. Should it be static? drivers/macintosh/adb-iop.c:230:5: warning: symbol 'adb_iop_autopoll' was not declared. Should it be static? drivers/macintosh/adb-iop.c:236:6: warning: symbol 'adb_iop_poll' was not declared. Should it be static? drivers/macintosh/adb-iop.c:241:5: warning: symbol 'adb_iop_reset_bus' was not declared. Should it be static? Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/25edf4450abd20e002b166ba3a11189dc1efa906.1590880623.git.fthain@telegraphics.com.au --- drivers/macintosh/adb-iop.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index 7ecc41bc7358..a2b28e09f2ce 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -166,21 +166,21 @@ static void adb_iop_start(void) adb_iop_complete); } -int adb_iop_probe(void) +static int adb_iop_probe(void) { if (!iop_ism_present) return -ENODEV; return 0; } -int adb_iop_init(void) +static int adb_iop_init(void) { pr_info("adb: IOP ISM driver v0.4 for Unified ADB\n"); iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB"); return 0; } -int adb_iop_send_request(struct adb_request *req, int sync) +static int adb_iop_send_request(struct adb_request *req, int sync) { int err; @@ -211,7 +211,7 @@ static int adb_iop_write(struct adb_request *req) local_irq_save(flags); - if (current_req != 0) { + if (current_req) { last_req->next = req; last_req = req; } else { @@ -227,18 +227,18 @@ static int adb_iop_write(struct adb_request *req) return 0; } -int adb_iop_autopoll(int devs) +static int adb_iop_autopoll(int devs) { /* TODO: how do we enable/disable autopoll? */ return 0; } -void adb_iop_poll(void) +static void adb_iop_poll(void) { iop_ism_irq_poll(ADB_IOP); } -int adb_iop_reset_bus(void) +static int adb_iop_reset_bus(void) { struct adb_request req; -- cgit v1.2.3 From 32226e81704398317e1cc5a82d24c0ef3cc25e5e Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 31 May 2020 09:17:03 +1000 Subject: 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 Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/dedcdfc62f43e85cc4c2a8d211a7e2fec7bc7c1a.1590880623.git.fthain@telegraphics.com.au --- drivers/macintosh/adb-iop.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers/macintosh') 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); } -- cgit v1.2.3 From e2954e5f727fad126258e83259b513988973c166 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 31 May 2020 09:17:03 +1000 Subject: macintosh/adb-iop: Implement sending -> idle state transition On leaving the 'sending' state, proceed to the 'idle' state if no reply is expected. Drop redundant test for adb_iop_state == sending && current_req. Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/6991996dd4aaf0b52cfd650172bf0f6fbe37a452.1590880623.git.fthain@telegraphics.com.au --- drivers/macintosh/adb-iop.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index f22792c95d4f..8594e4f9a830 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -77,15 +77,14 @@ static void adb_iop_done(void) static void adb_iop_complete(struct iop_msg *msg) { - struct adb_request *req; unsigned long flags; local_irq_save(flags); - req = current_req; - if ((adb_iop_state == sending) && req && req->reply_expected) { + if (current_req->reply_expected) adb_iop_state = awaiting_reply; - } + else + adb_iop_done(); local_irq_restore(flags); } -- cgit v1.2.3 From c66da95a39ec2bb95544c3def974d96e8c178f57 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 31 May 2020 09:17:03 +1000 Subject: macintosh/adb-iop: Implement SRQ autopolling The adb_driver.autopoll method is needed during ADB bus scan and device address assignment. Implement this method so that the IOP's list of device addresses can be updated. When the list is empty, disable SRQ autopolling. Signed-off-by: Finn Thain Tested-by: Stan Johnson Acked-by: Geert Uytterhoeven Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/0fb7fdcd99d7820bb27faf1f27f7f6f1923914ef.1590880623.git.fthain@telegraphics.com.au --- arch/m68k/include/asm/adb_iop.h | 1 + drivers/macintosh/adb-iop.c | 32 ++++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers/macintosh') diff --git a/arch/m68k/include/asm/adb_iop.h b/arch/m68k/include/asm/adb_iop.h index 195d7fb1268c..6aecd020e2fc 100644 --- a/arch/m68k/include/asm/adb_iop.h +++ b/arch/m68k/include/asm/adb_iop.h @@ -29,6 +29,7 @@ #define ADB_IOP_EXPLICIT 0x80 /* nonzero if explicit command */ #define ADB_IOP_AUTOPOLL 0x40 /* auto/SRQ polling enabled */ +#define ADB_IOP_SET_AUTOPOLL 0x20 /* set autopoll device list */ #define ADB_IOP_SRQ 0x04 /* SRQ detected */ #define ADB_IOP_TIMEOUT 0x02 /* nonzero if timeout */ diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index 8594e4f9a830..f3d1a460fbce 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c @@ -7,10 +7,6 @@ * 1999-07-01 (jmt) - First implementation for new driver architecture. * * 1999-07-31 (jmt) - First working version. - * - * TODO: - * - * o Implement SRQ handling. */ #include @@ -28,6 +24,7 @@ static struct adb_request *current_req; static struct adb_request *last_req; +static unsigned int autopoll_devs; static enum adb_iop_state { idle, @@ -123,7 +120,7 @@ static void adb_iop_listen(struct iop_msg *msg) amsg->flags & ADB_IOP_AUTOPOLL); } - msg->reply[0] = ADB_IOP_AUTOPOLL; + msg->reply[0] = autopoll_devs ? ADB_IOP_AUTOPOLL : 0; iop_complete_message(msg); if (req_done) @@ -231,9 +228,32 @@ static int adb_iop_write(struct adb_request *req) return 0; } +static void adb_iop_set_ap_complete(struct iop_msg *msg) +{ + struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message; + + autopoll_devs = (amsg->data[1] << 8) | amsg->data[0]; +} + static int adb_iop_autopoll(int devs) { - /* TODO: how do we enable/disable autopoll? */ + struct adb_iopmsg amsg; + unsigned long flags; + unsigned int mask = (unsigned int)devs & 0xFFFE; + + local_irq_save(flags); + + amsg.flags = ADB_IOP_SET_AUTOPOLL | (mask ? ADB_IOP_AUTOPOLL : 0); + amsg.count = 2; + amsg.cmd = 0; + amsg.data[0] = mask & 0xFF; + amsg.data[1] = (mask >> 8) & 0xFF; + + iop_send_message(ADB_IOP, ADB_CHAN, NULL, sizeof(amsg), (__u8 *)&amsg, + adb_iop_set_ap_complete); + + local_irq_restore(flags); + return 0; } -- cgit v1.2.3 From 59ea38f6b3af5636edf541768a1ed721eeaca99e Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 28 Jun 2020 14:23:12 +1000 Subject: macintosh/via-macii: Access autopoll_devs when inside lock The interrupt handler should be excluded when accessing the autopoll_devs variable. Fixes: d95fd5fce88f0 ("m68k: Mac II ADB fixes") # v5.0+ Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/5952dd8a9bc9de90f1acc4790c51dd42b4c98065.1593318192.git.fthain@telegraphics.com.au --- drivers/macintosh/via-macii.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index ac824d7b2dcf..6aa903529570 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -270,15 +270,12 @@ static int macii_autopoll(int devs) unsigned long flags; int err = 0; + local_irq_save(flags); + /* bit 1 == device 1, and so on. */ autopoll_devs = devs & 0xFFFE; - if (!autopoll_devs) - return 0; - - local_irq_save(flags); - - if (current_req == NULL) { + if (autopoll_devs && !current_req) { /* Send a Talk Reg 0. The controller will repeatedly transmit * this as long as it is idle. */ -- cgit v1.2.3 From f93bfeb55255bddaa16597e187a99ae6131b964a Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 28 Jun 2020 14:23:12 +1000 Subject: macintosh/via-macii: Poll the device most likely to respond Poll the most recently polled device by default, rather than the lowest device address that happens to be enabled in autopoll_devs. This improves input latency. Re-use macii_queue_poll() rather than duplicate that logic. This eliminates a static struct and function. Fixes: d95fd5fce88f0 ("m68k: Mac II ADB fixes") # v5.0+ Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/5836f80886ebcfbe5be5fb7e0dc49feed6469712.1593318192.git.fthain@telegraphics.com.au --- drivers/macintosh/via-macii.c | 99 +++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 46 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index 6aa903529570..d4f1a65c5f1f 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -77,6 +77,10 @@ static volatile unsigned char *via; #define ST_ODD 0x20 /* ADB state: odd data byte */ #define ST_IDLE 0x30 /* ADB state: idle, nothing to send */ +/* ADB command byte structure */ +#define ADDR_MASK 0xF0 +#define CMD_MASK 0x0F + static int macii_init_via(void); static void macii_start(void); static irqreturn_t macii_interrupt(int irq, void *arg); @@ -117,7 +121,8 @@ static int reply_len; /* number of bytes received in reply_buf or req->reply */ static int status; /* VIA's ADB status bits captured upon interrupt */ static int last_status; /* status bits as at previous interrupt */ static int srq_asserted; /* have to poll for the device that asserted it */ -static int command_byte; /* the most recent command byte transmitted */ +static u8 last_cmd; /* the most recent command byte transmitted */ +static u8 last_poll_cmd; /* the most recent Talk R0 command byte transmitted */ static int autopoll_devs; /* bits set are device addresses to be polled */ /* Check for MacII style ADB */ @@ -179,35 +184,49 @@ static int macii_init_via(void) /* Send an ADB poll (Talk Register 0 command prepended to the request queue) */ static void macii_queue_poll(void) { - /* No point polling the active device as it will never assert SRQ, so - * poll the next device in the autopoll list. This could leave us - * stuck in a polling loop if an unprobed device is asserting SRQ. - * In theory, that could only happen if a device was plugged in after - * probing started. Unplugging it again will break the cycle. - * (Simply polling the next higher device often ends up polling almost - * every device (after wrapping around), which takes too long.) - */ - int device_mask; - int next_device; static struct adb_request req; + unsigned char poll_command; + unsigned int poll_addr; + /* This only polls devices in the autopoll list, which assumes that + * unprobed devices never assert SRQ. That could happen if a device was + * plugged in after the adb bus scan. Unplugging it again will resolve + * the problem. This behaviour is similar to MacOS. + */ if (!autopoll_devs) return; - device_mask = (1 << (((command_byte & 0xF0) >> 4) + 1)) - 1; - if (autopoll_devs & ~device_mask) - next_device = ffs(autopoll_devs & ~device_mask) - 1; - else - next_device = ffs(autopoll_devs) - 1; + /* The device most recently polled may not be the best device to poll + * right now. Some other device(s) may have signalled SRQ (the active + * device won't do that). Or the autopoll list may have been changed. + * Try polling the next higher address. + */ + poll_addr = (last_poll_cmd & ADDR_MASK) >> 4; + if ((srq_asserted && last_cmd == last_poll_cmd) || + !(autopoll_devs & (1 << poll_addr))) { + unsigned int higher_devs; + + higher_devs = autopoll_devs & -(1 << (poll_addr + 1)); + poll_addr = ffs(higher_devs ? higher_devs : autopoll_devs) - 1; + } - adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_READREG(next_device, 0)); + /* Send a Talk Register 0 command */ + poll_command = ADB_READREG(poll_addr, 0); + + /* No need to repeat this Talk command. The transceiver will do that + * as long as it is idle. + */ + if (poll_command == last_cmd) + return; + + adb_request(&req, NULL, ADBREQ_NOSEND, 1, poll_command); req.sent = 0; req.complete = 0; req.reply_len = 0; req.next = current_req; - if (current_req != NULL) { + if (WARN_ON(current_req)) { current_req = &req; } else { current_req = &req; @@ -266,37 +285,22 @@ static int macii_write(struct adb_request *req) /* Start auto-polling */ static int macii_autopoll(int devs) { - static struct adb_request req; unsigned long flags; - int err = 0; local_irq_save(flags); /* bit 1 == device 1, and so on. */ autopoll_devs = devs & 0xFFFE; - if (autopoll_devs && !current_req) { - /* Send a Talk Reg 0. The controller will repeatedly transmit - * this as long as it is idle. - */ - adb_request(&req, NULL, ADBREQ_NOSEND, 1, - ADB_READREG(ffs(autopoll_devs) - 1, 0)); - err = macii_write(&req); + if (!current_req) { + macii_queue_poll(); + if (current_req && macii_state == idle) + macii_start(); } local_irq_restore(flags); - return err; -} -static inline int need_autopoll(void) -{ - /* Was the last command Talk Reg 0 - * and is the target on the autopoll list? - */ - if ((command_byte & 0x0F) == 0x0C && - ((1 << ((command_byte & 0xF0) >> 4)) & autopoll_devs)) - return 0; - return 1; + return 0; } /* Prod the chip without interrupts */ @@ -333,7 +337,12 @@ static void macii_start(void) */ /* store command byte */ - command_byte = req->data[1]; + last_cmd = req->data[1]; + + /* If this is a Talk Register 0 command, store the command byte */ + if ((last_cmd & CMD_MASK) == ADB_READREG(0, 0)) + last_poll_cmd = last_cmd; + /* Output mode */ via[ACR] |= SR_OUT; /* Load data */ @@ -424,10 +433,11 @@ static irqreturn_t macii_interrupt(int irq, void *arg) if (req->done) (*req->done)(req); - if (current_req) + if (!current_req) + macii_queue_poll(); + + if (current_req && macii_state == idle) macii_start(); - else if (need_autopoll()) - macii_autopoll(autopoll_devs); } if (macii_state == idle) { @@ -507,14 +517,11 @@ static irqreturn_t macii_interrupt(int irq, void *arg) macii_state = idle; - /* SRQ seen before, initiate poll now */ - if (srq_asserted) + if (!current_req) macii_queue_poll(); if (current_req) macii_start(); - else if (need_autopoll()) - macii_autopoll(autopoll_devs); if (macii_state == idle) via[B] = (via[B] & ~ST_MASK) | ST_IDLE; -- cgit v1.2.3 From b4d76c28eca369b8105fe3a0a9f396e3fbcd0dd5 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 28 Jun 2020 14:23:12 +1000 Subject: macintosh/via-macii: Handle /CTLR_IRQ signal correctly I'm told that the /CTLR_IRQ signal from the ADB transceiver gets interpreted by MacOS to mean SRQ, bus timeout or end-of-packet depending on the circumstances, and that Linux's via-macii driver does not correctly interpret this signal. Instead, the via-macii driver interprets certain received byte values (0x00 and 0xFF) as signalling end of packet and bus timeout (respectively). Problem is, those values can also appear under other circumstances. This patch changes the bus timeout, end of packet and SRQ detection logic to bring it closer to the logic that MacOS reportedly uses. Fixes: 1da177e4c3f41 ("Linux-2.6.12-rc2") # v5.0+ Reported-by: Mark Cave-Ayland Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/6541fda1d8db3ae87c3abe17d189a10dc96e2382.1593318192.git.fthain@telegraphics.com.au --- drivers/macintosh/via-macii.c | 166 ++++++++++++++++++++++++------------------ 1 file changed, 97 insertions(+), 69 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index d4f1a65c5f1f..6a5cd7de05ba 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -80,6 +80,8 @@ static volatile unsigned char *via; /* ADB command byte structure */ #define ADDR_MASK 0xF0 #define CMD_MASK 0x0F +#define OP_MASK 0x0C +#define TALK 0x0C static int macii_init_via(void); static void macii_start(void); @@ -119,9 +121,10 @@ static int reading_reply; /* store reply in reply_buf else req->reply */ static int data_index; /* index of the next byte to send from req->data */ static int reply_len; /* number of bytes received in reply_buf or req->reply */ static int status; /* VIA's ADB status bits captured upon interrupt */ -static int last_status; /* status bits as at previous interrupt */ -static int srq_asserted; /* have to poll for the device that asserted it */ +static bool bus_timeout; /* no data was sent by the device */ +static bool srq_asserted; /* have to poll for the device that asserted it */ static u8 last_cmd; /* the most recent command byte transmitted */ +static u8 last_talk_cmd; /* the most recent Talk command byte transmitted */ static u8 last_poll_cmd; /* the most recent Talk R0 command byte transmitted */ static int autopoll_devs; /* bits set are device addresses to be polled */ @@ -170,7 +173,6 @@ static int macii_init_via(void) /* Set up state: idle */ via[B] |= ST_IDLE; - last_status = via[B] & (ST_MASK | CTLR_IRQ); /* Shift register on input */ via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; @@ -336,13 +338,6 @@ static void macii_start(void) * And req->nbytes is the number of bytes of real data plus one. */ - /* store command byte */ - last_cmd = req->data[1]; - - /* If this is a Talk Register 0 command, store the command byte */ - if ((last_cmd & CMD_MASK) == ADB_READREG(0, 0)) - last_poll_cmd = last_cmd; - /* Output mode */ via[ACR] |= SR_OUT; /* Load data */ @@ -352,6 +347,9 @@ static void macii_start(void) macii_state = sending; data_index = 2; + + bus_timeout = false; + srq_asserted = false; } /* @@ -360,15 +358,17 @@ static void macii_start(void) * generating shift register interrupts (SR_INT) for us. This means there has * to be activity on the ADB bus. The chip will poll to achieve this. * - * The basic ADB state machine was left unchanged from the original MacII code - * by Alan Cox, which was based on the CUDA driver for PowerMac. - * The syntax of the ADB status lines is totally different on MacII, - * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle - * for sending and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. - * Start and end of a receive packet are signalled by asserting /IRQ on the - * interrupt line (/IRQ means the CTLR_IRQ bit in port B; not to be confused - * with the VIA shift register interrupt. /IRQ never actually interrupts the - * processor, it's just an ordinary input.) + * The VIA Port B output signalling works as follows. After the ADB transceiver + * sees a transition on the PB4 and PB5 lines it will crank over the VIA shift + * register which eventually raises the SR_INT interrupt. The PB4/PB5 outputs + * are toggled with each byte as the ADB transaction progresses. + * + * Request with no reply expected (and empty transceiver buffer): + * CMD -> IDLE + * Request with expected reply packet (or with buffered autopoll packet): + * CMD -> EVEN -> ODD -> EVEN -> ... -> IDLE + * Unsolicited packet: + * IDLE -> EVEN -> ODD -> EVEN -> ... -> IDLE */ static irqreturn_t macii_interrupt(int irq, void *arg) { @@ -388,31 +388,31 @@ static irqreturn_t macii_interrupt(int irq, void *arg) } } - last_status = status; status = via[B] & (ST_MASK | CTLR_IRQ); switch (macii_state) { case idle: - if (reading_reply) { - reply_ptr = current_req->reply; - } else { - WARN_ON(current_req); - reply_ptr = reply_buf; - } + WARN_ON((status & ST_MASK) != ST_IDLE); + + reply_ptr = reply_buf; + reading_reply = 0; + + bus_timeout = false; + srq_asserted = false; x = via[SR]; - if ((status & CTLR_IRQ) && (x == 0xFF)) { - /* Bus timeout without SRQ sequence: - * data is "FF" while CTLR_IRQ is "H" + if (!(status & CTLR_IRQ)) { + /* /CTLR_IRQ asserted in idle state means we must + * read an autopoll reply from the transceiver buffer. */ - reply_len = 0; - srq_asserted = 0; - macii_state = read_done; - } else { macii_state = reading; *reply_ptr = x; reply_len = 1; + } else { + /* bus timeout */ + macii_state = read_done; + reply_len = 0; } /* set ADB state = even for first data byte */ @@ -421,13 +421,52 @@ static irqreturn_t macii_interrupt(int irq, void *arg) case sending: req = current_req; - if (data_index >= req->nbytes) { + + if (status == (ST_CMD | CTLR_IRQ)) { + /* /CTLR_IRQ de-asserted after the command byte means + * the host can continue with the transaction. + */ + + /* Store command byte */ + last_cmd = req->data[1]; + if ((last_cmd & OP_MASK) == TALK) { + last_talk_cmd = last_cmd; + if ((last_cmd & CMD_MASK) == ADB_READREG(0, 0)) + last_poll_cmd = last_cmd; + } + } + + if (status == ST_CMD) { + /* /CTLR_IRQ asserted after the command byte means we + * must read an autopoll reply. The first byte was + * lost because the shift register was an output. + */ + macii_state = reading; + + reading_reply = 0; + reply_ptr = reply_buf; + *reply_ptr = last_talk_cmd; + reply_len = 1; + + /* reset to shift in */ + via[ACR] &= ~SR_OUT; + x = via[SR]; + } else if (data_index >= req->nbytes) { req->sent = 1; - macii_state = idle; if (req->reply_expected) { + macii_state = reading; + reading_reply = 1; + reply_ptr = req->reply; + *reply_ptr = req->data[1]; + reply_len = 1; + + via[ACR] &= ~SR_OUT; + x = via[SR]; } else { + macii_state = idle; + req->complete = 1; current_req = req->next; if (req->done) @@ -438,25 +477,26 @@ static irqreturn_t macii_interrupt(int irq, void *arg) if (current_req && macii_state == idle) macii_start(); - } - if (macii_state == idle) { - /* reset to shift in */ - via[ACR] &= ~SR_OUT; - x = via[SR]; - /* set ADB state idle - might get SRQ */ - via[B] = (via[B] & ~ST_MASK) | ST_IDLE; + if (macii_state == idle) { + /* reset to shift in */ + via[ACR] &= ~SR_OUT; + x = via[SR]; + /* set ADB state idle - might get SRQ */ + via[B] = (via[B] & ~ST_MASK) | ST_IDLE; + } + break; } } else { via[SR] = req->data[data_index++]; + } - if ((via[B] & ST_MASK) == ST_CMD) { - /* just sent the command byte, set to EVEN */ - via[B] = (via[B] & ~ST_MASK) | ST_EVEN; - } else { - /* invert state bits, toggle ODD/EVEN */ - via[B] ^= ST_MASK; - } + if ((via[B] & ST_MASK) == ST_CMD) { + /* just sent the command byte, set to EVEN */ + via[B] = (via[B] & ~ST_MASK) | ST_EVEN; + } else { + /* invert state bits, toggle ODD/EVEN */ + via[B] ^= ST_MASK; } break; @@ -465,28 +505,13 @@ static irqreturn_t macii_interrupt(int irq, void *arg) WARN_ON((status & ST_MASK) == ST_CMD || (status & ST_MASK) == ST_IDLE); - /* Bus timeout with SRQ sequence: - * data is "XX FF" while CTLR_IRQ is "L L" - * End of packet without SRQ sequence: - * data is "XX...YY 00" while CTLR_IRQ is "L...H L" - * End of packet SRQ sequence: - * data is "XX...YY 00" while CTLR_IRQ is "L...L L" - * (where XX is the first response byte and - * YY is the last byte of valid response data.) - */ - - srq_asserted = 0; if (!(status & CTLR_IRQ)) { - if (x == 0xFF) { - if (!(last_status & CTLR_IRQ)) { - macii_state = read_done; - reply_len = 0; - srq_asserted = 1; - } - } else if (x == 0x00) { + if (status == ST_EVEN && reply_len == 1) { + bus_timeout = true; + } else if (status == ST_ODD && reply_len == 2) { + srq_asserted = true; + } else { macii_state = read_done; - if (!(last_status & CTLR_IRQ)) - srq_asserted = 1; } } @@ -504,6 +529,9 @@ static irqreturn_t macii_interrupt(int irq, void *arg) case read_done: x = via[SR]; + if (bus_timeout) + reply_len = 0; + if (reading_reply) { reading_reply = 0; req = current_req; -- cgit v1.2.3 From b16b67689baa01a5616b651356df7ad3e47a8763 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 28 Jun 2020 14:23:12 +1000 Subject: macintosh/via-macii: Remove read_done state The driver state machine may enter the 'read_done' state when leaving the 'idle' or 'reading' state. This transition is pointless, as is the extra interrupt it requires. The interrupt is produced by the transceiver (even when it has no data to send) because an extra EVEN/ODD toggle was signalled by the driver. Drop the extra state to simplify the code. Fixes: 1da177e4c3f41 ("Linux-2.6.12-rc2") # v5.0+ Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/0253194363af4426f9788796811a6a29fb87c713.1593318192.git.fthain@telegraphics.com.au --- drivers/macintosh/via-macii.c | 70 +++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 42 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index 6a5cd7de05ba..d29c87943ca4 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -110,7 +110,6 @@ static enum macii_state { idle, sending, reading, - read_done, } macii_state; static struct adb_request *current_req; /* first request struct in the queue */ @@ -411,8 +410,8 @@ static irqreturn_t macii_interrupt(int irq, void *arg) reply_len = 1; } else { /* bus timeout */ - macii_state = read_done; reply_len = 0; + break; } /* set ADB state = even for first data byte */ @@ -471,20 +470,6 @@ static irqreturn_t macii_interrupt(int irq, void *arg) current_req = req->next; if (req->done) (*req->done)(req); - - if (!current_req) - macii_queue_poll(); - - if (current_req && macii_state == idle) - macii_start(); - - if (macii_state == idle) { - /* reset to shift in */ - via[ACR] &= ~SR_OUT; - x = via[SR]; - /* set ADB state idle - might get SRQ */ - via[B] = (via[B] & ~ST_MASK) | ST_IDLE; - } break; } } else { @@ -511,12 +496,28 @@ static irqreturn_t macii_interrupt(int irq, void *arg) } else if (status == ST_ODD && reply_len == 2) { srq_asserted = true; } else { - macii_state = read_done; + macii_state = idle; + + if (bus_timeout) + reply_len = 0; + + if (reading_reply) { + struct adb_request *req = current_req; + + req->reply_len = reply_len; + + req->complete = 1; + current_req = req->next; + if (req->done) + (*req->done)(req); + } else if (reply_len && autopoll_devs) { + adb_input(reply_buf, reply_len, 0); + } + break; } } - if (macii_state == reading && - reply_len < ARRAY_SIZE(reply_buf)) { + if (reply_len < ARRAY_SIZE(reply_buf)) { reply_ptr++; *reply_ptr = x; reply_len++; @@ -526,37 +527,22 @@ static irqreturn_t macii_interrupt(int irq, void *arg) via[B] ^= ST_MASK; break; - case read_done: - x = via[SR]; - - if (bus_timeout) - reply_len = 0; - - if (reading_reply) { - reading_reply = 0; - req = current_req; - req->reply_len = reply_len; - req->complete = 1; - current_req = req->next; - if (req->done) - (*req->done)(req); - } else if (reply_len && autopoll_devs) - adb_input(reply_buf, reply_len, 0); - - macii_state = idle; + default: + break; + } + if (macii_state == idle) { if (!current_req) macii_queue_poll(); if (current_req) macii_start(); - if (macii_state == idle) + if (macii_state == idle) { + via[ACR] &= ~SR_OUT; + x = via[SR]; via[B] = (via[B] & ~ST_MASK) | ST_IDLE; - break; - - default: - break; + } } local_irq_restore(flags); -- cgit v1.2.3 From 624cf5b538b507293ec761797bd8ce0702fefe64 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 28 Jun 2020 14:23:12 +1000 Subject: 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 Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/754cddfa045e5bfa53e5da199831de02e7d2f27f.1593318192.git.fthain@telegraphics.com.au --- drivers/macintosh/via-macii.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers/macintosh') 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; } -- cgit v1.2.3 From f87a162572c9f7c839a207c7de6c73ffe54a777c Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 28 Jun 2020 14:23:12 +1000 Subject: macintosh/via-macii: Use bool type for reading_reply variable Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/779551219a11b19e574dfcd87e4ef60af08c4fc3.1593318192.git.fthain@telegraphics.com.au --- drivers/macintosh/via-macii.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index 8d5ef77b4a43..e143ddb81de3 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -116,7 +116,7 @@ static struct adb_request *current_req; /* first request struct in the queue */ static struct adb_request *last_req; /* last request struct in the queue */ static unsigned char reply_buf[16]; /* storage for autopolled replies */ static unsigned char *reply_ptr; /* next byte in reply_buf or req->reply */ -static int reading_reply; /* store reply in reply_buf else req->reply */ +static bool reading_reply; /* store reply in reply_buf else req->reply */ static int data_index; /* index of the next byte to send from req->data */ static int reply_len; /* number of bytes received in reply_buf or req->reply */ static int status; /* VIA's ADB status bits captured upon interrupt */ @@ -394,7 +394,7 @@ static irqreturn_t macii_interrupt(int irq, void *arg) WARN_ON((status & ST_MASK) != ST_IDLE); reply_ptr = reply_buf; - reading_reply = 0; + reading_reply = false; bus_timeout = false; srq_asserted = false; @@ -442,7 +442,7 @@ static irqreturn_t macii_interrupt(int irq, void *arg) */ macii_state = reading; - reading_reply = 0; + reading_reply = false; reply_ptr = reply_buf; *reply_ptr = last_talk_cmd; reply_len = 1; @@ -456,7 +456,7 @@ static irqreturn_t macii_interrupt(int irq, void *arg) if (req->reply_expected) { macii_state = reading; - reading_reply = 1; + reading_reply = true; reply_ptr = req->reply; *reply_ptr = req->data[1]; reply_len = 1; @@ -466,7 +466,7 @@ static irqreturn_t macii_interrupt(int irq, void *arg) } else if ((req->data[1] & OP_MASK) == TALK) { macii_state = reading; - reading_reply = 0; + reading_reply = false; reply_ptr = reply_buf; *reply_ptr = req->data[1]; reply_len = 1; -- cgit v1.2.3 From 5c0c15a1953a7de2878d7e6f5711fd3322b11faa Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 28 Jun 2020 14:23:12 +1000 Subject: macintosh/via-macii: Use unsigned type for autopoll_devs variable Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/ca5be30ba745c08c2b7a1f0618f99c61b303e983.1593318192.git.fthain@telegraphics.com.au --- drivers/macintosh/via-macii.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index e143ddb81de3..447273967e1e 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -125,7 +125,7 @@ static bool srq_asserted; /* have to poll for the device that asserted it */ static u8 last_cmd; /* the most recent command byte transmitted */ static u8 last_talk_cmd; /* the most recent Talk command byte transmitted */ static u8 last_poll_cmd; /* the most recent Talk R0 command byte transmitted */ -static int autopoll_devs; /* bits set are device addresses to be polled */ +static unsigned int autopoll_devs; /* bits set are device addresses to poll */ /* Check for MacII style ADB */ static int macii_probe(void) @@ -291,7 +291,7 @@ static int macii_autopoll(int devs) local_irq_save(flags); /* bit 1 == device 1, and so on. */ - autopoll_devs = devs & 0xFFFE; + autopoll_devs = (unsigned int)devs & 0xFFFE; if (!current_req) { macii_queue_poll(); -- cgit v1.2.3 From 046ace8256489f32740da07de55a913ca09ce5cf Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 28 Jun 2020 14:23:12 +1000 Subject: macintosh/via-macii: Use the stack for reset request storage The adb_request struct can be stored on the stack because the request is synchronous and is completed before the function returns. Signed-off-by: Finn Thain Tested-by: Stan Johnson Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/a40f80dde90991757007b6962c386a208c970586.1593318192.git.fthain@telegraphics.com.au --- drivers/macintosh/via-macii.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index 447273967e1e..2f9be4ec7d34 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -313,7 +313,7 @@ static void macii_poll(void) /* Reset the bus */ static int macii_reset_bus(void) { - static struct adb_request req; + struct adb_request req; /* Command = 0, Address = ignored */ adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET); -- cgit v1.2.3 From 3327e58a04501e06aa531cdb4044aab214a6254a Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 28 Jun 2020 14:23:12 +1000 Subject: macintosh/via-macii: Clarify definition of macii_init() The function prototype correctly specifies the 'static' storage class. Let the function definition match the declaration for better readability. Signed-off-by: Finn Thain Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/c025aed0b1506399b73ff1d1bfa40ed641fcb3e3.1593318192.git.fthain@telegraphics.com.au --- drivers/macintosh/via-macii.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index 2f9be4ec7d34..060e03f2264b 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c @@ -140,7 +140,7 @@ static int macii_probe(void) } /* Initialize the driver */ -int macii_init(void) +static int macii_init(void) { unsigned long flags; int err; -- cgit v1.2.3