diff mbox series

[v2,2/6] esp_scsi: Track residual for PIO transfers

Message ID 11a3a80e74a006040460fa051747e6a79c6382ce.1539497520.git.fthain@telegraphics.com.au (mailing list archive)
State Changes Requested
Headers show
Series mac_esp, zorro_esp, esp_scsi: Various improvements | expand

Commit Message

Finn Thain Oct. 14, 2018, 6:12 a.m. UTC
If a target disconnects during a PIO data transfer the command may
fail when the target reconnects:

scsi host1: DMA length is zero!
scsi host1: cur adr[04380000] len[00000000]

The scsi bus is then reset. This happens because the residual reached
zero before the transfer was completed.

The usual residual calculation relies on the Transfer Count registers
which works for DMA transfers but not for PIO transfers. Fix the problem
by storing the PIO transfer residual and using that to correctly
calculate bytes_sent.

Fixes: 6fe07aaffbf0
Tested-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
---
 drivers/scsi/esp_scsi.c | 1 +
 drivers/scsi/esp_scsi.h | 2 ++
 drivers/scsi/mac_esp.c  | 2 ++
 3 files changed, 5 insertions(+)

Comments

Geert Uytterhoeven Oct. 14, 2018, 10:55 a.m. UTC | #1
Hi Finn,

On Sun, Oct 14, 2018 at 8:36 AM Finn Thain <fthain@telegraphics.com.au> wrote:
> If a target disconnects during a PIO data transfer the command may
> fail when the target reconnects:
>
> scsi host1: DMA length is zero!
> scsi host1: cur adr[04380000] len[00000000]
>
> The scsi bus is then reset. This happens because the residual reached
> zero before the transfer was completed.
>
> The usual residual calculation relies on the Transfer Count registers
> which works for DMA transfers but not for PIO transfers. Fix the problem
> by storing the PIO transfer residual and using that to correctly
> calculate bytes_sent.

Thanks for yur patch!

> Fixes: 6fe07aaffbf0

Fixes: 6fe07aaffbf0 ("[SCSI] m68k: new mac_esp scsi driver")

> Tested-by: Stan Johnson <userm57@yahoo.com>
> Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
> Tested-by: Michael Schmitz <schmitzmic@gmail.com>

> --- a/drivers/scsi/esp_scsi.h
> +++ b/drivers/scsi/esp_scsi.h
> @@ -540,6 +540,8 @@ struct esp {
>
>         void                    *dma;
>         int                     dmarev;
> +
> +       int                     send_cmd_residual;

unsigned int?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
Finn Thain Oct. 14, 2018, 10:14 p.m. UTC | #2
On Sun, 14 Oct 2018, Geert Uytterhoeven wrote:

> 
> > Fixes: 6fe07aaffbf0
> 
> Fixes: 6fe07aaffbf0 ("[SCSI] m68k: new mac_esp scsi driver")
> 

Fixed.

> > Tested-by: Stan Johnson <userm57@yahoo.com>
> > Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
> > Tested-by: Michael Schmitz <schmitzmic@gmail.com>
> 
> > --- a/drivers/scsi/esp_scsi.h
> > +++ b/drivers/scsi/esp_scsi.h
> > @@ -540,6 +540,8 @@ struct esp {
> >
> >         void                    *dma;
> >         int                     dmarev;
> > +
> > +       int                     send_cmd_residual;
> 
> unsigned int?
> 

My first thought was to use u32, same as esp_count. But it turns out that 
the end result really is an int --

static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
                               struct scsi_cmnd *cmd)
{
        int fifo_cnt, ecount, bytes_sent, flush_fifo;

        ...
        bytes_sent = esp->data_dma_len;
        bytes_sent -= ecount;
        bytes_sent -= esp->send_cmd_residual;
	...
        return bytes_sent;
}

Apparently over/underflow is a real possibility, because there is a test 
for this in esp_process_event().
diff mbox series

Patch

diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index c3fc34b9964d..9e5d3f7d29ae 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -1338,6 +1338,7 @@  static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
 
 	bytes_sent = esp->data_dma_len;
 	bytes_sent -= ecount;
+	bytes_sent -= esp->send_cmd_residual;
 
 	/*
 	 * The am53c974 has a DMA 'pecularity'. The doc states:
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 8163dca2071b..db4b6ea94caa 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -540,6 +540,8 @@  struct esp {
 
 	void			*dma;
 	int			dmarev;
+
+	int			send_cmd_residual;
 };
 
 /* A front-end driver for the ESP chip should do the following in
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index eb551f3cc471..71879f2207e0 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -427,6 +427,8 @@  static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
 			scsi_esp_cmd(esp, ESP_CMD_TI);
 		}
 	}
+
+	esp->send_cmd_residual = esp_count;
 }
 
 static int mac_esp_irq_pending(struct esp *esp)