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,