[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