On Fri, 23 Jun 2017, I wrote:

> 
> Does this patch help? It should be applied on top of this series of 4.
> 

Sorry, I sent the wrong diff. Please try this patch instead.

diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index e9a942d86865..95ae8edbecbc 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -481,6 +481,30 @@ static void generic_NCR5380_release_resources(struct 
Scsi_Host *instance)
                release_mem_region(base, region_size);
 }
 
+/* wait_for_53c80_access - wait for 53C80 registers to become accessible
+ * @hostdata: scsi host private data
+ *
+ * The registers within the 53C80 logic block are inaccessible until
+ * bit 7 in the 53C400 control status register gets asserted.
+ */
+
+static int wait_for_53c80_access(struct NCR5380_hostdata *hostdata)
+{
+       int count = 10000;
+
+       do {
+               udelay(4); /* DTC436 chip hangs without this */
+               if (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)
+                       return 0;
+       } while (--count > 0);
+
+       scmd_printk(KERN_ERR, hostdata->connected,
+                   "53c80 registers not accessible, device will be reset\n");
+       NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
+       NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
+       return -1;
+}
+
 /**
  * generic_NCR5380_pread - pseudo DMA receive
  * @hostdata: scsi host private data
@@ -493,18 +517,19 @@ static void generic_NCR5380_release_resources(struct 
Scsi_Host *instance)
 static inline int generic_NCR5380_pread(struct NCR5380_hostdata *hostdata,
                                         unsigned char *dst, int len)
 {
-       int blocks = len / 128;
-       int start = 0;
+       int result;
+       int start;
 
        NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
-       NCR5380_write(hostdata->c400_blk_cnt, blocks);
-       while (1) {
-               if (NCR5380_read(hostdata->c400_blk_cnt) == 0)
+       NCR5380_write(hostdata->c400_blk_cnt, len / 128);
+
+       for (start = 0; start < len; start += 128) {
+               if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
+                                          CSR_HOST_BUF_NOT_RDY, 0,
+                                          hostdata->c400_ctl_status,
+                                          CSR_GATED_53C80_IRQ,
+                                          CSR_GATED_53C80_IRQ, HZ / 64) < 0)
                        break;
-               if (NCR5380_read(hostdata->c400_ctl_status) & 
CSR_GATED_53C80_IRQ)
-                       goto out_wait;
-               while (NCR5380_read(hostdata->c400_ctl_status) & 
CSR_HOST_BUF_NOT_RDY)
-                       ; /* FIXME - no timeout */
 
                if (hostdata->io_port && hostdata->io_width == 2)
                        insw(hostdata->io_port + hostdata->c400_host_buf,
@@ -515,43 +540,16 @@ static inline int generic_NCR5380_pread(struct 
NCR5380_hostdata *hostdata,
                else
                        memcpy_fromio(dst + start,
                                hostdata->io + NCR53C400_host_buffer, 128);
-
-               start += 128;
-               blocks--;
-       }
-
-       if (blocks) {
-               while (NCR5380_read(hostdata->c400_ctl_status) & 
CSR_HOST_BUF_NOT_RDY)
-                       ; /* FIXME - no timeout */
-
-               if (hostdata->io_port && hostdata->io_width == 2)
-                       insw(hostdata->io_port + hostdata->c400_host_buf,
-                                                       dst + start, 64);
-               else if (hostdata->io_port)
-                       insb(hostdata->io_port + hostdata->c400_host_buf,
-                                                       dst + start, 128);
-               else
-                       memcpy_fromio(dst + start,
-                               hostdata->io + NCR53C400_host_buffer, 128);
-
-               start += 128;
-               blocks--;
        }
 
-       if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
-               printk("53C400r: no 53C80 gated irq after transfer");
-
-out_wait:
-       /* wait for 53C80 registers to be available */
-       while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG))
-               ;
+       result = wait_for_53c80_access(hostdata);
 
        if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
                pr_err("%s: No end dma signal (%d/%d)\n", __func__, start, len);
 
-       hostdata->pdma_residual = len - start;
+       hostdata->pdma_residual = NCR5380_read(hostdata->c400_blk_cnt) * 128;
 
-       return 0;
+       return result;
 }
 
 /**
@@ -566,36 +564,19 @@ static inline int generic_NCR5380_pread(struct 
NCR5380_hostdata *hostdata,
 static inline int generic_NCR5380_pwrite(struct NCR5380_hostdata *hostdata,
                                          unsigned char *src, int len)
 {
-       int blocks = len / 128;
-       int start = 0;
+       int result;
+       int start;
 
        NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
-       NCR5380_write(hostdata->c400_blk_cnt, blocks);
-       while (1) {
-               if (NCR5380_read(hostdata->c400_ctl_status) & 
CSR_GATED_53C80_IRQ)
-                       goto out_wait;
-
-               if (NCR5380_read(hostdata->c400_blk_cnt) == 0)
+       NCR5380_write(hostdata->c400_blk_cnt, len / 128);
+
+       for (start = 0; start < len; start += 128) {
+               if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
+                                          CSR_HOST_BUF_NOT_RDY, 0,
+                                          hostdata->c400_ctl_status,
+                                          CSR_GATED_53C80_IRQ,
+                                          CSR_GATED_53C80_IRQ, HZ / 64) < 0)
                        break;
-               while (NCR5380_read(hostdata->c400_ctl_status) & 
CSR_HOST_BUF_NOT_RDY)
-                       ; // FIXME - timeout
-
-               if (hostdata->io_port && hostdata->io_width == 2)
-                       outsw(hostdata->io_port + hostdata->c400_host_buf,
-                                                       src + start, 64);
-               else if (hostdata->io_port)
-                       outsb(hostdata->io_port + hostdata->c400_host_buf,
-                                                       src + start, 128);
-               else
-                       memcpy_toio(hostdata->io + NCR53C400_host_buffer,
-                                   src + start, 128);
-
-               start += 128;
-               blocks--;
-       }
-       if (blocks) {
-               while (NCR5380_read(hostdata->c400_ctl_status) & 
CSR_HOST_BUF_NOT_RDY)
-                       ; // FIXME - no timeout
 
                if (hostdata->io_port && hostdata->io_width == 2)
                        outsw(hostdata->io_port + hostdata->c400_host_buf,
@@ -606,26 +587,23 @@ static inline int generic_NCR5380_pwrite(struct 
NCR5380_hostdata *hostdata,
                else
                        memcpy_toio(hostdata->io + NCR53C400_host_buffer,
                                    src + start, 128);
-
-               start += 128;
-               blocks--;
        }
 
-out_wait:
-       /* wait for 53C80 registers to be available */
-       while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) {
-               udelay(4); /* DTC436 chip hangs without this */
-               /* FIXME - no timeout */
-       }
+       result = wait_for_53c80_access(hostdata);
 
        if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
                pr_err("%s: No end dma signal (%d/%d)\n", __func__, start, len);
 
-       hostdata->pdma_residual = len - start;
+       hostdata->pdma_residual = NCR5380_read(hostdata->c400_blk_cnt) * 128;
 
-       while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
-               ;       // TIMEOUT
-       return 0;
+       if (hostdata->pdma_residual == 0 &&
+           NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG,
+                                 TCR_LAST_BYTE_SENT, TCR_LAST_BYTE_SENT,
+                                 HZ / 64) < 0)
+               scmd_printk(KERN_ERR, hostdata->connected,
+                           "%s: Last Byte Sent timeout\n", __func__);
+
+       return result;
 }
 
 static int generic_NCR5380_dma_xfer_len(struct NCR5380_hostdata *hostdata,

Reply via email to