On Tuesday 27 June 2017 14:42:29 Finn Thain wrote:
> On Tue, 27 Jun 2017, Ondrej Zary wrote:
> > BTW. I've probably found the DTC write corruption. Added the following
> > check (13 is host buffer index register) -
>
> That register is not mentioned in my 53c400 datasheet.

Yes, it's not there. But we don't have 53C400A and DTC436 datasheets (this 
register works on both).

> > and it triggers sometimes: the value is 1 instead of 0. As we use only
> > 16-bit writes, I don't see how the value could ever be odd. Looks like a
> > bug in the chip. The index register corrupts during the transfer, not
> > after IRQ or timeout. The same check at beginning of pwrite() did not
> > trigger.
>
> Are you reading this register at the right moment? Have you tried waiting
> for it to reach zero, as in,
>
>       if (NCR5380_poll_politely(hostdata, 13, 0xff, 0, HZ / 64) < 0)
>               /* printk, reset etc */;

I have not but will try (expecting that it will not change by itself).

> Even if this is a reliable way to detect a short transfer, it would be
> nice to know the root cause. But I'm being unrealistic: the DTC436 vendor
> never responded to my requests for technical documentation.

According to the data corruption observed, it's not a short transfer. The 
corruption is always the same: one byte missing at the beginning of a 128 B 
block. It happens only with slow Quantum LPS 240 drive, not with faster IBM 
DORS-32160.

> > The index register is not writable so we must(?) reset the PDMA engine
> > to recover. However, this quick attempt to fix does not work, maybe we
> > should reload the block count and continue?
>
> I don't know if it is possible to recover. If the last byte never reached
> the scsi bus, then once you reset the 53c400 core, you need the driver to
> perform a single-byte PIO transfer after the short PDMA transfer. This
> would require that you set the residual appropriately (though in my
> experience that may not be sufficient).
>
> It may be better to simply limit the transfer to 512 bytes instead of
> attempting to recover based on an undocumented (?) register, etc. Seems
> like a bit of a hack.
>
> > --- a/drivers/scsi/g_NCR5380.c
> > +++ b/drivers/scsi/g_NCR5380.c
> > @@ -595,7 +603,13 @@ static inline int generic_NCR5380_pwrite(struct
> > NCR5380_hostdata *hostdata,
> >                                 goto out_wait;
> >                         }
> >                 }
> > -
> > +               idx = NCR5380_read(13);
> > +               if (idx != 0) {
> > +                       printk("host idx=%d, start=%d\n", idx, start);
> > +                       NCR5380_write(hostdata->c400_ctl_status,
> > CSR_RESET); +                      
> > NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); +                    
> >   goto out_wait;
> > +               }
> >                 if (hostdata->io_port && hostdata->io_width == 2)
> >                         outsw(hostdata->io_port +
> > hostdata->c400_host_buf, src + start, 64);
>
> I find it hard to reason about this code. For example, out_wait is to be
> removed. Let's get the preceding patches working and signed-off. Please go
> ahead and use a 512 B transfer for DTC436 testing if that will help get
> this patch series over the line.

OK, I agree. Let's fix the problems first and leave this hack for later.

-- 
Ondrej Zary

Reply via email to