From: Finn Thain <hidden> Date: 2020-06-28 04:31:55
Various issues with the via-macii driver have become apparent over the
years. Some examples:
- A Talk command response can be lost. This can result in phantom devices
being probed or an incorrect device handler ID being retrieved.
- A reply packet containing a null byte can get truncated. Such packets
are sometimes generated by ADB keyboards.
- A Talk Register 3 reply from device 15 (that is, command byte 0xFF)
can be mistaken for a bus timeout (empty packet).
This patch series contains fixes for all known bugs in the via-macii
driver, plus a few code style improvements. It has been successfully
tested on an Apple Centris 650 and qemu-system-m68k.
The patched kernel does regress on past QEMU releases, due to ADB
transceiver emulation bugs. Those bugs have been fixed in mainline QEMU.
My thanks go to Mark Cave-Ayland for that effort and for figuring out
the improvements to the signalling between the VIA and the transceiver.
Note to -stable maintainers: these fixes can be cherry-picked without
difficulty, if you have the 5 commits that appeared in v5.0:
b52dce8738938 macintosh/via-macii: Synchronous bus reset
5f93d7081a47e macintosh/via-macii: Remove BUG_ON assertions
5ce6185c2ef4e macintosh/via-macii: Simplify locking
351e5ad327d07 macintosh/via-macii, macintosh/adb-iop: Modernize printk calls
47fd2060660e6 macintosh/via-macii, macintosh/adb-iop: Clean up whitespace
Just for the sake of simplicity, the 'fixes' tags in this series limit
backporting to 'v5.0+'.
Finn Thain (9):
macintosh/via-macii: Access autopoll_devs when inside lock
macintosh/via-macii: Poll the device most likely to respond
macintosh/via-macii: Handle /CTLR_IRQ signal correctly
macintosh/via-macii: Remove read_done state
macintosh/via-macii: Handle poll replies correctly
macintosh/via-macii: Use bool type for reading_reply variable
macintosh/via-macii: Use unsigned type for autopoll_devs variable
macintosh/via-macii: Use the stack for reset request storage
macintosh/via-macii: Clarify definition of macii_init()
drivers/macintosh/via-macii.c | 324 +++++++++++++++++++---------------
1 file changed, 179 insertions(+), 145 deletions(-)
--
2.26.2
From: Finn Thain <hidden> Date: 2020-06-28 04:31:54
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+
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
---
drivers/macintosh/via-macii.c | 70 ++++++++++++++---------------------
1 file changed, 28 insertions(+), 42 deletions(-)
@@ -110,7 +110,6 @@ static enum macii_state {idle,sending,reading,-read_done,}macii_state;staticstructadb_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{
From: Finn Thain <hidden> Date: 2020-06-28 04:31:54
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+
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
---
drivers/macintosh/via-macii.c | 99 +++++++++++++++++++----------------
1 file changed, 53 insertions(+), 46 deletions(-)
@@ -117,7 +121,8 @@ static int reply_len; /* number of bytes received in reply_buf or req->reply */staticintstatus;/* VIA's ADB status bits captured upon interrupt */staticintlast_status;/* status bits as at previous interrupt */staticintsrq_asserted;/* have to poll for the device that asserted it */-staticintcommand_byte;/* the most recent command byte transmitted */+staticu8last_cmd;/* the most recent command byte transmitted */+staticu8last_poll_cmd;/* the most recent Talk R0 command byte transmitted */staticintautopoll_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) */staticvoidmacii_queue_poll(void){-/* No point polling the active device as it will never assert SRQ, so-*pollthenextdeviceintheautopolllist.Thiscouldleaveus-*stuckinapollingloopifanunprobeddeviceisassertingSRQ.-*Intheory,thatcouldonlyhappenifadevicewaspluggedinafter-*probingstarted.Unpluggingitagainwillbreakthecycle.-*(Simplypollingthenexthigherdeviceoftenendsuppollingalmost-*everydevice(afterwrappingaround),whichtakestoolong.)-*/-intdevice_mask;-intnext_device;staticstructadb_requestreq;+unsignedcharpoll_command;+unsignedintpoll_addr;+/* This only polls devices in the autopoll list, which assumes that+*unprobeddevicesneverassertSRQ.Thatcouldhappenifadevicewas+*pluggedinaftertheadbbusscan.Unpluggingitagainwillresolve+*theproblem.ThisbehaviourissimilartoMacOS.+*/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+*rightnow.Someotherdevice(s)mayhavesignalledSRQ(theactive+*devicewon'tdothat).Ortheautopolllistmayhavebeenchanged.+*Trypollingthenexthigheraddress.+*/+poll_addr=(last_poll_cmd&ADDR_MASK)>>4;+if((srq_asserted&&last_cmd==last_poll_cmd)||+!(autopoll_devs&(1<<poll_addr))){+unsignedinthigher_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+*aslongasitisidle.+*/+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 */staticintmacii_autopoll(intdevs){-staticstructadb_requestreq;unsignedlongflags;-interr=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-*thisaslongasitisidle.-*/-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);-returnerr;-}-staticinlineintneed_autopoll(void)-{-/* Was the last command Talk Reg 0-*andisthetargetontheautopolllist?-*/-if((command_byte&0x0F)==0x0C&&-((1<<((command_byte&0xF0)>>4))&autopoll_devs))-return0;-return1;+return0;}/* 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 */
From: Finn Thain <hidden> Date: 2020-06-28 04:32:05
The adb_request struct can be stored on the stack because the request
is synchronous and is completed before the function returns.
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
---
drivers/macintosh/via-macii.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
@@ -125,7 +125,7 @@ static bool srq_asserted; /* have to poll for the device that asserted it */staticu8last_cmd;/* the most recent command byte transmitted */staticu8last_talk_cmd;/* the most recent Talk command byte transmitted */staticu8last_poll_cmd;/* the most recent Talk R0 command byte transmitted */-staticintautopoll_devs;/* bits set are device addresses to be polled */+staticunsignedintautopoll_devs;/* bits set are device addresses to poll *//* Check for MacII style ADB */staticintmacii_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=(unsignedint)devs&0xFFFE;if(!current_req){macii_queue_poll();
From: Finn Thain <hidden> Date: 2020-06-28 04:32:08
The function prototype correctly specifies the 'static' storage class.
Let the function definition match the declaration for better readability.
Signed-off-by: Finn Thain <redacted>
---
drivers/macintosh/via-macii.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Finn Thain <hidden> Date: 2020-06-28 04:32:14
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 <redacted>
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
---
drivers/macintosh/via-macii.c | 166 ++++++++++++++++++++--------------
1 file changed, 97 insertions(+), 69 deletions(-)
@@ -119,9 +121,10 @@ static int reading_reply; /* store reply in reply_buf else req->reply */staticintdata_index;/* index of the next byte to send from req->data */staticintreply_len;/* number of bytes received in reply_buf or req->reply */staticintstatus;/* VIA's ADB status bits captured upon interrupt */-staticintlast_status;/* status bits as at previous interrupt */-staticintsrq_asserted;/* have to poll for the device that asserted it */+staticboolbus_timeout;/* no data was sent by the device */+staticboolsrq_asserted;/* have to poll for the device that asserted it */staticu8last_cmd;/* the most recent command byte transmitted */+staticu8last_talk_cmd;/* the most recent Talk command byte transmitted */staticu8last_poll_cmd;/* the most recent Talk R0 command byte transmitted */staticintautopoll_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)*Andreq->nbytesisthenumberofbytesofrealdataplusone.*/-/* 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 */
@@ -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){caseidle:-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:-*datais"FF"whileCTLR_IRQis"H"+if(!(status&CTLR_IRQ)){+/* /CTLR_IRQ asserted in idle state means we must+*readanautopollreplyfromthetransceiverbuffer.*/-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)casesending:req=current_req;-if(data_index>=req->nbytes){++if(status==(ST_CMD|CTLR_IRQ)){+/* /CTLR_IRQ de-asserted after the command byte means+*thehostcancontinuewiththetransaction.+*/++/* 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+*mustreadanautopollreply.Thefirstbytewas+*lostbecausetheshiftregisterwasanoutput.+*/+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];+}elseif(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;
@@ -116,7 +116,7 @@ static struct adb_request *current_req; /* first request struct in the queue */staticstructadb_request*last_req;/* last request struct in the queue */staticunsignedcharreply_buf[16];/* storage for autopolled replies */staticunsignedchar*reply_ptr;/* next byte in reply_buf or req->reply */-staticintreading_reply;/* store reply in reply_buf else req->reply */+staticboolreading_reply;/* store reply in reply_buf else req->reply */staticintdata_index;/* index of the next byte to send from req->data */staticintreply_len;/* number of bytes received in reply_buf or req->reply */staticintstatus;/* VIA's ADB status bits captured upon interrupt */
From: Finn Thain <hidden> Date: 2020-06-28 04:32:22
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+
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
---
drivers/macintosh/via-macii.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
From: Finn Thain <hidden> Date: 2020-06-28 04:32:27
The interrupt handler should be excluded when accessing the autopoll_devs
variable.
Fixes: d95fd5fce88f0 ("m68k: Mac II ADB fixes") # v5.0+
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
---
drivers/macintosh/via-macii.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
@@ -270,15 +270,12 @@ static int macii_autopoll(int devs)unsignedlongflags;interr=0;+local_irq_save(flags);+/* bit 1 == device 1, and so on. */autopoll_devs=devs&0xFFFE;-if(!autopoll_devs)-return0;--local_irq_save(flags);--if(current_req==NULL){+if(autopoll_devs&&!current_req){/* Send a Talk Reg 0. The controller will repeatedly transmit*thisaslongasitisidle.*/
From: Michael Ellerman <hidden> Date: 2020-07-27 07:26:55
On Sun, 28 Jun 2020 14:23:12 +1000, Finn Thain wrote:
Various issues with the via-macii driver have become apparent over the
years. Some examples:
- A Talk command response can be lost. This can result in phantom devices
being probed or an incorrect device handler ID being retrieved.
- A reply packet containing a null byte can get truncated. Such packets
are sometimes generated by ADB keyboards.
[...]
Hi,
On Sun, Jun 28, 2020 at 02:23:12PM +1000, Finn Thain wrote:
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+
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
With this patch applied, the qemu "q800" emulation no longer works and is stuck
in early boot. Any idea why that might be the case, and/or how to debug it ?
Thanks,
Guenter
@@ -117,7 +121,8 @@ static int reply_len; /* number of bytes received in reply_buf or req->reply */staticintstatus;/* VIA's ADB status bits captured upon interrupt */staticintlast_status;/* status bits as at previous interrupt */staticintsrq_asserted;/* have to poll for the device that asserted it */-staticintcommand_byte;/* the most recent command byte transmitted */+staticu8last_cmd;/* the most recent command byte transmitted */+staticu8last_poll_cmd;/* the most recent Talk R0 command byte transmitted */staticintautopoll_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) */staticvoidmacii_queue_poll(void){-/* No point polling the active device as it will never assert SRQ, so-*pollthenextdeviceintheautopolllist.Thiscouldleaveus-*stuckinapollingloopifanunprobeddeviceisassertingSRQ.-*Intheory,thatcouldonlyhappenifadevicewaspluggedinafter-*probingstarted.Unpluggingitagainwillbreakthecycle.-*(Simplypollingthenexthigherdeviceoftenendsuppollingalmost-*everydevice(afterwrappingaround),whichtakestoolong.)-*/-intdevice_mask;-intnext_device;staticstructadb_requestreq;+unsignedcharpoll_command;+unsignedintpoll_addr;+/* This only polls devices in the autopoll list, which assumes that+*unprobeddevicesneverassertSRQ.Thatcouldhappenifadevicewas+*pluggedinaftertheadbbusscan.Unpluggingitagainwillresolve+*theproblem.ThisbehaviourissimilartoMacOS.+*/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+*rightnow.Someotherdevice(s)mayhavesignalledSRQ(theactive+*devicewon'tdothat).Ortheautopolllistmayhavebeenchanged.+*Trypollingthenexthigheraddress.+*/+poll_addr=(last_poll_cmd&ADDR_MASK)>>4;+if((srq_asserted&&last_cmd==last_poll_cmd)||+!(autopoll_devs&(1<<poll_addr))){+unsignedinthigher_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+*aslongasitisidle.+*/+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 */staticintmacii_autopoll(intdevs){-staticstructadb_requestreq;unsignedlongflags;-interr=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-*thisaslongasitisidle.-*/-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);-returnerr;-}-staticinlineintneed_autopoll(void)-{-/* Was the last command Talk Reg 0-*andisthetargetontheautopolllist?-*/-if((command_byte&0x0F)==0x0C&&-((1<<((command_byte&0xF0)>>4))&autopoll_devs))-return0;-return1;+return0;}/* 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 */
Hi,
On Sun, Jun 28, 2020 at 02:23:12PM +1000, Finn Thain wrote:
The interrupt handler should be excluded when accessing the autopoll_devs
variable.
I am quite baffled by this patch. Other than adding an unnecessary lock /
unlock sequence, accessing a variable (which is derived from another
variable) from inside or outside a lock does not make a difference.
If autopoll_devs = devs & 0xfffe is 0 inside the lock, it will just
as much be 0 outside the lock, and vice versa.
Can you explain this in some more detail ? Not that is matters much since
the change already made it into mainline, but I would like to understand
what if anything I am missing here.
Thanks,
Guenter
quoted hunk
Fixes: d95fd5fce88f0 ("m68k: Mac II ADB fixes") # v5.0+
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
---
drivers/macintosh/via-macii.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
@@ -270,15 +270,12 @@ static int macii_autopoll(int devs)unsignedlongflags;interr=0;+local_irq_save(flags);+/* bit 1 == device 1, and so on. */autopoll_devs=devs&0xFFFE;-if(!autopoll_devs)-return0;--local_irq_save(flags);--if(current_req==NULL){+if(autopoll_devs&&!current_req){/* Send a Talk Reg 0. The controller will repeatedly transmit*thisaslongasitisidle.*/
From: Finn Thain <hidden> Date: 2020-08-09 22:58:52
On Sun, 9 Aug 2020, Guenter Roeck wrote:
Hi,
On Sun, Jun 28, 2020 at 02:23:12PM +1000, Finn Thain wrote:
quoted
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+
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
With this patch applied, the qemu "q800" emulation no longer works and
is stuck in early boot. Any idea why that might be the case, and/or how
to debug it ?
The problem you're seeing was mentioned in the cover letter,
https://lore.kernel.org/linux-m68k/cover.1593318192.git.fthain@telegraphics.com.au/
Since this series was merged, Linus' tree is no longer compatible with
long-standing QEMU bugs.
The best way to fix this is to upgrade QEMU (latest is 5.1.0-rc3). Or use
the serial console instead of the framebuffer console.
I regret the inconvenience but the alternative was worse: adding code to
Linux to get compatibility with QEMU bugs (which were added to QEMU due to
Linux bugs).
My main concern is correct operation on actual hardware, as always. But
some QEMU developers are working on support for operating systems besides
Linux.
Therefore, I believe that both QEMU and Linux should aim for compatibility
with actual hardware and not bug compatibility with each other.
From: Finn Thain <hidden> Date: 2020-08-09 23:15:34
On Sun, 9 Aug 2020, Guenter Roeck wrote:
Hi,
On Sun, Jun 28, 2020 at 02:23:12PM +1000, Finn Thain wrote:
quoted
The interrupt handler should be excluded when accessing the
autopoll_devs variable.
I am quite baffled by this patch. Other than adding an unnecessary lock
/ unlock sequence,
The new lock/unlock sequence means that the expression (autopoll_devs &&
!current_req) can be understood to be atomic. That makes it easier for me
to follow (being that both variables are shared state).
accessing a variable (which is derived from another variable) from
inside or outside a lock does not make a difference. If autopoll_devs =
devs & 0xfffe is 0 inside the lock, it will just as much be 0 outside
the lock, and vice versa.
Can you explain this in some more detail ? Not that is matters much
since the change already made it into mainline, but I would like to
understand what if anything I am missing here.
I think the new code is more readable and is obviously free of race
conditions. It's not obvious to me why the old code was free of race
conditions but if you can easily establish that by inspection then you are
a better auditor than I am. Regardless, I'll stick with "Keep It Simple,
Stupid".
Hi,
On Sun, Jun 28, 2020 at 02:23:12PM +1000, Finn Thain wrote:
quoted
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+
Tested-by: Stan Johnson <redacted>
Signed-off-by: Finn Thain <redacted>
With this patch applied, the qemu "q800" emulation no longer works and
is stuck in early boot. Any idea why that might be the case, and/or how
to debug it ?
The problem you're seeing was mentioned in the cover letter,
https://lore.kernel.org/linux-m68k/cover.1593318192.git.fthain@telegraphics.com.au/
Since this series was merged, Linus' tree is no longer compatible with
long-standing QEMU bugs.
The best way to fix this is to upgrade QEMU (latest is 5.1.0-rc3). Or use
the serial console instead of the framebuffer console.
I have no problem with that. Actually, I had checked the qemu commit log,
but somehow I had missed missed the commits there.
I regret the inconvenience but the alternative was worse: adding code to
Linux to get compatibility with QEMU bugs (which were added to QEMU due to
Linux bugs).
My main concern is correct operation on actual hardware, as always. But
some QEMU developers are working on support for operating systems besides
Linux.
Therefore, I believe that both QEMU and Linux should aim for compatibility
with actual hardware and not bug compatibility with each other.
I absolutely agree.
I repeated the test on the mainline kernel with qemu v5.1-rc3, and it works.
I also made sure that older versions of Linux still work with the qemu
v5.1.0-rc3. So everything is good, and sorry for the noise.
Thanks,
Guenter