[PATCH 1/2] gpib: tnt4882: fix nec7210 register access on ISA boards

Tommaso Perondi <[email protected]>
Newsgroups org.kernel.vger.linux-kernel
Message-ID <[email protected]>
ni_isa_attach_common() never assigns nec_priv->iobase.  It uses the local
iobase for request_region() and ioport_map() only, while every other
nec7210 based driver (pc2, cb7210, ines, cec) assigns it in its attach.

nec7210_locking_ioport_read_byte() and nec7210_locking_ioport_write_byte()
compute the port as priv->iobase + register_num * priv->offset.  With
iobase left at zero, every nec7210 register access of an AT-GPIB ISA board
goes to 0x00..0x0e, that is the first ISA DMA controller, instead of the
board's I/O window.

The TNT specific registers are reached through tnt_readb()/tnt_writeb(),
which use mmiobase, so they keep working and the board looks half alive:
CSR and BSR read back correctly and SETSC does set the system controller
bit, but ibsre() writes AUX_SREN into the 8237 mask register and REN is
never asserted on the bus, while update_status() reads the DMA status
register and reports bogus bus states.  Writes into the DMA controller
can also disturb unrelated ISA DMA users such as the floppy.

ni_isa_detach() tests nec_priv->iobase before release_region(), so the
I/O window is leaked as well: a second attach fails with -EBUSY and
leaves the board offline, after which every ioctl returns -EINVAL.

Before the commit below, nec_priv->iobase held the ioport_map() cookie
and the accessors cast it back to a port number, which worked on x86.
That commit split the field in two but did not restore the assignment.
It also left the tnt4882_board_reset() call in ni_isa_detach() guarded by
iobase, which used to mean "mapped"; move that guard to mmiobase, which
is what tnt4882_board_reset() writes through, so the reset cannot run
with a NULL mapping if ioport_map() fails.

No release_region() is added to the attach error paths on purpose:
ibonline() calls detach() when attach fails, and that is where the region
is released.

Tested on an AT-GPIB/TNT at 0x2c0, irq 11.  Before the patch REN stays
released after ibsre() and the primary address never reaches ADR; after
it, BSR reads 0x01 with REN asserted, ADR reads back the configured
address, and gpib_config can be run repeatedly.

Fixes: baf8855c9160 ("staging: gpib: fix address space mixup")
Cc: [email protected]
Signed-off-by: Tommaso Perondi <[email protected]>
---
 drivers/gpib/tnt4882/tnt4882_gpib.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpib/tnt4882/tnt4882_gpib.c b/drivers/gpib/tnt4882/tnt4882_gpib.c
index 3cd13f637ed4..b94af5c584f1 100644
--- a/drivers/gpib/tnt4882/tnt4882_gpib.c
+++ b/drivers/gpib/tnt4882/tnt4882_gpib.c
@@ -1066,6 +1066,7 @@ static int ni_isa_attach_common(struct gpib_board *board, const struct gpib_boar
 	// allocate ioports
 	if (!request_region(iobase, atgpib_iosize, "atgpib"))
 		return -EBUSY;
+	nec_priv->iobase = iobase;
 
 	nec_priv->mmiobase = ioport_map(iobase, atgpib_iosize);
 	if (!nec_priv->mmiobase)
@@ -1106,7 +1107,7 @@ static void ni_isa_detach(struct gpib_board *board)
 
 	if (tnt_priv) {
 		nec_priv = &tnt_priv->nec7210_priv;
-		if (nec_priv->iobase)
+		if (nec_priv->mmiobase)
 			tnt4882_board_reset(tnt_priv, board);
 		if (tnt_priv->irq)
 			free_irq(tnt_priv->irq, board);
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.